【結對情況】
- 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);
内部實作設計(類圖)
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL1IzNwQDN3ADMy0yN3cTOxgDM5ETNxATM3EDMy0iM3UjNxITMvwFMxcTMwIzLcJzN1YTMyEzLcd2bsJ2Lc12bj5ycn9Gbi52YucTMwIzcldWYtl2Lc9CX6MHc0RHaiojIsJye.png)
代碼規範
命名規範
- 類與結構體:第一個大寫字母開頭,後面跟随的字母全部用小寫。
- 變量:所有字母均小寫,使用下劃線“_”作為單詞的分隔。
- 指針: '*' 應靠近類型,而不是變量名。
- 引用: '&' 應靠近類型,而不是變量名。
排版規範
- 方法和函數的布局 :對于有較多參數的函數的寫法,如果參數較多,一行寫不下,我們應該分成幾行來寫,并且每個參數都另起一行對齊。
- 縮進:縮進的時候,每一層縮進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鞏固;目标檢測算法 |