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

Re-adds percentages and fix powerschool changes #304

Merged
merged 17 commits into from
Oct 13, 2021
Merged
Show file tree
Hide file tree
Changes from 12 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
27 changes: 21 additions & 6 deletions src/js/components/CategoryWeighting.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,18 @@
:bgcolor="(index % 2 == 0) ? '#edf3fe' : '#fff'"
>
<td v-if="category.newc">
<input v-model="category.category" @change="changeCategory(index, category.category)">
<button @click="delCategory(index)">Delete</button>
<input
v-model="category.category"
@change="changeCategory(index, category.category)"
>
<button @click="delCategory(index)">
Delete
</button>
</td>
<td v-else v-html="category.category" />
<td
v-else
v-html="category.category"
/>
<td>
<input
v-model.number="category.weighting"
Expand All @@ -61,7 +69,10 @@
</tr>
</tbody>
</table>
<button style="margin-left: 20px" @click="addCategory();">
<button
style="margin-left: 20px"
@click="addCategory();"
>
Add Category
</button>
<label v-if="categorySum != 100">Category weightings do not sum to 100%</label>
Expand All @@ -71,8 +82,12 @@
>
Save Weighting
</button>
<h2 v-if="categorySum==100">{{ hypo.grade }} ({{ hypo.fp }})<br></h2>
<div v-if="categorySum!=100"><br></div>
<h2 v-if="categorySum==100">
{{ hypo.grade }} ({{ hypo.fp }})<br>
</h2>
<div v-if="categorySum!=100">
<br>
</div>
<p>Note: Since teachers can adjust the weighting of each assignment as well, this number is not necessarily accurate. In addition, early in the year some categories(i.e the exam category) may contain no grades and the percentages would need to be adjusted accordingly.</p>
</div>
</template>
Expand Down
12 changes: 6 additions & 6 deletions src/js/components/GradeRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
-->

