Skip to content

Instantly share code, notes, and snippets.

@Gabryxx7
Last active June 11, 2022 09:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gabryxx7/6d035a39def3cf2b7ae62c295adfc7e3 to your computer and use it in GitHub Desktop.
Save Gabryxx7/6d035a39def3cf2b7ae62c295adfc7e3 to your computer and use it in GitHub Desktop.
Download and Upload all Canvas' Speed Grader's data including rubric comment, rating and submission times
node_modules/
package-lock.json
package.json
*quokka*
token.txt
*.json
*.csv
function downloadData(content, fileName, contentType) {
var a = document.createElement('a');
var file = new Blob([content], {type: contentType});
a.href = URL.createObjectURL(file);
a.download = fileName;
a.click();
}
var deadlines = [
{
date: Date.parse("jun 6 at 23:59"),
max_grade: 79
},
{
date: Date.parse("jun 10 at 23:59"),
max_grade: 0
}
]
function calculatePenalty(sData, deadlines){
sData["max_grade"] = 100;
for(const key1 in deadlines){
var deadline = deadlines[key1];
for(var key2 in sData["submissions_dates"]){
var submissionDate = sData["submissions_dates"][key2];
console.log(submissionDate.toDateString() + " > " + deadline["date"].toDateString() + ": " + (submissionDate > deadline["date"]));
if(submissionDate > deadline["date"]){
sData["max_grade"] = deadline["max_grade"];
}
}
}
return sData;
}
function getCriteria(){
var criteria = {};
$('tbody[data-testid=criterions]').first().find('tr[data-testid=rubric-criterion]').each(function(i,x){
var x = $(x);
var criterion = $(x).find('.description').text();
criteria[criterion] = {'rating':$(x).find('.rating-tier.selected > .rating-description').text().trim(),
'comment': $(x).find('.rating-footer div div').text().trim(),
'comment_editing':$(x).find('textarea[data-selenium=criterion_comments_text]').text().trim()}
// criteria['General Comment'] = $(x).find('#speed_grader_comment_textarea').text()
// criteria['General Comment'] = $(x).find('#speed_grader_comment_textarea').text()
});
return criteria;
}
function calculateScore(debug=false){
var criterias = getCriteria();
var numCriterias = 0;
var criteriaScores = [{"rating": "excellent", "score": 5}, {"rating": "good", "score": 3}, {"rating": "inadequate", "score": 0}]
var score = 0;
for(var key in criterias){
var criteria = criterias[key];
numCriterias++;
for(const criteriaScore of criteriaScores){
if(criteria["rating"].toLowerCase().trim() === criteriaScore["rating"].toLowerCase().trim()){
if(debug)
console.log(key +": " +criteria["rating"] + "= " + criteriaScore["score"] + "\t Total Score: " +score);
score += criteriaScore["score"];
}
}
}
console.log("Total Criterias: " +numCriterias);
console.log("Total score: " +score +"/"+(5*numCriterias));
console.log("Final Grade: " +(score * 100 / (5*numCriterias)) +"/" + (5*numCriterias * 100 / (5*numCriterias)) +"%");
}
function printCriteria(criteria, sep="\t"){
var ratings = "";
for (var key in criteria){
var value = criteria[key];
ratings += value['rating']+sep;
}
console.log(ratings.slice(0, -1));
}
function clickStudentByIndex(index){
var option = $('.ui-selectmenu-menu-dropdown .ui-selectmenu-hasIcon').get(index);
var optionLink = $(option).find("a");
option.focus();
optionLink.click(function() {
console.log(`clicked student ${index}...waiting...`);
setTimeout(function() { console.log('Called after delay.');},
5000);
});
}
function clickNextStudent(){
$('#next-student-button').get(0).click(function() {
console.log('clicked next student...waiting...');
setTimeout(function() { console.log('Called after delay.');},
5000);
});
}
function getStudentData(count){
var sData = {};
sName = $('.ui-selectmenu-status > .ui-selectmenu-item-header').text().trim();
console.log(count +' - '+sName);
sData['student'] = sName;
let re = /(\w{3} \d{2} at \d{2}:\d{2})/g;
sData['submissions_dates'] = $("#multiple_submissions").text().match(re);
if(sData['submissions_dates'] !== null){
sData['submissions_dates'] = sData['submissions_dates'].map(function(e) {
return Date.parse(e);
});
}
else{
sData['submissions_dates'] = [];
}
sData['files_submitted'] = $('.submission-file').map(function(i, x){
return $(x).find('.display_name').text().trim();
}).get();
sData['word_count'] =$('#submission_word_count').text().trim().split(':')[1];
sData['grade'] = $('#grading-box-points-possible .score').text().trim();
sData = Object.assign(sData, getCriteria());
sData['General Comment'] = $('#comments span.comment').map(function(i, x){
return $(x).text().trim();
}).get();
sData = calculatePenalty(sData, deadlines);
return sData;
}
function downloadComments(penalties){
clickStudentByIndex(0);
var data = [];
var sName = '';
var maxCount = 200;
var count = 0;
while(sName.trim().toLowerCase() != 'test student' && count < maxCount ){
count++;
let sData = getStudentData(count);
sName = sData["student"];
data.push(sData);
clickNextStudent();
// $('.speed_grader_nav_form').get(0).submit(function() {
// console.log('clicked...waiting...');
// setTimeout(function() { console.log('Called after delay.');},
// 1000);
// });
}
downloadData(JSON.stringify(data), 'speedGrader.json', 'text/json;charset=utf-8');
}
function readTextFile(file)
{
var rawFile = new XMLHttpRequest();
rawFile.open('GET', file, false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
var allText = rawFile.responseText;
alert(allText);
}
}
}
rawFile.send(null);
}
// This will parse a delimited string into an array of
// arrays. The default delimiter is the comma, but this
// can be overriden in the second argument.
function CSVToArray( strData, strDelimiter ){
// Check to see if the delimiter is defined. If not,
// then default to comma.
strDelimiter = (strDelimiter || ',');
// Create a regular expression to parse the CSV values.
var objPattern = new RegExp(
(
// Delimiters.
'(\\' + strDelimiter + '|\\r?\\n|\\r|^)' +
// Quoted fields.
'(?:\'([^\']*(?:\'\'[^\']*)*)\'|' +
// Standard fields.
'([^\'\\' + strDelimiter + '\\r\\n]*))'
),
'gi'
);
// Create an array to hold our data. Give the array
// a default empty first row.
var arrData = [[]];
// Create an array to hold our individual pattern
// matching groups.
var arrMatches = null;
// Keep looping over the regular expression matches
// until we can no longer find a match.
while (arrMatches = objPattern.exec( strData )){
// Get the delimiter that was found.
var strMatchedDelimiter = arrMatches[ 1 ];
// Check to see if the given delimiter has a length
// (is not the start of string) and if it matches
// field delimiter. If id does not, then we know
// that this delimiter is a row delimiter.
if (
strMatchedDelimiter.length &&
(strMatchedDelimiter != strDelimiter)
){
// Since we have reached a new row of data,
// add an empty row to our data array.
arrData.push( [] );
}
// Now that we have our delimiter out of the way,
// let's check to see which kind of value we
// captured (quoted or unquoted).
if (arrMatches[ 2 ]){
// We found a quoted value. When we capture
// this value, unescape any double quotes.
var strMatchedValue = arrMatches[ 2 ].replace(
new RegExp( '\'\'', 'g' ),
'\''
);
} else {
// We found a non-quoted value.
var strMatchedValue = arrMatches[ 3 ];
}
// Now that we have our value string, let's add
// it to the data array.
arrData[ arrData.length - 1 ].push( strMatchedValue );
}
// Return the parsed data.
return( arrData );
}
//var csv is the CSV file with headers
function csvJSON(csv){
var lines=csv.split("\n");
var result = [];
// NOTE: If your columns contain commas in their values, you'll need
// to deal with those before doing the next step
// (you might convert them to &&& or something, then covert them back later)
// jsfiddle showing the issue https://jsfiddle.net/
var headers=lines[0].split(",");
for(var i=1;i<lines.length;i++){
var obj = {};
var currentline=lines[i].split(",");
for(var j=0;j<headers.length;j++){
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
//return result; //JavaScript object
return JSON.stringify(result); //JSON
}
// readTextFile('file:///C://Users//Giaga//Downloads//INFO20005 Marking - Gabry.csv');
var csvString =
`Name,Penalty,Topic,Report ,,,,Chosen Websites,,,Analysis,,,,,,Solutions,,,,Client Brief,Grade,,,
Name,,,Structure and Organization,Writing,Visual Quality,Annotations,Quantity,Organization,Theme,Visual Analysis,Cribsheet sections, Screenshot Organization,Evidence-Based Analysis,Complete analysis,Summary,Quantity,Quality,Complete,Designs and Variety,,Sum/90,Sum/100,%,/25
"Name, Surname",0,"Board, card, and hobby games",Good,Good,Good,Good,Excellent,Excellent,Excellent,Inadequate,Inadequate,Inadequate,Good,Inadequate,Inadequate,Good,Excellent,Good,Good,Good,47.0,52.2,55,13.75
"Name, Surname",0,"Records (vinyl, CDs)",Excellent,Excellent,Good,Excellent,Excellent,Excellent,Excellent,Excellent,Excellent,Excellent,Excellent,Excellent,Good,Good,Excellent,Good,Good,Excellent,80.0,88.9,85,21.25
"Name, Surname",0,Musical instruments,Excellent,Inadequate,Inadequate,Good,Good,Good,Excellent,Excellent,Good,Good,Good,Good,Inadequate,Inadequate,Excellent,Good,Good,Inadequate,47.0,52.2,45,11.25
"Name, Surname",0,"Board, card, and hobby games",,,,,,,,,,,,,,,,,,,0,0,,
"Name, Surname",0,Books,Excellent,Good,Good,Good,Excellent,Excellent,Good,Excellent,Good,Excellent,Excellent,Good,Good,Excellent,Excellent,Excellent,Good,,69.0,76.7,75,18.75
"Name, Surname Tze Wen",0,Furniture,Good,Excellent,Good,Good,Excellent,Excellent,Excellent,Excellent,Good,Good,Excellent,Excellent,Good,Good,Good,Excellent,Good,,67.0,74.4,80,20
"Name, Surname",0,"Records (vinyl, CDs)",Good,Good,Excellent,Good,Good,Inadequate,Excellent,Excellent,Inadequate,Excellent,Excellent,Good,Good,Good,Good,Inadequate,Good,,52.0,57.8,60,15
"Name, Surname",0,"Records (vinyl, CDs)",Good,Good,Good,Excellent,Good,Good,Excellent,Excellent,Excellent,Excellent,Excellent,Good,Good,Good,Inadequate,Good,Good,,60.0,66.7,75,18.75
"Name, Surname",0,Used cars,Excellent,Excellent,Good,Good,Excellent,Excellent,Excellent,Good,Good,Good,Good,Excellent,Good,Excellent,Excellent,Excellent,Excellent,,71.0,78.9,80,20
"Name, Surname",0,"Board, card, and hobby games",Excellent,Good,Good,Good,Excellent,Excellent,Excellent,Excellent,Good,Excellent,Excellent,Good,Good,Good,Inadequate,Good,Good,Good,65.0,72.2,70,17.5
"Name, Surname",0,Furniture,Good,Good,Inadequate,Good,Good,Excellent,Excellent,Good,Inadequate,Good,Good,Good,Inadequate,Inadequate,Excellent,Inadequate,Inadequate,Inadequate,39.0,43.3,40,10
"Name, Surname Juliette",0,Used cars,Excellent,Excellent,Excellent,Good,Excellent,Excellent,Excellent,Excellent,Good,Good,Good,Excellent,Good,Good,Good,Good,Good,Good,70.0,77.8,70,17.5
"Name, Surname",0,"Board, card, and hobby games",Excellent,Good,Good,Good,Excellent,Excellent,Excellent,Good,Inadequate,Good,Good,Inadequate,Inadequate,Excellent,Good,Excellent,Excellent,Excellent,61.0,67.8,70,17.5
"Name, Surname",0,Furniture,Good,Good,Good,Good,Inadequate,Good,Excellent,Good,Good,Good,Good,Good,Good,Good,Good,Good,Good,Excellent,55.0,61.1,60,15
"Name, Surname",0,"Records (vinyl, CDs)",Good,Excellent,Good,Good,Excellent,Good,Excellent,Excellent,Excellent,Good,Good,Excellent,Good,Excellent,Excellent,Excellent,Good,Excellent,74.0,82.2,75,18.75
"Name, Surname",0,Used cars,Excellent,Excellent,Excellent,Good,Excellent,Excellent,Excellent,Good,Good,Good,Good,Good,Good,Excellent,Good,Good,Good,Inadequate,65.0,72.2,60,15
"Name, Surname",0,Musical instruments,Inadequate,Good,Good,Good,Excellent,Inadequate,Excellent,Good,Inadequate,Good,Inadequate,Good,Good,Good,Good,Good,Good,Inadequate,43.0,47.8,45,11.25
"Name, Surname",0,"Board, card, and hobby games",Inadequate,Good,Inadequate,Good,Inadequate,Excellent,Inadequate,Good,Inadequate,Good,Good,Inadequate,Good,Good,Good,Excellent,Good,Good,40.0,44.4,45,11.25
"Name, Surname",0,Books,Good,Good,Good,Good,Excellent,Good,Excellent,,,,,,,,,,,,25.0,27.8,,0
"Name, Surname",0,"Records (vinyl, CDs)",,,,,,,,,,,,,,,,,,,0.0,0.0,,0
"Name, Surname",0,Used cars,,,,,,,,,,,,,,,,,,,0.0,0.0,,0
"Name, Surname",0,"Board, card, and hobby games",,,,,,,,,,,,,,,,,,,0.0,0.0,,0
"Name, Surname",0,Musical instruments,,,,,,,,,,,,,,,,,,,0.0,0.0,,0
"Name, Surname",0,Furniture,,,,,,,,,,,,,,,,,,,0.0,0.0,,0
"Name, Surname",0,"Board, card, and hobby games",,,,,,,,,,,,,,,,,,,0.0,0.0,,0
"Name, Surname",0,Books,,,,,,,,,,,,,,,,,,,0.0,0.0,,0
"Name, Surname",0,Furniture,,,,,,,,,,,,,,,,,,,0.0,0.0,,0
"Name, Surname",0,"Records (vinyl, CDs)",,,,,,,,,,,,,,,,,,,0.0,0.0,,0
"Name, Surname",0,Used cars,,,,,,,,,,,,,,,,,,,0.0,0.0,,0
"Name, Surname",0,Musical instruments,,,,,,,,,,,,,,,,,,,0.0,0.0,,0
"Name, Surname,0,"Board, card, and hobby games",,,,,,,,,,,,,,,,,,,0.0,0.0,,0`;
var dataArray = CSVToArray(csvString);
var dataJson = csvJSON(csvString)
function uploadComments(csvString){
var dataArray = CSVToArray(csvString);
var dataJson = csvJSON(csvString)
var sName = '';
while(sName.trim().toLowerCase() != 'test student' && count < maxCount ){
$(".toggle_full_rubric").click()
count++;
sName = $('.ui-selectmenu-status > .ui-selectmenu-item-header').text().trim();
var sData = dataArray.find(x => x[0].trim().toLowerCase().indexOf(sName.toLowerCase().split(" ")[0].trim()) >= 0)
var primary = "";
for(i = 0; i < dataArray[0].length; i++){
var primary = dataArray[0][i].trim() != "" ? dataArray[0][i].trim() : primary;
var secondary = dataArray[1][i];
console.log(primary+" - "+secondary);
}
console.log(count +' - '+sName);
sData['student'] = sName;
sData['files_submitted'] = $('.submission-file').map(function(i, x){
return $(x).find('.display_name').text().trim();
}).get();
sData['word_count'] =$('#submission_word_count').text().trim().split(':')[1];
$('tbody[data-testid=criterions]').first().find('tr[data-testid=rubric-criterion]').each(function(i,x){
var x = $(x);
sData['grade'] = $('#grading-box-points-possible .score').text().trim();
sData[$(x).find('.description').text()] = {'rating':$(x).find('.rating-tier.selected > .rating-description').text().trim(),
'comment': $(x).find('.rating-footer div div').text().trim(),
'comment_editing':$(x).find('textarea[data-selenium=criterion_comments_text]').text().trim()}
sData['General Comment'] = $(x).find('#speed_grader_comment_textarea').text()
});
data[sName] = sData;
$('#next-student-button').get(0).click(function() {
console.log('clicked...waiting...');
setTimeout(function() { console.log('Called after delay.');},
5000);
});
// $('.speed_grader_nav_form').get(0).submit(function() {
// console.log('clicked...waiting...');
// setTimeout(function() { console.log('Called after delay.');},
// 1000);
// });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment