Add posts and old grade-calc
Fix small bugs >bad commit
This commit is contained in:
BIN
public/assets/images/baba_is_you_screencap.png
Normal file
BIN
public/assets/images/baba_is_you_screencap.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 140 KiB |
268
public/grade-calc/vanilla.js
Normal file
268
public/grade-calc/vanilla.js
Normal file
@@ -0,0 +1,268 @@
|
||||
(()=>{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -9,5 +9,6 @@
|
||||
{"title":"Mastodon", "link": "https://mastodon.social/@lambdapaul"},
|
||||
{"title":"Matrix", "link": "https://matrix.to/#/@lambdapaul:matrix.org"},
|
||||
{"title":"Keybase", "link": "https://keybase.io/lambdapaul"},
|
||||
{"title":"Playlists", "link": "/playlists"}
|
||||
{"title":"Playlists", "link": "/playlists"},
|
||||
{"title":"Posts", "link": "/posts"}
|
||||
]
|
||||
|
||||
1
public/posts.json
Normal file
1
public/posts.json
Normal file
@@ -0,0 +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"}]
|
||||
@@ -1,61 +0,0 @@
|
||||
{
|
||||
"type": "root",
|
||||
"domain": "paulw.xyz",
|
||||
"children": [
|
||||
{
|
||||
"name": "resources",
|
||||
"type": "route"
|
||||
},
|
||||
{
|
||||
"name": "recommended",
|
||||
"type": "route"
|
||||
},
|
||||
{
|
||||
"name": "playlists",
|
||||
"type": "route"
|
||||
},
|
||||
{
|
||||
"name": "grade-calc",
|
||||
"type": "route",
|
||||
"text": "Grade Calculator",
|
||||
"children": [
|
||||
{
|
||||
"name": "readme",
|
||||
"type": "route",
|
||||
"text": "Grade Calculator Read Me"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "about",
|
||||
"type": "route"
|
||||
},
|
||||
{
|
||||
"name": "github",
|
||||
"type": "external",
|
||||
"text": "GitHub",
|
||||
"url": "https://github.com/LambdaPaul"
|
||||
},
|
||||
{
|
||||
"name": "gitlab",
|
||||
"type": "external",
|
||||
"text": "GitLab",
|
||||
"url": "https://gitlab.com/LambdaPaul"
|
||||
},
|
||||
{
|
||||
"name": "mastodon",
|
||||
"type": "external",
|
||||
"url": "https://mastodon.social/@lambdapaul"
|
||||
},
|
||||
{
|
||||
"name": "keybase",
|
||||
"type": "external",
|
||||
"url": "https://keybase.io/lambdapaul"
|
||||
},
|
||||
{
|
||||
"name": "matrix",
|
||||
"type": "external",
|
||||
"url": "https://matrix.to/#/@lambdapaul:matrix.org"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
# Site.json File Specification
|
||||
|
||||
This is a very basic site structure specification used to generate some of the navigations pages and components of the website.
|
||||
|
||||
## Definitions
|
||||
|
||||
### Member
|
||||
|
||||
### Website
|
||||
|
||||
## Attributes
|
||||
|
||||
These are the keys to the object definition used to define the website. Not all of the attributes will be read by the application as they are dependent on the type of member. However, if they are, they must conform to this document.
|
||||
|
||||
### `name`
|
||||
|
||||
Name is one of the two required attributes for each member, along with type.
|
||||
|
||||
### `type`
|
||||
|
||||
|
||||
### `children`
|
||||
|
||||
Children is used to define sub-members of the current member.
|
||||
|
||||
### `text`
|
||||
|
||||
Text is used tto override the string that the capitalization of the name results in. If a change is not required, this may be omitted.
|
||||
|
||||
### `url`
|
||||
|
||||
### `domain`
|
||||
|
||||
## Types
|
||||
|
||||
The types are the different kinds of members that the page can have. They are defined with the `type` attribute. The current list is tentative.
|
||||
|
||||
### `root`
|
||||
|
||||
### `directory`
|
||||
|
||||
### `route`
|
||||
|
||||
### `external`
|
||||
Reference in New Issue
Block a user