<template>
<tr :bgcolor="(assignment.id % 2 == 0) ? '#edf3fe' : '#fff'">
<tr :bgcolor="assignment.id % 2 == 0 ? '#edf3fe' : '#fff'">
<td v-html="assignment.date" />
<td
v-if="!assignment.hypo"
Expand Down Expand Up @@ -60,14 +60,14 @@
alt="Missing"
>
</td>
<td width="14">
<td width="35">
<img
v-if="assignment.exempt"
src="/images/icon_exempt.gif"
alt="Exempt"
>
</td>
<td width="19">
<td width="35">
<img
v-if="assignment.excluded"
src="/images/icon_excluded.gif"
Expand Down Expand Up @@ -124,10 +124,10 @@
</tr>
</template>
<script>
import { avaliableGrades } from '../helpers';
import ClassAssignment from '../models/ClassAssignment';
import { avaliableGrades } from "../helpers";
import ClassAssignment from "../models/ClassAssignment";
export default {
name: 'GradeRow',
name: "GradeRow",
props: {
assignment: {
type: ClassAssignment,
Expand Down
24 changes: 18 additions & 6 deletions src/js/components/GradeTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,16 @@
<th class="center">
Grd
</th>
<th v-if="categoryWeighting">Exmp</th>
<th v-if="categoryWeighting">
Exmp
</th>
</tr>
<grade-row
v-for="assignment in assignments"
:key="assignment.id"
:assignment="assignment"
:categories="categories"
:categoryWeighting="categoryWeighting"
:category-weighting="categoryWeighting"
/>
<tr>
<td
Expand Down Expand Up @@ -87,7 +89,10 @@
</tr>
</tbody>
</table>
<button v-if="categoryWeighting" @click="addAssignment();">
<button
v-if="categoryWeighting"
@click="addAssignment();"
>
Add Assignment
</button>
</div>
Expand Down Expand Up @@ -133,20 +138,27 @@ export default {
}
let missing = 0;
for (var cat in catmap) {
if (grade[cat] == null) {
if (grade[cat] === null || grade[cat].every((element) => { return element === -1; })) {
console.log(cat);
if (catmap[cat].weighting !== "") {
missing += catmap[cat].weighting;
}
}
}
console.log(grade);
console.log(catmap);
let percent = 0;
for (cat in grade) {
let sum = 0;
let grade_count = 0;
for (i = 0; i < grade[cat].length; i++) {
sum += grade[cat][i];
if (grade[cat][i] !== -1) {
sum += grade[cat][i];
grade_count++;
}
}
if (catmap[cat].weighting !== "") {
percent += sum / grade[cat].length * catmap[cat].weighting;
percent += (sum / grade_count) * catmap[cat].weighting;
}
}
if (missing === 100) {
Expand Down
46 changes: 33 additions & 13 deletions src/js/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ function extractFinalPercent (html) {
let current_string = html.match(/(?=document\.write).*/g)[1];
current_string = /\[.*\]/g.exec(current_string)[0].slice(1, -1);
const temp = current_string.split(";");
number = Math.max(isNaN(temp[temp.length - 2]) ? -Infinity : parseFloat(temp[temp.length - 2]), isNaN(temp[temp.length - 1]) ? -Infinity : parseFloat(temp[temp.length - 1]));
number = Math.max(isNaN(temp[temp.length - 2]) || temp[temp.length - 2] ? parseFloat(temp[temp.length - 2]) : -Infinity, isNaN(temp[temp.length - 1]) || temp[temp.length - 1] ? parseFloat(temp[temp.length - 1]) : -Infinity);
} catch (e) {
return;
}
Expand All @@ -160,22 +160,41 @@ function extractFinalPercent (html) {
return number;
}

/**
* Extract the final percent from the course page html.
* @param {Number} frn course id used to get course percent
* @param {String} semester string representing semester that the request is for
* @returns {Number|undefined} The final percent
*/
async function getFinalPercent (frn, semester) {
let number;
try {
await fetch(`https://powerschool.sas.edu.sg/guardian/scores_ms_guardian.html?frn=${frn}&fg=${semester}`, { credentials: "same-origin" }).then(response => response.text()).then(response => {
const page = document.implementation.createHTMLDocument();
page.documentElement.innerHTML = response;
number = extractFinalPercent(page.querySelector('table.linkDescList').innerHTML);
});
} catch (e) {
return;
}
if (number === null) {
return;
}
return number;
}

/**
* Extract all grade categories from the course page html.
* @param {String} html course page html
* @param {Node} table node representing table
* @returns {String[]} List of all categories
*/
function extractGradeCategories (html) {
const cat = [];
let match;
html = html.replace(/(\r\n|\n|\r)/gm, "");
const reg = /(?:[0-9][0-9]\/[0-9][0-9]\/[0-9][0-9][0-9][0-9]<\/td> *<td>)(.+?(?=<\/td>))/g;
match = reg.exec(html);
while (match !== null) {
if (!cat.includes(match[1])) cat.push(match[1]);
match = reg.exec(html);
function extractGradeCategories (table) {
const table_rows = table.getElementsByTagName("tr");
const category_set = new Set();
for (let i = 1; i < table_rows.length - 1; i++) {
category_set.add(table_rows[i].getElementsByTagName("td")[1].getElementsByTagName("a")[0].innerText);
}
return cat;
return Array.from(category_set);
}

/**
Expand All @@ -187,7 +206,7 @@ function extractAssignmentList () {
const assignments = [];
[...table.querySelectorAll('tr')].slice(1, -1).forEach((e, i) => {
const curr = e.querySelectorAll('td');
assignments.push(new ClassAssignment(i, curr[0].innerHTML, curr[1].innerHTML, curr[2].innerHTML, isIndicatorPresent(curr[3]), isIndicatorPresent(curr[4]), isIndicatorPresent(curr[5]), isIndicatorPresent(curr[6]), isIndicatorPresent(curr[7]), curr[8].innerHTML, curr[10].innerHTML));
assignments.push(new ClassAssignment(i, curr[0].innerHTML, curr[1].innerText, curr[2].innerHTML, isIndicatorPresent(curr[3]), isIndicatorPresent(curr[4]), isIndicatorPresent(curr[5]), isIndicatorPresent(curr[6]), isIndicatorPresent(curr[7]), curr[9].innerHTML, curr[11].innerHTML));
});
return assignments;
}
Expand Down Expand Up @@ -344,6 +363,7 @@ export {
getSavedCategoryWeighting,
saveCategoryWeighting,
extractFinalPercent,
getFinalPercent,
extractGradeCategories,
extractAssignmentList,
assignments,
Expand Down
87 changes: 48 additions & 39 deletions src/js/saspowerschoolff.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const browser = require('webextension-polyfill');
import {
assignments,
calculate_gpa,
extractFinalPercent,
getFinalPercent,
extractGradeCategories,
gradeToGPA,
saveGradesLocally,
Expand Down Expand Up @@ -74,22 +74,21 @@ function main () {
});

const page_url = window.location.href.split('#')[0];
if (page_url === "https://powerschool.sas.edu.sg/guardian/homeHS.html") {
if (page_url === "https://powerschool.sas.edu.sg/guardian/home.html" || page_url === "https://powerschool.sas.edu.sg/guardian/homeHS.html") {
main_page();
} else if (page_url.match("https://powerschool.sas.edu.sg/guardian/scores") != null) {
class_page();
} else if (page_url === "https://powerschool.sas.edu.sg/guardian/home.html" || page_url === "https://powerschool.sas.edu.sg/public/" || page_url === "https://powerschool.sas.edu.sg/public/home.html") {
} else if (page_url === "https://powerschool.sas.edu.sg/public/" || page_url === "https://powerschool.sas.edu.sg/public/home.html") {
login_page();
}
}

function main_page () {
async function main_page () {
const student_name = getStudentName();
const { sem1_col, sem2_col } = getSemesterCols();
const second_semester = isSecondSemester(sem2_col);
const current_term = getCurrentTerm();
const { courses, promises_grade_calc_list } = getCourses(second_semester, sem1_col, sem2_col);

const { courses, promises_grade_calc_list } = await getCourses(second_semester, sem1_col, sem2_col);
showCurrentGPA(second_semester, courses, promises_grade_calc_list);

if (second_semester) {
Expand All @@ -110,18 +109,18 @@ function main_page () {
});
}

function class_page () {
async function class_page () {
// Show final percent
const number = extractFinalPercent($("table.linkDescList").html());
const currentUrl = new URL(document.location.href);
const number = await getFinalPercent(currentUrl.searchParams.get("frn"), currentUrl.searchParams.get("fg")) || "";
if (!number) {
return;
}
document.querySelector("table.linkDescList").append(html2node(`<tr><td><strong>Final Percent: </strong></td><td>` + number.toFixed(2) + ` <div class="tooltip saspes">&#9432;<span class="tooltiptext saspes">85: A+ | 75: A <br />65: B+ | 55: B <br />45: C+ | 35: C <br/>25: D+ | 15: D</span></div></td></tr>`));

addHypoAssignment(number);
addVueGrades();

document.querySelector('div.box-round').insertAdjacentHTML('afterend', `<select style="margin-left:20px; text-align-last: center; border-radius: 4px;" id='hypo-select'><option value='none'>Hypothetical Assigment Mode</option><option value='single'>Add Single Assignment</option><option value='category'>Category Weighting (beta)</option></select>`);
document.querySelector('div.box-round').insertAdjacentHTML('afterend', `<select style="margin-left:20px; text-align-last: center; border-radius: 4px;" id='hypo-select'><option value='none'>Hypothetical Assigment Mode</option><option value='single'>Add Single Assignment</option><option value='category'>Category Weighting (beta)</option></select><br><br>`);
gt.setCategoryWeighting(false);
document.getElementById('saspes-hypo-assignment').style.display = "none";
document.getElementById('saspes-categories').style.display = "none";
Expand Down Expand Up @@ -291,7 +290,7 @@ function getCurrentTerm () {
* @param sem2_col The column of the second semester
* @returns {Course[]} array of Course objects representing the Courses of the user
*/
function getCourses (second_semester, sem1_col, sem2_col) {
async function getCourses (second_semester, sem1_col, sem2_col) {
const $grade_rows = $('#quickLookup table.grid').find('tr');
const courses = [];
const promises_grade_calc_list = [];
Expand All @@ -300,48 +299,58 @@ function getCourses (second_semester, sem1_col, sem2_col) {
let $course;
if (second_semester) {
const $cells = $grade_rows.eq(i).find('td');
$course = $cells.eq(sem2_col).find('a[href^="scores.html"]');
const $first_grade = $cells.eq(sem1_col).find('a[href^="scores.html"]');
$course = $cells.eq(sem2_col).find('a[href*="scores.html"]');
const $first_grade = $cells.eq(sem1_col).find('a[href*="scores.html"]');
if ($first_grade.length === 1) {
if (gradeToGPA($first_grade.text()) !== -1) {
promises_grade_calc_list.push(new Promise((resolve, reject) => {
fetch(`https://powerschool.sas.edu.sg/guardian/${$first_grade.attr('href')}`, { credentials: "same-origin" }).then(response => response.text()).then(response => {
const page = document.implementation.createHTMLDocument();
page.documentElement.innerHTML = response;
const finalPercent = extractFinalPercent(page.querySelector('table.linkDescList').innerHTML) || "";
if (gradeToGPA($first_grade.text()) !== -1) {
new (Vue.extend(ClassGrade))({
propsData: {
course: new Course("", `https://powerschool.sas.edu.sg/guardian/${$first_grade.attr('href')}`, $first_grade.text(), finalPercent),
},
}).$mount($first_grade.get(0));
const currentUrlString = `https://powerschool.sas.edu.sg/guardian/${$first_grade.attr('href')}`;
const currentUrl = new URL(currentUrlString);
getFinalPercent(currentUrl.searchParams.get("frn"), currentUrl.searchParams.get("fg")).then(finalPercent => {
if (!finalPercent) {
finalPercent = "";
}
resolve("Success");
fetch(currentUrlString, { credentials: "same-origin" }).then(response => response.text()).then(response => {
if (gradeToGPA($first_grade.text()) !== -1) {
new (Vue.extend(ClassGrade))({
propsData: {
course: new Course("", currentUrlString, $first_grade.text(), finalPercent),
},
}).$mount($first_grade.get(0));
}
resolve("Success");
});
});
}));
}
}
} else {
$course = $grade_rows.eq(i).find('td a[href^="scores.html"]').eq(0);
$course = $grade_rows.eq(i).find('td a[href*="scores.html"]').eq(0);
}
if ($course.length === 1) {
const temp = $course.parents().eq(1).children("td[align=left]").text().match(".*(?=Details)")[0];
if (gradeToGPA($course.text()) !== -1) {
promises_grade_calc_list.push(new Promise((resolve, reject) => {
fetch(`https://powerschool.sas.edu.sg/guardian/${$course.attr('href')}`, { credentials: "same-origin" }).then(response => response.text()).then(response => {
const page = document.implementation.createHTMLDocument();
page.documentElement.innerHTML = response;
const finalPercent = extractFinalPercent(page.querySelector('table.linkDescList').innerHTML) || "";
const assignment_list = assignments(page.querySelector('body'));
courses.push(new Course(temp.trim(), `https://powerschool.sas.edu.sg/guardian/${$course.attr('href')}`, $course.text(), finalPercent, assignment_list));
if (gradeToGPA($course.text()) !== -1) {
new (Vue.extend(ClassGrade))({
propsData: {
course: courses[courses.length - 1],
},
}).$mount($course.get(0));
const currentUrlString = `https://powerschool.sas.edu.sg/guardian/${$course.attr('href')}`;
const currentUrl = new URL(currentUrlString);
getFinalPercent(currentUrl.searchParams.get("frn"), currentUrl.searchParams.get("fg")).then(finalPercent => {
if (!finalPercent) {
finalPercent = "";
}
resolve("Success");
fetch(currentUrlString, { credentials: "same-origin" }).then(response => response.text()).then(response => {
const page = document.implementation.createHTMLDocument();
page.documentElement.innerHTML = response;
const assignment_list = assignments(page.querySelector('body'));
courses.push(new Course(temp.trim(), currentUrlString, $course.text(), finalPercent, assignment_list));
if (gradeToGPA($course.text()) !== -1) {
new (Vue.extend(ClassGrade))({
propsData: {
course: courses[courses.length - 1],
},
}).$mount($course.get(0));
}
resolve("Success");
});
});
}));
}
Expand Down Expand Up @@ -416,7 +425,7 @@ function addHypoGradeCalc (courses) {
*/
function addVueGrades () {
const assignments = extractAssignmentList();
const cat = extractGradeCategories(document.querySelector("#content-main > div.box-round > table:nth-child(4) > tbody").innerHTML);
const cat = extractGradeCategories(document.querySelector("#content-main > div.box-round > table:nth-child(4) > tbody"));
gt = new (Vue.extend(GradeTable))({ // remake grade table to easily read grades
propsData: {
categories: cat,
Expand Down