school/cs142/smcquay/lab03/grade.cc

212 lines
5.6 KiB
C++

#include <iostream>
#include <sstream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
const int MIN_SCORE = 0;
const string usage = "\
usage: grade [-n, --by-name] [-p, --by-points] [-v, --verbose]";
struct student {
string name;
int lab_score;
int exam_score;
int final_score;
string letter_grade;
};
typedef struct student student;
ostream & operator<<(ostream & os, const student & s) {
os << "name: '" << s.name
<< ", final score: " << s.final_score
<< ", grade: " << s.letter_grade;
return os;
}
bool sort_by_name(const student & a, const student & b) {
return a.name < b.name;
}
bool sort_by_score(const student & a, const student & b) {
return a.final_score > b.final_score;
}
struct grade {
int max_score;
int min_late_days;
int max_late_days;
};
typedef struct grade grade;
struct result {
int score;
int late_days;
};
typedef struct result result;
result collect_grade(string name, int score_max,
int late_min, int late_max, bool verbose);
string determine_letter_grade(int score);
int main(int argc, char * argv[]) {
bool verbose = false;
bool by_points = false;
bool by_name = false;
for(int i = 0; i < argc; i++) {
string cur_arg = argv[i];
if(cur_arg == "--verbose" or cur_arg == "-v") {
verbose = true;
}
if(cur_arg == "--by-points" or cur_arg == "-p") {
by_points = true;
}
if(cur_arg == "--by-name" or cur_arg == "-n") {
by_name = true;
}
if(cur_arg == "--help" or cur_arg == "-h") {
cout << usage << endl;
return 0;
}
}
if (by_points and by_name) {
cerr << "only specify one sort order" << endl;
return -1;
}
map<string, grade> labs = {
{"Lab01", {20, -2, 2}},
{"Lab02", {20, -2, 2}},
{"Lab03", {30, -3, 3}},
{"Lab04", {30, -3, 3}},
{"Lab05", {30, -3, 3}},
{"Lab06", {30, -3, 3}},
{"Lab07", {30, -3, 3}},
{"Lab08", {30, -3, 3}},
{"Lab09", {20, -2, 2}},
{"Lab10", {20, -2, 2}},
{"Lab11", {40, -4, 4}},
{"exam1", {100, 0, 3}},
{"exam2", {100, 0, 3}},
{"final", {100, 0, 3}},
};
vector<student> students;
while (!cin.eof()) {
if(verbose)
cerr << "Please enter name of student: ";
string name;
getline(cin, name);
if (!name.empty()) {
int total_lab_points = 0;
int total_exam_points = 0;
for(pair<string, grade> l: labs) {
string n = l.first;
grade g = l.second;
try {
result cur_result = collect_grade(n, g.max_score,
g.min_late_days, g.max_late_days, verbose);
total_lab_points += cur_result.score;
if (n.substr(0, 3) == "lab")
total_lab_points -= 5 * cur_result.late_days;
else if (n.substr(0, 4) == "exam" or n.substr(0, 4) == "final")
total_exam_points -= 20 * cur_result.late_days;
} catch (string e) {
cerr << e << endl;
return 1;
}
}
int final_score = total_lab_points + total_exam_points;
student s = {name, total_lab_points, total_exam_points,
final_score, determine_letter_grade(final_score)};
students.push_back(s);
}
}
if(by_name) {
sort(students.begin(), students.end(), sort_by_name);
}
else if (by_points) {
sort(students.begin(), students.end(), sort_by_score);
}
for(student s: students) {
cout << s << endl;
}
return 0;
}
result collect_grade(string name, int score_max,
int late_min, int late_max, bool verbose=false) {
int score = 0;
if(verbose) {
cerr << "Please enter score for " << name
<< "[" << MIN_SCORE << ", " << score_max << "]: ";
}
cin >> score;
if (!(MIN_SCORE <= score and score <= score_max)) {
ostringstream s;
s << score << " is not in accepted range: ["
<< MIN_SCORE << ", "
<< score_max << "]" << endl;
throw s.str();
}
int late_days;
if (verbose) {
cerr << "Please enter late days ["
<< late_min << ", " << late_max << "]: ";
}
cin >> late_days;
if (!(late_min <= late_days and late_days <= late_max)) {
ostringstream s;
s << late_days << " is not in accepted range: ["
<< late_min << ", "
<< late_max << "]" << endl;
throw s.str();
}
result r = {score, late_days};
return r;
}
string determine_letter_grade(int score) {
string letter_grade;
if(score >= 570)
letter_grade = "A";
if(score < 570 && score >=540)
letter_grade = "A-";
if(score < 540 && score >= 522)
letter_grade = "B+";
if(score < 522 && score >= 498)
letter_grade = "B";
if(score < 498 && score >= 480)
letter_grade = "B-";
if(score < 480 && score >= 462)
letter_grade = "C+";
if(score < 462 && score >= 438)
letter_grade = "C";
if(score < 438 && score >= 420)
letter_grade = "C-";
if(score < 420 && score >= 402)
letter_grade = "D+";
if(score < 402 && score >= 378)
letter_grade = "D";
if(score < 378 && score >= 360)
letter_grade = "D-";
if(score < 360)
letter_grade = "E";
return letter_grade;
}