Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding documentation #128

Merged
merged 5 commits into from
Nov 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions public/js/buttonFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,12 @@ let exportTableData = async function(prefs) {
}), filename);
};

/**
* Imports a JSON file and adds the data as a TableDataObject to the
*
* @param {object} obj - Data loaded from json file
* @returns {Promise<string>}
*/
let importTableData = async function(obj) {

//#ifndef lite
Expand Down
33 changes: 25 additions & 8 deletions public/js/calculate_grade.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
/**
*
* @param {Object[]} assignments
* @param {Object} categories
* @param decimals
* @param init_grade
* @param {string} grade
* @returns {string|{categoryScores: {}, categoryPercent: string, categoryGrades: {}, totalPercent: string, categoryMaxScores: {}}}
*/

function computeGrade(assignments, categories, decimals, init_grade, grade) {
let categoryScores = {}, categoryMaxScores = {}, categoryGrades = {};
for (let category in categories) {
Expand All @@ -8,13 +18,13 @@ function computeGrade(assignments, categories, decimals, init_grade, grade) {

let totalScore = 0, totalMaxScore = 0;
if (Object.keys(categories).length === 0) {
for (let j = 0; j < assignments.length; j++) {
totalScore += parseFloat(assignments[j].score);
totalMaxScore += parseFloat(assignments[j].max_score);
for (let assignment of assignments) {
totalScore += parseFloat(assignment.score);
totalMaxScore += parseFloat(assignment.max_score);
}

let totalPercent = totalScore / totalMaxScore;
return "" + (Math.round(totalPercent * 10000) / 100);
return (Math.round(totalPercent * 10000) / 100).toString();
} else {
for (let i = 0; i < assignments.length; i++) {
if (!isNaN(assignments[i].score)) {
Expand All @@ -34,25 +44,32 @@ function computeGrade(assignments, categories, decimals, init_grade, grade) {
categoryGrades[category] = "N/A";
} else {
categoryGrades[category] = (0.0 + categoryScores[category]) / categoryMaxScores[category];
categoryPercent += ((0.0 + categoryScores[category]) / categoryMaxScores[category]) * parseFloat(categories[category]);
categoryPercent += (0.0 + categoryScores[category]) / categoryMaxScores[category] * parseFloat(categories[category]);
}
}

categoryPercent /= counterWeight;

let totalPercent = totalScore / totalMaxScore;
let output = (parseFloat(grade)/100) + categoryPercent - parseFloat(init_grade);
let output = parseFloat(grade)/100 + categoryPercent - parseFloat(init_grade);

return {
categoryPercent: "" + (Math.round(output * Math.pow(10, decimals + 2)) / Math.pow(10, decimals)),
totalPercent: "" + (Math.round(totalPercent * Math.pow(10, decimals + 2)) / Math.pow(10, decimals)),
categoryPercent: (Math.round(output * Math.pow(10, decimals + 2)) / Math.pow(10, decimals)).toString(),
totalPercent: (Math.round(totalPercent * Math.pow(10, decimals + 2)) / Math.pow(10, decimals)).toString(),
categoryScores,
categoryMaxScores,
categoryGrades,
};
}
}

/**
*
* @param assignments
* @param categories
* @param currentGrade
* @returns {string|{categoryScores: {}, categoryGrades: {}, categoryPercent: number, type: string, categoryMaxScores: {}}}
*/
function determineGradeType(assignments, categories, currentGrade) {
let categoryScores = {}, categoryMaxScores = {}, categoryGrades = {};
for (let category in categories) {
Expand Down
165 changes: 98 additions & 67 deletions public/js/home.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// State

const termConverter = ['current', 'q1', 'q2', 'q3', 'q4'];
let pdf_index = 0;
let pdfrendering = false;
Expand All @@ -13,8 +15,23 @@ let exportModal = document.getElementById('export_modal');
let importModal = document.getElementById('import_modal');
let term_dropdown_active = true;
let currentTerm = "current";
/**
* All the data provided by Aspine API
* @typedef TableDataObject
* @property {GPA} [cumGPA]
* @property {Term} [currentTermData]
* @property {string} [name]
* @property {Overview[]} [overview]
* @property {RecentActivity} [recent]
* @property {Schedule} [schedule]
* @property {Terms} [terms]
* @property {?string} [username]
* @property {boolean} [imported=true]
*/
/** @type {TableDataObject[]}*/
let tableData = [{ name: "Current Year" }];
let currentTableDataIndex = 0;
/**@type {TableDataObject}*/
let currentTableData = tableData[currentTableDataIndex];
let selected_class_i;
let termsReset = {};
Expand Down Expand Up @@ -79,15 +96,29 @@ let noStats = function() {
document.getElementById("stats_modal_content").style.height = "5rem";
};

/**
* Hide a modal window
* @param {string} key Name of modal window.
*/
let hideModal = function(key) {
modals[key].style.display = "none";
if (key === "stats") noStats();

if (key === "corrections") {
document.getElementById("corrections_modal_input").value = "";
switch (key)
{
case 'stats':
noStats();
break;
case 'corrections':
document.getElementById("corrections_modal_input").value = "";
break;
default:
console.error(`${key} is not a valid modal name`)
}
}

/**
* Un-hide a modal window
* @param {string} key Name of modal window.
*/
let showModal = function(key) {
modals[key].style.display = "inline-block";
}
Expand All @@ -105,14 +136,14 @@ let recentAttendance = new Tabulator("#recentAttendance", {

let recentActivity = new Tabulator("#recentActivity", {
// height: 400,
layout:"fitColumns",
layout: "fitColumns",
columns: [
{title:"Date", field:"date", formatter: rowFormatter},
{title:"Class", field:"classname", formatter: classFormatter},
{title:"Assignment", field:"assignment", formatter: rowFormatter, headerSort: false},
{title:"Score", field:"score", formatter: rowFormatter, headerSort: false},
{title:"Max Score", field:"max_score", formatter: rowFormatter, headerSort: false},
{title:"Percentage", field:"percentage", formatter: rowGradeFormatter},
{title: "Date", field: "date", formatter: rowFormatter},
{title: "Class", field: "classname", formatter: classFormatter},
{title: "Assignment", field: "assignment", formatter: rowFormatter, headerSort: false},
{title: "Score", field: "score", formatter: rowFormatter, headerSort: false},
{title: "Max Score", field: "max_score", formatter: rowFormatter, headerSort: false},
{title: "Percentage", field: "percentage", formatter: rowGradeFormatter},
],
rowClick: function(e, row) { //trigger an alert message when the row is clicked
// questionable
Expand Down Expand Up @@ -160,11 +191,11 @@ let categoriesTable = new Tabulator("#categoriesTable", {
layout: "fitColumns",
layoutColumnsOnNewData: true,
columns: [
{title:"Category", field:"category", formatter: rowFormatter, headerSort: false},
{title:"Weight", field:"weight", formatter:weightFormatter, headerSort: false},
{title:"Score", field:"score", formatter: rowFormatter, headerSort: false},
{title:"Max Score", field:"maxScore", formatter: rowFormatter, headerSort: false},
{title:"Percentage", field:"grade", formatter: rowGradeFormatter, headerSort:false},
{title: "Category", field: "category", formatter: rowFormatter, headerSort: false},
{title: "Weight", field: "weight", formatter: weightFormatter, headerSort: false},
{title: "Score", field: "score", formatter: rowFormatter, headerSort: false},
{title: "Max Score", field: "maxScore", formatter: rowFormatter, headerSort: false},
{title: "Percentage", field: "grade", formatter: rowGradeFormatter, headerSort: false},
//filler column to match the assignments table
//{title: "", width:1, align:"center", headerSort: false},
{
Expand All @@ -181,7 +212,7 @@ let categoriesTable = new Tabulator("#categoriesTable", {
if (currentFilterRow !== row.getPosition()) {
currentFilterRow = row.getPosition();
assignmentsTable.addFilter([
{field: "category", type:"=", value: row.getData().category}
{field: "category", type: "=", value: row.getData().category}
]);
}
else {
Expand All @@ -192,15 +223,15 @@ let categoriesTable = new Tabulator("#categoriesTable", {

let mostRecentTable = new Tabulator("#mostRecentTable", {
// height: 400,
layout:"fitColumns",
layout: "fitColumns",
columns: [
//{title:"Date", field:"date", formatter: rowFormatter, headerSort: false},
{title:"Date", field:"date", formatter: rowFormatter},
{title:"Class", field:"classname", formatter: classFormatter},
{title:"Assignment", field:"assignment", formatter: rowFormatter, headerSort: false},
{title:"Score", field:"score", formatter: rowFormatter, headerSort: false},
{title:"Max Score", field:"max_score", formatter: rowFormatter, headerSort: false},
{title:"Percentage", field:"percentage", formatter: rowGradeFormatter},
{title: "Date", field: "date", formatter: rowFormatter},
{title: "Class", field: "classname", formatter: classFormatter},
{title: "Assignment", field: "assignment", formatter: rowFormatter, headerSort: false},
{title: "Score", field: "score", formatter: rowFormatter, headerSort: false},
{title: "Max Score", field: "max_score", formatter: rowFormatter, headerSort: false},
{title: "Percentage", field: "percentage", formatter: rowGradeFormatter},
],
rowClick: function(e, row) { //trigger an alert message when the row is clicked
$("#mostRecentDiv").hide();
Expand Down Expand Up @@ -259,28 +290,12 @@ let assignmentsTable = new Tabulator("#assignmentsTable", {
{
title: "Category",
field: "category",
editor:"select",
editor: "select",
editorParams: function(cell) {
let catCategories = [];

for (
let k = 0;
k < Object.keys(
currentTableData.currentTermData.classes[selected_class_i].categories
).length;
k++
) {
catCategories.push((
Object.keys(
currentTableData.currentTermData.classes[selected_class_i].categories
)[k] + " (" +
(
Object.values(
currentTableData.currentTermData.classes[selected_class_i].categories
)[k] * 100
) + "%)"
));
}
for (let category of Object.keys(currentTableData.currentTermData.classes[selected_class_i].categories))
catCategories.push(`${category} (${category * 100}%)`);
return {values: catCategories};
},
formatter: rowFormatter,
Expand Down Expand Up @@ -620,9 +635,8 @@ let classesTable = new Tabulator("#classesTable", {
.removeAttr("aria-label")
.removeAttr("tabindex")
.removeClass("hastooltip");
}
else {
$(`#export_checkbox_terms_${term}`) .attr("disabled", true);
} else {
$(`#export_checkbox_terms_${term}`).attr("disabled", true);
$(`#export_checkbox_terms_${term} ~ span`)
.attr("aria-label", isAccessibleObj.reason)
.attr("tabindex", 0)
Expand All @@ -647,7 +661,7 @@ let classesTable = new Tabulator("#classesTable", {

assignmentsTable.clearFilter();
currentFilterRow = -1;

document.getElementById("categoriesTable").style.display = "block";
document.getElementById("assignmentsTable").style.display = "block";
selected_class_i = row.getPosition();
Expand Down Expand Up @@ -693,18 +707,39 @@ $("#corrections_modal_input").keypress(({ which }) => {
correct();
}
});

/*
* Callback for response from /data
/**
* @typedef {object} Classes
* @param {string} name
* @param {string} grade
* @param {object} categories
* @param {object[]} assignments
* @param {object} tokens
*
* @typedef {object} RecentActivity
* @param {RecentAttendance[]} recentAttendanceArray
* @param {RecentAssignments[]} recentActivityArray
* @param {string} studentName
*
* @typedef {object} scrapedStudent
* @param {Classes[]} response.classes
* @param {RecentActivity} response.recent
* @param {Overview[]} response.overview
* @param {string} response.username
* @param {string} response.quarter
*
* @typedef {object} noLogin response object on no login
* @oaram {boolean} noLogin.nologin - parameter present on login fail
*/
/** Callback for response from /data
*
* includedTerms is an optional parameter which contains the terms
* included in an import (in the case that currentTableData is imported
* and not all of the terms' data have been put into currentTableData)
* @param {noLogin|scrapedStudent} response
* @param {(scrapedStudent|string)} includedTerms - optional parameter which contains the terms included in an import (in the case that
* currentTableData is imported and not all of the terms' data have been put into currentTableData)
*/
function responseCallback(response, includedTerms) {
// console.log(response);
if (response.nologin) {
tableData = [];
tableData = []; // TODO: dont manipulate global state here, return values
currentTableData = undefined;
currentTableDataIndex = -1;

Expand All @@ -715,7 +750,7 @@ function responseCallback(response, includedTerms) {
return;
}
if (response.recent.login_fail) {
location.href='/logout';
location.href = '/logout';
}

if (response.classes.length === 0) {
Expand Down Expand Up @@ -764,7 +799,7 @@ function responseCallback(response, includedTerms) {

$("#loader").hide();

//parsing the data extracted by the scrappers, and getting tableData ready for presentation
//parsing the data extracted by the scrapers, and getting tableData ready for presentation
if (typeof currentTableData.terms === 'undefined') {
currentTableData.terms = {
current: {},
Expand Down Expand Up @@ -818,9 +853,8 @@ function responseCallback(response, includedTerms) {
currentTableData.recent.recentActivityArray[i].max_score = currentTableData.currentTermData.classes[temp_classIndex].assignments[assignmentIndex].max_score;
currentTableData.recent.recentActivityArray[i].percentage = currentTableData.currentTermData.classes[temp_classIndex].assignments[assignmentIndex].percentage;
currentTableData.recent.recentActivityArray[i].color = currentTableData.currentTermData.classes[temp_classIndex].assignments[assignmentIndex].color;
}
catch(err) {
console.log("Please report this error on the Aspine github issue pages. ID Number 101. Error: " + err);
} catch (err) {
console.error("Please report this error on the Aspine github issue pages. ID Number 101. Error: " + err);
}
}

Expand All @@ -837,9 +871,9 @@ function responseCallback(response, includedTerms) {
}
document.getElementById("cum_gpa").innerHTML = "Cumulative GPA: " + currentTableData.cumGPA.percent.toFixed(2);

// Calculate for each quarter
// Calculate GPA for each quarter
for (let i = 1; i <= 4; i++) {
currentTableData.terms["q" + i].GPA = computeGPAQuarter(currentTableData.overview,i);
currentTableData.terms["q" + i].GPA = computeGPAQuarter(currentTableData.overview, i);
}

//Stuff to do now that tableData is initialized
Expand Down Expand Up @@ -1047,8 +1081,7 @@ function openTab(evt, tab_name) {
dataType: "json json",
success: pdfCallback
});
}
else if (typeof currentTableData.pdf_files !== 'undefined') {
} else if (typeof currentTableData.pdf_files !== 'undefined') {
generate_pdf(pdf_index);
}
// Redraw PDF to fit new viewport dimensions when transitioning
Expand All @@ -1060,11 +1093,9 @@ function openTab(evt, tab_name) {
};
if (elem.onfullscreenchange !== undefined) {
elem.onfullscreenchange = handlefullscreenchange;
}
else if (elem.mozonfullscreenchange !== undefined) { // Firefox
} else if (elem.mozonfullscreenchange !== undefined) { // Firefox
elem.mozonfullscreenchange = handlefullscreenchange;
}
else if (elem.MSonfullscreenchange !== undefined) { // Internet Explorer
} else if (elem.MSonfullscreenchange !== undefined) { // Internet Explorer
elem.MSonfullscreenchange = handlefullscreenchange;
}
}
Expand Down
Loading