天天看點

第六次作業--結對程式設計第二次

【結對情況】

  • 530雨勤 – 随機資料生成子產品,json相關代碼
  • 501安琪 – 比對算法子產品

【各種傳送門】

  • title
  • github
  • json

【設計說明】

  • 接口設計(API)

friend void student_from_json(const json& j, Student& student);

friend void department_from_json(const json& j, Department& department);

friend void read(string file_name, DistributeSystem& ds);

friend void matched_student_to_json(const Student& student);

friend void standalone_student_to_json(const Student& student);

friend void matched_department_to_json(const Department& department);

friend void standalone_department_to_json(const Department& department);

  • 内部實作設計(類圖)

第六次作業--結對程式設計第二次
  • 代碼規範

  • 命名規範

    • 類與結構體:第一個大寫字母開頭,後面跟随的字母全部用小寫。
    • 變量:所有字母均小寫,使用下劃線“_”作為單詞的分隔。
    • 指針: '*' 應靠近類型,而不是變量名。
    • 引用: '&' 應靠近類型,而不是變量名。
  • 排版規範

    • 方法和函數的布局 :對于有較多參數的函數的寫法,如果參數較多,一行寫不下,我們應該分成幾行來寫,并且每個參數都另起一行對齊。
    • 縮進:縮進的時候,每一層縮進4個空格;不要使用TAB,用空格。
    • 行規則:保證一行隻寫一條語句,一行隻定義一個變量。
    • 花括号{}規則:括号的左半邊與關鍵字同行,右邊換行,并且與關鍵字對齊。
    • 所有的 if, while 和 do 語句,要麼用單行格式,要麼使用花括号格式。
    • 圓括号 () 規則:圓括号與關鍵字之間應放一個空格; 圓括号與函數名之間不要有空格。
    • Continue 和break: Continue 和break 實際上起到與goto一樣的作用,是以,盡量少用為上。并且,Continue與break最好不要連用。
    • 運算符号的規則 : 一進制操作符如(!、~ 等等)應貼近操作對象; 二進制操作符如(+、*、%、== 等等)應在前後留白格;++ 和 -- 盡量使用前置運算。
    • 變量聲明語句塊: 變量應該是随用随聲明,不要集中在函數前,例如for語句的循環變量,應隻在for語句中定義。
  • 注釋

    • Include 語句注釋:如果有必要,#include語句也應有注釋,它可以告訴我們,為什麼要包含這個頭檔案。
    • 語句塊注釋:盡量用代碼代替注釋,如果決定用注釋,避免喃喃自語或含糊不明的注釋。
  • 編碼要求

    • 不要忽略編譯器的警告:編譯器的警告,通常能夠訓示出編碼存在的筆誤或邏輯錯誤。是以,不能輕視編譯器的任何警告,準确來說是,不允許代碼在編譯時産生任何警告資訊。
    • 初始化所有的變量:無論如何,都要初始化所有的變量。我們無法保證編譯器會給個什麼樣的初值。
    • 保持函數短小精悍:一般情況下,一個函數最好在一個螢幕内,不要超過三個螢幕。
  • 測試資料生成

  • 第六次作業--結對程式設計第二次
  • 第六次作業--結對程式設計第二次
  • 第六次作業--結對程式設計第二次
  • 第六次作業--結對程式設計第二次
  • 比對算法設計(思想/流程)

    • 配置設定原則及思想:

      • 一看志願。學生待配置設定隊列先按照志願順序進行排序,配置設定時,第一志願優于二、三、四、五志願,以此類推;
      • 二看最低績點要求。部門提出最低績點要求,以此作為進入部門的敲門磚,當且僅當學生滿足此條件,才考慮條件3 ——行程時間
      • 三看行程時間。學生滿足最低績點要求後,通過比對其與志願部門的活動時間,檢視是否有沖突。當行程時間無沖突時,有兩種情況,一種是該部門未滿,則學生就可以入選該志願部門;另一種是該部門已滿,則考慮條件4 ——标簽類似數;
      • 四看标簽類似數。當部門已滿,通過學生與部門間的标簽類似數進行重篩選,決定去留。
      • 算法流程圖:
        第六次作業--結對程式設計第二次
  • 比對算法評價

  • 該算法是我們一起商量後決定實作的,較為貼切現實情況并且簡潔易于了解的。有考慮過通過各部分占比進行權衡統計再配置設定,但最終得出的結論是并不符合現實情況,例如現實中部門對于學生成績的要求,一般是給個最低的标準,防止部分學生因為部門活動影響學生,是以沒有必要按照績點高低進行排序篩選。我們一緻認為,在比對中最重要就是<有志願——績點滿足要求——時間無沖突>這三個部分,至于其他的都是在這些的基礎上進行拓展,是以,我們認為我們的比對算法還是較為合理的。但是,設想都是特别美好的,當我們開始跑時,我們發現,比對率簡直低啊,居然不到一半,考慮到有一下幾個原因:第一,有部分部門的納新人數為零;第二,有部分學生的志願隻有1個;第三,比對算法考慮的還不夠周到。雖然說比對率并不能反映一切,但是這麼低也不正常,我反思。

【關鍵代碼】

/*根據配置設定原則進行學生-部門配置設定*/
void DistributeSystem::distribute() 
{
	queue<Student> student_que; //待配置設定的學生隊列
	for (int i = 0; i < student_number; ++i) 
		student_que.push(stu[i]); // 初始都是未配置設定狀态,都加進隊列
           
while (!student_que.empty()) 
	{
    	int ss = student_que.front().student_no;
		int sss = get_student_index(ss);
    	Student& s = stu[sss];   //通路學生隊列隊首元素
    	student_que.pop();
           
// 第一步考慮學生s的第student_cur個志願(部門為d)
		int ww = s.student_cur;
		int www = s.student_wish[ww];
		int wwww = get_department_index(www);
		Department& d = dep[wwww];   //通路部門隊列隊首元素
           
if (s.student_score >= d.department_score_limit)
		{
			//第二步考慮學生與部門時間是否有沖突
			int same_schedule_num = 0;
			for (int i = 0; i < s.schedule_count; ++i)
			{
				for (int j = 0; j < d.schedule_count; ++j)
					if (s.student_schedule[i] == d.department_schedule[j])
						same_schedule_num++;
			}
>
			if (same_schedule_num > 0)
			{
				s.student_cur++;
				if (s.student_cur < s.wish_count)
				{
					// 如果五個志願還沒考慮完畢的話,放入隊列中繼續參與配置設定
					student_que.push(s);
				}
			}
			else  
			{
				//若時間無沖突
				//第三步考慮部門是否已收滿
				if (d.department_member_limit > d.chosen_num)
				{
					// 如果部門d還有剩餘名額,直接中選
					int ss = 0;
					ss = s.student_no;
					int dd = d.chosen_num;
					d.student_no[dd] = ss;
					int ddd = s.chosen_num;
					s.department_no[ddd] = d.department_no;
					s.chosen_num++;
					s.student_cur++;
					d.chosen_num++;
					if (s.student_cur < s.wish_count)
					{
						// 如果五個志願還沒考慮完畢的話,放入隊列中繼續參與配置設定
						student_que.push(s);
					}					
				}  //未收満
				//若已收滿,第四步考慮标簽類似數
				//先找到部門d<已中選學生中>标簽類似數最少的學生s'
				//将學生s的标簽類似數和s’最少标簽數的進行對比
				else     
				{
					//若部門無空餘名額
					int least_stu_no = -1; // 部門d<已中選學生中>标簽類似數最少的學生s’編号
					int pos = -1;  // 以及s'在部門的<已中選清單中>的下标
					int stu_pos = -1;  //s'在<學生數組>中的下标
					int less_stu_dep_pos = -1; //部門d在s'的<已中選部門數組>中的下标
					int least_tag_same_num = 10;  //最少的标簽類似數
					s.now_tag_same_num = get_student_now_tag_same_num(s.student_no, d.department_no);  //學生s與部門d的标簽類似數
					for (int i = 0; i < d.chosen_num; ++i)
					{
						// 在部門d中查找标簽類似數最少的學生編号
						stu_pos = get_student_index(d.student_no[i]);   //部門已中選學生在<學生>數組的下标
						Student dmp = stu[stu_pos];  //對應的已中選學生
						less_stu_dep_pos = get_stu_department_index(stu_pos, dmp.chosen_num, d.department_no);
           
if (least_tag_same_num > dmp.tag_same_num[less_stu_dep_pos])
    					{
    						least_tag_same_num = dmp.tag_same_num[less_stu_dep_pos];
    						least_stu_no = dmp.student_no;
    						pos = i;
    					}
    				}
           
//再判斷納新人數是否為0 以及 學生s的标簽類似數和最少标簽類似數less_tag_same_num的大小關系
					//若納新人數為0 或者 學生s的标簽類似數<=最少标簽類似數less_tag_same_num ,考慮學生s的下一個志願
					if (d.department_member_limit == 0 || s.now_tag_same_num <= least_tag_same_num)
					{
						s.student_cur++;
						// 如果五個志願還沒考慮完畢的話,放入隊列中繼續參與配置設定
						if (s.student_cur < s.wish_count)
							student_que.push(s);
					}
    				else
    				{
    					// 否則學生s就直接替換掉标簽類似數最少的那個學生
    					int least_stu_index = get_student_index(least_stu_no);  //被替換掉的學生s.在<學生數組>中的下标
    					Student& least_stu = stu[least_stu_index];
    					int least_stu_department_index = get_stu_department_index(least_stu_index, least_stu.chosen_num, d.department_no); //部門d在被替換掉的學生s.<已中選部門數組>中的下标
		    			least_stu.department_no[least_stu_department_index] = -1;  //被替換掉的學生該部門隊列
    					//此時學生s已中選,儲存中選資訊
    					s.department_no[s.student_cur] = d.department_no;
    					s.tag_same_num[s.student_cur] = s.now_tag_same_num;
    					s.chosen_num++;
    					d.student_no[pos] = s.student_no;
    				} //替換
    			} //若部門無空餘名額
    		}//行程無沖突
    	} //績點滿足
    	else 
    	{
    		s.student_cur++;
    		// 如果五個志願還沒考慮完畢的話,放入隊列中繼續參與配置設定
    		if (s.student_cur < s.wish_count) 
    			student_que.push(s);
    	}
    }
}
           

