Remove grade-calc
This commit is contained in:
parent
389d4611e5
commit
9ca3e18dd4
@ -1,199 +0,0 @@
|
||||
import React, { ReactElement } from 'react';
|
||||
|
||||
export default class GradeCalc {
|
||||
maxscore = 0;
|
||||
sections: Array<ReactElement> = [];
|
||||
inputSection: Array<ReactElement[]> = [[]];
|
||||
outputSection: Array<ReactElement> = [];
|
||||
fields: Array<ReactElement[]> = [];
|
||||
grades: number[] = [];
|
||||
ugrades: number[] = [];
|
||||
both = false;
|
||||
totalOutput: ReactElement;
|
||||
config: any[];
|
||||
|
||||
constructor(config: {title: string, percentage: number}, outCallback: (arg: Array<ReactElement>) => void) {
|
||||
this.totalOutput = React.createElement('div');
|
||||
let dConfig = JSON.parse(JSON.stringify(config)); // dirty clone
|
||||
let sanConfig = [];
|
||||
for (let conf of dConfig) {
|
||||
if (conf.percentage === undefined || conf.name === undefined)
|
||||
continue;
|
||||
if (conf.title === undefined)
|
||||
conf.title = conf.name[0].toUpperCase() + conf.name.slice(1);
|
||||
sanConfig.push(conf);
|
||||
}
|
||||
this.config = sanConfig;
|
||||
for (let [i, conf] of this.config.entries()) {
|
||||
this.maxscore += conf.percentage;
|
||||
|
||||
this.inputSection[i] = [];
|
||||
this.outputSection[i] = React.createElement('div');
|
||||
|
||||
if (conf.bothMethods) {
|
||||
this.both = true;
|
||||
}
|
||||
|
||||
this.sections[i] = (this.createSection(i));
|
||||
}
|
||||
|
||||
// for (let [k, v] of this.fields.entries()) {
|
||||
// for (let field of v) {
|
||||
// this.addInputEventListener(k, field);
|
||||
// }
|
||||
// }
|
||||
|
||||
outCallback(this.sections);
|
||||
}
|
||||
|
||||
createSection(id: number): ReactElement {
|
||||
|
||||
const conf = this.config[id];
|
||||
|
||||
const heading = React.createElement('h2', {}, `${conf.title} (${conf.percentage}%)`);
|
||||
|
||||
let info = null
|
||||
if (conf.info !== undefined)
|
||||
info = (React.createElement('div', {}, conf.info));
|
||||
|
||||
|
||||
this.fields[id] = [];
|
||||
let inputSection: Array<ReactElement> | ReactElement = [];
|
||||
if (conf.points !== undefined) {
|
||||
for (let i = 0; i < conf.points.length; i++) {
|
||||
inputSection[i] = this.createInputSection(id, i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
inputSection = this.createInputSection(id, 0, true);
|
||||
}
|
||||
|
||||
const section = React.createElement('div', {className: conf.name}, heading, info, inputSection,
|
||||
// this.outputSection[id]
|
||||
);
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
createInputSection(sectId: number, inputId: number, soleInput: boolean = false): ReactElement {
|
||||
const conf = this.config[sectId];
|
||||
|
||||
let label = '';
|
||||
if (soleInput)
|
||||
label = `${conf.title} Score: `;
|
||||
else
|
||||
label = `${conf.title} ${inputId + 1} Score: `;
|
||||
|
||||
const field = React.createElement('input', {
|
||||
className: `input ${conf.name}-score`,
|
||||
onKeyUp: () => {
|
||||
if (conf.output !== undefined && conf.output)
|
||||
this.showSectionGrade(inputId);
|
||||
this.showTotalGrade();
|
||||
}
|
||||
});
|
||||
|
||||
this.fields[sectId][inputId] = field;
|
||||
let suffix = (soleInput) ? '%' : ` / ${conf.points[inputId]} pts`;
|
||||
|
||||
const inputSection = React.createElement('div', {className: 'input-section'}, label, field, suffix);
|
||||
|
||||
this.inputSection[sectId][inputId] = inputSection;
|
||||
return inputSection;
|
||||
}
|
||||
|
||||
calculateSectionGrade(id: number, unweighted = false): number {
|
||||
// let conf = this.config[id];
|
||||
// let fields = this.fields[id];
|
||||
// if (fields === undefined)
|
||||
// return 0;
|
||||
// if (conf.points === undefined) {
|
||||
// return parseFloat(fields[0].value);
|
||||
// }
|
||||
|
||||
// let total = 0;
|
||||
|
||||
// if (unweighted) {
|
||||
// let counter = 0;
|
||||
// for (let [i, field] of fields.entries()) {
|
||||
// let val = parseFloat(field.value);
|
||||
// if (isNaN(val))
|
||||
// continue;
|
||||
// total += val / conf.points[i];
|
||||
// counter++;
|
||||
// }
|
||||
|
||||
// return (total / counter * 100);
|
||||
// }
|
||||
|
||||
// total = fields.reduce((acc, cur) => {
|
||||
// const c = parseFloat(cur.value);
|
||||
|
||||
// return isNaN(c) ? acc : acc + c;
|
||||
// }, 0);
|
||||
|
||||
// let max_total = 0;
|
||||
// for (const [i, field] of conf.points.entries()) {
|
||||
// if (isNaN(parseFloat(fields[i].value)))
|
||||
// continue;
|
||||
// max_total += field;
|
||||
// }
|
||||
|
||||
// return (total / max_total * 100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
showSectionGrade(id: number) {
|
||||
let conf = this.config[id];
|
||||
let grade = this.calculateSectionGrade(id);
|
||||
let ugrade = this.calculateSectionGrade(id, true);
|
||||
|
||||
|
||||
this.grades[id] = grade * parseFloat(conf.percentage) / 100;
|
||||
this.ugrades[id] = ugrade * parseFloat(conf.percentage) / 100;
|
||||
|
||||
const outGrade = !isNaN(grade) ? grade.toFixed(2) : "...";
|
||||
const outUgrade = !isNaN(ugrade) ? ugrade.toFixed(2) : "...";
|
||||
if (conf.bothMethods) {
|
||||
this.outputSection[id].props.children
|
||||
= `Score (weighted): ${outGrade}%<br> Score (unweighted): ${outUgrade}%`;
|
||||
return;
|
||||
}
|
||||
|
||||
this.outputSection[id].props.value = `Score: ${grade}`;
|
||||
}
|
||||
|
||||
showTotalGrade() {
|
||||
for (let [k, conf] of this.config.entries()) {
|
||||
if (!conf.output) {
|
||||
this.grades[k] = this.calculateSectionGrade(k) * parseFloat(conf.percentage) / 100;
|
||||
this.ugrades[k] = this.calculateSectionGrade(k, true) * parseFloat(conf.percentage) / 100;
|
||||
}
|
||||
}
|
||||
|
||||
let grade: number = this.grades.reduce((a, c) => {
|
||||
if (isNaN(c))
|
||||
return a;
|
||||
return a + c
|
||||
}, 0);
|
||||
let ugrade: number = this.ugrades.reduce((a, c) => {
|
||||
if (isNaN(c))
|
||||
return a;
|
||||
return a + c
|
||||
}, 0);
|
||||
|
||||
const outGrade = !isNaN(grade) ? grade.toFixed(2) : "...";
|
||||
const outUgrade = !isNaN(ugrade) ? ugrade.toFixed(2) : "...";
|
||||
if (this.both) {
|
||||
// this.totalOutput.props.children
|
||||
// = `Total Score (weighted): ${outGrade}%<br> Total Score (unweighted): ${outUgrade}%`;
|
||||
return;
|
||||
}
|
||||
|
||||
// this.totalOutput.props.children = `Total Score: ${outGrade}%`;
|
||||
}
|
||||
|
||||
get elemTotal() {
|
||||
return this.totalOutput;
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
import React, { ReactElement, useEffect, useState } from 'react';
|
||||
import Layout from '../../components/layout';
|
||||
import Link from 'next/link';
|
||||
import GradeCalc from '../../components/_gc';
|
||||
|
||||
function GradeCalcPage() {
|
||||
const [calculator, setCalculator] = useState<any>();
|
||||
let [jsonInput, setJsonInput] = useState('[]');
|
||||
|
||||
function loadConfig(filename: string): void {
|
||||
const client = new XMLHttpRequest();
|
||||
client.open('GET', filename);
|
||||
client.onreadystatechange = () => {
|
||||
setJsonInput(client.responseText);
|
||||
}
|
||||
client.send();
|
||||
}
|
||||
|
||||
function generate() {
|
||||
setCalculator('');
|
||||
let conf = null;
|
||||
try {
|
||||
conf = JSON.parse(jsonInput);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
return;
|
||||
}
|
||||
let cb = (out: ReactElement[]) => {
|
||||
setCalculator([... calculator, out]);
|
||||
}
|
||||
const gc = new GradeCalc(conf, cb);
|
||||
if (calculator)
|
||||
setCalculator([... calculator, React.createElement('div', {className: 'asf'}, gc.elemTotal)]);
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout name="Grade Calc" title='Grade Calculator'>
|
||||
<div className='block'>
|
||||
<div className='about-container'>
|
||||
<h2>About</h2>
|
||||
Check out the <Link href='/grade-calc/readme'><a >README.md</a></Link> file
|
||||
to learn more about the configuration structure.
|
||||
<h3>Usage</h3>
|
||||
<ol>
|
||||
<li>Either configure the calculator using the text box below or load one from the existing JSON files to
|
||||
generate one.</li>
|
||||
<li>Click <code>Generate</code>.</li>
|
||||
<li>Enter the input values.</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div className='json-textarea'>
|
||||
<h2>Configuration</h2>
|
||||
<hr />
|
||||
<h3>Load config from file</h3>
|
||||
<ul>
|
||||
<li><a onClick={() => loadConfig('/grade-calc/config/map2302.json')}>MAP2302 - ODE I Fall 2019 (map2302.json)</a></li>
|
||||
<li><a onClick={() => loadConfig('/grade-calc/config/eee3307c.json')}>EEE3307C - Electronics I Spring 2021 (eee3307c.json)</a></li>
|
||||
<li><a onClick={() => loadConfig('/grade-calc/config/eel4742c.json')}>EEL4742C - Embedded Systems Spring 2021 (eel4742c.json)</a></li>
|
||||
<li><a onClick={() => loadConfig('/grade-calc/config/eel4781.json')}>EEL4781 - Computer Comm. Networks Spring 2021 (eel4781.json)</a></li>
|
||||
</ul>
|
||||
<div className='button-container'>
|
||||
<button className='button' onClick={generate}>Generate →</button>
|
||||
</div>
|
||||
<textarea id='json' rows={30} value={jsonInput} onChange={(t) => {setJsonInput(t.currentTarget.value)}}></textarea>
|
||||
|
||||
</div>
|
||||
<div className='calculator-container'>
|
||||
{calculator}
|
||||
</div>
|
||||
<span className='clear'></span>
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
// export default GradeCalcPage;
|
||||
|
||||
export default function WIP() {
|
||||
useEffect(() => {
|
||||
const script = document.createElement('script');
|
||||
|
||||
script.src = '/grade-calc/vanilla.js';
|
||||
script.async = true;
|
||||
|
||||
document.body.appendChild(script);
|
||||
|
||||
return () => {
|
||||
document.body.removeChild(script);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Layout name='Grade Calc' title='[WIP] Grade Calculator'>
|
||||
<section className='grade-calc'>
|
||||
Check back later as the port of this page is a Work in Progress.
|
||||
</section>
|
||||
</Layout>);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import Layout from '../../components/layout';
|
||||
|
||||
// @ts-ignore
|
||||
import ReadmeMd from '../../public/grade-calc/README.md';
|
||||
|
||||
|
||||
function GCReadme() {
|
||||
return (<Layout name="Read Me" ancestors={[{name:'Grade Calc', path: 'grade-calc'}]}>
|
||||
<section className='block'>
|
||||
<ReactMarkdown>{ReadmeMd}</ReactMarkdown>
|
||||
</section>
|
||||
</Layout>);
|
||||
}
|
||||
|
||||
export default GCReadme;
|
@ -1,23 +0,0 @@
|
||||
# Grade Calculator
|
||||
|
||||
Some professors do not properly configure the Canvas grade percentages based on their syllabus. Instead, they opt to use Excel to calculate the final grades after everything. It can be hard to estimate how much effort I should allocate for those classes without making an Excel file.
|
||||
|
||||
So I wrote this to quickly configure a calculator to see what I will end up getting in a class based on how much effort I put in.
|
||||
|
||||
## Short Summary of the JSON structure
|
||||
|
||||
The JSON is expected to have an array of section descriptions.
|
||||
|
||||
`name : string` is used as the class name. They have to be unique for each section to work as expected.
|
||||
|
||||
`title : string` is used as the heading for the sections.
|
||||
|
||||
`percentage : number` is used to weigh the section for the final grade.
|
||||
|
||||
`output : boolean` when true, it calculates the section score.
|
||||
|
||||
`points : [number]` used for each assignment in the section.
|
||||
|
||||
`bothMethods : boolean` when true, the weighted and unweighted scores are calculated.
|
||||
|
||||
`info : string` used for section description.
|
@ -1,25 +0,0 @@
|
||||
[
|
||||
{
|
||||
"name": "final",
|
||||
"title": "Final",
|
||||
"percentage": 40,
|
||||
"info": ""
|
||||
},
|
||||
{
|
||||
"name": "midterm",
|
||||
"title": "Midterm",
|
||||
"percentage": 30
|
||||
},
|
||||
{
|
||||
"name": "homework",
|
||||
"title": "Homework",
|
||||
"percentage": 10,
|
||||
"points": [100,100,100,100,100,100]
|
||||
},
|
||||
{
|
||||
"name": "lab",
|
||||
"title": "Lab",
|
||||
"percentage": 20,
|
||||
"info": "Lab score is accurate and does not need any sub-calculation."
|
||||
}
|
||||
]
|
@ -1,29 +0,0 @@
|
||||
[
|
||||
{
|
||||
"name": "exams",
|
||||
"percentage": 70,
|
||||
"points": [
|
||||
100,
|
||||
100,
|
||||
100
|
||||
],
|
||||
"title": "Exams"
|
||||
},
|
||||
{
|
||||
"name": "homework",
|
||||
"percentage": 15,
|
||||
"points": [
|
||||
90,
|
||||
50,
|
||||
110,
|
||||
90
|
||||
],
|
||||
"title": "Homework"
|
||||
},
|
||||
{
|
||||
"info": "Lab score is accurate and does not need any sub-calculation.",
|
||||
"name": "lab",
|
||||
"percentage": 15,
|
||||
"title": "Lab"
|
||||
}
|
||||
]
|
@ -1,35 +0,0 @@
|
||||
[
|
||||
{
|
||||
"name": "midterm",
|
||||
"percentage": 25,
|
||||
"info":"http://www.ece.ucf.edu/~yuksem/teaching/EEL-4781-Spring-2021.html"
|
||||
},
|
||||
{
|
||||
"name": "final",
|
||||
"percentage": 25
|
||||
},
|
||||
{
|
||||
"name": "project",
|
||||
"percentage": 15,
|
||||
"info":"Webserver project"
|
||||
},
|
||||
{
|
||||
"name": "homework",
|
||||
"percentage": 20,
|
||||
"points": [
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
100
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "lab",
|
||||
"percentage": 15,
|
||||
"points": [
|
||||
100,
|
||||
100
|
||||
]
|
||||
}
|
||||
]
|
@ -1,41 +0,0 @@
|
||||
[
|
||||
{
|
||||
"name": "final",
|
||||
"title": "Final",
|
||||
"percentage": 25,
|
||||
"info": ""
|
||||
},
|
||||
{
|
||||
"name": "midterm",
|
||||
"title": "Midterm",
|
||||
"percentage": 50,
|
||||
"points": [
|
||||
20,
|
||||
20,
|
||||
20
|
||||
],
|
||||
"output": true
|
||||
},
|
||||
{
|
||||
"name": "quiz",
|
||||
"title": "Quiz",
|
||||
"percentage": 10,
|
||||
"points": [
|
||||
30,
|
||||
10,
|
||||
15
|
||||
],
|
||||
"output": true,
|
||||
"bothMethods": true
|
||||
},
|
||||
{
|
||||
"name": "homework",
|
||||
"title": "Homework",
|
||||
"percentage": 10
|
||||
},
|
||||
{
|
||||
"name": "attendance",
|
||||
"title": "Attendance",
|
||||
"percentage": 5
|
||||
}
|
||||
]
|
@ -1,268 +0,0 @@
|
||||
(()=>{
|
||||
const cont = `
|
||||
<div class="about-container block">
|
||||
<h2>About</h2>
|
||||
Check out the <a href="https://github.com/lambdapaul/www/blob/master/public/grade-calc/README.md">README.md</a> file
|
||||
to learn more about the configuration structure.
|
||||
<h3>Usage</h3>
|
||||
<ol>
|
||||
<li>Either configure the calculator using the text box below or load one from the existing JSON files to
|
||||
generate one.</li>
|
||||
<li>Click <code>Generate</code>.</li>
|
||||
<li>Enter the input values.</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="calculator-container block">
|
||||
</div>
|
||||
<div class="json-textarea block">
|
||||
<h2>Configuration</h2>
|
||||
<h3>Load config from file</h3>
|
||||
<ul>
|
||||
<li><a href="javascript:void(0)" onclick="loadConfig('/grade-calc/config/map2302.json')">MAP2302 - ODE I Fall 2019 (map2302.json)</a></li>
|
||||
<li><a href="javascript:void(0)" onclick="loadConfig('/grade-calc/config/eee3307c.json')">EEE3307C - Electronics I Spring 2021 (eee3307c.json)</a></li>
|
||||
<li><a href="javascript:void(0)" onclick="loadConfig('/grade-calc/config/eel4742c.json')">EEL4742C - Embedded Systems Spring 2021 (eel4742c.json)</a></li>
|
||||
<li><a href="javascript:void(0)" onclick="loadConfig('/grade-calc/config/eel4781.json')">EEL4781 - Computer Comm. Networks Spring 2021 (eel4781.json)</a></li>
|
||||
</ul>
|
||||
<div class="button-container">
|
||||
<button class="button" onclick="generate()">Generate →</button>
|
||||
</div>
|
||||
<textarea id="json" id="" rows="30"></textarea>
|
||||
|
||||
</div><span class="clear"></span>`;
|
||||
document.querySelector('.grade-calc').innerHTML = cont;
|
||||
})(); // eh
|
||||
|
||||
function generate() {
|
||||
let calcSection = document.querySelector(".calculator-container");
|
||||
calcSection.innerHTML = "";
|
||||
try {
|
||||
conf = JSON.parse(document.getElementById("json").value);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
calcSection.innerHTML = e;
|
||||
return;
|
||||
}
|
||||
let cb = (out) => {
|
||||
for (let o of out) {
|
||||
calcSection.appendChild(o);
|
||||
}
|
||||
}
|
||||
gc = new __GradeCalc(conf, cb);
|
||||
|
||||
calcSection.appendChild(gc.elemTotal);
|
||||
}
|
||||
|
||||
function loadConfig(filename) {
|
||||
var client = new XMLHttpRequest();
|
||||
client.open('GET', filename);
|
||||
client.onreadystatechange = function () {
|
||||
document.getElementById("json").value = (client.responseText);
|
||||
}
|
||||
client.send();
|
||||
}
|
||||
|
||||
class __GradeCalc {
|
||||
maxscore = 0;
|
||||
sections = [];
|
||||
inputSection = [];
|
||||
outputSection = [];
|
||||
fields = [];
|
||||
grades = [];
|
||||
ugrades = [];
|
||||
both = false;
|
||||
totalOutput = null;
|
||||
|
||||
constructor(config, outCallback) {
|
||||
this.totalOutput = document.createElement("div");
|
||||
let dConfig = JSON.parse(JSON.stringify(config)); // dirty clone
|
||||
let sanConfig = [];
|
||||
for (let conf of dConfig) {
|
||||
if (conf.percentage === undefined || conf.name === undefined)
|
||||
continue;
|
||||
if (conf.title === undefined)
|
||||
conf.title = conf.name[0].toUpperCase() + conf.name.slice(1);
|
||||
sanConfig.push(conf);
|
||||
}
|
||||
this.config = sanConfig;
|
||||
for (let [i, conf] of this.config.entries()) {
|
||||
this.maxscore += conf.percentage;
|
||||
|
||||
this.inputSection[i] = [];
|
||||
this.outputSection[i] = document.createElement("div");
|
||||
|
||||
if (conf.bothMethods) {
|
||||
this.both = true;
|
||||
}
|
||||
|
||||
this.sections[i] = (this.createSection(i));
|
||||
}
|
||||
|
||||
for (let [k, v] of this.fields.entries()) {
|
||||
for (let field of v) {
|
||||
this.addInputEventListener(k, field);
|
||||
}
|
||||
}
|
||||
|
||||
outCallback(this.sections);
|
||||
}
|
||||
|
||||
createSection(id) {
|
||||
let conf = this.config[id];
|
||||
|
||||
var section = document.createElement("div");
|
||||
section.classList.add(conf.name);
|
||||
|
||||
var heading = document.createElement("h2");
|
||||
heading.innerHTML = `${conf.title} (${conf.percentage}%)`;
|
||||
|
||||
section.appendChild(heading);
|
||||
|
||||
if (conf.info !== undefined)
|
||||
section.appendChild(document.createTextNode(conf.info));
|
||||
|
||||
this.fields[id] = [];
|
||||
if (conf.points !== undefined) {
|
||||
for (var i = 0; i < conf.points.length; i++) {
|
||||
section.appendChild(this.createInputSection(id, i));
|
||||
}
|
||||
}
|
||||
else {
|
||||
section.appendChild(this.createInputSection(id, 0, true));
|
||||
}
|
||||
|
||||
|
||||
section.appendChild(this.outputSection[id]);
|
||||
return section;
|
||||
}
|
||||
|
||||
createInputSection(sectId, inputId, soleInput = false) {
|
||||
let conf = this.config[sectId];
|
||||
let inputSection = document.createElement("div");
|
||||
inputSection.classList.add("input-section");
|
||||
|
||||
let label = document.createElement("label");
|
||||
if (soleInput)
|
||||
label.innerHTML = `${conf.title} Score: `;
|
||||
else
|
||||
label.innerHTML = `${conf.title} ${inputId + 1} Score: `;
|
||||
|
||||
let field = document.createElement("input");
|
||||
field.classList.add(`input`);
|
||||
field.classList.add(`${conf.name}-score`);
|
||||
this.fields[sectId][inputId] = field;
|
||||
|
||||
let suffix = (soleInput) ? "%" : ` / ${conf.points[inputId]} pts`;
|
||||
|
||||
inputSection.appendChild(label);
|
||||
inputSection.appendChild(field);
|
||||
inputSection.appendChild(document.createTextNode(suffix));
|
||||
|
||||
this.inputSection[sectId][inputId] = inputSection;
|
||||
return inputSection;
|
||||
}
|
||||
|
||||
addInputEventListener(id, field, event = "keyup") {
|
||||
let conf = this.config[id];
|
||||
field.addEventListener(event, () => {
|
||||
if (conf.output !== undefined && conf.output)
|
||||
this.showSectionGrade(id);
|
||||
this.showTotalGrade();
|
||||
});
|
||||
}
|
||||
|
||||
calculateSectionGrade(id, unweighted = false) {
|
||||
let conf = this.config[id];
|
||||
let fields = this.fields[id];
|
||||
if (fields === undefined)
|
||||
return;
|
||||
if (conf.points === undefined) {
|
||||
return parseFloat(fields[0].value);
|
||||
}
|
||||
|
||||
let total = 0;
|
||||
|
||||
if (unweighted) {
|
||||
let counter = 0;
|
||||
for (let [i, field] of fields.entries()) {
|
||||
let val = parseFloat(field.value);
|
||||
if (isNaN(val))
|
||||
continue;
|
||||
total += val / conf.points[i];
|
||||
counter++;
|
||||
}
|
||||
|
||||
return (total / counter * 100);
|
||||
}
|
||||
|
||||
total = fields.reduce((acc, cur) => {
|
||||
let c = parseFloat(cur.value);
|
||||
if (isNaN(c))
|
||||
return acc;
|
||||
return acc + parseFloat(c);
|
||||
}, 0);
|
||||
|
||||
let max_total = 0;
|
||||
for (let [i, field] of conf.points.entries()) {
|
||||
if (isNaN(parseFloat(fields[i].value)))
|
||||
continue;
|
||||
max_total += field;
|
||||
}
|
||||
|
||||
return (total / max_total * 100);
|
||||
}
|
||||
|
||||
showSectionGrade(id) {
|
||||
let conf = this.config[id];
|
||||
let grade = this.calculateSectionGrade(id);
|
||||
let ugrade = this.calculateSectionGrade(id, true);
|
||||
|
||||
|
||||
this.grades[id] = grade * parseFloat(conf.percentage) / 100;
|
||||
this.ugrades[id] = ugrade * parseFloat(conf.percentage) / 100;
|
||||
|
||||
grade = !isNaN(grade) ? grade.toFixed(2) : "...";
|
||||
ugrade = !isNaN(ugrade) ? ugrade.toFixed(2) : "...";
|
||||
if (conf.bothMethods) {
|
||||
this.outputSection[id].innerHTML
|
||||
= `Score (weighted): ${grade}%<br> Score (unweighted): ${ugrade}%`;
|
||||
return;
|
||||
}
|
||||
|
||||
this.outputSection[id].innerHTML = `Score: ${grade}`;
|
||||
}
|
||||
|
||||
showTotalGrade() {
|
||||
for (let [k, conf] of this.config.entries()) {
|
||||
if (!conf.output) {
|
||||
this.grades[k] = this.calculateSectionGrade(k) * parseFloat(conf.percentage) / 100;
|
||||
this.ugrades[k] = this.calculateSectionGrade(k, true) * parseFloat(conf.percentage) / 100;
|
||||
}
|
||||
}
|
||||
|
||||
let grade = this.grades.reduce((a, c) => {
|
||||
if (isNaN(c))
|
||||
return a;
|
||||
return a + c
|
||||
}, 0);
|
||||
let ugrade = this.ugrades.reduce((a, c) => {
|
||||
if (isNaN(c))
|
||||
return a;
|
||||
return a + c
|
||||
}, 0);
|
||||
|
||||
grade = !isNaN(grade) ? grade.toFixed(2) : "...";
|
||||
ugrade = !isNaN(ugrade) ? ugrade.toFixed(2) : "...";
|
||||
if (this.both) {
|
||||
this.totalOutput.innerHTML
|
||||
= `Total Score (weighted): ${grade}%<br> Total Score (unweighted): ${ugrade}%`;
|
||||
return;
|
||||
}
|
||||
|
||||
this.totalOutput.innerHTML = `Total Score: ${grade}%`;
|
||||
}
|
||||
|
||||
get elemTotal() {
|
||||
return this.totalOutput;
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
{"title":"About", "link": "/about"},
|
||||
{"title":"Resources", "link": "/resources"},
|
||||
{"title":"Recommended", "link": "/recommended"},
|
||||
{"title":"Grade Calculator", "link": "/grade-calc"},
|
||||
{"title":"GitHub", "link": "https://github.com/lambdapaul"},
|
||||
{"title":"GitLab", "link": "https://gitlab.com/lambdapaul"},
|
||||
{"title":"Twitter", "link": "https://twitter.com/lambda_paul"},
|
||||
|
@ -1 +1 @@
|
||||
[{"title":"Steam Info","slug":"steam-info","last_updated":"2022-02-14T09:18:29.604Z"},{"title":"Thoughts on Baba Is You","slug":"thoughts-on-baba-is-you","last_updated":"2021-10-29T04:00:00.000Z"}]
|
||||
[{"title":"Thoughts on Baba Is You","slug":"thoughts-on-baba-is-you","last_updated":"2021-10-30T00:43:00.000Z"}]
|
Loading…
Reference in New Issue
Block a user