Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature: RainbowGrades] Add Hover Text and Penalty Logic for Bad Status #82

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 111 additions & 64 deletions table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);

Expand All @@ -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 << "<td " << c.hoverText << "style=\"border:1px solid #aaaaaa; background-color:#" << c.color << "; " << outline << "\" align=\"" << c.align << "\">";
} else {
ostr << "<td style=\"border:1px solid #aaaaaa; background-color:#" << c.color << "; " << outline << "\" align=\"" << c.align << "\">";
}

if (0) { //rotate == 90) {
ostr << "<div style=\"position:relative\"><p class=\"rotate\">";
}
ostr << "<font size=-1>";
std::string mynote = c.getNote();
// Rendering the content of the cell
if (0) { //rotate == 90) {
ostr << "<div style=\"position:relative\"><p class=\"rotate\">";
}
ostr << "<font size=-1>";
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 << "<div></div>";
} 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 << "<br><em>" << mynote << "</em>";
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 << "<div></div>";
} 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 << "<br><em>" << mynote << "</em>";
}
}
}
ostr << "</font>";
if (0) { //rotate == 90) {
ostr << "</p></div>";
}
ostr << "</td>";
return ostr;
ostr << "</font>";
if (0) { //rotate == 90) {
ostr << "</p></div>";
}
ostr << "</td>";
return ostr;
}


std::string TableCell::make_cell_string(bool csv_mode) const{
std::string ret;
std::string mynote = this->getNote();
Expand All @@ -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<int> which_students,
Expand Down Expand Up @@ -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 << "<td class='hoverable-cell red-outline' data-hover-text='" << hover_text << "'>" << cell.getData() << "</td>\n";
} else {
ostr << "<td>" << cell.getData() << "</td>\n";
}
}
}


if (transpose) {
for (std::vector<int>::iterator c = which_data.begin(); c != which_data.end(); c++) {
Expand Down
23 changes: 18 additions & 5 deletions table.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
};


Expand Down Expand Up @@ -87,4 +100,4 @@ class Table {

private:
std::vector<std::vector<TableCell>> cells;
};
};
Loading