212 lines
5.6 KiB
C++
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;
|
||
|
}
|