From d85deab5cd09c31f395ca85a9c99459d8b3bfe34 Mon Sep 17 00:00:00 2001 From: Buster Holzbauer Date: Mon, 2 Jul 2018 09:39:39 -0400 Subject: [PATCH] Individual message improvements / migration to JSON (#3) * Added test targets, fixed crash when count > defined gradeables * Fixed percentages. Not sure how a 0 point, all EC category could work, despite existing comment about it, so just ignoring that problem for now. * Further percentage fixes * First draft of using only the message.json instead of message.html * special_message and exam_seating can work together --- MakefileHelper | 7 +++++++ gradeable.h | 4 +++- main.cpp | 16 ++++++++++------ output.cpp | 44 +++++++++++++++++++++++++++++++++++--------- student.cpp | 28 ++++++++++++++++++++++++++-- 5 files changed, 81 insertions(+), 18 deletions(-) diff --git a/MakefileHelper b/MakefileHelper index d842339..c2d93e1 100644 --- a/MakefileHelper +++ b/MakefileHelper @@ -51,6 +51,13 @@ pull: push: rsync -azP individual_summary_html/* ${USERNAME}@${HWSERVER}:${REPORTS_DIRECTORY}/summary_html/ +pull_test: + mkdir -p raw_data/ + rsync -azPq ${REPORTS_DIRECTORY}/all_grades/ raw_data/ + +push_test: + rsync -azPq individual_summary_html/* ${REPORTS_DIRECTORY}/summary_html/ + flags = -g memory_debug : memory_flags = -m32 diff --git a/gradeable.h b/gradeable.h index 2baccea..6c7e0eb 100644 --- a/gradeable.h +++ b/gradeable.h @@ -111,7 +111,9 @@ class Gradeable { return released.find(id)->second; } float getItemMaximum(const std::string &id) const { - assert (maximums.find(id) != maximums.end()); + if (maximums.find(id) == maximums.end()){ + return 0; + } return maximums.find(id)->second; } float getScaleMaximum(const std::string &id) const { diff --git a/main.cpp b/main.cpp index a13ee83..2e17374 100644 --- a/main.cpp +++ b/main.cpp @@ -138,7 +138,8 @@ std::vector MESSAGES; std::ofstream priority_stream("priority.txt"); std::ofstream late_days_stream("late_days.txt"); -void PrintExamRoomAndZoneTable(std::ofstream &ostr, Student *s, const nlohmann::json &special_message); +//void PrintExamRoomAndZoneTable(std::ofstream &ostr, Student *s, const nlohmann::json &special_message); +void PrintExamRoomAndZoneTable(nlohmann::json &mj, Student *s, const nlohmann::json &special_message); //==================================================================== @@ -1539,17 +1540,17 @@ void output_helper(std::vector &students, std::string &GLOBAL_sort_or nlohmann::json mj; - std::string file2 = INDIVIDUAL_FILES_OUTPUT_DIRECTORY + students[S]->getUserName() + "_message.html"; + //std::string file2 = INDIVIDUAL_FILES_OUTPUT_DIRECTORY + students[S]->getUserName() + "_message.html"; std::string file2_json = INDIVIDUAL_FILES_OUTPUT_DIRECTORY + students[S]->getUserName() + "_message.json"; - std::ofstream ostr2(file2.c_str()); + //std::ofstream ostr2(file2.c_str()); std::ofstream ostr2_json(file2_json.c_str()); - mj["username"] = students[S]->getUserName(); + /*mj["username"] = students[S]->getUserName(); mj["building"] = "DCC"; mj["room"] = "308"; mj["zone"] = "A"; - ostr2_json << mj.dump(4); + ostr2_json << mj.dump(4);*/ #if 0 @@ -1575,7 +1576,10 @@ void output_helper(std::vector &students, std::string &GLOBAL_sort_or special_message = *special_message_itr; } - PrintExamRoomAndZoneTable(ostr2,students[S],special_message); + //PrintExamRoomAndZoneTable(ostr2,students[S],special_message); + PrintExamRoomAndZoneTable(mj,students[S],special_message); + + ostr2_json << mj.dump(4); int prev = students[S]->getAllowedLateDays(0); diff --git a/output.cpp b/output.cpp index 1e57789..72f2498 100644 --- a/output.cpp +++ b/output.cpp @@ -326,13 +326,16 @@ void colorit(std::ostream &ostr, // ========================================================== -void PrintExamRoomAndZoneTable(std::ofstream &ostr, Student *s, const nlohmann::json &special_message) { +//void PrintExamRoomAndZoneTable(std::ofstream &ostr, Student *s, const nlohmann::json &special_message) { +void PrintExamRoomAndZoneTable(nlohmann::json &mj, Student *s, const nlohmann::json &special_message) { + + Student *s_tmp = s; if (special_message.size() > 0) { - ostr << "\n"; + /*ostr << "
\n"; ostr << "\n"; - ostr << "
\n"; - ostr << "\n"; + ostr << "
\n";*/ assert (special_message.find("title") != special_message.end()); std::string title = special_message.value("title","MISSING TITLE"); @@ -340,7 +343,8 @@ void PrintExamRoomAndZoneTable(std::ofstream &ostr, Student *s, const nlohmann:: assert (special_message.find("description") != special_message.end()); std::string description = special_message.value("description","provided_files.zip"); - ostr << "

" << title << "

" << std::endl; + //ostr << "

" << title << "

" << std::endl; + mj["special_message"]["title"] = title; assert (special_message.find("files") != special_message.end()); nlohmann::json files = *(special_message.find("files")); @@ -362,15 +366,18 @@ void PrintExamRoomAndZoneTable(std::ofstream &ostr, Student *s, const nlohmann:: std::string filename = files.value(std::to_string(which),""); assert (filename != ""); - ostr << " \n"; + mj["special_message"]["filename"] = filename; + mj["special_message"]["description"] = description; + /*ostr << " \n"; ostr << "
" << description << "
" << description << "
\n"; ostr << "
\n"; + ostr << "\n";*/ + + s = s_tmp; //Reset the student pointer in case exam seating needs it. } // ============================================================== - if ( DISPLAY_EXAM_SEATING == false) return; std::string room = GLOBAL_EXAM_DEFAULT_ROOM; @@ -401,7 +408,7 @@ void PrintExamRoomAndZoneTable(std::ofstream &ostr, Student *s, const nlohmann:: #if 1 - ostr << "\n"; + /*ostr << "
\n"; // ostr << "
\n"; ostr << "
\n"; ostr << "\n"; @@ -423,7 +430,26 @@ void PrintExamRoomAndZoneTable(std::ofstream &ostr, Student *s, const nlohmann:: } - ostr << "
\n"; + ostr << "
\n";*/ + + mj["seating"]["title"] = GLOBAL_EXAM_TITLE; + mj["seating"]["date"] = GLOBAL_EXAM_DATE; + mj["seating"]["room"] = room; + mj["seating"]["zone"] = zone; + if (row != "N/A" && row !="") { + mj["seating"]["row"] = row; + } + if (seat != "N/A" && seat !="") { + mj["seating"]["seat"] = seat; + } + + // It shouldn't be Rainbow Grades job to know that on the server it's zone_images/ + // this should be done server side. Also allows server to let course specify hosting + // images on server or at a different location. + if (s->getExamZoneImage() != "") { + mj["seating"]["title"] = s->getExamZoneImage(); + } + #else diff --git a/student.cpp b/student.cpp index 3f96733..c2423c8 100644 --- a/student.cpp +++ b/student.cpp @@ -127,12 +127,36 @@ float Student::GradeablePercent(GRADEABLE_ENUM g) const { return lowest_test_counts_half_pct(); } + //Do one pass to get the defined item scores + float nonzero_sum = 0; + int nonzero_count = 0; + for (int i = 0; i < GRADEABLES[g].getCount(); i++) { + float s = getGradeableItemGrade(g,i).getValue(); + std::string id = GRADEABLES[g].getID(i); + if(!id.empty()){ + float m = GRADEABLES[g].getItemMaximum(id); + if(m > 0){ + nonzero_sum += m; + nonzero_count++; + } + } + } + + //If there are no gradeables with a max >0, bucket is 0% anyway + //XXX: Not sure if this is going to break totally extra-credit categories. Test this. + if(nonzero_count == 0){ + return 0.0; + } + // collect the scores in a vector std::vector scores; for (int i = 0; i < GRADEABLES[g].getCount(); i++) { float s = getGradeableItemGrade(g,i).getValue(); std::string id = GRADEABLES[g].getID(i); - float m = GRADEABLES[g].getItemMaximum(id); + float m = nonzero_sum/nonzero_count; + if(!id.empty()){ + m = GRADEABLES[g].getItemMaximum(id); + } float p = GRADEABLES[g].getItemPercentage(id); float sm = GRADEABLES[g].getScaleMaximum(id); scores.push_back(score_object(s,m,p,sm)); @@ -160,7 +184,7 @@ float Student::GradeablePercent(GRADEABLE_ENUM g) const { float sm = scores[i].scale_max; float my_max = std::max(m,sm); if (p < 0) { - assert (my_max > 0); + assert(my_max > 0); if (sum_max > 0) { p = std::max(m,sm) / sum_max; } else {