diff --git a/table.cpp b/table.cpp index e8f065d..6c9808a 100644 --- a/table.cpp +++ b/table.cpp @@ -74,10 +74,28 @@ TableCell::TableCell(const std::string& c, float d, int precision, const std::st TableCell::TableCell(float d, const std::string& c, int precision, const std::string& n, int ldu, CELL_CONTENTS_STATUS v,const std::string& e,bool ai, const std::string& a, - int s, int /*r*/,const std::string& reason,const std::string& gID,const std::string& userName, int daysExtended) { + int s, int /*r*/,const std::string& reason,const std::string& gID,const std::string& userName, + int daysExtended, float penalty_per_day, bool automatic_zero) { assert (c.size() == 6); assert (precision >= 0); color=c; + + // Store the original score before penalties + float original_score = d; + + // Apply penalty if not an automatic zero + if (automatic_zero) { + d = 0; // Set final score to 0 if automatic zero + } else if (late_days_used > 0) { + // Apply penalty if not an automatic zero + if (automatic_zero) { + d = 0; // Set final score to 0 if automatic zero + } else if (late_days_used > 0) { + d = d * (1.0f - penalty_per_day * late_days_used); // Apply percentage deduction for late days + } + } + + // Ensure numeric precision if (fabs(d) > 0.0001) { std::stringstream ss; ss << std::setprecision(precision) << std::fixed << d; @@ -86,47 +104,40 @@ TableCell::TableCell(float d, const std::string& c, int precision, const std::st data = ""; } note=n; - late_days_used=ldu, + late_days_used=ldu; visible=v; align=a; span=s; rotate = 0; academic_integrity = ai; event = e; - -// Bool in order of priority - top to bottom -// Don't think we need this logic, but leaving it as sort of assert - if (event == "Overridden"){ + + // Generating hover text with penalty information or automatic zero + if (event == "Overridden") { override = true; bad_status = inquiry = extension = version_conflict = cancelled = false; - } else if (event == "Extension"){ + } else if (event == "Extension") { extension = true; inquiry = bad_status = override = version_conflict = cancelled = false; - if (reason != ""){ - hoverText = "class=\"hoverable-cell\" data-hover-text=\"" + userName + " received a " + std::to_string(daysExtended) + " day extension due to " + reason + " on " + gID + "\" "; - } else { - hoverText = "class=\"hoverable-cell\" data-hover-text=\""+userName+" received a "+std::to_string(daysExtended)+" day extension without specified reason on "+gID+"\" "; - } - } else if (event == "Open"){ - inquiry = true; - bad_status = override = extension = version_conflict = cancelled = false; - } else if (event == "Cancelled"){ - cancelled = true; - inquiry = bad_status = override = extension = version_conflict = false; - } else if (event == "Version_conflict"){ - version_conflict = true; - inquiry = bad_status = override = extension = cancelled = false; - } else if (event == "Bad"){ + hoverText = "class=\"hoverable-cell\" data-hover-text=\"" + CSVSanitizeString(userName) + + " received a " + std::to_string(daysExtended) + " day extension\" "; + } else if (event == "Bad") { bad_status = true; override = inquiry = extension = version_conflict = cancelled = false; - hoverText = "class=\"hoverable-cell\" data-hover-text=\"" + userName + " received a bad status on " + gID + "\" "; - } else { - inquiry = bad_status = override = extension = version_conflict = cancelled = false; + if (automatic_zero) { + hoverText = "class=\"hoverable-cell\" data-hover-text=\"" + CSVSanitizeString(userName) + + " received an automatic zero due to late submission.\" "; + } else { + hoverText = "class=\"hoverable-cell\" data-hover-text=\"" + CSVSanitizeString(userName) + + " received a bad status on " + CSVSanitizeString(gID) + ". Original score: " + + std::to_string(original_score) + ", Final score after " + std::to_string(late_days_used) + + " late days and a penalty of " + std::to_string(penalty_per_day * 100) + "% per day: " + data + "\" "; + } + } } - std::ostream& operator<<(std::ostream &ostr, const TableCell &c) { assert (c.color.size() == 6); @@ -149,55 +160,51 @@ std::ostream& operator<<(std::ostream &ostr, const TableCell &c) { outline = "outline:4px solid #fc0303; outline-offset: -4px;"; } + // Render with hover text for bad_status or extension if (c.extension || c.bad_status) { ostr << ""; } else { ostr << ""; } - if (0) { //rotate == 90) { - ostr << "

"; - } - ostr << ""; - std::string mynote = c.getNote(); + // Rendering the content of the cell + if (0) { //rotate == 90) { + ostr << "

"; + } + ostr << ""; + std::string mynote = c.getNote(); - if (c.academic_integrity) - { - ostr << mark; - } - else if ((c.data == "" && mynote=="") - || c.visible==CELL_CONTENTS_HIDDEN - || (c.visible==CELL_CONTENTS_VISIBLE_INSTRUCTOR && GLOBAL_instructor_output == false) - || (c.visible==CELL_CONTENTS_VISIBLE_STUDENT && GLOBAL_instructor_output == true)) { - ostr << "

"; - } else { - ostr << c.data; - if (c.late_days_used > 0) { - if (c.late_days_used > 3) { ostr << " (" << std::to_string(c.late_days_used) << "*)"; } - else { ostr << " " << std::string(c.late_days_used,'*'); } + if (c.academic_integrity) + { + ostr << mark; } - - - if (mynote.length() > 0 && - mynote != " " && - (global_details - /* - || - c.visible==CELL_CONTENTS_HIDDEN - */ - ) - ) { - ostr << "
" << mynote << ""; + else if ((c.data == "" && mynote=="") + || c.visible==CELL_CONTENTS_HIDDEN + || (c.visible==CELL_CONTENTS_VISIBLE_INSTRUCTOR && GLOBAL_instructor_output == false) + || (c.visible==CELL_CONTENTS_VISIBLE_STUDENT && GLOBAL_instructor_output == true)) { + ostr << "
"; + } else { + ostr << c.data; + if (c.late_days_used > 0) { + if (c.late_days_used > 3) { ostr << " (" << std::to_string(c.late_days_used) << "*)"; } + else { ostr << " " << std::string(c.late_days_used,'*'); } + } + + if (mynote.length() > 0 && + mynote != " " && + global_details) { + ostr << "
" << mynote << ""; + } } - } - ostr << "
"; - if (0) { //rotate == 90) { - ostr << "

"; - } - ostr << ""; - return ostr; + ostr << ""; + if (0) { //rotate == 90) { + ostr << "

"; + } + ostr << ""; + return ostr; } + std::string TableCell::make_cell_string(bool csv_mode) const{ std::string ret; std::string mynote = this->getNote(); @@ -222,7 +229,29 @@ std::string TableCell::make_cell_string(bool csv_mode) const{ return CSVSanitizeString(ret); } +bool TableCell::hasRedOutline() const { + return red_outline; +} + +bool TableCell::isAutomaticZero() const { + return automatic_zero; +} + +bool TableCell::hasPenalty() const { + return penalty; +} + +float TableCell::getOriginalScore() const { + return original_score; +} +float TableCell::getScore() const { + return score; +} + +std::string TableCell::getData() const { + return data; +} void Table::output(std::ostream& ostr, std::vector which_students, @@ -292,6 +321,24 @@ void Table::output(std::ostream& ostr, } +// ------------------------------------------------------------------------------- +// ADD HOVER TEXT FOR CELLS WITH RED OUTLINE +for (const auto& row : cells) { + for (const auto& cell : row) { + std::string hover_text; + if (cell.hasRedOutline()) { + if (cell.isAutomaticZero()) { + hover_text = "This assignment received an automatic zero because it was submitted too late."; + } else if (cell.hasPenalty()) { + hover_text = "This assignment received a grade penalty for being late. Original score: " + std::to_string(cell.getOriginalScore()) + ", Score after penalty: " + std::to_string(cell.getScore()); + } + ostr << "" << cell.getData() << "\n"; + } else { + ostr << "" << cell.getData() << "\n"; + } + } +} + if (transpose) { for (std::vector::iterator c = which_data.begin(); c != which_data.end(); c++) { diff --git a/table.h b/table.h index 8159cd2..33b55d1 100644 --- a/table.h +++ b/table.h @@ -23,10 +23,11 @@ class TableCell { CELL_CONTENTS_STATUS v=CELL_CONTENTS_VISIBLE, const std::string& a="left" , int s=1, int r=0); TableCell(const std::string& c , float d , int precision, const std::string& n="", int ldu=0, CELL_CONTENTS_STATUS v=CELL_CONTENTS_VISIBLE, const std::string& a="right", int s=1, int r=0); - TableCell(float d ,const std::string& c , int precision, const std::string& n="", int ldu=0, - CELL_CONTENTS_STATUS v=CELL_CONTENTS_VISIBLE, const std::string& e="", bool ai = false, const std::string& a="right", - int s=1, int r=0, const std::string& reason="",const std::string& gID="",const std::string& userName="",int daysExtended=0); - + TableCell(float d, const std::string& c, int precision, const std::string& n, int ldu, + CELL_CONTENTS_STATUS v, const std::string& e, bool ai, const std::string& a, + int s, int r, const std::string& reason, const std::string& gID, const std::string& userName, + int daysExtended, float penalty_per_day, bool automatic_zero); + std::string make_cell_string(bool csv_mode) const; std::string color; std::string data; @@ -40,6 +41,12 @@ class TableCell { bool cancelled = false; bool version_conflict = false; bool bad_status = false; + bool hasRedOutline() const; + bool isAutomaticZero() const; + bool hasPenalty() const; + float getOriginalScore() const; + float getScore() const; + std::string getData() const; std::string hoverText = ""; std::string align; enum CELL_CONTENTS_STATUS visible; @@ -49,6 +56,12 @@ class TableCell { const std::string& getNote() const { return note; } private: std::string note; + bool red_outline; + bool automatic_zero; + bool penalty; + float original_score; + float score; + std::string data; }; @@ -87,4 +100,4 @@ class Table { private: std::vector> cells; -}; +}; \ No newline at end of file