Upload files to ''
This commit is contained in:
parent
17a9a4dd53
commit
c568338e83
BIN
CSCI251-A1- Spring 2019.pdf
Normal file
BIN
CSCI251-A1- Spring 2019.pdf
Normal file
Binary file not shown.
24
Readme.txt
Normal file
24
Readme.txt
Normal file
@ -0,0 +1,24 @@
|
||||
// License: AGPLv3 or later. https://www.gnu.org/licenses/licenses.html
|
||||
|
||||
Compile on UOW Banshee server using either of the following command in terminal/shell:
|
||||
$ make
|
||||
OR
|
||||
$ CC -std=c++11 -o ABC driver.cpp abc.cpp general_functions.cpp
|
||||
|
||||
As per test on my machine using folowwing code, there is no memory leak:
|
||||
$ valgrind --tool=memcheck ./ABC Students.txt Subjects.txt Teachers.txt Results.txt
|
||||
|
||||
However, there is leak when running bcheck on banshee. This could be because of bug in compiler CC.
|
||||
|
||||
Documentation:
|
||||
|
||||
Commenting explaning functions use and rational are in header files. Comments explaning implementation of functions are in cpp files.
|
||||
|
||||
Exit codes error list:
|
||||
(Read standard error output to find the exact reason of errors.)
|
||||
1 - Error related to arguments recived
|
||||
2 - Error while reading file
|
||||
3 - Error while processing subjects file lines string into subject structs
|
||||
4 - Error while processing teachers file lines string into teacher structs
|
||||
5 - Subject code in student's subject list or teacher's subject list is out of range (more than number of subjects)
|
||||
6 - Error while writting results to output-file
|
541
abc.cpp
Normal file
541
abc.cpp
Normal file
@ -0,0 +1,541 @@
|
||||
// License: AGPLv3 or later. https://www.gnu.org/licenses/licenses.html
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
# include "general_functions.h"
|
||||
# include "abc.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
const int MAX_ATTEMPTS_ALLOWED = 3;
|
||||
|
||||
input_files_name perform_checks_on_args(
|
||||
int argc, char *argv[])
|
||||
{
|
||||
if (argc != 5)
|
||||
{
|
||||
cerr << "Expected 5 arguments, received " << argc
|
||||
<< " argument(s). Please provide exactly 5 arguments and "
|
||||
"in correct order i.e.:\n"
|
||||
"1. Program name/path (received automatically)\n"
|
||||
"2. Students File such as Students.txt\n"
|
||||
"3. Subjects File such as Subjects.txt\n"
|
||||
"4. Teachers File such as Teachers.txt\n"
|
||||
"5. Output-file such as Results.txt\n"
|
||||
"\n"
|
||||
"Run program similar to this:\n"
|
||||
"$ ./ABC Students.txt Subjects.txt Teachers.txt "
|
||||
"Results.txt\n";
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
input_files_name args;
|
||||
args.students = argv[1];
|
||||
args.subjects = argv[2];
|
||||
args.teachers = argv[3];
|
||||
args.results = argv[4];
|
||||
return args;
|
||||
}
|
||||
}
|
||||
|
||||
input_files_textlines read_input_files(
|
||||
input_files_name file_names)
|
||||
{
|
||||
input_files_textlines files_textlines;
|
||||
files_textlines.students = get_textfile_lines(
|
||||
file_names.students);
|
||||
files_textlines.subjects = get_textfile_lines(
|
||||
file_names.subjects);
|
||||
files_textlines.teachers = get_textfile_lines(
|
||||
file_names.teachers);
|
||||
|
||||
print_three_newlines();
|
||||
|
||||
return files_textlines;
|
||||
}
|
||||
|
||||
vector<student> generate_students_struct(
|
||||
vector<string> students_lines)
|
||||
{
|
||||
cout << "Processing students file text:" << endl;
|
||||
|
||||
vector<student> students;
|
||||
int line_number = 0;
|
||||
for (auto student_line:students_lines)
|
||||
{
|
||||
line_number++;
|
||||
|
||||
// Ignoring empty line. Giving no warning/error for it either.
|
||||
if (student_line.size() == 0)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
student a_student;
|
||||
string ability_string;
|
||||
string consistency_string;
|
||||
string subject_sring;
|
||||
|
||||
istringstream line(student_line);
|
||||
getline(line, a_student.name, ',');
|
||||
getline(line, a_student.code, ',');
|
||||
getline(line, ability_string, ',');
|
||||
a_student.ability = stoi(ability_string);
|
||||
getline(line, consistency_string, ',');
|
||||
a_student.consistency = stoi(consistency_string);
|
||||
getline(line, a_student.program, ':');
|
||||
while(getline(line, subject_sring, ','))
|
||||
{
|
||||
int subject_code = stoi(subject_sring);
|
||||
if (subject_code > 0)
|
||||
a_student.subjects.push_back(subject_code);
|
||||
else
|
||||
throw "Anything that you can";
|
||||
}
|
||||
|
||||
if (a_student.name.size() == 0
|
||||
or a_student.code.size() != 6
|
||||
or is_string_some_positive_number(
|
||||
a_student.code) == false
|
||||
or a_student.ability < 0
|
||||
or a_student.ability > 100
|
||||
or a_student.consistency < 0
|
||||
or a_student.consistency > 15
|
||||
or a_student.program.size() == 0
|
||||
or a_student.subjects.size() == 0)
|
||||
{
|
||||
throw "All the things that you can";
|
||||
}
|
||||
|
||||
students.push_back(a_student);
|
||||
|
||||
cout << "Student Name: " << a_student.name << '\n'
|
||||
<< "Code: " << a_student.code << '\n'
|
||||
<< "Ability: " << a_student.ability << '\n'
|
||||
<< "Consistency: " << a_student.consistency << '\n'
|
||||
<< "Program Name: " << a_student.program << '\n'
|
||||
<< "Subjects code: ";
|
||||
for (auto subject_code: a_student.subjects)
|
||||
{
|
||||
cout << subject_code << " ";
|
||||
}
|
||||
cout << '\n' << endl;
|
||||
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "Non-Fatal Error Occured while processing student"
|
||||
<< " file lines into student structs. However as per "
|
||||
<< "specifiction, skipping proccesing anymore "
|
||||
<< "students.\n"
|
||||
<< "Line number: " << line_number << " is not in "
|
||||
<< "proper format.\n"
|
||||
<< "Actual Line:\n"
|
||||
<< student_line << "\n"
|
||||
<< "Expected line format:\n"
|
||||
<< "Name,Student code,Ability,Consistency,Program "
|
||||
<< "name:Subject list\n"
|
||||
<< "Where,\n"
|
||||
<< "1. Name is an non-empty string.\n"
|
||||
<< "2. Student code is 6 *digit* string.\n"
|
||||
<< "3. Ability is an integer in range 0 to 100.\n"
|
||||
<< "4. Consistency is an integer in range 0 to 15.\n"
|
||||
<< "5. Program name is an non-empty string.\n"
|
||||
<< "6. Subject list is the list of comma-seprated "
|
||||
<< "positive integers representing subject codes.\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
print_three_newlines();
|
||||
|
||||
return students;
|
||||
}
|
||||
|
||||
vector<subject> generate_subjects_struct(
|
||||
vector<string> subjects_lines)
|
||||
{
|
||||
cout << "Processing subjects file text:" << endl;
|
||||
|
||||
vector<subject> subjects;
|
||||
int line_number = 0;
|
||||
for (auto subject_line: subjects_lines)
|
||||
{
|
||||
line_number++;
|
||||
|
||||
// Ignoring empty line. Giving no warning/error for it either.
|
||||
if (subject_line.size() == 0)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
subject a_subject;
|
||||
string difficulty_string;
|
||||
string variability_string;
|
||||
|
||||
istringstream line(subject_line);
|
||||
getline(line, a_subject.name, ',');
|
||||
getline(line, difficulty_string, ',');
|
||||
a_subject.difficulty = stoi(difficulty_string);
|
||||
getline(line, variability_string);
|
||||
a_subject.variability = stoi(variability_string);
|
||||
|
||||
if (a_subject.name.size() == 0
|
||||
or a_subject.difficulty < -15
|
||||
or a_subject.difficulty > 15
|
||||
or a_subject.variability < -3
|
||||
or a_subject.variability > 3)
|
||||
{
|
||||
throw "Buzzwords";
|
||||
}
|
||||
|
||||
subjects.push_back(a_subject);
|
||||
|
||||
cout << "Subject Name: " << a_subject.name << '\n'
|
||||
<< "Difficulty: " << a_subject.difficulty << '\n'
|
||||
<< "Variability: " << a_subject.variability << '\n'
|
||||
<< endl;
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cerr << "Fatal error occured while processing subjects "
|
||||
<< "file lines into subject structs. Line: "
|
||||
<< line_number << " is not in proper format.\n"
|
||||
<< "Actual line:\n"
|
||||
<< subject_line << "\n"
|
||||
<< "Expected line format: \n"
|
||||
<< "Name,Difficulty,Variability\n"
|
||||
<< "Where,\n"
|
||||
<< "1. Name is a non-empty string.\n"
|
||||
<< "2. Diffuculty is interger in range -15 to 15.\n"
|
||||
<< "3. Variability is integer in range -3 to 3.\n";
|
||||
exit(3);
|
||||
}
|
||||
}
|
||||
|
||||
print_three_newlines();
|
||||
|
||||
return subjects;
|
||||
}
|
||||
|
||||
vector<teacher> generate_teachers_struct(
|
||||
vector<string> teachers_lines)
|
||||
{
|
||||
cout << "Processing teachers file text:" << endl;
|
||||
|
||||
vector<teacher> teachers;
|
||||
int line_number = 0;
|
||||
for (auto teacher_line: teachers_lines)
|
||||
{
|
||||
line_number++;
|
||||
|
||||
// Ignoring empty line. Giving no warning/error for it either.
|
||||
if (teacher_line.size() == 0)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
teacher a_teacher;
|
||||
istringstream line(teacher_line);
|
||||
string toughness_string;
|
||||
string variability_string;
|
||||
string subject_string;
|
||||
|
||||
getline(line, a_teacher.name, ',');
|
||||
getline(line, toughness_string, ',');
|
||||
a_teacher.toughness = stoi(toughness_string);
|
||||
getline(line, variability_string, ':');
|
||||
a_teacher.variability = stoi(variability_string);
|
||||
while(getline(line, subject_string, ','))
|
||||
{
|
||||
int subject_code = stoi(subject_string);
|
||||
if (subject_code > 0)
|
||||
a_teacher.subjects.push_back(subject_code);
|
||||
else
|
||||
throw "Cheesy praises at teacher";
|
||||
}
|
||||
|
||||
if (a_teacher.name.size() == 0
|
||||
or a_teacher.toughness < -15
|
||||
or a_teacher.toughness > 15
|
||||
or a_teacher.variability < -3
|
||||
or a_teacher.variability > 3
|
||||
or a_teacher.subjects.size() == 0)
|
||||
{
|
||||
throw "some swag";
|
||||
}
|
||||
|
||||
cout << "Teacher Name: " << a_teacher.name << '\n'
|
||||
<< "Toughness: " << a_teacher.toughness << '\n'
|
||||
<< "Variability: " << a_teacher.variability << '\n'
|
||||
<< endl;
|
||||
|
||||
teachers.push_back(a_teacher);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cerr << "Fatal error occured while processing teachers "
|
||||
<< "file lines into teacher structs. Line: "
|
||||
<< line_number << " is not in proper format.\n"
|
||||
<< "Actual line:\n"
|
||||
<< teacher_line << "\n"
|
||||
<< "Expected line format: \n"
|
||||
<< "Name,Toughness,Variability:Subjects List\n"
|
||||
<< "Where,\n"
|
||||
<< "1. Name is a non-empty string.\n"
|
||||
<< "2. Toughness is interger in range -15 to 15.\n"
|
||||
<< "3. Variability is integer in range -3 to 3.\n"
|
||||
<< "4. Subects list is comma-seprated list of positive"
|
||||
<< "integers representing subjects codes.\n";
|
||||
exit(4);
|
||||
}
|
||||
}
|
||||
|
||||
print_three_newlines();
|
||||
|
||||
return teachers;
|
||||
}
|
||||
|
||||
void add_teachers_vector_index_number_to_subjects_struct(
|
||||
vector<teacher> &teachers,
|
||||
vector<subject> &subjects)
|
||||
{
|
||||
for (int i=0; i < teachers.size(); i++)
|
||||
{
|
||||
for (auto subject_code: teachers[i].subjects)
|
||||
{
|
||||
if (subject_code <= subjects.size())
|
||||
{
|
||||
/* -1 and +1 since indexes starts from 0.
|
||||
*/
|
||||
subjects[subject_code-1].teachers.push_back(i+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Fatal error. Subject code " << subject_code
|
||||
<< " of teacher: " << i+1 << " i.e. "
|
||||
<< teachers[i].name << " is more than total "
|
||||
<< "number of subjects i.e. " << subjects.size()
|
||||
<< '\n';
|
||||
exit(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void process_students_and_generate_results(
|
||||
vector<student> &students,
|
||||
vector<subject> &subjects,
|
||||
vector<teacher> &teachers)
|
||||
{
|
||||
cout << "Processing students results:" << endl;
|
||||
|
||||
int student_number = 0;
|
||||
for (auto &a_student: students)
|
||||
{
|
||||
student_number++;
|
||||
int attempts = 0;
|
||||
|
||||
cout << "Processing student " << student_number << " i.e. "
|
||||
<< a_student.name << ":" << endl;
|
||||
|
||||
for (int i=0; i < a_student.subjects.size(); i++)
|
||||
{
|
||||
attempts++;
|
||||
result a_result;
|
||||
|
||||
a_result.subject_code = a_student.subjects[i];
|
||||
if (a_result.subject_code > subjects.size())
|
||||
{
|
||||
cerr << "Fatal error. Subject code "
|
||||
<< a_result.subject_code << " of student: "
|
||||
<< student_number << " i.e. " << a_student.name
|
||||
<< " is more than total number of subjects i.e. "
|
||||
<< subjects.size() << '\n';
|
||||
exit(5);
|
||||
}
|
||||
// -1 since index starts at 0
|
||||
auto &a_subject = subjects[a_result.subject_code-1];
|
||||
a_result.subject_name = a_subject.name;
|
||||
|
||||
a_result.teacher_code = pick_teacher_randomly(
|
||||
a_subject.teachers);
|
||||
// -1 since index starts at 0
|
||||
auto &a_teacher = teachers[a_result.teacher_code-1];
|
||||
a_result.teacher_name = a_teacher.name;
|
||||
|
||||
int attempts_based_marks_modifier = (attempts-1)*5;
|
||||
a_result.mean = (
|
||||
a_student.ability
|
||||
- a_subject.difficulty
|
||||
- a_teacher.toughness
|
||||
+ attempts_based_marks_modifier);
|
||||
|
||||
a_result.standard_deviation = (
|
||||
a_student.consistency
|
||||
- a_subject.variability
|
||||
- a_teacher.variability);
|
||||
a_result.standard_deviation = absolute_number(
|
||||
a_result.standard_deviation);
|
||||
|
||||
int minimum_possible_marks = (
|
||||
a_result.mean - a_result.standard_deviation);
|
||||
minimum_possible_marks = bigger_number(
|
||||
minimum_possible_marks, 0);
|
||||
minimum_possible_marks = smaller_number(
|
||||
minimum_possible_marks, 100);
|
||||
|
||||
int maximum_possible_marks = (
|
||||
a_result.mean + a_result.standard_deviation);
|
||||
maximum_possible_marks = smaller_number(
|
||||
maximum_possible_marks, 100);
|
||||
maximum_possible_marks = bigger_number(
|
||||
maximum_possible_marks, 0);
|
||||
|
||||
int marks = random_int(
|
||||
minimum_possible_marks,
|
||||
maximum_possible_marks);
|
||||
a_result.marks = marks;
|
||||
a_result.grade = return_grade_for_float((float)marks);
|
||||
a_student.results.push_back(a_result);
|
||||
|
||||
cout << a_result.subject_name << " ("
|
||||
<< a_result.subject_code << ") by "
|
||||
<< a_result.teacher_name << " ("
|
||||
<< a_result.teacher_code << ") Attempt: "
|
||||
<< attempts << " Mean: "
|
||||
<< a_result.mean << " Standard Deviation: "
|
||||
<< a_result.standard_deviation << " Maximum: "
|
||||
<< maximum_possible_marks << " Minimum: "
|
||||
<< minimum_possible_marks << " Marks: "
|
||||
<< a_result.marks << " Grade: " << a_result.grade
|
||||
<< endl;
|
||||
|
||||
// Supplementary provided.
|
||||
if (marks >= 45 and marks < 50)
|
||||
{
|
||||
int supplementary_marks_modifier = 5;
|
||||
a_result.mean += supplementary_marks_modifier;
|
||||
marks = random_int(
|
||||
minimum_possible_marks,
|
||||
maximum_possible_marks)
|
||||
+ supplementary_marks_modifier;
|
||||
a_result.marks = marks;
|
||||
|
||||
if (marks >= 50)
|
||||
{
|
||||
a_result.grade = "SP";
|
||||
}
|
||||
else
|
||||
a_result.grade = "F";
|
||||
|
||||
a_student.results.push_back(a_result);
|
||||
|
||||
cout << "Supplementary Marks: " << a_result.marks
|
||||
<< " Grade: " << a_result.grade << endl;
|
||||
}
|
||||
|
||||
// Fail.
|
||||
if (a_result.grade == "F")
|
||||
{
|
||||
/* Max attempts allowed reached. Excluded from college.
|
||||
* No more subjects are taught.
|
||||
*/
|
||||
if (attempts >= MAX_ATTEMPTS_ALLOWED)
|
||||
{
|
||||
a_student.overall_marks += marks;
|
||||
cout << endl; //cosmetic hotfix
|
||||
a_student.overall_grade_or_status = "F";
|
||||
a_student.subjects_studied += 1;
|
||||
break;
|
||||
}
|
||||
// Repeat same subject
|
||||
else
|
||||
{
|
||||
i--;
|
||||
}
|
||||
}
|
||||
// Study next subject with attempt reset to 0.
|
||||
else
|
||||
{
|
||||
a_student.overall_marks += marks;
|
||||
attempts = 0;
|
||||
a_student.subjects_studied += 1;
|
||||
}
|
||||
|
||||
// line between every subject attempt
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
a_student.percentage = ((float)
|
||||
((a_student.overall_marks*100)/\
|
||||
a_student.subjects_studied)/100.0);
|
||||
|
||||
if (a_student.overall_grade_or_status == "?")
|
||||
{
|
||||
a_student.overall_grade_or_status =\
|
||||
return_grade_for_float(a_student.percentage);
|
||||
}
|
||||
|
||||
cout << "Overall Percentage: " << a_student.percentage
|
||||
<< " Overall Grade: " << a_student.overall_grade_or_status
|
||||
<< '\n' << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void write_results_to_output_file(
|
||||
vector<student> &students, std::string results_file_name)
|
||||
{
|
||||
ofstream results_file(results_file_name);
|
||||
|
||||
if (!results_file.good())
|
||||
{
|
||||
cerr << "Fatal Error: Could not write results to output-file:"
|
||||
<< results_file_name << "\n"
|
||||
<< "Possibly do not have write acces to directory\n";
|
||||
exit(6);
|
||||
}
|
||||
|
||||
for (auto a_student: students)
|
||||
{
|
||||
results_file << a_student.code << "-" << a_student.name << ","\
|
||||
<< a_student.program << "-" << a_student.percentage << "-"\
|
||||
<< a_student.overall_grade_or_status << ":";
|
||||
for (auto a_result:a_student.results)
|
||||
{
|
||||
results_file << a_result.subject_code << "-"\
|
||||
<< a_result.subject_name << ","\
|
||||
<< a_result.teacher_code << "-"\
|
||||
<< a_result.teacher_name << ","\
|
||||
<< a_result.mean << "+-"\
|
||||
<< a_result.standard_deviation << "=>"\
|
||||
<< a_result.marks << "-" << a_result.grade << ";";
|
||||
}
|
||||
results_file << "\n";
|
||||
}
|
||||
results_file.close();
|
||||
}
|
||||
|
||||
int pick_teacher_randomly(vector<int> teachers_codes)
|
||||
{
|
||||
int selected_teacher_index = random_int(
|
||||
0, (teachers_codes.size()-1));
|
||||
return teachers_codes[selected_teacher_index];
|
||||
}
|
||||
|
||||
string return_grade_for_float(float percentage)
|
||||
{
|
||||
if (percentage >= 85.0)
|
||||
return "HD";
|
||||
else if (percentage >= 75.0)
|
||||
return "D";
|
||||
else if (percentage >= 65.0)
|
||||
return "C";
|
||||
else if (percentage >= 50.0)
|
||||
return "P";
|
||||
else
|
||||
return "F";
|
||||
}
|
120
abc.h
Normal file
120
abc.h
Normal file
@ -0,0 +1,120 @@
|
||||
// License: AGPLv3 or later. https://www.gnu.org/licenses/licenses.html
|
||||
|
||||
/* Functions which are written specifically for A Big College (ABC)
|
||||
*/
|
||||
|
||||
#ifndef _ABC_H_
|
||||
#define _ABC_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct input_files_name
|
||||
{
|
||||
std::string students;
|
||||
std::string subjects;
|
||||
std::string teachers;
|
||||
std::string results; // output-file
|
||||
};
|
||||
|
||||
struct input_files_textlines
|
||||
{
|
||||
std::vector<std::string> students;
|
||||
std::vector<std::string> subjects;
|
||||
std::vector<std::string> teachers;
|
||||
};
|
||||
|
||||
struct teacher
|
||||
{
|
||||
/* teacher's index no.+1 is treated as teacher code which is used
|
||||
* internally in subject's struct as teachers who can teach those
|
||||
* subjects
|
||||
*/
|
||||
// int code;
|
||||
std::string name;
|
||||
int toughness;
|
||||
int variability;
|
||||
std::vector<int> subjects;
|
||||
};
|
||||
|
||||
struct result
|
||||
{
|
||||
int subject_code;
|
||||
/* Even though redundant, it makes function statements a lot more
|
||||
* readable.
|
||||
*/
|
||||
std::string subject_name;
|
||||
int teacher_code;
|
||||
// Same as previous comment
|
||||
std::string teacher_name;
|
||||
int mean;
|
||||
int standard_deviation;
|
||||
int marks;
|
||||
std::string grade;
|
||||
};
|
||||
|
||||
struct student
|
||||
{
|
||||
std::string name;
|
||||
std::string code;
|
||||
int ability;
|
||||
int consistency;
|
||||
std::string program;
|
||||
// Only the last attempt of every subject is added to overall_marks
|
||||
int overall_marks = 0;
|
||||
/* Following calculation is used to obtain percentage upto two decimal
|
||||
* points precision only:
|
||||
* ((float)((overall_marks*100)/subjects_studied)/100.0)
|
||||
*/
|
||||
float percentage;
|
||||
/* If fail, F will be added at exclusion time. Else, will be
|
||||
* calculated based on percentage.
|
||||
*/
|
||||
std::string overall_grade_or_status = "?";
|
||||
std::vector<int> subjects;
|
||||
// used for calculating overall percentage
|
||||
int subjects_studied = 0;
|
||||
std::vector<result> results;
|
||||
};
|
||||
|
||||
struct subject
|
||||
{
|
||||
// subject's index no.+1 is treated as subject code
|
||||
// int code;
|
||||
std::string name;
|
||||
int difficulty;
|
||||
int variability;
|
||||
std::vector<int> teachers;
|
||||
};
|
||||
|
||||
input_files_name perform_checks_on_args(
|
||||
int argc, char *argv[]);
|
||||
|
||||
input_files_textlines read_input_files(
|
||||
input_files_name file_names);
|
||||
|
||||
std::vector<student> generate_students_struct(
|
||||
std::vector<std::string> students);
|
||||
|
||||
std::vector<subject> generate_subjects_struct(
|
||||
std::vector<std::string> subjects);
|
||||
|
||||
std::vector<teacher> generate_teachers_struct(
|
||||
std::vector<std::string> teachers);
|
||||
|
||||
void add_teachers_vector_index_number_to_subjects_struct(
|
||||
std::vector<teacher> &teachers,
|
||||
std::vector<subject> &subjects);
|
||||
|
||||
void process_students_and_generate_results(
|
||||
std::vector<student> &students,
|
||||
std::vector<subject> &subjects,
|
||||
std::vector<teacher> &teachers);
|
||||
|
||||
void write_results_to_output_file(
|
||||
std::vector<student> &students, std::string results_file_name);
|
||||
|
||||
int pick_teacher_randomly(std::vector<int> teachers_codes);
|
||||
|
||||
std::string return_grade_for_float(float percentage);
|
||||
|
||||
#endif
|
33
driver.cpp
Normal file
33
driver.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
// License: AGPLv3 or later. https://www.gnu.org/licenses/licenses.html
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "abc.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
input_files_name args = perform_checks_on_args(argc, argv);
|
||||
|
||||
input_files_textlines input_files_by_line = read_input_files(
|
||||
args);
|
||||
|
||||
vector<student> students = generate_students_struct(
|
||||
input_files_by_line.students);
|
||||
|
||||
vector<subject> subjects = generate_subjects_struct(
|
||||
input_files_by_line.subjects);
|
||||
|
||||
vector<teacher> teachers = generate_teachers_struct(
|
||||
input_files_by_line.teachers);
|
||||
|
||||
add_teachers_vector_index_number_to_subjects_struct(teachers, subjects);
|
||||
|
||||
process_students_and_generate_results(
|
||||
students, subjects, teachers);
|
||||
|
||||
write_results_to_output_file(students, args.results);
|
||||
|
||||
return 0;
|
||||
}
|
65
general_functions.cpp
Normal file
65
general_functions.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
// License: AGPLv3 or later. https://www.gnu.org/licenses/licenses.html
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
# include "general_functions.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
vector<string> get_textfile_lines(std::string filename)
|
||||
{
|
||||
ifstream file(filename);
|
||||
vector<string> file_lines;
|
||||
|
||||
if (! file.good())
|
||||
{
|
||||
cerr << "Failed to open/read file: " << filename\
|
||||
<< ". Non-exhaustive list of possible reasons:\n"\
|
||||
<< "1. File does not exist.\n"\
|
||||
<< "2. Unable to read file due to:\n"\
|
||||
<< "2.1 Don't have read access to file\n"\
|
||||
<< "2.2 File is opened elsewhere and some program have a "\
|
||||
<< "lock on file.\n";
|
||||
exit(2);
|
||||
}
|
||||
|
||||
cout << "Reading file: " << filename << endl;
|
||||
|
||||
while (file.good())
|
||||
{
|
||||
string line;
|
||||
getline(file, line);
|
||||
file_lines.push_back(line);
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
return file_lines;
|
||||
}
|
||||
|
||||
int random_int(int lower_bound, int upper_bound)
|
||||
{
|
||||
static std::random_device seed;
|
||||
static std::mt19937 random_number_generator(seed());
|
||||
std::uniform_int_distribution<std::mt19937::result_type> range(
|
||||
lower_bound, upper_bound);
|
||||
return range(random_number_generator);
|
||||
}
|
||||
|
||||
bool is_string_some_positive_number(std::string a_string)
|
||||
{
|
||||
for (int i=0; i < a_string.size(); i++)
|
||||
{
|
||||
string character(1, a_string[i]);
|
||||
try
|
||||
{
|
||||
stoi(character);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
64
general_functions.h
Normal file
64
general_functions.h
Normal file
@ -0,0 +1,64 @@
|
||||
// License: AGPLv3 or later. https://www.gnu.org/licenses/licenses.html
|
||||
|
||||
/* General functions which can be used in any program
|
||||
*/
|
||||
|
||||
#ifndef _GENERAL_FUNCTIONS_H_
|
||||
#define _GENERAL_FUNCTIONS_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
std::vector<std::string> get_textfile_lines(std::string filename);
|
||||
|
||||
int random_int(int lower_bound, int upper_bound);
|
||||
|
||||
bool is_string_some_positive_number(std::string a_string);
|
||||
|
||||
/* Its a good practice to prototype all functions including which are
|
||||
* defined in header file itself such as inline functions before defining
|
||||
* any function. This way, even if we use one function in another
|
||||
* function, we do not have to worry about function undefined error
|
||||
* possibilities.
|
||||
*/
|
||||
|
||||
inline int absolute_number(int number);
|
||||
|
||||
inline int smaller_number(int a, int b);
|
||||
|
||||
inline int bigger_number(int a, int b);
|
||||
|
||||
/* this function is used between different parts of program's standard
|
||||
* output for better sepration of dissimilar outputs
|
||||
*/
|
||||
inline void print_three_newlines();
|
||||
|
||||
inline int absolute_number(int number)
|
||||
{
|
||||
if (number < 0)
|
||||
return -(number);
|
||||
else
|
||||
return number;
|
||||
}
|
||||
|
||||
inline int smaller_number(int a, int b)
|
||||
{
|
||||
if (a > b)
|
||||
return b;
|
||||
else
|
||||
return a;
|
||||
}
|
||||
|
||||
inline int bigger_number(int a, int b)
|
||||
{
|
||||
if (a < b)
|
||||
return b;
|
||||
else
|
||||
return a;
|
||||
}
|
||||
|
||||
inline void print_three_newlines()
|
||||
{
|
||||
std::cout << "\n" << std::endl;
|
||||
}
|
||||
|
||||
#endif
|
11
makefile
Normal file
11
makefile
Normal file
@ -0,0 +1,11 @@
|
||||
ABC: driver.o abc.o general_functions.o
|
||||
CC -std=c++11 -o ABC driver.o abc.o general_functions.o && rm *.o
|
||||
|
||||
driver.o: driver.cpp abc.h
|
||||
CC -std=c++11 -c driver.cpp
|
||||
|
||||
abc.o: abc.cpp general_functions.h
|
||||
CC -std=c++11 -c abc.cpp
|
||||
|
||||
general_functions.o: general_functions.cpp
|
||||
CC -std=c++11 -c general_functions.cpp
|
Loading…
Reference in New Issue
Block a user