【測試運作】

  • 所有測試資料
  • 測試200位同學,20個部門的情況

    • 輸入資料
      • 第六次作業--結對程式設計第二次
    • 輸出資料
      • 第六次作業--結對程式設計第二次
  • 測試500位同學,30個部門的情況

      • 第六次作業--結對程式設計第二次
      • 第六次作業--結對程式設計第二次
  • 測試1000位同學,50個部門的情況

      • 第六次作業--結對程式設計第二次
      • 第六次作業--結對程式設計第二次
  • 測試5000位同學,100個部門的情況

      • 第六次作業--結對程式設計第二次
      • 第六次作業--結對程式設計第二次
  • 結果彙總

學生人數 部門人數 學生未配置設定人數 部門未配置設定數量 學生比對率 部門比對率 耗時(s)
200 20 128 36% 100% 4
500 30 322 6
1000 50 722 28% 10
5000 100 3626 27% 21
  • 效能分析報告

第六次作業--結對程式設計第二次
第六次作業--結對程式設計第二次
第六次作業--結對程式設計第二次

【困難與解決】

  • json學習——雨勤

  • 使用了助教在微信群中推薦的json,這個json的方法和網上最廣泛流傳的jsoncpp不大一樣,沒有Value、Reader和Writer。找資料的能力真的比較欠缺,其實網上有相應的中文部落格解讀,隻是我一直沒找對,于是很吃力地翻譯閱讀github上的文檔。
  • 時間——雨勤

    • 問題:我在假期中主要進行了對json的學習,開假後就去漳州比賽(明明是公費旅遊),白天課也很多,留給結對作業的時間十分有限。
    • 解決:本周,無論在外地、在宿舍,夜夜修仙。
    • 效果:傷身。
  • 交流——雨勤

    • 問題:一開始進行了讨論,制定了基本的原則與方案,但在後來代碼實作的過程中,由于算法實作的一些原因,對最初的設計做出了修改,但兩人之間并沒有進行良好的溝通回報,以至于後來在咨詢隊友一些變量細節問題時,突然發現對大原則變了……
    • 解決:向比對子產品的大佬低頭,有什麼需要您說的算:)
  • 規範——雨勤

    • 問題:兩人各有自己的代碼習慣,雖然制定了代碼規範,但好像沒能嚴格的執行。
    • 解決:是時候事後諸葛了,改。
  • 計劃——安琪

    • 問題:實作初期趕着時間,想趕緊搭個架構出來好和小夥伴對接,蜜汁自信連流程圖都沒畫就直接上手,導緻算法設計模糊混亂,浪費了相當一部分時間。
    • 解決:冷靜分析後覺得還是不能本末倒置,于是老老實實把流程圖畫了下,覺得思路瞬間清晰了不少。
  • 不符預期——安琪

    • 問題:算法實作過程中發現之前和隊友小夥伴讨論的原則存在一些問題,并不是很合理,且實作起來也相當麻煩。
    • 解決:改、删。(勤勤我對不起你)

【對安琪的評價】

  • 關鍵詞:效率 投入 配合
  • 沒有隊友我大概已經上天了。
  • 這麼好的大腿我是怎麼抱到的?
  • 隊友安琪是一個進取心很強的girl,她會要求自己的工作一定在計劃内完成,不會把時間浪費在其他繁瑣的事情上。做決定的時候很果斷,當我還在糾結題目表述不清,我們該這樣還是該這樣的時候,安琪已經“我們就這樣做”了。

【對雨勤的評價】

  • 關鍵詞: 認真 負責 包容
  • 什麼,居然還要寫隊友缺點?
  • 那大概就是太可愛了,導緻我不能專心敲代碼了_
  • 因為一些不可抗拒因素,在實作階段不能和雨勤進行很好的溝通交流,有部分細節擅作主張改完之後才跟她說,雖然她選擇了原諒(給大佬遞帽子),但還是很對不起她,害她要熬夜返工orz。面對json這種我看了兩遍還是不大懂是什麼鬼的東西,雨勤也不在怕的,很好的完成了,要好好親親她了O(∩_∩)O。

【PSP】

PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃 120
· Estimate · 估計這個任務需要多少時間 240
Development 開發 2010 1960
· Analysis · 需求分析 (包括學習新技術) 600 360
· Design Spec · 生成設計文檔
· Design Review · 設計複審 (和同僚稽核設計文檔)
· Coding Standard · 代碼規範 (為目前的開發制定合适的規範) 60
· Design · 具體設計
· Coding · 具體編碼 900 1010
· Code Review · 代碼複審
· Test · 測試(自我測試,修改代碼,送出修改)
Reporting 報告 110
· Test Report · 測試報告
· Size Measurement · 計算工作量
· Postmortem & Process Improvement Plan · 事後總結, 并提出過程改進計劃 180
合計 2840 2190

【學習進度條】

第N周 本周學習消耗時(小時) 累計學習消耗時(小時) 重要成長
2 閱讀《建構之法》,了解結對程式設計,學習NABCD競争性需求分析的架構
5.25 9.25 JSON相關知識學習與實戰演練;c++基礎知識複習
5 15.25 計算機視覺基礎知識、OpenCV鞏固;目标檢測算法