NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Cursed Knowledge (9¾)
// @namespace off2class
// @version 14.41
// @description «I work to support my hobby. So If you asked me which I’d choose, my job or my hobby, my hobby takes priority.»
// @author 3rdUnknown
// @homepageURL https://openuserjs.org/scripts/3rdUnknown/Cursed_Knowledge_(9%C2%BE)
// @copyright 2021
// @license MIT
// @match https://*.off2class.com/student/*
// @match https://*.off2class.com/student
// @require https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.3.1/chart.min.js
// @require https://ics-ikeda.github.io/shuffle-text/build/shuffle-text.js
// @grant GM_getResourceText
// @grant GM_addStyle
// @run-at document-idle
// @updateURL https://openuserjs.org/meta/3rdUnknown/Cursed_Knowledge_(9¾).meta.js
// ==/UserScript==
(function() {
'use strict';
//“Did you know? If a colony of ants gets rid of the laziest one, another one will just start being lazy instead?”
if ((window.location.pathname.indexOf('student/lesson') !== -1) || (window.location.pathname.indexOf('student/placement') !== -1)) {
enableCopy();
} else if (window.location.pathname.indexOf('student/homework') !== -1) {
let lessonInfo = document.querySelector(".mt-2");
let lessonInfoContainer = createLessonInfo(lessonInfo);
enableCopy();
const created = o2c.page.homework.created_at;
const updated = o2c.page.homework.updated_at;
const lesson = o2c.page.homework.lesson_id;
const dueDate = o2c.page.studentHomework.due_date;
const createdAt = o2c.page.studentHomework.created_at;
const submitted = o2c.page.studentHomework.latest_student_answer.answer.submitted;
const submittedAt = o2c.page.studentHomework.latest_student_answer.answer.submitted_at;
addElement('gif','https://7355608.fun/images/cat.gif', lessonInfoContainer);
addElement('title', `Lesson ID: ${lesson}`, lessonInfoContainer);
addElement('data', `Test was created: ${created}`, lessonInfoContainer);
addElement('data', `Test was updated: ${updated}`, lessonInfoContainer);
addElement('data', `Homework was assigned: ${createdAt}`, lessonInfoContainer);
addElement('data', `Due date: ${dueDate}`, lessonInfoContainer);
addElement('title', diffDate(dueDate, (new Date()), 'Test will be closed after: '), lessonInfoContainer);
if (submitted) {
addElement('title', diffDate(submittedAt, (new Date(createdAt)), 'Test was done after: '), lessonInfoContainer);
}
} else {
// FixMe: chart size dirty hack
GM_addStyle ( `
canvas {
width:900px !important;
height:600px !important;
}
.pt-4 {
padding-top: 3.5rem!important;
}
#student-dashboard .homework-table {
background-image: url(https://7355608.fun/images/board2.png)!important;
}
` );
let pwndLogo = 'https://7355608.fun/images/glitch_logo.gif';
document.querySelector('#site_logo').src=pwndLogo;
let pwndTeacher = `https://7355608.fun/images/teacher${Math.floor(Math.random() * 5) + 1}.png`;
document.querySelector('.teacher').src=pwndTeacher;
// Shuffle Text
window.addEventListener('load', init);
function init() {
var effectList = [];
var elementList1 = [document.querySelector("#navbarSupportedContent span")];
var elementList2 = [];
var elementList = elementList1.concat(elementList2);
for (var i = 0; i < elementList.length; i++) {
var element = elementList[i];
element.dataset.index = i;
effectList[i] = new ShuffleText(element);
element.addEventListener('mouseenter', function () {
effectList[+this.dataset.index].start();
});
element.addEventListener('mouseleave', function () {
effectList[+this.dataset.index].start();
});
effectList[i].start();
}
}
let colors = [{
main: 'rgb(255, 99, 132)',
light: 'rgb(255, 99, 132, 0.2)'
},{
main: 'rgb(75, 192, 192)',
light: 'rgb(75, 192, 192, 0.2)'
},{
main: 'rgb(255, 205, 86)',
light: 'rgb(255, 205, 86, 0.2)'
}];
const x = [];
Object.entries(o2c.page.completedTests.data).forEach(([key, value]) => {
console.log(`${key}: ${value.id}`)
console.log(`${key}: ${value.assigned_on}`)
console.log(`${key}: ${value.isCompleted}`)
const xxx = fetch(`https://${window.location.hostname}/student/placement/${value.id}/result`)
.then(function(response) {
// When the page is loaded convert it to text
return response.text()
})
.then(function(html) {
// Initialize the DOM parser
let parser = new DOMParser();
// Parse the text
let doc = parser.parseFromString(html, "text/html");
// You can now even select part of that html as you would in the regular DOM
let parsed = doc.querySelectorAll('script')[4];
parsed = parsed.innerText;
let parsedStats = parsed.split('o2c.page')[4];
parsedStats = parsedStats.split('.stats = ')[1];
parsedStats = parsedStats.slice(0, -10);
parsedStats = JSON.parse(parsedStats);
console.log(parsedStats["grading-1"]);
let datasetTemplate = {
label: '',
data: [],
fill: true,
backgroundColor: colors[key].light,
borderColor: colors[key].main,
pointBackgroundColor: colors[key].main,
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: colors[key].main,
};
let score = '';
Object.entries(parsedStats["grading-1"]).forEach(([key, value]) => {
console.log(`${key}: ${value.correct}`);
score = `${score} ${grading('grade', key)}:${grading('score', value.correct)}`;
datasetTemplate.data.push(parseInt(value.correct));
});
let parsedLevel = parsed.split('o2c.page')[6];
parsedLevel = parsedLevel.split('.proficiency = ')[1];
parsedLevel = parsedLevel.slice(0, -10);
parsedLevel = JSON.parse(parsedLevel);
let label = `${parsedLevel.name} ${parsedLevel.shortName} (${value.assigned_on})`;
console.log(`${label}`);
// Updating "PLACEMENT TEST RESULTS" dashboard
let placementTestData = `${value.assigned_on.split(" ")[1]} ${value.assigned_on.split(" ")[0]}th`;
let cells = document.querySelectorAll("#completedTests table td");
cells.forEach(function(item, index, arr) {
if (item.innerText == placementTestData) {
arr[index-1].innerHTML = `📚 ${parsedLevel.shortName}: ${score}`;
}
});
//
datasetTemplate.label = label;
return datasetTemplate
})
.catch(function(err) {
console.log('Failed to fetch page: ', err);
});
x.push(xxx)
});
Promise.all(x).then(datasets => {
datasets.reverse();
console.log(datasets);
// FixMe: add optional chart by click
// block = document.querySelector("div.teacher-image-box");
// container = createChart(block);
var popCanvas = document.getElementById("popChart");
var barChart = new Chart(popCanvas, {
type: 'bar',
data: {
labels: ["A1", "A2", "B1", "B2", "C1"],
datasets: datasets,
},
options: {
elements: {
line: {
borderWidth: 3,
}
}
}
});
});
let block = document.querySelector("#navbarSupportedContent");
let container = createDiv(block);
startTime();
//fixed size of blocks
let div = document.getElementsByClassName('col-md-2 col-lg-2')[0];
div.classList.remove("col-md-2", "col-lg-2");
div.classList.add("col-md-3", "col-lg-3");
div = document.getElementsByClassName('col-12 col-sm-12 col-md-10 col-lg-10')[0];
div.classList.remove("col-12", "col-sm-12", "col-md-10", "col-lg-10");
div.classList.add("col-9", "col-sm-9", "col-md-9", "col-lg-9");
}
})();
function createDiv(container) {
let newDiv = document.createElement("div");
newDiv.id = "clock";
insertAfter(newDiv, container);
return newDiv;
}
function createChart(container) {
let newCanvas = document.createElement("canvas");
newCanvas.id = "popChart";
insertAfter(newCanvas, container);
return newCanvas;
}
function createLessonInfo(container) {
var newDiv = document.createElement("div");
newDiv.id = "knowledge";
newDiv.setAttribute("style", "position: absolute; top: 25px; left: 200px; width: max-content;");
insertAfter(newDiv, container);
return newDiv;
}
function addElement(key, value, container) {
let newEl;
if (key === 'title') {
newEl = document.createElement("p");
newEl.className = "homework-header";
newEl.setAttribute("style", "margin-bottom: 0.5em;");
newEl.innerHTML = `<br><b> ${value} </b>`;
} else if (key === 'gif') {
newEl = document.createElement("img");
newEl.src = value;
} else {
newEl = document.createElement("p");
newEl.setAttribute("style", "margin-bottom: 0.5em;");
newEl.innerHTML = `${value}`;
}
container.appendChild(newEl);
}
function insertAfter(newNode, existingNode) {
existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);
}
function enableCopy() {
let allowText = function(e){
e.stopImmediatePropagation();
return true;
};
document.addEventListener('copy', allowText, true);
document.addEventListener('cut', allowText, true);
}
function startTime() {
var h1,h2,m1,m2;
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
h1 = Math.trunc(h/10);
h2 = h%10;
m1 = Math.trunc(m/10);
m2 = m%10;
document.getElementById('clock').innerHTML =
'<img src="https://7355608.fun/images/'+h1+'.gif" alt="'+h1+'" width="20%" border="0">'+
'<img src="https://7355608.fun/images/'+h2+'.gif" alt="'+h2+'" width="20%" border="0">'+
' : '+
'<img src="https://7355608.fun/images/'+m1+'.gif" alt="'+m1+'" width="20%" border="0">'+
'<img src="https://7355608.fun/images/'+m2+'.gif" alt="'+m2+'" width="20%" border="0">';
var t = setTimeout(startTime, 10000);
}
function diffDate(dueDate, nowDate, text) {
const dateNow = nowDate;
const dateFuture = new Date(dueDate);
if (dateNow > dateFuture) {
return `${text} closed`
}
let diffInMilliSeconds = Math.abs(dateFuture - dateNow) / 1000;
// calculate days
const days = Math.floor(diffInMilliSeconds / 86400);
diffInMilliSeconds -= days * 86400;
console.log('Days', days);
// calculate hours
const hours = Math.floor(diffInMilliSeconds / 3600) % 24;
diffInMilliSeconds -= hours * 3600;
console.log('Hours', hours);
// calculate minutes
const minutes = Math.floor(diffInMilliSeconds / 60) % 60;
diffInMilliSeconds -= minutes * 60;
console.log('Minutes', minutes);
return `${text} ${days} days ${hours} hours ${minutes} minutes`;
}
function grading(type, text) {
console.log(`grading: type=${type} | text=${text}`);
if (type == 'grade') {
switch (text) {
case '10':
return '<b>A1</b>';
break;
case '20':
return '<b>A2</b>';
break;
case '30':
return '<b>B1</b>';
break;
case '50':
return '<b>B2</b>';
break;
case '60':
return '<b>C1</b>';
break;
default:
return text
}
} else if (type == 'score') {
if (text <= 10) {
return `<b><font color="red">${text}</font></b>`
} else if (text <= 15) {
return `<b><font color="orange">${text}</font></b>`
} else if (text > 15) {
return `<b><font color="green">${text}</font></b>`
} else {
return text
}
}
}