Transferred from GitHub
This commit is contained in:
parent
2b1c46cc68
commit
c3794c8a09
25 changed files with 26245 additions and 0 deletions
33
CMakeLists.txt
Normal file
33
CMakeLists.txt
Normal file
|
@ -0,0 +1,33 @@
|
|||
# Version Info
|
||||
cmake_minimum_required(VERSION 3.5.0)
|
||||
project(TestDesk VERSION 0.1.0 LANGUAGES C CXX)
|
||||
include(CTest)
|
||||
enable_testing()
|
||||
|
||||
# Files
|
||||
set(SOURCES
|
||||
src/tester/question.cpp
|
||||
src/tester/quiz.cpp
|
||||
|
||||
src/interface/cli.cpp
|
||||
src/interface/gui_fltk.cpp
|
||||
|
||||
src/main.cpp
|
||||
)
|
||||
|
||||
# Executable
|
||||
add_executable(TestDesk ${SOURCES})
|
||||
|
||||
# Libraries
|
||||
target_include_directories(TestDesk PRIVATE ${PROJECT_SOURCE_DIR}/inc)
|
||||
target_link_directories(TestDesk PRIVATE ${PROJECT_SOURCE_DIR}/lib)
|
||||
|
||||
target_link_libraries(TestDesk fltk)
|
||||
|
||||
# Directory
|
||||
set_target_properties(TestDesk PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/build)
|
||||
|
||||
# Compile info
|
||||
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
|
||||
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
||||
include(CPack)
|
0
bin/.empty
Normal file
0
bin/.empty
Normal file
0
data/exams/.empty
Normal file
0
data/exams/.empty
Normal file
15
inc/base.h
Normal file
15
inc/base.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef H_BASE
|
||||
#define H_BASE
|
||||
|
||||
// Includes
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include "tools/json.hpp"
|
||||
|
||||
// Namespaces
|
||||
using namespace nlohmann;
|
||||
|
||||
#endif
|
30
inc/interface/cli.h
Normal file
30
inc/interface/cli.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef H_TCLI
|
||||
#define H_TCLI
|
||||
|
||||
// Includes
|
||||
#include <base.h>
|
||||
#include <tester/question.h>
|
||||
#include <tester/quiz.h>
|
||||
|
||||
// Classes
|
||||
class Tester_CLI{
|
||||
private:
|
||||
// Variables
|
||||
|
||||
// Functions
|
||||
|
||||
public:
|
||||
// Variables
|
||||
|
||||
// Constructor
|
||||
Tester_CLI();
|
||||
|
||||
// Functions
|
||||
void AskQuestions(Quiz quiz, int num);
|
||||
|
||||
static int Letter2Number(const char* letter);
|
||||
void DisplayQuestion(int index, int qmax, std::string title, Question* question);
|
||||
void DisplayScore(Score score, std::string title);
|
||||
};
|
||||
|
||||
#endif
|
116
inc/interface/gui_fltk.h
Normal file
116
inc/interface/gui_fltk.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
#ifndef H_GUI
|
||||
#define H_GUI
|
||||
|
||||
// Includes
|
||||
#include <base.h>
|
||||
#include <tester/question.h>
|
||||
#include <tester/quiz.h>
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/Fl_Radio_Button.H>
|
||||
#include <FL/Fl_Radio_Round_Button.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Scroll.H>
|
||||
#include <FL/Fl_Group.H>
|
||||
#include <FL/Fl_Input.H>
|
||||
#include <FL/Fl_Value_Input.H>
|
||||
#include <FL/Fl_Input_Choice.H>
|
||||
|
||||
// Structures
|
||||
typedef struct MissedQuestion{
|
||||
// Variables
|
||||
char* title;
|
||||
char* prompt;
|
||||
char* user;
|
||||
char* correct;
|
||||
} MissedQuestion;
|
||||
typedef struct HubData{
|
||||
Fl_Input_Choice* name;
|
||||
Fl_Value_Input* questions;
|
||||
} HubData;
|
||||
|
||||
// Classes
|
||||
class Window_GUI{
|
||||
private:
|
||||
// Variables
|
||||
Fl_Window* window;
|
||||
|
||||
public:
|
||||
// Variables
|
||||
static Window_GUI* instance;
|
||||
Fl_Window* getWindow();
|
||||
|
||||
// Constructors
|
||||
Window_GUI(const char* title, int w, int h);
|
||||
|
||||
// Functions
|
||||
void Update();
|
||||
void Show(int argc, char* argv[]);
|
||||
};
|
||||
|
||||
class Hub_GUI{
|
||||
private:
|
||||
// Variables
|
||||
Fl_Box* title;
|
||||
Fl_Box* subtitle;
|
||||
Fl_Box* credits;
|
||||
Fl_Input_Choice* quizName;
|
||||
Fl_Value_Input* numQuestions;
|
||||
Fl_Button* start;
|
||||
|
||||
// Functions
|
||||
std::vector<std::string> getQuizzes();
|
||||
|
||||
public:
|
||||
// Variables
|
||||
static Hub_GUI* instance;
|
||||
|
||||
// Constructors
|
||||
Hub_GUI();
|
||||
|
||||
// Functions
|
||||
void Clean();
|
||||
};
|
||||
class Tester_GUI{
|
||||
private:
|
||||
// Variables
|
||||
Fl_Button* g_exam_next;
|
||||
Fl_Button* g_exam_back;
|
||||
Fl_Box* g_exam_progress;
|
||||
Fl_Box* g_exam_title;
|
||||
Fl_Box* g_exam_question;
|
||||
std::vector<Fl_Radio_Round_Button*> questionButtons;
|
||||
|
||||
std::vector<MissedQuestion> mQuestions;
|
||||
Fl_Group* g_grade_header;
|
||||
Fl_Box* g_grade_prompt;
|
||||
Fl_Box* g_grade_user;
|
||||
Fl_Box* g_grade_correct;
|
||||
int gCurrent, gMax;
|
||||
|
||||
// Functions
|
||||
|
||||
public:
|
||||
// Variables
|
||||
static Tester_GUI* instance;
|
||||
|
||||
Quiz* quiz;
|
||||
int sResponse;
|
||||
|
||||
// Constructors
|
||||
Tester_GUI(Quiz* quiz);
|
||||
|
||||
// Functions
|
||||
void Instantiate();
|
||||
void Populate();
|
||||
|
||||
void gPopulate();
|
||||
void gNav(int dir);
|
||||
|
||||
void LastQuestion();
|
||||
void EndTest();
|
||||
};
|
||||
|
||||
#endif
|
21
inc/tester/question.h
Normal file
21
inc/tester/question.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef H_QUESTION
|
||||
#define H_QUESTION
|
||||
|
||||
// Includes
|
||||
#include "base.h"
|
||||
|
||||
// Classes
|
||||
class Question{
|
||||
public:
|
||||
// Variables
|
||||
std::string prompt;
|
||||
std::vector<std::string> responses;
|
||||
int correct;
|
||||
|
||||
// Constructor
|
||||
Question(std::string prompt, std::vector<std::string> responses, int correct);
|
||||
|
||||
// Functions
|
||||
};
|
||||
|
||||
#endif
|
47
inc/tester/quiz.h
Normal file
47
inc/tester/quiz.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#ifndef H_QUIZ
|
||||
#define H_QUIZ
|
||||
|
||||
// Includes
|
||||
#include <base.h>
|
||||
#include "question.h"
|
||||
|
||||
// Classes
|
||||
class Score{
|
||||
public:
|
||||
// Variables
|
||||
float percentage;
|
||||
int incorrect;
|
||||
int correct;
|
||||
|
||||
std::vector<Question*> qIncorrect;
|
||||
std::vector<int> aIncorrect;
|
||||
std::vector<int> iIncorrect;
|
||||
|
||||
// Constructor
|
||||
Score();
|
||||
};
|
||||
|
||||
class Quiz{
|
||||
private:
|
||||
// Variables
|
||||
std::vector<Question*> questions;
|
||||
std::vector<int> answers;
|
||||
|
||||
public:
|
||||
// Variables
|
||||
std::string name;
|
||||
std::string description;
|
||||
int qCurrent;
|
||||
|
||||
// Constructors
|
||||
Quiz(const char* quizPath, int wantedQuestions);
|
||||
|
||||
// Functions
|
||||
void qAnswer(int answer);
|
||||
Question* qGet();
|
||||
int qSize();
|
||||
|
||||
Score qScore();
|
||||
};
|
||||
|
||||
#endif
|
24766
inc/tools/json.hpp
Normal file
24766
inc/tools/json.hpp
Normal file
File diff suppressed because it is too large
Load diff
0
lib/.empty
Normal file
0
lib/.empty
Normal file
BIN
old/fltk_version.zip
Normal file
BIN
old/fltk_version.zip
Normal file
Binary file not shown.
94
src/interface/cli.cpp
Normal file
94
src/interface/cli.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
// Header
|
||||
#include <interface/cli.h>
|
||||
|
||||
// Constants
|
||||
std::vector<std::string> indexes = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q"};
|
||||
|
||||
|
||||
// Constructors
|
||||
Tester_CLI::Tester_CLI(){
|
||||
/*
|
||||
INIT CLI (Command Line Interface)
|
||||
*/
|
||||
|
||||
// Clearing the screen
|
||||
system("clear");
|
||||
}
|
||||
|
||||
// Functions
|
||||
int Tester_CLI::Letter2Number(const char* letter){
|
||||
for(unsigned int i = 0; i < indexes.size(); i++){
|
||||
if(indexes[i] == letter){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
void Tester_CLI::AskQuestions(Quiz quiz, int num){
|
||||
// Displaying questions
|
||||
quiz.qCurrent = 0;
|
||||
for(unsigned int i = 0; i < quiz.qSize(); i++){
|
||||
DisplayQuestion(quiz.qCurrent, quiz.qSize(), quiz.name, quiz.qGet());
|
||||
|
||||
std::string typed;
|
||||
std::cout << "Answer: ";
|
||||
std::cin >> typed;
|
||||
|
||||
quiz.qAnswer(Tester_CLI::Letter2Number(typed.c_str()));
|
||||
quiz.qCurrent++;
|
||||
}
|
||||
|
||||
// Showing results
|
||||
DisplayScore(quiz.qScore(), quiz.name);
|
||||
}
|
||||
void Tester_CLI::DisplayQuestion(int index, int qmax, std::string title, Question* question){
|
||||
// Clear screen
|
||||
system("clear");
|
||||
|
||||
// Test title
|
||||
std::cout << "-- " << title << " --" << "\n";
|
||||
std::cout << "\n";
|
||||
|
||||
// Giving the question's prompt
|
||||
std::cout << "(" << index+1 << " / " << qmax << ") " << question->prompt << "\n";
|
||||
std::cout << "\n";
|
||||
|
||||
// Spitting out responses
|
||||
for(unsigned int i = 0; i < question->responses.size(); i++){
|
||||
std::cout << indexes[i] << ") " << question->responses[i] << "\n";
|
||||
}
|
||||
|
||||
std::cout << "\n";
|
||||
}
|
||||
void Tester_CLI::DisplayScore(Score score, std::string title){
|
||||
// Clear screen
|
||||
system("clear");
|
||||
|
||||
// Test title
|
||||
std::cout << "-- " << title << " --" << "\n";
|
||||
|
||||
// Quick Stats
|
||||
std::cout << "\n";
|
||||
std::cout << "- Summary -" << "\n";
|
||||
std::cout << "\tGrade: " << score.percentage << "%\n";
|
||||
std::cout << "\tCorrect: " << score.correct << " / " << (score.correct + score.incorrect) << "\n";
|
||||
if(score.incorrect) {std::cout << "\t" << "You missed " << score.incorrect << " questions.\n";}
|
||||
std::cout << "\n";
|
||||
|
||||
// Did we miss any?
|
||||
if(score.incorrect <= 0){
|
||||
std::cout << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Showing wrong answers
|
||||
std::cout << "\n";
|
||||
std::cout << "- Missed Questions -" << "\n";
|
||||
for(unsigned int i = 0; i < score.incorrect; i++){
|
||||
std::cout << score.iIncorrect[i] + 1 << ") " << score.qIncorrect[i]->prompt << "\n";
|
||||
std::cout << "\n";
|
||||
std::cout << "You said: \t\t" << score.qIncorrect[i]->responses[score.aIncorrect[i]] << "\n";
|
||||
std::cout << "Correct answer: \t" << score.qIncorrect[i]->responses[score.qIncorrect[i]->correct] << "\n";
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
462
src/interface/gui_fltk.cpp
Normal file
462
src/interface/gui_fltk.cpp
Normal file
|
@ -0,0 +1,462 @@
|
|||
// Header
|
||||
#include <interface/gui_fltk.h>
|
||||
|
||||
// Functions
|
||||
void btnNext(Fl_Widget*, void* data){
|
||||
// Getting info from data
|
||||
std::vector<Fl_Radio_Round_Button*> *buttons = (std::vector<Fl_Radio_Round_Button*> *)data;
|
||||
|
||||
// Going through buttons
|
||||
for(unsigned int i = 0; i < buttons->size(); i++){
|
||||
if(buttons->at(i)->value()){
|
||||
// Printing that we answered
|
||||
printf("Answered: %i\n", i);
|
||||
|
||||
// Answering the question
|
||||
Tester_GUI::instance->quiz->qAnswer(i);
|
||||
Tester_GUI::instance->quiz->qCurrent++;
|
||||
|
||||
if(Tester_GUI::instance->quiz->qCurrent == Tester_GUI::instance->quiz->qSize() - 1){
|
||||
Tester_GUI::instance->LastQuestion();
|
||||
}
|
||||
|
||||
// Do we have more questions?
|
||||
if(Tester_GUI::instance->quiz->qCurrent < Tester_GUI::instance->quiz->qSize()){
|
||||
// Updating the question board
|
||||
Tester_GUI::instance->Populate();
|
||||
}
|
||||
else{
|
||||
// Ending exam
|
||||
Tester_GUI::instance->EndTest();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void btnQuit(Fl_Widget*, void* data){
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
void btnGNext(Fl_Widget*, void* data){
|
||||
Tester_GUI::instance->gNav(1);
|
||||
Tester_GUI::instance->gPopulate();
|
||||
}
|
||||
void btnGBack(Fl_Widget*, void* data){
|
||||
Tester_GUI::instance->gNav(-1);
|
||||
Tester_GUI::instance->gPopulate();
|
||||
}
|
||||
void btnHStart(Fl_Widget*, void* data){
|
||||
// Cast
|
||||
HubData* hData = (HubData*)data;
|
||||
|
||||
// Getting values
|
||||
const char* quizName = hData->name->value();
|
||||
int quizAmount = (int)(floor(hData->questions->value()));
|
||||
|
||||
if(quizAmount > 0){
|
||||
// Loading a quiz
|
||||
Quiz* quiz = new Quiz(("data/exams/" + std::string(quizName) + ".json").c_str(), quizAmount);
|
||||
|
||||
// Cleanup
|
||||
Hub_GUI::instance->Clean();
|
||||
|
||||
// Creating the GUI
|
||||
Tester_GUI::instance = new Tester_GUI(quiz);
|
||||
|
||||
// Redrawing the window
|
||||
Window_GUI::instance->getWindow()->redraw();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> split(std::string line, char delimeter){
|
||||
std::vector<std::string> splits;
|
||||
std::string temp;
|
||||
for(unsigned int i = 0; i < line.size(); i++){
|
||||
if(line[i] == delimeter){
|
||||
splits.push_back(temp);
|
||||
temp = "";
|
||||
}
|
||||
else{
|
||||
temp += line[i];
|
||||
}
|
||||
}
|
||||
splits.push_back(temp);
|
||||
return splits;
|
||||
}
|
||||
|
||||
// Statics
|
||||
Window_GUI* Window_GUI::instance;
|
||||
Hub_GUI* Hub_GUI::instance;
|
||||
Tester_GUI* Tester_GUI::instance;
|
||||
|
||||
// Variables
|
||||
Fl_Window* Window_GUI::getWindow(){
|
||||
return window;
|
||||
}
|
||||
|
||||
// Constructors
|
||||
Window_GUI::Window_GUI(const char* title, int w, int h){
|
||||
// Creating a window
|
||||
this->window = new Fl_Window(w, h, title);
|
||||
}
|
||||
Hub_GUI::Hub_GUI(){
|
||||
// Title
|
||||
this->title = new Fl_Box(205, 35, 335, 50, "TestDesk");
|
||||
title->labelsize(42);
|
||||
|
||||
// Subtitle
|
||||
this->subtitle = new Fl_Box(275, 80, 200, 25, "The simple study assistant.");
|
||||
subtitle->labelsize(14);
|
||||
|
||||
// Credits
|
||||
this->credits = new Fl_Box(0, 505, 255, 20, "Created by OBJNULL (Maddox Werts)");
|
||||
credits->labelsize(14);
|
||||
|
||||
// Quiz Name
|
||||
this->quizName = new Fl_Input_Choice(285, 227, 180, 28, "Quiz Name");
|
||||
|
||||
// Getting quiz questions
|
||||
std::vector<std::string> quizzes = getQuizzes();
|
||||
for(unsigned int i = 0; i < quizzes.size(); i++){
|
||||
char* bytes = new char[quizzes[i].length() + 1];
|
||||
strcpy(bytes, quizzes[i].c_str());
|
||||
|
||||
quizName->add(bytes);
|
||||
}
|
||||
|
||||
// Question amounts
|
||||
this->numQuestions = new Fl_Value_Input(285, 257, 180, 28, "Questions");
|
||||
|
||||
// Start button
|
||||
this->start = new Fl_Button(310, 290, 120, 30, "Start");
|
||||
|
||||
HubData* data = new HubData{quizName, numQuestions};
|
||||
|
||||
start->callback(btnHStart, (void*)data);
|
||||
}
|
||||
Tester_GUI::Tester_GUI(Quiz* quiz){
|
||||
// Setting Quiz pointer
|
||||
this->quiz = quiz;
|
||||
this->quiz->qCurrent = 0;
|
||||
|
||||
// Update to the current question
|
||||
Instantiate();
|
||||
}
|
||||
|
||||
// Functions
|
||||
void Window_GUI::Update(){
|
||||
this->window->end();
|
||||
}
|
||||
|
||||
void Window_GUI::Show(int argc, char* argv[]){
|
||||
this->window->show(argc, argv);
|
||||
}
|
||||
|
||||
std::vector<std::string> Hub_GUI::getQuizzes(){
|
||||
// Result object
|
||||
std::vector<std::string> result;
|
||||
|
||||
// Going through exams
|
||||
for (const auto& entry : std::filesystem::recursive_directory_iterator("data/exams/")) {
|
||||
if (std::filesystem::is_regular_file(entry)) {
|
||||
// Getting the file name
|
||||
std::string line = std::string(entry.path().string());
|
||||
std::string strippedName = split(split(line, '/')[2], '.')[0];
|
||||
|
||||
if(strippedName != ""){
|
||||
std::cout << strippedName << "\n";
|
||||
result.push_back(strippedName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return Result
|
||||
return result;
|
||||
}
|
||||
void Hub_GUI::Clean(){
|
||||
Window_GUI::instance->getWindow()->remove(this->title);
|
||||
Window_GUI::instance->getWindow()->remove(this->subtitle);
|
||||
Window_GUI::instance->getWindow()->remove(this->credits);
|
||||
Window_GUI::instance->getWindow()->remove(this->quizName);
|
||||
Window_GUI::instance->getWindow()->remove(this->numQuestions);
|
||||
Window_GUI::instance->getWindow()->remove(this->start);
|
||||
Window_GUI::instance->getWindow()->redraw();
|
||||
}
|
||||
|
||||
void Tester_GUI::Instantiate(){
|
||||
// Progress
|
||||
this->g_exam_progress = new Fl_Box(760, 5, 13, 20);
|
||||
this->g_exam_progress->align(FL_ALIGN_LEFT);
|
||||
|
||||
std::string progressText = "Question " + std::to_string(this->quiz->qCurrent+1) + " / " + std::to_string(this->quiz->qSize());
|
||||
char* progressFinal = new char[progressText.length() + 1];
|
||||
strcpy(progressFinal, progressText.c_str());
|
||||
|
||||
this->g_exam_progress->label(progressFinal);
|
||||
Window_GUI::instance->getWindow()->add(this->g_exam_progress);
|
||||
|
||||
// Title
|
||||
std::string promptText = this->quiz->qGet()->prompt;
|
||||
char* promptFinal = new char[promptText.length() + 1];
|
||||
strcpy(promptFinal, promptText.c_str());
|
||||
|
||||
// Adding a exam question
|
||||
this->g_exam_question = new Fl_Box(20, 45, 730, 85, promptFinal);
|
||||
this->g_exam_question->align(FL_ALIGN_LEFT|FL_ALIGN_CLIP|FL_ALIGN_WRAP|FL_ALIGN_INSIDE);
|
||||
this->g_exam_question->labelsize(14);
|
||||
Window_GUI::instance->getWindow()->add(this->g_exam_question);
|
||||
|
||||
// Adding a exam title
|
||||
this->g_exam_title = new Fl_Box(10, 10, 5, 30, this->quiz->name.c_str());
|
||||
this->g_exam_title->align(FL_ALIGN_RIGHT);
|
||||
this->g_exam_title->labelsize(24);
|
||||
Window_GUI::instance->getWindow()->add(this->g_exam_title);
|
||||
|
||||
// Adding next button
|
||||
this->g_exam_next = new Fl_Button(700, 485, 60, 30);
|
||||
this->g_exam_next->labeltype(FL_NORMAL_LABEL);
|
||||
this->g_exam_next->label("Next");
|
||||
this->g_exam_next->box(FL_UP_BOX);
|
||||
Window_GUI::instance->getWindow()->add(this->g_exam_next);
|
||||
|
||||
// Adding buttons for each question response
|
||||
for(unsigned int i = 0; i < this->quiz->qGet()->responses.size(); i++){
|
||||
std::string qResponse = this->quiz->qGet()->responses[i];
|
||||
|
||||
Fl_Radio_Round_Button* nRB = new Fl_Radio_Round_Button(45, 145+(i*40), 700, 25);
|
||||
|
||||
nRB->labeltype(FL_NORMAL_LABEL);
|
||||
nRB->label(this->quiz->qGet()->responses[i].c_str());
|
||||
|
||||
nRB->box(FL_NO_BOX);
|
||||
nRB->down_box(FL_ROUND_DOWN_BOX);
|
||||
nRB->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP|FL_ALIGN_CLIP);
|
||||
|
||||
this->questionButtons.push_back(nRB);
|
||||
Window_GUI::instance->getWindow()->add(nRB);
|
||||
}
|
||||
|
||||
// Next Callback
|
||||
this->g_exam_next->callback(btnNext, (void*)&this->questionButtons);
|
||||
}
|
||||
void Tester_GUI::Populate(){
|
||||
// Progress
|
||||
std::string progressText = "Question " + std::to_string(this->quiz->qCurrent+1) + " / " + std::to_string(this->quiz->qSize());
|
||||
char* progressFinal = new char[progressText.length() + 1];
|
||||
strcpy(progressFinal, progressText.c_str());
|
||||
|
||||
this->g_exam_progress->label(progressFinal);
|
||||
|
||||
// Title
|
||||
std::string promptText = std::to_string(this->quiz->qCurrent+1) +") " + this->quiz->qGet()->prompt;
|
||||
char* promptFinal = new char[promptText.length() + 1];
|
||||
strcpy(promptFinal, promptText.c_str());
|
||||
|
||||
// Setting the question title
|
||||
this->g_exam_question->label(promptFinal);
|
||||
|
||||
// Clearing the existing answers
|
||||
for(unsigned int i = 0; i < questionButtons.size(); i++){
|
||||
Window_GUI::instance->getWindow()->remove(questionButtons[i]);
|
||||
delete questionButtons[i];
|
||||
}
|
||||
|
||||
// Clearing array
|
||||
this->questionButtons.clear();
|
||||
|
||||
// Adding new question buttons
|
||||
for(unsigned int i = 0; i < this->quiz->qGet()->responses.size(); i++){
|
||||
std::string qResponse = this->quiz->qGet()->responses[i];
|
||||
|
||||
Fl_Radio_Round_Button* nRB = new Fl_Radio_Round_Button(45, 145+(i*40), 700, 40);
|
||||
|
||||
nRB->labeltype(FL_NORMAL_LABEL);
|
||||
nRB->label(this->quiz->qGet()->responses[i].c_str());
|
||||
|
||||
nRB->box(FL_NO_BOX);
|
||||
nRB->down_box(FL_ROUND_DOWN_BOX);
|
||||
nRB->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP|FL_ALIGN_CLIP);
|
||||
|
||||
this->questionButtons.push_back(nRB);
|
||||
Window_GUI::instance->getWindow()->add(nRB);
|
||||
}
|
||||
|
||||
// After Adding more elements
|
||||
Window_GUI::instance->getWindow()->redraw();
|
||||
}
|
||||
|
||||
void Tester_GUI::gPopulate(){
|
||||
this->g_grade_header->label(mQuestions[gCurrent].title);
|
||||
this->g_grade_prompt->label(mQuestions[gCurrent].prompt);
|
||||
this->g_grade_user->label(mQuestions[gCurrent].user);
|
||||
this->g_grade_correct->label(mQuestions[gCurrent].correct);
|
||||
}
|
||||
void Tester_GUI::gNav(int dir){
|
||||
this->gCurrent += dir;
|
||||
if(this->gCurrent > gMax - 1){
|
||||
this->gCurrent = 0;
|
||||
}
|
||||
else if(this->gCurrent < 0){
|
||||
this->gCurrent = gMax - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Tester_GUI::LastQuestion(){
|
||||
printf("LAST QUESTION\n");
|
||||
this->g_exam_next->label("Submit");
|
||||
}
|
||||
void Tester_GUI::EndTest(){
|
||||
// DEBUG
|
||||
printf("Your exam has ended.\n");
|
||||
|
||||
// Clearing current screen
|
||||
Window_GUI::instance->getWindow()->remove(g_exam_question);
|
||||
Window_GUI::instance->getWindow()->remove(g_exam_next);
|
||||
Window_GUI::instance->getWindow()->remove(g_exam_back);
|
||||
for(unsigned int i = 0; i < this->questionButtons.size(); i++){
|
||||
Window_GUI::instance->getWindow()->remove(questionButtons[i]);
|
||||
}
|
||||
|
||||
// Scoring the test
|
||||
Score score = Tester_GUI::instance->quiz->qScore();
|
||||
|
||||
// Adding the top section
|
||||
if(true){
|
||||
// Adding new elements
|
||||
Fl_Box* title = new Fl_Box(270, 100, 215, 30);
|
||||
title->labeltype(FL_NORMAL_LABEL);
|
||||
title->labelsize(24);
|
||||
|
||||
// Adding percentage in a weird way
|
||||
std::string qTitleText = "";
|
||||
|
||||
if(score.percentage < 75){
|
||||
qTitleText += "Failed";
|
||||
}
|
||||
else{
|
||||
qTitleText += "Passed";
|
||||
}
|
||||
|
||||
qTitleText += " (";
|
||||
|
||||
std::string percent_raw = std::to_string(score.percentage);
|
||||
qTitleText += percent_raw.substr(0, percent_raw.length() - 4);
|
||||
|
||||
qTitleText += "%)";
|
||||
|
||||
char* qTitleFinal = new char[qTitleText.length() + 1];
|
||||
strcpy(qTitleFinal, qTitleText.c_str());
|
||||
|
||||
title->label(qTitleFinal);
|
||||
Window_GUI::instance->getWindow()->add(title);
|
||||
|
||||
// The questions you got right and wrong
|
||||
Fl_Box* qRatio = new Fl_Box(270, 130, 215, 30);
|
||||
qRatio->labeltype(FL_NORMAL_LABEL);
|
||||
qRatio->labelsize(16);
|
||||
|
||||
std::string qRatioText = "";
|
||||
qRatioText += std::string(std::to_string(score.correct));
|
||||
qRatioText += " / ";
|
||||
qRatioText += std::to_string(score.correct + score.incorrect);
|
||||
|
||||
char* qRatioFinal = new char[qRatioText.length() + 1];
|
||||
strcpy(qRatioFinal, qRatioText.c_str());
|
||||
|
||||
qRatio->label(qRatioFinal);
|
||||
Window_GUI::instance->getWindow()->add(qRatio);
|
||||
}
|
||||
|
||||
// Adding the missed answers section
|
||||
if(true){
|
||||
// FUNCTION
|
||||
gMax = score.qIncorrect.size();
|
||||
|
||||
mQuestions.clear();
|
||||
for(unsigned int i = 0; i < gMax; i++){
|
||||
// Title
|
||||
std::string titleText = "Question ";
|
||||
titleText += std::to_string(score.iIncorrect[i]+1);
|
||||
char* titleFinal = new char[titleText.length() + 1];
|
||||
strcpy(titleFinal, titleText.c_str());
|
||||
|
||||
// Prompt
|
||||
std::string promptText = score.qIncorrect[i]->prompt;
|
||||
char* promptFinal = new char[promptText.length() + 1];
|
||||
strcpy(promptFinal, promptText.c_str());
|
||||
|
||||
// You Said
|
||||
std::string mYouSaidText = "You Said: ";
|
||||
mYouSaidText += score.qIncorrect[i]->responses[score.aIncorrect[i]];
|
||||
char* mYouSaidFinal = new char[mYouSaidText.length() + 1];
|
||||
strcpy(mYouSaidFinal, mYouSaidText.c_str());
|
||||
|
||||
// Correct
|
||||
std::string mCorrectText = "Correct: ";
|
||||
mCorrectText += score.qIncorrect[i]->responses[score.qIncorrect[i]->correct];
|
||||
char* mCorrectFinal = new char[mCorrectText.length() + 1];
|
||||
strcpy(mCorrectFinal, mCorrectText.c_str());
|
||||
|
||||
// New missed question
|
||||
MissedQuestion mq = MissedQuestion();
|
||||
mq.title = titleFinal;
|
||||
mq.prompt = promptFinal;
|
||||
mq.user = mYouSaidFinal;
|
||||
mq.correct = mCorrectFinal;
|
||||
|
||||
// Pushing back final result
|
||||
mQuestions.push_back(mq);
|
||||
}
|
||||
|
||||
// UI
|
||||
if(mQuestions.size() > 0){
|
||||
Fl_Group* missedQuestions = new Fl_Group(10, 200, 750, 280);
|
||||
missedQuestions->labelsize(19);
|
||||
missedQuestions->label("Missed Questions");
|
||||
Window_GUI::instance->getWindow()->add(missedQuestions);
|
||||
|
||||
// Going through all missed questions
|
||||
this->g_grade_header = new Fl_Group(20, 225, 730, 150);
|
||||
this->g_grade_header->labelsize(14);
|
||||
this->g_grade_header->label(mQuestions[0].title);
|
||||
missedQuestions->add(this->g_grade_header);
|
||||
|
||||
// Question prompt
|
||||
this->g_grade_prompt = new Fl_Box(25, 230, 710, 100);
|
||||
this->g_grade_prompt->align(FL_ALIGN_CLIP|FL_ALIGN_WRAP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
|
||||
this->g_grade_prompt->labelsize(14);
|
||||
this->g_grade_prompt->label(mQuestions[0].prompt);
|
||||
this->g_grade_header->add(this->g_grade_prompt);
|
||||
|
||||
// You said
|
||||
this->g_grade_user = new Fl_Box(40, 330, 5, 20);
|
||||
this->g_grade_user->align(FL_ALIGN_RIGHT);
|
||||
this->g_grade_user->labelsize(14);
|
||||
this->g_grade_user->label(mQuestions[0].user);
|
||||
this->g_grade_header->add(this->g_grade_user);
|
||||
|
||||
// Correct
|
||||
this->g_grade_correct = new Fl_Box(40, 350, 5, 20);
|
||||
this->g_grade_correct->align(FL_ALIGN_RIGHT);
|
||||
this->g_grade_correct->labelsize(14);
|
||||
this->g_grade_correct->label(mQuestions[0].correct);
|
||||
this->g_grade_header->add(this->g_grade_correct);
|
||||
|
||||
// Next
|
||||
Fl_Button* next = new Fl_Button(680, 485, 80, 30, "Next");
|
||||
next->callback(btnGNext);
|
||||
Window_GUI::instance->getWindow()->add(next);
|
||||
|
||||
// Next
|
||||
Fl_Button* back = new Fl_Button(595, 485, 80, 30, "Back");
|
||||
back->callback(btnGBack);
|
||||
Window_GUI::instance->getWindow()->add(back);
|
||||
}
|
||||
}
|
||||
|
||||
// Adding quit button
|
||||
Fl_Button* quit = new Fl_Button(10, 485, 80, 30, "Quit");
|
||||
quit->callback(btnQuit);
|
||||
Window_GUI::instance->getWindow()->add(quit);
|
||||
|
||||
// Redraw
|
||||
Window_GUI::instance->getWindow()->redraw();
|
||||
}
|
92
src/main.cpp
Normal file
92
src/main.cpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
// Includes
|
||||
#include <base.h>
|
||||
#include <tester/quiz.h>
|
||||
#include <interface/cli.h>
|
||||
#include <interface/gui_fltk.h>
|
||||
|
||||
// Variables
|
||||
std::string quizPath = "data/exams/";
|
||||
int numOfQuestions = 15;
|
||||
int flagsSet = 0;
|
||||
|
||||
// Functions
|
||||
void cli_version(){
|
||||
// Loading a new test
|
||||
Quiz quiz = Quiz(quizPath.c_str(), numOfQuestions);
|
||||
|
||||
// Init application
|
||||
Tester_CLI cli;
|
||||
|
||||
// Asking the user questions
|
||||
cli.AskQuestions(quiz, numOfQuestions);
|
||||
}
|
||||
int gui_version(int argc, char* argv[]){
|
||||
// Creating the window app
|
||||
Window_GUI::instance = new Window_GUI("TestDesk", 770, 525);
|
||||
|
||||
if(flagsSet >= 2){
|
||||
// Loading a quiz
|
||||
Quiz* quiz = new Quiz(quizPath.c_str(), numOfQuestions);
|
||||
|
||||
// Creating the GUI
|
||||
Tester_GUI::instance = new Tester_GUI(quiz);
|
||||
}
|
||||
else{
|
||||
Hub_GUI::instance = new Hub_GUI();
|
||||
}
|
||||
|
||||
// Finalizing and showing the window after creating GUI elements
|
||||
Window_GUI::instance->Update();
|
||||
Window_GUI::instance->Show(argc, argv);
|
||||
|
||||
// Running FLTK
|
||||
return Fl::run();
|
||||
}
|
||||
|
||||
// Entry point
|
||||
int main(int argc, char* argv[]){
|
||||
// Getting argument(s)
|
||||
std::vector<std::string> args;
|
||||
for(unsigned int i = 0; i < argc; i++){
|
||||
args.push_back(std::string(argv[i]));
|
||||
}
|
||||
|
||||
// Checking the arguments
|
||||
if(argc > 1){
|
||||
if(args[1] == "--help"){
|
||||
printf("Usage: TestDesk [OPTIONS]\n");
|
||||
printf("OPTIONS: \n");
|
||||
printf("\t-t: Sets the test you want to use (ex: CompTIA 1101)\n");
|
||||
printf("\t-q: Sets the amount of questions to be quizzed on (random)\n");
|
||||
printf("\t--help: Displays how to use the program\n");
|
||||
printf("\t--cli: Starts program in a Command Line Interface.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Getting typed arguments
|
||||
for(unsigned i = 0; i < argc; i++){
|
||||
// Converting the char array into a string
|
||||
std::string arg_string = std::string(argv[i]);
|
||||
|
||||
// What do we want?
|
||||
if(arg_string == "--cli"){
|
||||
cli_version();
|
||||
return 0;
|
||||
}
|
||||
if(arg_string == "-q"){
|
||||
numOfQuestions = std::stoi(argv[i+1]);
|
||||
i++;
|
||||
flagsSet++;
|
||||
}
|
||||
if(arg_string == "-t"){
|
||||
quizPath += argv[i+1];
|
||||
quizPath += ".json";
|
||||
i++;
|
||||
flagsSet++;
|
||||
}
|
||||
}
|
||||
|
||||
// Starting the GUI Version
|
||||
return gui_version(argc, argv);
|
||||
}
|
9
src/tester/question.cpp
Normal file
9
src/tester/question.cpp
Normal file
|
@ -0,0 +1,9 @@
|
|||
// Header
|
||||
#include <tester/question.h>
|
||||
|
||||
Question::Question(std::string prompt, std::vector<std::string> responses, int correct){
|
||||
// Getting the JSON stuff
|
||||
this->prompt = prompt;
|
||||
this->responses = responses;
|
||||
this->correct = correct;
|
||||
}
|
117
src/tester/quiz.cpp
Normal file
117
src/tester/quiz.cpp
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Includes
|
||||
#include <tester/quiz.h>
|
||||
|
||||
// Constructors
|
||||
Score::Score(){
|
||||
percentage = 0;
|
||||
incorrect = 0;
|
||||
correct = 0;
|
||||
}
|
||||
Quiz::Quiz(const char* quizPath, int wantedQuestions){
|
||||
// Load the quiz from path
|
||||
std::ifstream file(quizPath);
|
||||
|
||||
// Parsing JSON
|
||||
json qData = json::parse(file);
|
||||
|
||||
// Did it work?
|
||||
if(qData == nullptr){
|
||||
// Exit
|
||||
printf("ERROR: Failed to parse JSON.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Getting important data
|
||||
this->name = qData["name"];
|
||||
this->description = qData["description"];
|
||||
|
||||
// Loading questions
|
||||
std::vector<Question*> tquestions;
|
||||
for(unsigned int i = 0; i < qData["questions"].size(); i++){
|
||||
// Current questions
|
||||
json lq = qData["questions"][i];
|
||||
|
||||
// Loading responses
|
||||
std::vector<std::string> responses;
|
||||
for(unsigned int i = 0; i < lq["responses"].size(); i++){
|
||||
responses.push_back(lq["responses"][i]);
|
||||
}
|
||||
|
||||
// Creating a new question
|
||||
Question* nq = new Question(lq["prompt"], responses, lq["correct"]);
|
||||
|
||||
// Adding it into the list
|
||||
tquestions.push_back(nq);
|
||||
}
|
||||
|
||||
// Making sure it is 100% random
|
||||
srand(time(NULL));
|
||||
|
||||
// Adding 15 random questions from that list
|
||||
int i = 0;
|
||||
std::vector<int> usedQuestions;
|
||||
while(i < wantedQuestions){
|
||||
// Wanted question index
|
||||
int qIndex = std::rand() % (tquestions.size());
|
||||
|
||||
// Did we already call it?
|
||||
bool alreadyUsed = false;
|
||||
for(int j = 0; j < usedQuestions.size(); j++){
|
||||
if(usedQuestions[j] == qIndex){
|
||||
alreadyUsed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Adding question to index
|
||||
if(!alreadyUsed
|
||||
&& tquestions[qIndex] != nullptr){
|
||||
this->questions.push_back(tquestions[qIndex]);
|
||||
i++;
|
||||
}
|
||||
|
||||
// Already got our questions?
|
||||
if(i >= wantedQuestions){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Functions
|
||||
void Quiz::qAnswer(int answer){
|
||||
answers.push_back(answer);
|
||||
}
|
||||
Question* Quiz::qGet(){
|
||||
return this->questions[this->qCurrent];
|
||||
}
|
||||
int Quiz::qSize(){
|
||||
return this->questions.size();
|
||||
}
|
||||
|
||||
Score Quiz::qScore(){
|
||||
// Result
|
||||
Score result;
|
||||
|
||||
// Going through all questions
|
||||
for(unsigned int i = 0; i < this->questions.size(); i++){
|
||||
if(this->questions[i]->correct == this->answers[i]){
|
||||
result.correct++;
|
||||
}
|
||||
else{
|
||||
result.incorrect++;
|
||||
result.qIncorrect.push_back(this->questions[i]);
|
||||
result.aIncorrect.push_back(this->answers[i]);
|
||||
result.iIncorrect.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate percentage
|
||||
float fC = result.correct;
|
||||
float fI = result.correct + result.incorrect;
|
||||
float fP = fC / fI;
|
||||
float rP = (float)( (int)(fP * 10000) );
|
||||
result.percentage = rP / 100;
|
||||
|
||||
// Return result
|
||||
return result;
|
||||
}
|
BIN
tools/providers/__pycache__/messer.cpython-312.pyc
Normal file
BIN
tools/providers/__pycache__/messer.cpython-312.pyc
Normal file
Binary file not shown.
BIN
tools/providers/__pycache__/vceplus.cpython-311.pyc
Normal file
BIN
tools/providers/__pycache__/vceplus.cpython-311.pyc
Normal file
Binary file not shown.
BIN
tools/providers/__pycache__/vceplus.cpython-312.pyc
Normal file
BIN
tools/providers/__pycache__/vceplus.cpython-312.pyc
Normal file
Binary file not shown.
92
tools/providers/messer.py
Normal file
92
tools/providers/messer.py
Normal file
|
@ -0,0 +1,92 @@
|
|||
def Letter2Number(letter):
|
||||
if("A" in letter):
|
||||
return 0
|
||||
if("B" in letter):
|
||||
return 1
|
||||
if("C" in letter):
|
||||
return 2
|
||||
if("D" in letter):
|
||||
return 3
|
||||
if("E" in letter):
|
||||
return 4
|
||||
if("F" in letter):
|
||||
return 5
|
||||
if("G" in letter):
|
||||
return 6
|
||||
if("H" in letter):
|
||||
return 7
|
||||
if("I" in letter):
|
||||
return 8
|
||||
if("J" in letter):
|
||||
return 9
|
||||
if("K" in letter):
|
||||
return 10
|
||||
|
||||
def ParseMesser(lines):
|
||||
result = []
|
||||
|
||||
# Pre-Stuff
|
||||
tempQuestion = {
|
||||
"type": 0,
|
||||
"prompt": "",
|
||||
"responses": [],
|
||||
"correct": 0
|
||||
}
|
||||
state = 0
|
||||
|
||||
# Going through lines
|
||||
for line in lines:
|
||||
match(state):
|
||||
case 0: # Awaiting question
|
||||
if("Practice Exam A - Answers" in line
|
||||
or "Practice Exam B - Answers" in line
|
||||
or "Practice Exam C - Answers" in line):
|
||||
state = 1
|
||||
case 1: # Writing into prompt
|
||||
if("*" in line):
|
||||
if("PICK TWO" in line):
|
||||
state = 0
|
||||
tempQuestion = {
|
||||
"type": 0,
|
||||
"prompt": "",
|
||||
"responses": [],
|
||||
"correct": 0
|
||||
}
|
||||
state = 2
|
||||
else:
|
||||
for l in line:
|
||||
if(l == '\n'):
|
||||
tempQuestion["prompt"] += " "
|
||||
else:
|
||||
tempQuestion["prompt"] += l
|
||||
case 2: # Awaiting for answers
|
||||
if(line == "" or line == " " or line == "\n" or line == None):
|
||||
state = 3
|
||||
case 3: # Adding responses
|
||||
if(line == "" or line == " " or line == "\n" or line == None):
|
||||
state = 4
|
||||
else:
|
||||
if(len(line.split(".")) <= 1):
|
||||
print("SKIPED QUESTION: " + tempQuestion["prompt"])
|
||||
tempQuestion = {
|
||||
"type": 0,
|
||||
"prompt": "",
|
||||
"responses": [],
|
||||
"correct": 0
|
||||
}
|
||||
state = 0
|
||||
else:
|
||||
tempQuestion["responses"].append(line.split(".")[1])
|
||||
case 4: # Awaiting for Correct Answer
|
||||
if("The Answer" in line):
|
||||
tempQuestion["correct"] = Letter2Number(line.split(":")[1].split(".")[0])
|
||||
result.append(tempQuestion)
|
||||
tempQuestion = {
|
||||
"type": 0,
|
||||
"prompt": "",
|
||||
"responses": [],
|
||||
"correct": 0
|
||||
}
|
||||
state = 0
|
||||
|
||||
return result
|
72
tools/providers/vceplus.py
Normal file
72
tools/providers/vceplus.py
Normal file
|
@ -0,0 +1,72 @@
|
|||
def Letter2Number(letter):
|
||||
if("A" in letter):
|
||||
return 0
|
||||
if("B" in letter):
|
||||
return 1
|
||||
if("C" in letter):
|
||||
return 2
|
||||
if("D" in letter):
|
||||
return 3
|
||||
if("E" in letter):
|
||||
return 4
|
||||
if("F" in letter):
|
||||
return 5
|
||||
if("G" in letter):
|
||||
return 6
|
||||
if("H" in letter):
|
||||
return 7
|
||||
if("I" in letter):
|
||||
return 8
|
||||
if("J" in letter):
|
||||
return 9
|
||||
if("K" in letter):
|
||||
return 10
|
||||
|
||||
def ParseVCE(lines):
|
||||
# Result object
|
||||
result = []
|
||||
|
||||
# Pre-Stuff
|
||||
tempQuestion = {
|
||||
"type": 0,
|
||||
"prompt": "",
|
||||
"responses": [],
|
||||
"correct": 0
|
||||
}
|
||||
state = 0
|
||||
|
||||
# Going through lines
|
||||
for line in lines:
|
||||
match(state):
|
||||
case 0: # Awaiting question
|
||||
if("QUESTION" in line):
|
||||
state = 1
|
||||
case 1: # Writing to prompt
|
||||
if("A." in line):
|
||||
state = 2
|
||||
else:
|
||||
tempQuestion["prompt"] += line
|
||||
case 2: # Awaiting for answers
|
||||
if(line == "" or line == " " or line == "\n" or line == None):
|
||||
state = 3
|
||||
case 3: #Adding responses
|
||||
if(line == "" or line == " " or line == "\n" or line == None):
|
||||
state = 4
|
||||
else:
|
||||
tempQuestion["responses"].append(line)
|
||||
case 4: # Awaiting for correct answer
|
||||
if("Correct" in line):
|
||||
print(line)
|
||||
tempQuestion["correct"] = Letter2Number(line.split(": ")[1])
|
||||
elif("Section: " in line):
|
||||
result.append(tempQuestion)
|
||||
tempQuestion = {
|
||||
"type": 0,
|
||||
"prompt": "",
|
||||
"responses": [],
|
||||
"correct": 0
|
||||
}
|
||||
state = 0
|
||||
|
||||
# Return result
|
||||
return result
|
128
tools/testConverter.py
Normal file
128
tools/testConverter.py
Normal file
|
@ -0,0 +1,128 @@
|
|||
####################
|
||||
## Test Converter ##
|
||||
####################
|
||||
## A free script to convert a text file into a TestDesk compatible JSON file.
|
||||
|
||||
# Imports
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
|
||||
import providers.messer as MSR
|
||||
import providers.vceplus as VCE
|
||||
|
||||
# Variables
|
||||
result = {
|
||||
"name": None,
|
||||
"description": None,
|
||||
"questions": []
|
||||
}
|
||||
commands = [
|
||||
{
|
||||
"token": "--name"
|
||||
},
|
||||
{
|
||||
"token": "--desc"
|
||||
},
|
||||
{
|
||||
"token": "--in"
|
||||
},
|
||||
{
|
||||
"token": "--out"
|
||||
}
|
||||
]
|
||||
args = []
|
||||
|
||||
quizProvider = 0
|
||||
quizPath = ""
|
||||
quizOut = ""
|
||||
|
||||
# Functions
|
||||
def readArgs():
|
||||
global commands, args
|
||||
for arg in range(len(sys.argv)):
|
||||
for cmd in commands:
|
||||
if(cmd["token"] == sys.argv[arg]):
|
||||
args.append({
|
||||
"key": cmd["token"],
|
||||
"value": sys.argv[arg+1]
|
||||
})
|
||||
arg += 1
|
||||
|
||||
def argExists(key):
|
||||
global args
|
||||
for arg in args:
|
||||
if(arg["key"] == key):
|
||||
return True
|
||||
return False
|
||||
def argValue(key):
|
||||
global args
|
||||
for arg in args:
|
||||
if(arg["key"] == key):
|
||||
return arg["value"]
|
||||
return None
|
||||
|
||||
def getMetadata():
|
||||
global result, quizProvider, quizPath, quizOut
|
||||
|
||||
# Asking for a test name and description
|
||||
if(argExists("--name")):
|
||||
result["name"] = argValue("--name")
|
||||
else:
|
||||
result["name"] = input("Give your test a name.\n[Test Name]: ")
|
||||
if(argExists("--desc")):
|
||||
result["description"] = argValue("--desc")
|
||||
else:
|
||||
result["description"] = input("Describe what your test is for.\n[Description]: ")
|
||||
|
||||
# Asking for quiz provider
|
||||
print("Select the provider that has given you the PDF file.")
|
||||
print("1. VCEplus")
|
||||
print("2. Professor Messer")
|
||||
quizProvider = int(input("[Provider]: "))
|
||||
|
||||
# Asking for quiz info
|
||||
if(argExists("--in")):
|
||||
quizPath = argValue("--in")
|
||||
else:
|
||||
quizPath = input("Drag and Drop your text file into this window\n(Use https://pdftotext.com/ to convert your PDF file into a text file.)\n[In Location]: ")
|
||||
if(argExists("--out")):
|
||||
quizOut = argValue("--out")
|
||||
else:
|
||||
quizOut = input("Write a path to where you want to save your JSON file (ex: data/exams/test.json)\nYour Working Directory: " + os.getcwd() + "\n[Out Location]: ")
|
||||
def readFile():
|
||||
global quizPath, quizProvider, result
|
||||
|
||||
# Opening quiz
|
||||
quizFile = open(quizPath, 'r')
|
||||
|
||||
# Did the user type it in wrong?
|
||||
if(quizFile == None):
|
||||
print("ERROR: Invalid path for Quiz!")
|
||||
exit()
|
||||
|
||||
# Based on provider, LOAD
|
||||
match(quizProvider):
|
||||
case 1:
|
||||
questions = VCE.ParseVCE(quizFile.readlines())
|
||||
case 2:
|
||||
questions = MSR.ParseMesser(quizFile.readlines())
|
||||
|
||||
# Result
|
||||
result["questions"] = questions
|
||||
|
||||
def writeFile():
|
||||
global quizOut, result
|
||||
|
||||
quizFile = open(quizOut, 'w')
|
||||
quizFile.write(json.dumps(result))
|
||||
quizFile.close()
|
||||
|
||||
def main():
|
||||
readArgs()
|
||||
getMetadata()
|
||||
readFile()
|
||||
writeFile()
|
||||
|
||||
# Entry Point
|
||||
main()
|
58
ui/FLTK/TestDesk-Grade.fl
Normal file
58
ui/FLTK/TestDesk-Grade.fl
Normal file
|
@ -0,0 +1,58 @@
|
|||
# data file for the Fltk User Interface Designer (fluid)
|
||||
version 1.0309
|
||||
header_name {.h}
|
||||
code_name {.cxx}
|
||||
Function {make_window()} {open
|
||||
} {
|
||||
Fl_Window {} {
|
||||
label TestDesk open
|
||||
xywh {613 329 770 525} type Double visible
|
||||
} {
|
||||
Fl_Box {} {
|
||||
label {CompTIA A+ (1101)}
|
||||
xywh {10 10 5 30} labelsize 24 align 8
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Passed (75%)}
|
||||
xywh {270 100 215 30} labelsize 24 align 16
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {30/40}
|
||||
xywh {270 130 215 30} labelsize 16
|
||||
}
|
||||
Fl_Scroll {} {
|
||||
label {Missed Questions} open
|
||||
xywh {5 200 760 315} labelsize 19
|
||||
} {
|
||||
Fl_Group {} {
|
||||
label {Question 13} open
|
||||
xywh {5 225 760 290}
|
||||
} {
|
||||
Fl_Box {} {
|
||||
label {A technician installed a new router at a small office. After the Installation, the technician notices that all devices have a I69.254.x.x IP address. Printers and fileshares are still working, but PCs cannot access the Internet. Which of the following should the technician configure on the router to enable devices to connect to the internet?}
|
||||
xywh {25 230 710 100} align 212
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {You Said: APIPA}
|
||||
xywh {40 330 5 20} align 8
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Correct: DNS}
|
||||
xywh {40 350 5 20} align 8
|
||||
}
|
||||
Fl_Button {} {
|
||||
label Quit
|
||||
xywh {5 485 80 30}
|
||||
}
|
||||
Fl_Button {} {
|
||||
label Next
|
||||
xywh {680 485 80 30}
|
||||
}
|
||||
Fl_Button {} {
|
||||
label Back
|
||||
xywh {595 485 80 30}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
ui/FLTK/TestDesk-Hub.fl
Normal file
45
ui/FLTK/TestDesk-Hub.fl
Normal file
|
@ -0,0 +1,45 @@
|
|||
# data file for the Fltk User Interface Designer (fluid)
|
||||
version 1.0309
|
||||
header_name {.h}
|
||||
code_name {.cxx}
|
||||
Function {make_window()} {open
|
||||
} {
|
||||
Fl_Window {} {
|
||||
label TestDesk open
|
||||
xywh {594 365 770 525} type Double visible
|
||||
} {
|
||||
Fl_Box {} {
|
||||
label TestDesk
|
||||
xywh {205 35 335 50} labelsize 42
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {The simple study assistant.}
|
||||
xywh {275 80 200 25}
|
||||
}
|
||||
Fl_Button {} {
|
||||
label Start
|
||||
xywh {285 290 180 30}
|
||||
}
|
||||
Fl_Value_Input {} {
|
||||
label Questions
|
||||
xywh {285 257 180 28}
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Created by OBJNULL (Maddox Werts)}
|
||||
xywh {0 505 255 20}
|
||||
}
|
||||
Fl_Input_Choice {} {
|
||||
label {Quiz Name} open
|
||||
xywh {285 227 180 28}
|
||||
} {
|
||||
MenuItem {} {
|
||||
label {Quiz A}
|
||||
xywh {0 0 34 24}
|
||||
}
|
||||
MenuItem {} {
|
||||
label {Quiz B}
|
||||
xywh {0 0 34 24}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
48
ui/FLTK/TestDesk-Tester.fl
Normal file
48
ui/FLTK/TestDesk-Tester.fl
Normal file
|
@ -0,0 +1,48 @@
|
|||
# data file for the Fltk User Interface Designer (fluid)
|
||||
version 1.0309
|
||||
header_name {.h}
|
||||
code_name {.cxx}
|
||||
Function {make_window()} {open
|
||||
} {
|
||||
Fl_Window {} {
|
||||
label TestDesk open
|
||||
xywh {549 227 770 525} type Double color 48 labelcolor 48 visible
|
||||
} {
|
||||
Fl_Box {} {
|
||||
label {CompTIA A+ (1101)}
|
||||
xywh {10 10 5 30} labelsize 24 align 8
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Which of the following would an administrator use to migrate virtual machines from on premises to the cloud?}
|
||||
xywh {20 45 730 85} align 212
|
||||
}
|
||||
Fl_Round_Button {} {
|
||||
label laaS
|
||||
xywh {45 145 250 25} down_box ROUND_DOWN_BOX
|
||||
}
|
||||
Fl_Round_Button {} {
|
||||
label SaaS
|
||||
xywh {45 175 250 25} down_box ROUND_DOWN_BOX
|
||||
}
|
||||
Fl_Round_Button {} {
|
||||
label DBaaS
|
||||
xywh {45 205 250 25} down_box ROUND_DOWN_BOX
|
||||
}
|
||||
Fl_Round_Button {} {
|
||||
label DRaaS
|
||||
xywh {45 235 250 25} down_box ROUND_DOWN_BOX
|
||||
}
|
||||
Fl_Button {} {
|
||||
label Next
|
||||
xywh {700 485 60 30}
|
||||
}
|
||||
Fl_Button {} {
|
||||
label Back
|
||||
xywh {635 485 60 30}
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Question 1/2}
|
||||
xywh {760 5 13 20} align 4
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue