From a87c5abb2cdb636ee975fd51574e4f519fce7a55 Mon Sep 17 00:00:00 2001 From: Liran BN Date: Tue, 7 Oct 2014 17:26:11 +0300 Subject: [PATCH] add graph. fixes more isses --- main/CourseTab/coursestablemanager.cpp | 19 +- main/mainscreen.cpp | 10 + src/jceData/Grades/gradePage.cpp | 253 +++++++++++++++--------- src/jceData/Grades/gradePage.h | 29 +-- src/jceData/Grades/graph/gradegraph.cpp | 144 +++++++++++++- src/jceData/Grades/graph/gradegraph.h | 4 + src/jceData/Grades/graph/gradegraph.ui | 17 +- 7 files changed, 359 insertions(+), 117 deletions(-) diff --git a/main/CourseTab/coursestablemanager.cpp b/main/CourseTab/coursestablemanager.cpp index ce215a7..de8e6dc 100644 --- a/main/CourseTab/coursestablemanager.cpp +++ b/main/CourseTab/coursestablemanager.cpp @@ -53,6 +53,8 @@ void coursesTableManager::insertJceCoursesIntoTable() */ void coursesTableManager::setCoursesList(QString &html) { + if (gp != NULL) + gp->~GradePage(); gp = new GradePage(html); } /** @@ -229,7 +231,9 @@ double coursesTableManager::getAvg() void coursesTableManager::showGraph() { if (gp != NULL) - this->graph->show(); + { + this->graph->showGraph(gp); + } } @@ -247,12 +251,13 @@ void coursesTableManager::influnceCourseChanged(bool ignoreCourseStatus) } else { - for (gradeCourse *c: *gp->getCourses()) - { - if (!(isCourseAlreadyInserted(c->getSerialNum()))) - if (c->getPoints() == 0) - addRow(c); - } + if (this->gp != NULL) + for (gradeCourse *c: *gp->getCourses()) + { + if (!(isCourseAlreadyInserted(c->getSerialNum()))) + if (c->getPoints() == 0) + addRow(c); + } } } diff --git a/main/mainscreen.cpp b/main/mainscreen.cpp index 0eb638a..eb94e3d 100644 --- a/main/mainscreen.cpp +++ b/main/mainscreen.cpp @@ -172,6 +172,7 @@ void MainScreen::on_ratesButton_clicked() } QApplication::restoreOverrideCursor(); } + bool MainScreen::checkIfValidDates() { bool flag = false; @@ -188,29 +189,35 @@ bool MainScreen::checkIfValidDates() } return flag; } + void MainScreen::on_checkBoxCoursesInfluence_toggled(bool checked) { qDebug() << Q_FUNC_INFO << "only main courses toggeled" << checked; this->userLoginSetting->setInfluenceCourseOnly(checked); this->courseTableMgr->influnceCourseChanged(checked); } + void MainScreen::on_spinBoxCoursesFromYear_valueChanged(int arg1) { ui->spinBoxCoursesFromYear->setValue(arg1); } + void MainScreen::on_spinBoxCoursesToYear_valueChanged(int arg1) { ui->spinBoxCoursesToYear->setValue(arg1); } + void MainScreen::on_spinBoxCoursesFromSemester_valueChanged(int arg1) { ui->spinBoxCoursesFromSemester->setValue(arg1%4); } + void MainScreen::on_spinBoxCoursesToSemester_valueChanged(int arg1) { ui->spinBoxCoursesToSemester->setValue(arg1%4); } + void MainScreen::on_coursesTable_itemChanged(QTableWidgetItem *item) { if (this->courseTableMgr->changes(item->text(),item->row(),item->column())) @@ -221,17 +228,20 @@ void MainScreen::on_coursesTable_itemChanged(QTableWidgetItem *item) QMessageBox::critical(this,tr("Error"),tr("Missmatching data")); } } + void MainScreen::on_clearTableButton_clicked() { qDebug() << Q_FUNC_INFO << "in: " << ui->tabWidget->currentWidget()->objectName(); courseTableMgr->clearTable(); ui->avgLCD->display(courseTableMgr->getAvg()); } + void MainScreen::on_graphButton_clicked() { courseTableMgr->showGraph(); } + //EVENTS ON CALENDAR TAB void MainScreen::on_getCalendarBtn_clicked() { diff --git a/src/jceData/Grades/gradePage.cpp b/src/jceData/Grades/gradePage.cpp index 8e0c08d..456d19f 100644 --- a/src/jceData/Grades/gradePage.cpp +++ b/src/jceData/Grades/gradePage.cpp @@ -1,153 +1,226 @@ #include "gradePage.h" +static int maxYear = 0; +static int minYear = 9999; + GradePage::GradePage(QString html) : Page() { - courses = new std::list(); - tempHtml = getString(html); - coursesListInit(tempHtml); + courses = new std::list(); + tempHtml = getString(html); + coursesListInit(tempHtml); } GradePage::~GradePage() { - for(Course* c : *courses) - delete c; - delete courses; + for(Course* c : *courses) + delete c; + delete courses; } void GradePage::removeCourse(QString courseSerialID) { - for(gradeCourse* c : *courses) + for(gradeCourse* c : *courses) { - if (c->getSerialNum() == courseSerialID.toInt()) + if (c->getSerialNum() == courseSerialID.toInt()) { - courses->remove(c); - delete c; - return; + courses->remove(c); + delete c; + return; } } } void GradePage::coursesListInit(QString &linesTokinzedString) { - std::list stringHolder; - QString temp; - gradeCourse* cTemp = NULL; - char* tok; - char* textToTok = strdup(linesTokinzedString.toStdString().c_str()); - tok = strtok(textToTok,"\n"); - while (tok != NULL) //putting every line in a string holder before parsing it + std::list stringHolder; + QString temp; + gradeCourse* cTemp = NULL; + char* tok; + char* textToTok = strdup(linesTokinzedString.toStdString().c_str()); + tok = strtok(textToTok,"\n"); + while (tok != NULL) //putting every line in a string holder before parsing it { - temp = tok; - stringHolder.push_back(temp); - tok = strtok(NULL, "\n"); + temp = tok; + stringHolder.push_back(temp); + tok = strtok(NULL, "\n"); } - for (QString temp: stringHolder) + for (QString temp: stringHolder) { - cTemp = lineToCourse(temp); - if (cTemp != NULL) - courses->push_back(cTemp); + cTemp = lineToCourse(temp); + if (cTemp != NULL) + courses->push_back(cTemp); } } gradeCourse* GradePage::lineToCourse(QString line) { - gradeCourse *tempC = NULL; - QString templinearray[COURSE_FIELDS];//[serial,name,type,points,hours,grade,additions] - int serial,year,semester,courseNumInList; - double points,hours,grade; - QString name,type, additions; - QString tempS = ""; - int i = 0; - char* tok; - char* cLine = strdup(line.toStdString().c_str()); - tok = strtok(cLine, "\t"); - while(tok != NULL) + gradeCourse *tempC = NULL; + QString templinearray[COURSE_FIELDS];//[serial,name,type,points,hours,grade,additions] + int serial,year,semester,courseNumInList; + double points,hours,grade; + QString name,type, additions; + QString tempS = ""; + int i = 0; + char* tok; + char* cLine = strdup(line.toStdString().c_str()); + tok = strtok(cLine, "\t"); + while(tok != NULL) { - tempS = tok; + tempS = tok; - if (i == gradeCourse::CourseScheme::SERIAL) //we need to extract the serial manually + if (i == gradeCourse::CourseScheme::SERIAL) //we need to extract the serial manually { - tempS = ""; - char *tokTemp; - tokTemp = tok; - while (!(isdigit((int)*tokTemp))) //getting to serial number starting pointer - tokTemp++; + tempS = ""; + char *tokTemp; + tokTemp = tok; + while (!(isdigit((int)*tokTemp))) //getting to serial number starting pointer + tokTemp++; - while (isdigit((int)*tokTemp)) //serial number + while (isdigit((int)*tokTemp)) //serial number { - tempS += QString(*tokTemp); - tokTemp++; + tempS += QString(*tokTemp); + tokTemp++; } - templinearray[i] = tempS.trimmed(); - templinearray[i+1] = QString(tokTemp).trimmed(); - i +=2; //skipping on serial and course name + templinearray[i] = tempS.trimmed(); + templinearray[i+1] = QString(tokTemp).trimmed(); + i +=2; //skipping on serial and course name } - else + else { - templinearray[i] = tempS.trimmed(); - i++; + templinearray[i] = tempS.trimmed(); + i++; } - if (i == COURSE_FIELDS) - break; - tok=strtok(NULL, "\t"); + if (i == COURSE_FIELDS) + break; + tok=strtok(NULL, "\t"); } - if (templinearray[0] == "") //empty parsing + if (templinearray[0] == "") //empty parsing { - qCritical() << Q_FUNC_INFO << "empty parsing"; - return NULL; + qCritical() << Q_FUNC_INFO << "empty parsing"; + return NULL; } - year = templinearray[gradeCourse::CourseScheme::YEAR].toInt(); - semester = templinearray[gradeCourse::CourseScheme::SEMESTER].toInt(); - courseNumInList = templinearray[gradeCourse::CourseScheme::COURSE_NUMBER_IN_LIST].toInt(); - serial = templinearray[gradeCourse::CourseScheme::SERIAL].toInt(); + year = templinearray[gradeCourse::CourseScheme::YEAR].toInt(); + semester = templinearray[gradeCourse::CourseScheme::SEMESTER].toInt(); + courseNumInList = templinearray[gradeCourse::CourseScheme::COURSE_NUMBER_IN_LIST].toInt(); + serial = templinearray[gradeCourse::CourseScheme::SERIAL].toInt(); - name = templinearray[gradeCourse::CourseScheme::NAME]; - type = templinearray[gradeCourse::CourseScheme::TYPE]; + name = templinearray[gradeCourse::CourseScheme::NAME]; + type = templinearray[gradeCourse::CourseScheme::TYPE]; - points = templinearray[gradeCourse::CourseScheme::POINTS].toDouble(); - hours = templinearray[gradeCourse::CourseScheme::HOURS].toDouble(); + points = templinearray[gradeCourse::CourseScheme::POINTS].toDouble(); + hours = templinearray[gradeCourse::CourseScheme::HOURS].toDouble(); - if (isGradedYet(templinearray[gradeCourse::CourseScheme::GRADE])) - grade = templinearray[gradeCourse::CourseScheme::GRADE].toDouble(); - else - grade = NO_GRADE_YET; + if (isGradedYet(templinearray[gradeCourse::CourseScheme::GRADE])) + grade = templinearray[gradeCourse::CourseScheme::GRADE].toDouble(); + else + grade = NO_GRADE_YET; - additions = templinearray[gradeCourse::CourseScheme::ADDITION]; + additions = templinearray[gradeCourse::CourseScheme::ADDITION]; - tempC = new gradeCourse(year,semester,courseNumInList,serial,name,type,points,hours,grade,additions); - return tempC; + if (year >= maxYear) + maxYear = year; + + if (year <= minYear) + minYear = year; + + tempC = new gradeCourse(year,semester,courseNumInList,serial,name,type,points,hours,grade,additions); + return tempC; } //checking if one of the chars inside grade is not a number bool GradePage::isGradedYet(QString grade) { - if (strlen(grade.toStdString().c_str()) <= 1) + if (strlen(grade.toStdString().c_str()) <= 1) + return false; + + for (char c: grade.toStdString()) + { + if (c == '\0') + break; + if (((!isdigit((int)c)) && (!isspace((int)c)))) //48 = 0, 57 = 9 return false; - for (char c: grade.toStdString()) - { - if (c == '\0') - break; - if (((!isdigit((int)c)) && (!isspace((int)c)))) //48 = 0, 57 = 9 - return false; - } - return true; + return true; } +/** + * @brief GradePage::getAvg getting avg + * @return - gpa avg of all courses + */ double GradePage::getAvg() { - double avg = 0; - double points = 0; - for(gradeCourse* c : *courses) + double avg = 0; + double points = 0; + for (gradeCourse* c : *courses) { - if ((c->getGrade() != 0)) + if ((c->getGrade() != 0)) { - avg += c->getGrade() * c->getPoints(); - points += c->getPoints(); + avg += c->getGrade() * c->getPoints(); + points += c->getPoints(); } } - avg /= points; - return avg; + avg /= points; + return avg; +} +/** + * @brief GradePage::getAvg getting avg of given year + * @param year - year (yyyy) + * @return - gpa avg of given year + */ +double GradePage::getAvg(int year) +{ + double avg = 0; + double points = 0; + for (gradeCourse* c : *courses) + { + if ((c->getGrade() != 0) && (c->getYear() == year)) + { + avg += c->getGrade() * c->getPoints(); + points += c->getPoints(); + } + } + if (points != 0) + avg /= points; + else + avg=0; + return avg; +} +/** + * @brief GradePage::getAvg + * @param year - year (yyyy) + * @param semester - semeser (1-3) + * @return -gpa avg of given year in given semester + */ +double GradePage::getAvg(int year, int semester) +{ + double avg = 0; + double points = 0; + for (gradeCourse* c : *courses) + { + if ((c->getGrade() != 0) && (c->getYear() == year) && (c->getSemester() == semester)) + { + avg += c->getGrade() * c->getPoints(); + points += c->getPoints(); + } + } + if (points != 0) + avg /= points; + else + avg=0; + return avg; +} +/** + * @brief GradePage::getMinYearInList + * @return the minimal year inside courses list + */ +int GradePage::getMinYearInList() +{ + return minYear; +} + +int GradePage::getMaxYearInList() +{ + return maxYear; } diff --git a/src/jceData/Grades/gradePage.h b/src/jceData/Grades/gradePage.h index ea4ee28..677c0e5 100644 --- a/src/jceData/Grades/gradePage.h +++ b/src/jceData/Grades/gradePage.h @@ -15,25 +15,32 @@ class GradePage : public Page { - + public: - GradePage(QString html); - ~GradePage(); + GradePage(QString html); + ~GradePage(); - void removeCourse(QString courseSerialID); - double getAvg(); + void removeCourse(QString courseSerialID); + double getAvg(); + double getAvg(int year); + double getAvg(int year, int semester); - std::list* getCourses() { return courses; } + int getMinYearInList(); + int getMaxYearInList(); + + + std::list* getCourses() { return courses; } private: - void coursesListInit(QString &linesTokinzedString); - gradeCourse* lineToCourse(QString line); + void coursesListInit(QString &linesTokinzedString); + gradeCourse* lineToCourse(QString line); - bool isGradedYet(QString grade); + bool isGradedYet(QString grade); - std::list* courses; - QString tempHtml; + std::list* courses; + + QString tempHtml; }; diff --git a/src/jceData/Grades/graph/gradegraph.cpp b/src/jceData/Grades/graph/gradegraph.cpp index f581cd3..b0d114b 100644 --- a/src/jceData/Grades/graph/gradegraph.cpp +++ b/src/jceData/Grades/graph/gradegraph.cpp @@ -2,14 +2,148 @@ #include "ui_gradegraph.h" gradegraph::gradegraph(QWidget *parent, GradePage *gpPTR) : - QDialog(parent), - ui(new Ui::gradegraph) + QDialog(parent), + ui(new Ui::gradegraph) { - ui->setupUi(this); - this->gp = gpPTR; + ui->setupUi(this); + this->gp = gpPTR; + +} + +void gradegraph::showGraph(GradePage *gpPTR) +{ + this->gp = gpPTR; + setVisualization(); + setGraphsData(); + this->show(); } gradegraph::~gradegraph() { - delete ui; + delete ui; +} + +void gradegraph::setGraphsData() +{ + int minYearInList = gp->getMinYearInList(); //2012 + int maxYearInList = gp->getMaxYearInList()+1; //2016 + int xRangeForYear = (maxYearInList - minYearInList+2)*3; //6*3=18 + QVector SemesterialAvg(xRangeForYear),yearlyAvg(xRangeForYear),sem(xRangeForYear); + + for (int yearCount=0,i=1; igetAvg(minYearInList+yearCount); + yearlyAvg[i] = lastAvg; + + // add the text label at the top: + QCPItemText *textLabel = new QCPItemText(ui->graphwidget); + ui->graphwidget->addItem(textLabel); + textLabel->position->setCoords(i, lastAvg+1.5); // place position at center/top of axis rect + textLabel->setText(QString::number(lastAvg,'g',4)); + textLabel->setFont(QFont(font().family(), 8)); // make font a bit larger + textLabel->setPen(QPen(Qt::black)); // show black border around text + yearCount++; + + } + else + { + if (i+4 < xRangeForYear) //semesters + { + double avg = gp->getAvg(minYearInList+yearCount,(i-1)%4); + SemesterialAvg[i+4] = avg; + // add the text label at the top: + + QCPItemText *textLabel = new QCPItemText(ui->graphwidget); + ui->graphwidget->addItem(textLabel); + textLabel->position->setCoords(i+4, avg+0.5); // place position at center/top of axis rect + textLabel->setText(QString::number(avg,'g',4)); + textLabel->setFont(QFont(font().family(), 8)); // make font a bit larger + textLabel->setPen(QPen(Qt::black)); // show black border around text + + + } + + yearlyAvg[i] = 0; + } + } + //yearly + ui->graphwidget->graph(0)->setData(sem,yearlyAvg); + //yearly + ui->graphwidget->graph(1)->setData(sem,SemesterialAvg); +} + +/** + * @brief gradegraph::setvisualization set graph borders text, range and looking + */ +void gradegraph::setVisualization() +{ + ui->graphwidget->axisRect()->setupFullAxesBox(true); //make the graph looks like a box + + ui->graphwidget->addGraph(); //yearly and semesterial graphs + ui->graphwidget->addGraph(); + + ui->graphwidget->graph(0)->setName(tr("Yearly Average")); + ui->graphwidget->graph(0)->setLineStyle(QCPGraph::lsLine); + ui->graphwidget->graph(0)->setPen(QPen(Qt::GlobalColor::blue)); + + ui->graphwidget->graph(1)->setName(tr("Semesterial Average")); + ui->graphwidget->graph(1)->setLineStyle(QCPGraph::lsLine); + ui->graphwidget->graph(1)->setPen(QPen( QColor(Qt::GlobalColor::red))); + + int minYearInList = gp->getMinYearInList(); + int maxYearInList = gp->getMaxYearInList()+1; + int xRangeForYear = (maxYearInList - minYearInList+2)*3; + + QVector xStrings(0); + for (int year=minYearInList,i = 0; i < xRangeForYear-1; ++i) + { + //set year x axe label to be yyyy A B C yyyy+1 A B C yyyy+2.... + int semesterChar = i%4; + QString tempString; + switch (semesterChar) + { + case 1: + tempString = tr("A"); + xStrings << tempString; + break; + case 2: + tempString = tr("B"); + xStrings << tempString; + break; + case 3: + tempString = tr("C"); + xStrings << tempString; + break; + case 0: + tempString = QString::number(year); + xStrings << tempString; + year++; + break; + + } + } + ui->graphwidget->yAxis->setLabel(tr("AVG Grade")); + ui->graphwidget->yAxis->setTickLabelFont(QFont(QFont().family(), 8)); + ui->graphwidget->yAxis->setRange(50,100); + ui->graphwidget->yAxis->setTickStep(2); + ui->graphwidget->yAxis->setAutoSubTicks(false); + ui->graphwidget->yAxis->setAutoTickStep(false); + ui->graphwidget->yAxis->setSubTickCount(5); + + + ui->graphwidget->xAxis->setLabel(tr("Years")); + ui->graphwidget->xAxis->setAutoTickLabels(false); + ui->graphwidget->xAxis->setTickVectorLabels(xStrings); + ui->graphwidget->xAxis->setTickLabelFont(QFont(QFont().family(), 7)); + ui->graphwidget->xAxis->setAutoTickStep(false); + ui->graphwidget->xAxis->setTickStep(1); + ui->graphwidget->xAxis->setAutoSubTicks(false); + ui->graphwidget->xAxis->setSubTickCount(1); + ui->graphwidget->xAxis->setRange(1,xRangeForYear); + + ui->graphwidget->legend->setVisible(true); //show graph name on top right } diff --git a/src/jceData/Grades/graph/gradegraph.h b/src/jceData/Grades/graph/gradegraph.h index 649c40e..97195ad 100644 --- a/src/jceData/Grades/graph/gradegraph.h +++ b/src/jceData/Grades/graph/gradegraph.h @@ -15,11 +15,15 @@ class gradegraph : public QDialog public: gradegraph(QWidget *parent = 0, GradePage *gpPTR = 0); + void showGraph(GradePage *gpPTR); ~gradegraph(); private: GradePage *gp; + + void setVisualization(); + void setGraphsData(); Ui::gradegraph *ui; }; diff --git a/src/jceData/Grades/graph/gradegraph.ui b/src/jceData/Grades/graph/gradegraph.ui index 75cf324..99691cc 100644 --- a/src/jceData/Grades/graph/gradegraph.ui +++ b/src/jceData/Grades/graph/gradegraph.ui @@ -6,14 +6,14 @@ 0 0 - 597 - 461 + 624 + 527 Dialog - + @@ -34,7 +34,16 @@ - + + + + 0 + 0 + + + + +