Kostiggig

BGTU_QUIZ

Apr 12th, 2023
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.37 KB | None | 0 0
  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. #include <set>
  5. #include <vector>
  6. #include <cstdlib>
  7. #include <ctime>
  8. #include <unordered_map>
  9.  
  10. #define QUESTION_LENGTH 1024
  11. #define RADNOM_UNIQUE_QUESTIONS_COUNT 7
  12. #define MAX_QUESTIONS_COUNT_PER_TOPIC 10
  13. #define QUESTION_ANSWERS_DIVIDER 'd'
  14.  
  15. #define TOPICS_COUNT 3
  16. #define MAX_FINAL_TEST_QUESTIONS_COUNT 20
  17.  
  18. #define EXCELLENT_MARK_IN_PERCENTAGE 90
  19. #define GOOD_MARK_IN_PERCENTAGE 80
  20. #define SATISFIED_MARK_IN_PERCENTAGE 60
  21. #define BAD_MARK_IN_PERCENTAGE 50
  22.  
  23. using namespace std;
  24.  
  25. unordered_map<string, int> topic_title_to_index_map;
  26. unordered_map<int, string> topic_index_to_title_map;
  27. unordered_map<int, string> topic_index_to_questions_file_map;
  28. unordered_map<int, string> topic_index_to_answers_file_map;
  29.  
  30. struct QuestionAndAnswers {
  31.     int number;
  32.     int topic_index;
  33.     string question;
  34.     string answers;
  35. };
  36.  
  37. struct FuckedUpQuestion {
  38.     int number;
  39.     string question;
  40. };
  41.  
  42. void train_by_selected_topic() { // todo
  43.     cout << "train_by_selected_topic";
  44. }
  45.  
  46. int generate_random_qunique_questions(
  47.     const QuestionAndAnswers all_questions[MAX_QUESTIONS_COUNT_PER_TOPIC],
  48.     QuestionAndAnswers random_questions[RADNOM_UNIQUE_QUESTIONS_COUNT]
  49. ) {
  50.     srand(time(0));
  51.     set<int> seen_question;
  52.  
  53.     int curr = 0;
  54.  
  55.     while(curr < RADNOM_UNIQUE_QUESTIONS_COUNT) {
  56.         int random_question_index = 0 + (rand() % MAX_QUESTIONS_COUNT_PER_TOPIC);
  57.         if(seen_question.count(random_question_index) <= 0) {
  58.             seen_question.insert(random_question_index);
  59.             random_questions[curr++] = all_questions[random_question_index];
  60.         }
  61.     }
  62. }
  63.  
  64. vector<string> split_string(const string& s, char delimiter) {
  65.     vector<string> tokens;
  66.     size_t start = 0, end = 0;
  67.     while ((end = s.find(delimiter, start)) != string::npos) {
  68.         tokens.push_back(s.substr(start, end - start));
  69.         start = end + 1;
  70.     }
  71.     tokens.push_back(s.substr(start));
  72.     return tokens;
  73. }
  74.  
  75. string generate_formatted_answer(string answer) {
  76.     vector<string> answers = split_string(answer, QUESTION_ANSWERS_DIVIDER);
  77.         string formatted_answer = "";
  78.         if(answers.size() > 0) {
  79.             for (const string& answer : answers) {
  80.                 formatted_answer = formatted_answer + "\n" + answer;
  81.             }
  82.         } else {
  83.             formatted_answer = answer;
  84.         }
  85.  
  86.     return formatted_answer;
  87. }
  88.  
  89. void generate_quesitons_and_answers_by_topic(string file_name, string topic, QuestionAndAnswers all_questions[MAX_QUESTIONS_COUNT_PER_TOPIC]) {
  90.     ifstream file(file_name);
  91.     string q_number, q, a, divider;
  92.  
  93.     int question_index = 0;
  94.     while(getline(file, q_number) && getline(file, q) && getline(file, a) && getline(file, divider)) {
  95.         QuestionAndAnswers question;
  96.         question.number = stoi(q_number);
  97.         question.question = q;
  98.         question.topic_index = topic_title_to_index_map[topic];
  99.         question.answers = generate_formatted_answer(a);
  100.  
  101.         all_questions[question_index++] = question;
  102.     }
  103. }
  104.  
  105. void generate_correct_answers_by_topic(string file_name, int correct_answers[MAX_QUESTIONS_COUNT_PER_TOPIC]) {
  106.     ifstream file(file_name);
  107.     string answer;
  108.     int ans_index = 0;
  109.     while(getline(file, answer)) {
  110.         correct_answers[ans_index++] = stoi(answer, nullptr, 10);
  111.     }
  112. }
  113.  
  114. void print_errors_after_quiz_if_needed(int size, FuckedUpQuestion *fucked_up_questions) {
  115.     if(size > 0) {
  116.  
  117.         cout << "Count of fucked up questions - " << size << endl;
  118.         for(int i = 0; i < size; i++) {
  119.             FuckedUpQuestion question = fucked_up_questions[i];
  120.             cout << "Q" << question.number << ": " << question.question << endl;
  121.         }
  122.     } else {
  123.         cout << "You have answered all the questions correctly! Congrats!!!";
  124.     }
  125. }
  126.  
  127. int calculate_mark(int fucked_questions_size, int all_questions_size) {
  128.     int mark = -1;
  129.  
  130.     double in_percentage = (double(all_questions_size - fucked_questions_size) / double(all_questions_size)) * 100;
  131.     if(in_percentage >= EXCELLENT_MARK_IN_PERCENTAGE) {
  132.         mark = 5;
  133.     } else {
  134.         if(in_percentage >= GOOD_MARK_IN_PERCENTAGE) {
  135.             mark = 4;
  136.         } else {
  137.             if(in_percentage >= SATISFIED_MARK_IN_PERCENTAGE) {
  138.                 mark = 3;
  139.             } else {
  140.                 mark = 2;
  141.             }
  142.         }
  143.     }
  144.  
  145.     return mark;
  146. }
  147.  
  148. void test_by_selected_topic() {
  149.     cout << endl << "------Choose the topic------" << endl;
  150.     int chosen_topic = -1;
  151.  
  152.     while(true) {
  153.         for(int index = 0; index < TOPICS_COUNT; index++) {
  154.             cout << endl << (index + 1) << " - " << topic_index_to_title_map[index];
  155.         }
  156.         cout << endl << "0 - Exit: ";
  157.  
  158.         cin >> chosen_topic;
  159.  
  160.         if(chosen_topic == 0) break;
  161.         if(chosen_topic >= 1 && chosen_topic <= TOPICS_COUNT) break;
  162.     }
  163.  
  164.     if (chosen_topic == 0) return;
  165.  
  166.     int chosen_topic_index = chosen_topic - 1;
  167.  
  168.     int correct_answers[MAX_QUESTIONS_COUNT_PER_TOPIC];
  169.     generate_correct_answers_by_topic(topic_index_to_answers_file_map[chosen_topic_index], correct_answers);
  170.    
  171.     QuestionAndAnswers all_questions[MAX_QUESTIONS_COUNT_PER_TOPIC];
  172.    
  173.     generate_quesitons_and_answers_by_topic(
  174.         topic_index_to_questions_file_map[chosen_topic_index],
  175.         topic_index_to_title_map[chosen_topic_index], all_questions
  176.     );
  177.  
  178.     QuestionAndAnswers random_questions[RADNOM_UNIQUE_QUESTIONS_COUNT];
  179.     generate_random_qunique_questions(all_questions, random_questions);
  180.  
  181.  
  182.     FuckedUpQuestion *fucked_up_questions = NULL;
  183.     int fuckued_up_question_index = 0;
  184.  
  185.     for(int i = 0; i < RADNOM_UNIQUE_QUESTIONS_COUNT; i++) {
  186.         QuestionAndAnswers question = random_questions[i];
  187.         int correct_anwer_to_the_question = correct_answers[question.number - 1];
  188.  
  189.         int answer = -1;
  190.         while(true) {
  191.             cout << endl << endl << "Q" << question.number << ": " << question.question << "\n " << question.answers << ": ";
  192.             cin >> answer;
  193.             if(answer > 0 && answer < 5) break;
  194.         }
  195.  
  196.         if(correct_anwer_to_the_question != answer) {
  197.             fucked_up_questions = (FuckedUpQuestion*)realloc(fucked_up_questions, sizeof(FuckedUpQuestion) * (fuckued_up_question_index + 1));
  198.            
  199.             FuckedUpQuestion fucked_up_question;
  200.             fucked_up_question.number = question.number;
  201.             fucked_up_question.question = question.question;
  202.  
  203.             fucked_up_questions[fuckued_up_question_index++] = fucked_up_question;
  204.         }
  205.     }    
  206.  
  207.     cout << endl << "Your mark is " << calculate_mark(fuckued_up_question_index, RADNOM_UNIQUE_QUESTIONS_COUNT) << endl;
  208.     print_errors_after_quiz_if_needed(fuckued_up_question_index, fucked_up_questions);
  209.  
  210. }
  211.  
  212. void pass_final_test() {
  213.     srand(time(0));
  214.  
  215.     QuestionAndAnswers topic_to_question_and_answers[TOPICS_COUNT][MAX_QUESTIONS_COUNT_PER_TOPIC];
  216.     int topic_to_question_answer[TOPICS_COUNT][MAX_QUESTIONS_COUNT_PER_TOPIC];
  217.  
  218.     for(int i = 0; i < TOPICS_COUNT; i++) {
  219.         string questions_file_name = topic_index_to_questions_file_map[i];
  220.         string answers_file_name = topic_index_to_answers_file_map[i];
  221.         generate_quesitons_and_answers_by_topic(questions_file_name, topic_index_to_title_map[i], topic_to_question_and_answers[i]);
  222.         generate_correct_answers_by_topic(answers_file_name, topic_to_question_answer[i]);
  223.     }
  224.  
  225.     int curr = 0;
  226.     int last_topic_index = -1;
  227.     set<string> seen;
  228.  
  229.     QuestionAndAnswers random_questions[MAX_FINAL_TEST_QUESTIONS_COUNT];
  230.     while(curr < MAX_FINAL_TEST_QUESTIONS_COUNT) {
  231.         int rand_topic_index = 0 + (rand() % TOPICS_COUNT);
  232.         if(last_topic_index == rand_topic_index) continue;
  233.             int rand_question_by_topic_index = 0 + (rand() % MAX_QUESTIONS_COUNT_PER_TOPIC);
  234.             string question_id = topic_index_to_questions_file_map[rand_topic_index] + ":" + to_string(rand_question_by_topic_index);
  235.             if(seen.count(question_id) <= 0) {
  236.                 seen.insert(question_id);
  237.                 random_questions[curr++] = topic_to_question_and_answers[rand_topic_index][rand_question_by_topic_index];
  238.                 last_topic_index = rand_topic_index;
  239.             }
  240.     }
  241.  
  242.     FuckedUpQuestion *fucked_up_questions = NULL;
  243.     int fuckued_up_question_index = 0;
  244.  
  245.     for(int i = 0; i < MAX_FINAL_TEST_QUESTIONS_COUNT; i++) {
  246.         QuestionAndAnswers question = random_questions[i];
  247.         int correct_anwer_to_the_question = topic_to_question_answer[question.topic_index][question.number - 1];
  248.  
  249.         int answer = -1;
  250.         while(true) {
  251.             cout << endl << endl << "Q" << question.number << ": " << question.question << "\n " << question.answers << ": ";
  252.             cin >> answer;
  253.             if(answer > 0 && answer < 5) break;
  254.         }
  255.  
  256.         if(correct_anwer_to_the_question != answer) {
  257.             fucked_up_questions = (FuckedUpQuestion*)realloc(fucked_up_questions, sizeof(FuckedUpQuestion) * (fuckued_up_question_index + 1));
  258.            
  259.             FuckedUpQuestion fucked_up_question;
  260.             fucked_up_question.number = question.number;
  261.             fucked_up_question.question = question.question;
  262.  
  263.             fucked_up_questions[fuckued_up_question_index++] = fucked_up_question;
  264.         }
  265.     }
  266.  
  267.     cout << endl << "Your mark is " << calculate_mark(fuckued_up_question_index, MAX_FINAL_TEST_QUESTIONS_COUNT);
  268. }
  269.  
  270. void init_quiz_components() {
  271.     topic_title_to_index_map["T1"] = 0;
  272.     topic_title_to_index_map["T2"] = 1;
  273.     topic_title_to_index_map["T3"] = 2;
  274.  
  275.     topic_index_to_title_map[0] = "T1";
  276.     topic_index_to_title_map[1] = "T2";
  277.     topic_index_to_title_map[2] = "T3";
  278.  
  279.     topic_index_to_questions_file_map[0] = "q_and_a/questions_1.txt";
  280.     topic_index_to_questions_file_map[1] = "q_and_a/questions_2.txt";
  281.     topic_index_to_questions_file_map[2] = "q_and_a/questions_3.txt";
  282.  
  283.     topic_index_to_answers_file_map[0] = "q_and_a/correct_answers_1.txt";
  284.     topic_index_to_answers_file_map[1] = "q_and_a/correct_answers_2.txt";
  285.     topic_index_to_answers_file_map[2] = "q_and_a/correct_answers_3.txt";
  286. }
  287.  
  288. void show_student_menu() {
  289.     cout << endl << "------Student menu------" << endl;
  290.  
  291.     init_quiz_components();
  292.  
  293.     int menu_item = -1;
  294.     while(true) {
  295.          cout << "\n1 - Training by a topic"
  296.         << "\n2 - Testing by a topic"
  297.         << "\n3 - Final test"
  298.         << "\n0 - Exit: ";
  299.          cin >> menu_item;
  300.  
  301.         if(menu_item == 0) break;
  302.  
  303.         switch(menu_item) {
  304.             case 1: train_by_selected_topic(); break;
  305.             case 2: test_by_selected_topic(); break;
  306.             case 3: pass_final_test(); break;
  307.             default: cout << endl << "Menu item by " << menu_item << " cannot be found" << endl;
  308.         }
  309.     }
  310. }
  311.  
  312. int main() {
  313.     int menu_item = -1;
  314.  
  315.     while(true) {
  316.          cout << endl << "Login yourself. "
  317.          << "\n 1 - Teacher"
  318.          << "\n 2 - Student"
  319.          << "\n 0 - Exit: ";
  320.          cin >> menu_item;
  321.  
  322.         if (menu_item == 0) break;
  323.  
  324.         switch(menu_item) {
  325.             case 1: break; // todo login as a teacher
  326.             case 2: show_student_menu(); break; // todo login as a student
  327.             default: cout << endl << "Menu item by " << menu_item << " cannot be found" << endl; break;
  328.         }
  329.     }
  330.  
  331.     return 0;
  332. }
  333.  
Add Comment
Please, Sign In to add comment