Skip to content

Instantly share code, notes, and snippets.

@acbart
Created October 26, 2022 20:47
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 acbart/56dd50b66b1357552cf12decaa3d477d to your computer and use it in GitHub Desktop.
Save acbart/56dd50b66b1357552cf12decaa3d477d to your computer and use it in GitHub Desktop.
Assignment Stats
(async function() {
function startDialog(title, body) {
if ($('#dialog').length == 0) {
$(document.body).append('<div title="' + title +
'" id="dialog"></div>');
}
$("#dialog").dialog({
autoOpen: false,
show: "blind",
hide: "explode",
width: '80%',
height: document.documentElement.clientHeight - 100
});
$("#dialog").dialog("open");
$('#dialog').html(body);
}
function stats(arr) {
// sort array ascending
const asc = arr.sort((a, b) => a - b);
const sum = arr => arr.reduce((a, b) => a + b, 0);
const mean = sum(arr) / arr.length;
// sample standard deviation
const mu = mean;
const diffArr = arr.map(a => (a - mu) ** 2);
const std = Math.sqrt(sum(diffArr) / (arr.length - 1));
const quantile = (arr, q) => {
const sorted = asc;
const pos = (sorted.length - 1) * q;
const base = Math.floor(pos);
const rest = pos - base;
if (sorted[base + 1] !== undefined) {
return sorted[base] + rest * (sorted[base + 1] - sorted[base]);
} else {
return sorted[base];
}
};
const q25 = quantile(arr, .25);
const q50 = quantile(arr, .50);
const q75 = quantile(arr, .75);
const min = asc[0];
const max = asc[asc.length-1];
const median = q50;
return [mean, std, min, q25, median, q75, max];
}
const submissions = (await $.post("https://udel.instructure.com/api/graphql", {
"query": `query MyQuery($courseId: ID!) {
course(id: $courseId) {
id
submissionsConnection {
nodes {
score
submissionStatus
assignment {
name
dueAt
assignmentGroup {
name
}
}
}
}
}
}
`, variables: {courseId: ENV.COURSE_ID}
}))
let gathered = {};
submissions.data.course.submissionsConnection.nodes.forEach(node => {
if (!(node.assignment.name in gathered)) {
gathered[node.assignment.name] = {due: node.assignment.dueAt, missing: 0, submitted: [],
group: node.assignment.assignmentGroup.name};
}
const data = gathered[node.assignment.name];
if (node.assignment.dueAt < data.due) {
data.due = node.assignment.dueAt;
}
if (node.submissionStatus === "unsubmitted" || node.score === 0) { data.missing += 1 } else {
data.submitted.push(node.score);
}
});
gathered = Object.entries(gathered).map(([x,y])=>({name: x, ...y}));
gathered.sort((a, b) => ((a.group+a.name).localeCompare((b.group+b.name))));
let table = [`<table class='table table-bordered table-condensed table-striped'>
<tr>
<th>Group</th>
<th>Assignment</th>
<th>Missing</th>
<th>Submitted</th>
<th>Mean</th>
<th>Std</th>
<th>Min</th>
<th>25%</th>
<th>Median</th>
<th>75%</th>
<th>Max</th>
</tr>`];
gathered.forEach(g => {
const gStats = stats(g.submitted).map(l=>Math.round(l*100)/100);
table.push("<tr>"+[g.group, g.name, g.missing, g.submitted.length, ...gStats].map(s => `<td>${s}</td>`).join("")+"</tr>");
});
table.push(`</table>`);
startDialog("Assignment Statistics", table.join(""));
// Missing, # Submitted, Mean Submitted Score, Std Submitted Score, Min, Lower Quartile, Median Submitted Score, Upper Quartile, Max
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment