17
17
#include " lichen_config.h"
18
18
#include " submission.h"
19
19
#include " hash_location.h"
20
+ #include " score.h"
20
21
21
22
22
23
// =============================================================================
@@ -34,11 +35,11 @@ typedef unsigned int version_number;
34
35
35
36
// represents an element in a ranking of students by percent match
36
37
struct StudentRanking {
37
- StudentRanking (const user_id &s , int v, const std::string &sg, float p ) : student(s ), version(v), source_gradeable(sg), percent(p ) {}
38
+ StudentRanking (const user_id &id , int v, const std::string &sg, const Score &s ) : student(id ), version(v), source_gradeable(sg), score(s ) {}
38
39
user_id student;
39
40
version_number version;
40
41
std::string source_gradeable;
41
- float percent ;
42
+ Score score ;
42
43
};
43
44
44
45
@@ -54,7 +55,8 @@ bool matchingPositionsAreAdjacent(const nlohmann::json &first, const nlohmann::j
54
55
55
56
nlohmann::json::const_iterator itr1 = first[" matchingpositions" ].begin ();
56
57
nlohmann::json::const_iterator itr2 = second[" matchingpositions" ].begin ();
57
- // iterate over each matching submission (first and second are the same length so we don't have to check for the end of second)
58
+ // iterate over each matching submission (first and second are the same length
59
+ // so we don't have to check for the end of second)
58
60
for (; itr1 != first[" matchingpositions" ].end (); itr1++, itr2++) {
59
61
if ((*itr1)[" end" ].get <int >() + 1 != (*itr2)[" end" ].get <int >()) {
60
62
return false ;
@@ -88,8 +90,8 @@ void incrementEndPositionsForMatches(nlohmann::json &others) {
88
90
89
91
90
92
bool ranking_sorter (const StudentRanking &a, const StudentRanking &b) {
91
- return a.percent > b.percent ||
92
- (a.percent == b.percent && a.student < b.student );
93
+ return a.score > b.score ||
94
+ (a.score == b.score && a.student < b.student );
93
95
}
94
96
95
97
@@ -156,7 +158,9 @@ int main(int argc, char* argv[]) {
156
158
// stores all hashes from other gradeables
157
159
std::unordered_map<hash, std::unordered_map<user_id, std::vector<HashLocation>>> other_gradeables;
158
160
// stores the highest match for every student, used later for generating overall_rankings.txt
159
- std::unordered_map<std::string, std::pair<int , float >> highest_matches;
161
+ std::unordered_map<user_id, std::pair<int , Score>> highest_matches;
162
+ // keeps track of max matching hashes across all submissions, used for calculation of ranking score
163
+ unsigned int max_hashes_matched = 0 ;
160
164
161
165
time_t start, end;
162
166
time (&start);
@@ -331,15 +335,19 @@ int main(int argc, char* argv[]) {
331
335
332
336
// Save this submissions highest percent match for later when we generate overall_rankings.txt
333
337
float percentMatch = (*submission_itr)->getPercentage ();
338
+ unsigned int totalMatchingHashes = (*submission_itr)->getMatchCount ();
339
+ Score submission_score (totalMatchingHashes, percentMatch);
340
+ if (max_hashes_matched < totalMatchingHashes) {
341
+ max_hashes_matched = totalMatchingHashes;
342
+ }
334
343
335
- std::unordered_map<std::string, std::pair<int , float > >::iterator highest_matches_itr = highest_matches.find ((*submission_itr)->student ());
344
+ std::unordered_map<user_id, std::pair<int , Score> >::iterator highest_matches_itr = highest_matches.find ((*submission_itr)->student ());
345
+ std::pair<int , Score> new_pair = {(*submission_itr)->version (), submission_score};
336
346
if (highest_matches_itr == highest_matches.end ()) {
337
- highest_matches[(*submission_itr)->student ()].first = (*submission_itr)->version ();
338
- highest_matches[(*submission_itr)->student ()].second = percentMatch;
347
+ highest_matches.insert ({(*submission_itr)->student (), new_pair});
339
348
}
340
- else if (percentMatch > highest_matches_itr->second .second ) {
341
- highest_matches_itr->second .first = (*submission_itr)->version ();
342
- highest_matches_itr->second .second = percentMatch;
349
+ else if (submission_score > highest_matches_itr->second .second ) {
350
+ highest_matches_itr->second = new_pair;
343
351
}
344
352
345
353
// =========================================================================
@@ -547,8 +555,10 @@ int main(int argc, char* argv[]) {
547
555
// the percent match is currently calculated using the number of hashes that match between this
548
556
// submission and the other submission, over the total number of hashes this submission has.
549
557
// In other words, the percentage is how much of this submission's code was plgairised from the other.
550
- float percent = (100.0 * version_itr->second .size ()) / unique_hashes.size ();
551
- student_ranking.push_back (StudentRanking (matches_itr->first , version_itr->first , gradeables_itr->first , percent));
558
+ unsigned int num_hashes_matched = version_itr->second .size ();
559
+ float percent = (100.0 * num_hashes_matched) / unique_hashes.size ();
560
+ student_ranking.push_back (StudentRanking (matches_itr->first , version_itr->first , gradeables_itr->first , Score (num_hashes_matched, percent)));
561
+ student_ranking.back ().score .calculateScore (num_hashes_matched);
552
562
}
553
563
}
554
564
}
@@ -564,10 +574,10 @@ int main(int argc, char* argv[]) {
564
574
// finally, write the file of ranking for this submission
565
575
for (unsigned int i = 0 ; i < student_ranking.size (); i++) {
566
576
ranking_student_ostr
567
- << std::setw (6 ) << std::setprecision ( 2 ) << std::fixed << student_ranking[i].percent << " % "
568
- << std::setw (15 ) << std::left << student_ranking[i].student << " "
569
- << std::setw (3 ) << std::left << student_ranking[i].version << " "
570
- << std::setw (1 ) << std::right << student_ranking[i].source_gradeable << std::endl;
577
+ << std::setw (15 ) << std::left << student_ranking[i].student << " "
578
+ << std::setw (3 ) << std::left << student_ranking[i].version << " "
579
+ << std::setw (1 ) << std::right << student_ranking[i].source_gradeable << " "
580
+ << std::setw (6 ) << std::setprecision ( 2 ) << std::fixed << student_ranking[i].score . getPercent () << " % " << std::endl;
571
581
}
572
582
573
583
// =========================================================================
@@ -599,18 +609,19 @@ int main(int argc, char* argv[]) {
599
609
// take the map of highest matches and convert it to a vector so we can sort it
600
610
// by percent match and then save it to a file
601
611
std::vector<StudentRanking> ranking;
602
- for (std::unordered_map<std::string , std::pair<int , float > >::iterator itr
612
+ for (std::unordered_map<user_id , std::pair<int , Score > >::iterator itr
603
613
= highest_matches.begin (); itr != highest_matches.end (); ++itr) {
604
614
ranking.push_back (StudentRanking (itr->first , itr->second .first , " " , itr->second .second ));
615
+ ranking[ranking.size ()-1 ].score .calculateScore (max_hashes_matched);
605
616
}
606
617
607
618
std::sort (ranking.begin (), ranking.end (), ranking_sorter);
608
-
609
619
for (unsigned int i = 0 ; i < ranking.size (); i++) {
610
620
ranking_ostr
611
- << std::setw (6 ) << std::setprecision (2 ) << std::fixed << ranking[i].percent << " % "
612
- << std::setw (15 ) << std::left << ranking[i].student << " "
613
- << std::setw (3 ) << std::right << ranking[i].version << std::endl;
621
+ << std::left << std::setw (20 ) << ranking[i].student << " "
622
+ << std::setw (3 ) << ranking[i].version << " "
623
+ << std::right << std::setw (4 ) << std::setprecision (1 ) << std::fixed << ranking[i].score .getPercent () << " % "
624
+ << std::setw (5 ) << ranking[i].score .getHashesMatched () << std::endl;
614
625
}
615
626
616
627
// ===========================================================================
0 commit comments