-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsstats.js
1 lines (1 loc) · 68.7 KB
/
sstats.js
1
var classl={},yearl={},teacherl={},currstudent={},subjects=[],mostrecentsemester="",totalsemesters=[],notsubjects=["MLS","M2S","gradeclass"],langsubjects=["EN","M2","ML","SV","SVA"],aessubjects=["BL","HKK","MU","SL"],sosubjects=["HI","RE","SH","GE"],nosubjects=["BI","FY","KE"],coresubjects=["SV","SVA","EN","MA"];function student(e,t,a){this.id=e,this.name=t,this.grades=a}function makeclass(e,t){e[t.class]={}}function linreg(e){var t=0,a=0;for(let s of e)t+=s.x,a+=s.y;t/=Object.keys(e).length,a/=Object.keys(e).length;var s=0,r=0;for(let n of e)s+=(n.x-t)*(n.y-a),r+=(n.x-t)**2;return[s/r,a-s/r*t]}function median(e){var t=e.length;if(0===t)return 0;if(1===t)return e[0];var a=[...e].sort();if(t%2==0){var s=t/2,r=t/2+1;return isNaN(s)||isNaN(r)?[s,r]:(a[s]+a[r])/2}return a[t/2-.5]}function meanmaxleastres(e,t){var a=0,s=0;for(let r of e)diff=Math.abs(r.y-r.x*t[0]-t[1]),a+=diff,diff>s&&(s=diff);return[a/e.length,s]}function makestudent(e,t){name=t.fname.concat(" ",t.lname),term=t.archiveid.concat(t.term),grade={},grade[term]={},e[t.class][t.studentid]=new student(t.studentid,name,grade),e[t.class][t.studentid].grades[term].gradeclass=t.gradeclass,e[t.class][t.studentid].grades[term][t.gradesubject]=+t.gradeid,["ML","M2"].includes(t.gradesubject)&&(e[t.class][t.studentid].grades[term][t.gradesubject.concat("S")]=t.specialization)}function addgradetostudent(e,t){rowterm=t.archiveid.concat(t.term),rowterm>mostrecentsemester&&(mostrecentsemester=(" "+rowterm).slice(1)),totalsemesters.includes(rowterm)||(totalsemesters.push(rowterm),totalsemesters.sort(),totalsemesters.reverse()),Object.keys(e[t.studentid].grades).includes(rowterm)?e[t.studentid].grades[rowterm][t.gradesubject]=+t.gradeid:(e[t.studentid].grades[rowterm]={gradeclass:t.gradeclass},e[t.studentid].grades[rowterm][t.gradesubject]=+t.gradeid),["ML","M2"].includes(t.gradesubject)&&(e[t.studentid].grades[rowterm][t.gradesubject.concat("S")]=t.specialization)}function filldownVTgrades(e){terms=Object.keys(e);for(let t of terms)if(htterm=t.slice(0,2).concat("HT"),"VT"==t.slice(2)&&terms.includes(htterm)){vtsubs=Object.keys(e[t]),htsubs=Object.keys(e[htterm]);for(let a of htsubs)vtsubs.includes(a)&&0!=e[t][a]||(e[t][a]=e[htterm][a])}return e}function selectnewstudent(){(1==d3.select("#cdselect").property("checked")?localStorage.carryDown=1:localStorage.carryDown=0,selectindex=document.getElementById("studentSelector").selectedIndex,document.getElementById("idSelector").selectedIndex=selectindex,0==selectindex)?clearpage():(currentclass=d3.select("#classSelector").property("value"),currentstudent=d3.select("#idSelector").property("value"),1==localStorage.carryDown?((currstudent=JSON.parse(JSON.stringify(classl[currentclass][currentstudent]))).grades=carrydowngrades(currstudent.grades),currstudent.merits=termmerits(currstudent.grades),currstudent.advanced=advstats(currstudent)):currstudent=classl[currentclass][currentstudent],d3.select("#cssettingsbutton").remove(),makestudenttable(currstudent),makescattergraph(currstudent),makestudentbargraph(currstudent),makeadvanced(currstudent),d3.select("#schartsettings").attr("hidden","true"),d3.select("#charts").append("p").attr("id","cssettingsbutton").html("<u><b>open settings pane</b></u>").on("click",function(){"true"==d3.select("#schartsettings").attr("hidden")?(d3.select("#schartsettings").attr("hidden",null),d3.select("#cssettingsbutton").html("<u><b>close settings pane</b></u>")):(d3.select("#schartsettings").attr("hidden","true"),d3.select("#cssettingsbutton").html("<u><b>open settings pane</b></u>"))}))}function sortidbyname(e,t){return classl[selectValue][e].name<classl[selectValue][t].name?-1:classl[selectValue][t].name<classl[selectValue][e].name?1:0}function selectnewclass(){selectindex=document.getElementById("classSelector").selectedIndex,selectValue=d3.select("#classSelector").property("value"),d3.select("#studentSelector").selectAll("option").remove(),d3.select("#studentSelector").append("option").text("Select a student"),0!=selectindex&&(keyslist=Object.keys(classl[selectValue]).sort(sortidbyname),keyslist.unshift(keyslist[0]),d3.select("#studentSelector").selectAll("option").data(keyslist).enter().append("option").text(function(e){return classl[selectValue][e].name}),d3.select("#idSelector").selectAll("option").remove(),d3.select("#idSelector").selectAll("option").data(keyslist).enter().append("option").text(function(e){return e})),clearpage()}function clearpage(){d3.select("#bigtable").html(""),d3.select("#scatterplot").remove(),d3.select("#cssettingsbutton").remove(),d3.select("#barchart").remove(),d3.select("#ybarchartsettings").html(""),d3.select("#tablesettings").html(""),d3.select("#schartsettings").attr("hidden","true"),d3.select("#advancedinfo").html(""),d3.select("#teachersummary").html(""),d3.select("#summaryContent").html(""),d3.select("#summarySelector").html("")}function gradenumtolet(e){return grades={1:"E",2:"D",3:"C",4:"B",5:"A",6:"F",7:"M",8:"-"},null!=grades[e]?grades[e]:e}function gradelettonum(e){return grades={E:"1",D:"2",C:"3",B:"4",A:"5",F:"6",M:"7","-":"8"},null!=grades[e]?grades[e]:e}function gradetomerits(e){return grades={1:10,2:12.5,3:15,4:17.5,5:20,6:0},null!=grades[e]?grades[e]:-1}function divby0(e,t){return 0==t?0:e/t}function gradechangeamount(e,t){return grades=[1,2,3,4,5,6,"1","2","3","4","5","6"],grades.includes(e)&&grades.includes(t)?(t%=6)-(e%=6):"n/a"}function addtombysubject(e,t,a){t in a?(a[t].total+=e,a[t].count+=1):a[t]={total:e,count:1}}function termmerits(e){var t={tmerits:{},tmaverage:{},tmlangaverage:{},tmaesaverage:{},tmsoaverage:{},tmnoaverage:{},tmcoreaverage:{},mbysubject:{}},a={};for(let h of Object.keys(e)){var s=0,r=0,n=0,c=0,l=0,d=0,o=0,i=0,u=0,m=0,g=0,p=0;for(let t of Object.keys(e[h]))!notsubjects.includes(t)&&[1,2,3,4,5,6].includes(e[h][t])&&(merits=gradetomerits(e[h][t]),s+=merits,o+=1,langsubjects.includes(t)&&(r+=merits,i+=1),aessubjects.includes(t)&&(n+=merits,u+=1),sosubjects.includes(t)&&(c+=merits,g+=1),nosubjects.includes(t)&&(l+=merits,m+=1),coresubjects.includes(t)&&(d+=merits,p+=1),addtombysubject(merits,t,a));0!=o?(t.tmerits[h]=s,t.tmaverage[h]=s/o,t.tmlangaverage[h]=divby0(r,i),t.tmaesaverage[h]=divby0(n,u),t.tmsoaverage[h]=divby0(c,g),t.tmnoaverage[h]=divby0(l,m),t.tmcoreaverage[h]=divby0(d,p)):(t.tmerits[h]=0,t.tmaverage[h]=0,t.tmlangaverage[h]=0,t.tmaesaverage[h]=0,t.tmsoaverage[h]=0,t.tmnoaverage[h]=0,t.tmcoreaverage[h]=0)}for(let e of Object.keys(a))t.mbysubject[e]=divby0(a[e].total,a[e].count);return t}function sortsubjectorder(e,t){return subjectorder={gradeclass:-1,BL:0,EN:4,HKK:1,IDH:11,MA:12,M2:7,M2S:8,ML:9,MLS:10,MU:2,BI:16,FY:17,KE:18,GE:12,HI:13,RE:14,SH:15,SL:3,SV:5,SVA:6,TK:19},e in subjectorder&&t in subjectorder?subjectorder[e]-subjectorder[t]:e in subjectorder?-1:t in subjectorder?1:0}function sortmeritorder(e,t){return meritsortorder={tmerits:0,tmaverage:10,tmcoreaverage:15,tmaesaverage:20,tmlangaverage:30,tmsoaverage:40,tmnoaverage:50},e in meritsortorder&&t in meritsortorder?meritsortorder[e]-meritsortorder[t]:e in meritsortorder?-1:t in meritsortorder?1:0}function gettableheaders(e){var t=[];for(var a in e)t=t.concat(Object.keys(e[a]));return subjects_Set=new Set(t),(t=[...subjects_Set]).sort(sortsubjectorder)}function merittonum(e){if(isNaN(e)||""==e)return e;var t=Number(e);return t<0?e:t<5?6:t<11.25?1:t<13.75?2:t<16.25?3:t<18.75?4:t<=20?5:e}function merittolet(e){return gradenumtolet(merittonum(e))}function getaveragesubjgrade(e,t,a=0){var s=e[t];return"number"==typeof s?s.toFixed(2):1==a?t:""}function carrydowngrades(e){var t=JSON.parse(JSON.stringify(e)),a=Object.keys(t).sort(),s=Object.keys(t[a[0]]);for(i=1;i<a.length;i++){for(let e of s)e in t[a[i]]||(t[a[i]][e]=t[a[i-1]][e]);for(let e of Object.keys(t[a[i]]))s.includes(e)||s.push(e)}return t}function makestudenttable(e){mysubs=gettableheaders(e.grades),mysubs.unshift("Semester"),d3.select("#bigtable").html(""),d3.select("#bigtable").append("table").attr("id","stutable").append("tr").attr("id","tableheader").selectAll("th").data(mysubs).enter().append("th").text(function(e){return e.concat("\t")}),terms=Object.keys(e.grades).sort();for(var t=0;t<terms.length;t++){d3.select("#stutable").append("tr").attr("id","t".concat(terms[t])).selectAll("td").data(mysubs).enter().append("td").attr("class",function(a){return"grade".concat(e.grades[terms[t]][a])}).text(function(a){return"Semester"!=a?gradenumtolet(e.grades[terms[t]][a],"\t"):terms[t]}),termrow=d3.select("#t".concat(terms[t])),header=d3.select("#tableheader");for(let a of Object.keys(e.merits).sort(sortmeritorder))"mbysubject"!=a&&(merit=e.merits[a][terms[t]],"tmerits"!=a&&(merit=merit.toFixed(2)),termrow.append("td").text(merit))}stutable=d3.select("#stutable"),stutable.append("tr").attr("id","avrow").selectAll("td").data(mysubs).enter().append("td").attr("class",function(t){return"grade".concat(merittonum(getaveragesubjgrade(e.merits.mbysubject,t,1)))}).text(function(t){return getaveragesubjgrade(e.merits.mbysubject,t)}),stutable.append("tr").selectAll("td").data(mysubs).enter().append("td").attr("class",function(t){return"grade".concat(merittonum(getaveragesubjgrade(e.merits.mbysubject,t,1)))}).text(function(t){return merittolet(getaveragesubjgrade(e.merits.mbysubject,t))}),header.append("th").text("Merits"),header.append("th").text("Av. Merits"),header.append("th").text("Core Av."),header.append("th").text("Lang. Av."),header.append("th").text("Aes. Av."),header.append("th").text("SO Av."),header.append("th").text("NO Av.")}function getsemesters(e,t){if(!["cohort","class"].includes(t))throw"incorrect depth in function 'getsemesters'";var a=[];if("class"==t)for(let t of Object.keys(e))for(let s of Object.keys(e[t].grades))a.includes(s)||a.push(s);else for(let t of Object.keys(e))for(let s of getsemesters(e[t],"class"))a.includes(s)||a.push(s);return a.sort()}var graphselectlookup={tmaverage:["Av. Merits","Average Merits"],tmcoreaverage:["Core Av.","Average Core Merits"],tmlangaverage:["Lang Av.","Average Language Merits"],tmaesaverage:["Aes. Av.","Average Aes. Merits"],tmsoaverage:["SO. Av.","Average SO. Merits"],tmnoaverage:["NO. Av.","Average NO. Merits"]};function getscatterdata(e,t="tmaverage"){for(var a of(data=[],Object.keys(e.merits[t]).sort()))data.push({x:a,y:e.merits[t][a]});return data}function makescattergraph(e=currstudent){d3.select("#scatterplot").remove(),null==e&&(e=classl[d3.select("#classSelector").property("value")][d3.select("#idSelector").property("value")]);var t=[];for(let e of Object.keys(graphselectlookup))1==d3.select("#cds".concat(e)).property("checked")&&t.push(e);0==t.length&&(d3.select("#cdstmaverage").property("checked","true"),t=["tmaverage"]);var a=30,s=30,r=30,n=60,c=360-n-s,l=300-a-r,d=getscatterdata(e,t[0]),o=d3.select("#scatterplotcontainer").append("svg").attr("id","scatterplot").attr("class","chart").attr("width",c+n+s).attr("height",l+a+r).append("g").attr("transform","translate("+n+","+a+")"),i=d3.scaleBand().domain(d.map(function(e){return e.x})).range([0,c]).padding(1);o.append("g").attr("transform","translate(0,"+l+")").call(d3.axisBottom(i)).selectAll("text").attr("transform","translate(-10,0)rotate(-45)").style("text-anchor","end");var u=d3.scaleLinear().domain([0,20]).range([l,0]);o.append("g").call(d3.axisLeft(u)),o.append("text").attr("text-anchor","end").attr("transform","rotate(-90)").attr("y",20-n).attr("x",-a-l/2+80).text("Average Merits");var m=0;do{currdata=t[m],currcolour="var(--".concat(currdata,"-color)"),o.append("path").datum(d).attr("fill","none").attr("style","stroke:".concat(currcolour)).attr("stroke.width",2).attr("d",d3.line().x(function(e){return i(e.x)}).y(function(e){return u(e.y)})),o.append("g").selectAll("dot").data(d).enter().append("circle").attr("cx",function(e){return i(e.x)}).attr("cy",function(e){return u(e.y)}).attr("r",3).attr("style","fill:".concat(currcolour)),1==d3.select("#dotvaluessel").property("checked")&&o.append("g").selectAll("text").data(d).enter().append("text").attr("transform",function(e){return`translate(${i(e.x)},${u(e.y)})`}).attr("dy","1em").attr("dx","-1em").text(function(e){return e.y.toFixed(2)}),d=getscatterdata(e,t[m+=1])}while(m<t.length);1==d3.select("#charttitlesel").property("checked")&&o.append("g").append("text").attr("id","charttitle").style("text-anchor","middle").attr("x",c/2).attr("y",-5).text(d3.select("#studentSelector").property("value"))}function makegradebarchart(e,t="#barchartcontainer",a="#barchart"){d3.select(a).remove();var s=30,r=30,n=30,c=60,l=360-c-r,d=300-s-n,o=d3.select(t).append("svg").attr("id","barchart").attr("class","chart").attr("width",l+c+r).attr("height",d+s+n).append("g").attr("transform","translate("+c+","+s+")"),i=d3.scaleBand().domain(e.map(function(e){return e.x})).range([0,l]).padding(.2);o.append("g").attr("transform","translate(0,"+d+")").call(d3.axisBottom(i)).selectAll("text").style("text-anchor","end");var u=d3.max(e,function(e){return e.y}),m=0;m=u>20?20:u-1;var g=d3.scaleLinear().domain([0,u]).range([d,0]);o.append("g").call(d3.axisLeft(g).tickFormat(d3.format("d")).ticks(m)),o.selectAll("mybar").data(e).enter().append("rect").style("fill",function(e){return"var(--grade".concat(gradelettonum(e.x),"-color)")}).attr("x",function(e){return i(e.x)}).attr("width",i.bandwidth()).attr("y",function(e){return g(e.y)}).attr("height",function(e){return d-g(e.y)})}function makestudentbargraph(e=currstudent){var t=[0,0,0,0,0,0,0,0,0],a=Object.keys(e.grades).sort()[Object.keys(e.grades).length-1];for(let s of Object.keys(e.grades[a]))notsubjects.includes(s)||(t[e.grades[a][s]]+=1);var s=[];for(var r of[5,4,3,2,1,6,7,8])s.push({x:gradenumtolet(r),y:t[r]});makegradebarchart(s)}function makeybarchartsettings(e,t){["bar","stack"].includes(sessionStorage.yBarChartType)||(sessionStorage.yBarChartType="bar");var a=0;if(d3.select("#ybarchartsettings").html(""),d3.select("#ybarchartsettings").attr("hidden",null),d3.select("#ybarchartsettings").append("table").attr("class","tabs").html("<tr><td id = 'ybc0' onclick = selectybarchartsetting('bar')".concat(">Show Grades Per Semester</td><td id = 'ybc1'"," onclick=selectybarchartsetting('stack')",">Show Distribution Over Time</td></tr>")),"bar"==sessionStorage.yBarChartType){d3.select("#ybarchartsettings").append("select").attr("id","ychartsemesterselect");var s=getsemesters(e,t);s.reverse();for(let e of s)d3.select("#ychartsemesterselect").append("option").text(e);d3.select("#ychartsemesterselect").on("change",selectybarchartyear)}else a=1;mybsselected=document.getElementById("ybc".concat(a)),mybsselected.className="tabselected"}function selectybarchartsetting(e){if(!["bar","stack"].includes(e))throw"Invalid bar chart in 'selectybarchartsetting'";sessionStorage.yBarChartType=e,selectnewyearclass()}function selectybarchartyear(){var e=d3.select("#yearSelector").property("value"),t=d3.select("#ychartsemesterselect").property("value");if(0==document.getElementById("classSelector").selectedIndex){var a={};for(let t of Object.keys(classl))t.charAt(0)==e&&(a[t]=classl[t]);makegradebarchart(getsummarygradecount(a,"cohort",t))}else{var s=d3.select("#classSelector").property("value");makegradebarchart(getsummarygradecount(classl[s],"class",t))}}function makestackedgradebarchart(e){d3.select("#barchart").remove(),series=d3.stack().keys(["-","M","F","E","D","C","B","A"])(e);var t=30,a=30,s=30,r=60,n=360-r-a,c=300-t-s,l=d3.select("#barchartcontainer").append("svg").attr("id","barchart").attr("class","chart").attr("width",n+r+a).attr("height",c+t+s).append("g").attr("transform","translate("+r+","+t+")"),d=d3.scaleBand().domain(e.map(function(e){return e.semester})).range([0,n]).padding(.2);l.append("g").attr("transform","translate(0,"+c+")").call(d3.axisBottom(d)).selectAll("text").style("text-anchor","end");var o=d3.max(series,e=>d3.max(e,e=>e[1])),i=d3.scaleLinear().domain([0,o]).range([c,0]),u=d3.min([o,20]);l.append("g").call(d3.axisLeft(i).tickFormat(d3.format("d")).ticks(u)),l.append("g").selectAll("g").data(series).join("g").attr("fill",function(e){return"var(--grade".concat(gradelettonum(e.key),"-color)")}).selectAll("rect").data(e=>e).join("rect").attr("x",(e,t)=>d(e.data.semester)).attr("y",e=>i(e[1])).attr("height",e=>i(e[0])-i(e[1])).attr("width",d.bandwidth())}function getstackedgrades(e,t,a=null){if(!["cohort","class"].includes(t))throw"incorrect depth in function 'getstackedgrades'";var s=[],r=0,n=getsemesters(e,t);for(let c of n){currentobj={semester:c};for(let s of getsummarygradecount(e,t,c,a))currentobj[s.x]=s.y,r+=s.y;currentobj.total=r,s.push(JSON.parse(JSON.stringify(currentobj))),r=0}return s}function getsummarygradecount(e,t,a=null,s=null){var r=[];if(!["cohort","class"].includes(t))throw"incorrect depth in function 'getsummarygradecount'";var n=[0,0,0,0,0,0,0,0,0];if("class"==t){var c="",l=!1;null==a?l=!0:c=a;for(let t of Object.keys(e)){var d=Object.keys(e[t].grades).sort();if(1==l&&(c=d[d.length-1]),d.includes(c))for(let a of Object.keys(e[t].grades[c]))null!=s&&a!=s||notsubjects.includes(a)||(n[e[t].grades[c][a]]+=1)}for(var o of[5,4,3,2,1,6,7,8])r.push({x:gradenumtolet(o),y:n[o]})}else{for(let t of Object.keys(e))for(var i=getsummarygradecount(e[t],"class",a,s),u=0;u<i.length;u++)n[u]+=i[u].y;var m=[5,4,3,2,1,6,7,8];for(o=0;o<n.length;o++)r.push({x:gradenumtolet(m[o]),y:n[o]})}return r}function makeadvanced(e=currstudent){var t=e.advanced.linav,a=e.advanced.leastres;d3.select("#advancedinfo").html("<b>Slope:</b> ".concat(t.toFixed(2)," (What does this mean? - The number reflects change. Positive numbers mean grades are increasing, negative means decreasing. Bigger numbers mean bigger changes.)")),d3.select("#advancedinfo").append("p").html("<b>Mean residue:</b> ".concat(a[0].toFixed(2)," (What does this mean? - This number reflects how accurate the slope is. The larger it is, the 'weirder' the data, and the less consistently the student's grade has changed.)")),d3.select("#advancedinfo").append("p").html("<b>Max residue:</b> ".concat(a[1].toFixed(2)," (What does this mean? - Compare this number to the mean residue. If they are similar, all of the student's grades are equally 'weird'. If they are different, only some of the grades are suspect. This should be investigated.)"))}function advstats(e){for(cleandata=getscatterdata(e),cleandata=getscatterdata(e),i=0;i<cleandata.length;i++)cleandata[i].x=i;var t=linreg(cleandata),a=meanmaxleastres(cleandata,t);return{linav:t[0],leastres:a}}function selecttoptab(e){var t=["#studenttab","#ygtab","#subjtab","#teachtab","#sumtab"];if(!t.includes(e))throw"Not valid tab in selecttoptab.";for(let a of t)e===a?d3.select(a).attr("class","tabselected"):d3.select(a).classed("tabselected",!1)}function makeclassl(){return students.then(function(e){var t=[];return Promise.all(e.map(function(e){if("-"==e.gradeclass&&(e.gradeclass=e.class),subjects.includes(e.gradesubject)||subjects.push(e.gradesubject),null!=e.fname)return e.class in classl?t.includes(e.studentid)&&Object.keys(classl[e.class]).includes(e.studentid)?addgradetostudent(classl[e.class],e):(makestudent(classl,e),t.push(e.studentid)):(makeclass(classl,e),makestudent(classl,e),t.push(e.studentid)),1})),1}).then(function(e){for(let e of Object.keys(classl))for(let a of Object.keys(classl[e])){var t=classl[e][a];t.grades=filldownVTgrades(t.grades),t.merits=termmerits(t.grades),t.advanced=advstats(t)}}),subjects=subjects.sort(sortsubjectorder),classl}function makestudents(){contents.html(""),selecttoptab("#studenttab"),checkclassl.then(function(){d3.select("#sscontent").append("div").attr("id","selectors");d3.select("#sscontent").append("div").attr("id","datasettings"),d3.select("#sscontent").append("div").attr("id","bigtable"),d3.select("#sscontent").append("div").attr("id","charts"),d3.select("#charts").append("div").attr("id","scatterplotcontainer"),d3.select("#charts").append("div").attr("id","barchartcontainer"),d3.select("#charts").append("div").attr("id","schartsettings").attr("hidden","true"),d3.select("#sscontent").append("div").attr("id","advancedinfo");d3.select("#selectors").append("select").attr("id","classSelector").selectAll("option").data(["Select a class"].concat(Object.keys(classl).sort())).enter().append("option").text(function(e){return e});d3.select("#classSelector").on("change",selectnewclass);d3.select("#selectors").append("select").attr("id","studentSelector").selectAll("option").data(["Select a student"]).enter().append("option").text(function(e){return e});d3.select("#studentSelector").on("change",selectnewstudent);d3.select("#selectors").append("select").attr("id","idSelector").attr("hidden","true").append("option").text("");var e=d3.select("#datasettings").append("input").attr("id","cdselect").attr("type","checkbox");1==localStorage.carryDown&&e.attr("checked",!0),d3.select("#cdselect").on("change",selectnewstudent),d3.select("#datasettings").append("text").text("Carry down grades"),csettings=d3.select("#schartsettings"),csettings.append("h3").text("Chart Settings"),csettingstable=csettings.append("table").attr("id","csettingst"),csettingstable.html("<tr><td><input type = 'checkbox' id='dotvaluessel'></td>".concat("<td>Show values under dots</td></tr>","<tr><td><input type = 'checkbox' id='charttitlesel' checked></td>","<td>Display chart title</td></tr>")),d3.select("#dotvaluessel").attr("onclick","makescattergraph()"),d3.select("#charttitlesel").attr("onclick","makescattergraph()");var t=Object.keys(graphselectlookup);csettings.append("table").attr("id","chartdatashow").selectAll("tr").data(t).enter().append("tr").html(function(e){return"<td><input id='cds".concat(e,"' type='checkbox'></td><td>",graphselectlookup[e][1]," </td><td><span style='font-weight: ","bold; color: var(--",e,"-color)'>—","</span></td>")});for(let e of t)d3.select("#cds".concat(e)).attr("onclick","makescattergraph()");d3.select("#cdstmaverage").property("checked","true")}).catch(console.log.bind(console)),console.log(classl)}function makeyearl(e){var t=[];for(let a of Object.keys(e))t.includes(a.slice(0,1))?yearl[a.slice(0,1)][a]={summary:{}}:(yearl[a.slice(0,1)]={},yearl[a.slice(0,1)][a]={summary:{}},yearl[a.slice(0,1)].summary={},t.push(a.slice(0,1)));getyearaverages(e,yearl),console.log(yearl)}function makeyearlCarry(e){count=0,classlcopy=JSON.parse(JSON.stringify(e));for(let t of Object.keys(classlcopy))for(let a of Object.keys(classlcopy[t]))classlcopy[t][a].grades=carrydowngrades(e[t][a].grades),count+=1;makeyearl(classlcopy)}function makecarriedyear(){0==localStorage.carryDown?makeyearl(classl):makeyearlCarry(classl)}function makeyeargroup(){contents.html(""),selecttoptab("#ygtab");makecarriedyear();d3.select("#sscontent").append("div").attr("id","selectors").append("select").attr("id","yearSelector");d3.select("#yearSelector").append("option").text("Select Year Group");for(let e of Object.keys(yearl))d3.select("#yearSelector").append("option").text(e);d3.select("#yearSelector").on("change",selectnewyear),d3.select("#selectors").append("select").attr("id","classSelector").append("option").text("Select Class"),d3.select("#sscontent").append("div").attr("id","datasettings"),d3.select("#sscontent").append("div").attr("id","bigtable"),d3.select("#sscontent").append("div").attr("id","charts"),d3.select("#charts").append("div").attr("id","barchartcontainer"),d3.select("#barchartcontainer").append("div").attr("id","ybarchartsettings").attr("hidden","true"),d3.select("#sscontent").append("div").attr("id","advancedinfo");var e=d3.select("#datasettings").append("input").attr("id","cdselect").attr("type","checkbox");d3.select("#datasettings").append("text").text("Carry down grades"),1==localStorage.carryDown&&e.attr("checked",!0),d3.select("#cdselect").on("change",function(){1==d3.select("#cdselect").property("checked")?localStorage.carryDown=1:localStorage.carryDown=0,makecarriedyear(),selectnewyearclass()})}function selectyeardatasetting(e){var t=d3.select("#yearSelector").property("value");yearl[t];sessionStorage.yTableDisplay=e,selectnewyearclass()}function getclasssubs(e){var t=[];for(let a of Object.keys(e))if("summary"!=a)for(let s of Object.keys(e[a].average))t.includes(s)||t.push(s);return t.sort(sortsubjectorder),t}function getyearsubs(e){var t=[];for(let a of Object.keys(e))if("summmary"!=a)for(let s of Object.keys(e[a]))if("summary"!=s)for(let r of Object.keys(e[a][s].average))t.includes(r)||t.push(r);return t.sort(sortsubjectorder),t}function selectnewyear(){if(0==document.getElementById("yearSelector").selectedIndex)clearpage();else{clearpage();var e=d3.select("#yearSelector").property("value"),t=yearl[e];d3.select("#classSelector").selectAll("option").remove(),d3.select("#classSelector").append("option").text("Year Summary");for(let e of Object.keys(t).sort())"summary"!=e&&d3.select("#classSelector").append("option").text(e);d3.select("#classSelector").on("change",selectnewyearclass),makeyeartable(t);var a={};for(let t of Object.keys(classl))t.charAt(0)==e&&(a[t]=classl[t]);makeybarchartsettings(a,"cohort"),"stack"==sessionStorage.yBarChartType?makestackedgradebarchart(getstackedgrades(a,"cohort")):makegradebarchart(getsummarygradecount(a,"cohort"))}}function selectnewyearclass(){if(0==document.getElementById("classSelector").selectedIndex)selectnewyear();else{clearpage();var e=d3.select("#yearSelector").property("value"),t=d3.select("#classSelector").property("value");makeclasstable(yearl[e][t]);var a=getfailingstudents(classl[t],"class");d3.select("#bigtable").append("table").attr("id","failing"),d3.select("#failing").append("th").text("Students currently failing a subject").attr("colspan","2"),d3.select("#failing").selectAll("tr").data(Object.keys(a).sort()).enter().append("tr").html(function(e){return"<tr><td>".concat(e,"</td><td>",Object.keys(a[e]).slice(1),"</td></tr>")}),makeybarchartsettings(classl[t],"class"),"stack"==sessionStorage.yBarChartType?makestackedgradebarchart(getstackedgrades(classl[t],"class")):makegradebarchart(getsummarygradecount(classl[t],"class"))}}function teacheraddgrade(e,t){var a=t.archiveid.concat(t.term);Object.keys(e).includes(a)||(e[a]={});var s=t.gradeclass;Object.keys(e[a]).includes(s)||(e[a][s]={});var r=t.gradesubject;Object.keys(e[a][s]).includes(r)||(e[a][s][r]={});var n=semesterbefore(classl[t.class][t.studentid].grades,a);if(0!=n)var c=classl[t.class][t.studentid].grades[n][r];else c="";e[a][s][r][t.studentid]={fname:t.fname,lname:t.lname,grade:t.gradeid,spec:t.specialization,prevgrade:c}}function toggleshowonlyrecent(){0==sessionStorage.tShowAllTeachers?sessionStorage.tShowAllTeachers=1:sessionStorage.tShowAllTeachers=0,maketeacher()}function generateteacherl(){teachers=[],students.then(function(e){e.map(function(e){if(e.teacher.includes(", "))var t=e.teacher.split(", ");else t=[e.teacher];for(let a of t)""!=a&&"-"!=a||(a="NO NAME"),teachers.includes(a)||(teachers.push(a),teacherl[a]={}),teacheraddgrade(teacherl[a],e)})})}function maketeacher(){const e=new Promise(function(e,t){teacherl!={}&&generateteacherl(),e("1")});contents.html(""),selecttoptab("#teachtab"),e.then(function(){d3.select("#sscontent").append("div").attr("id","selectors");var e=[];if(1!=sessionStorage.tShowAllTeachers){sessionStorage.tShowAllTeachers=0;for(let t of Object.keys(teacherl).sort())Object.keys(teacherl[t]).sort().reverse()[0]===mostrecentsemester&&e.push(t)}else e=Object.keys(teacherl).sort();d3.select("#selectors").append("select").attr("id","teacherSelector").selectAll("option").data(["Select a Teacher"].concat(e)).enter().append("option").text(function(e){return e});d3.select("#teacherSelector").on("change",selectnewteacher);d3.select("#selectors").append("select").attr("id","teacherTermSelector").append("option").text("Select a Semester");d3.select("#teacherTermSelector").on("change",selectnewteachersemester),d3.select("#selectors").append("input").attr("id","tShowOnlyRecent").attr("type","checkbox"),1!=sessionStorage.tShowAllTeachers&&d3.select("#tShowOnlyRecent").attr("checked",!0),d3.select("#selectors").append("span").text("Show only teachers who gave grades in ".concat(mostrecentsemester)),d3.select("#tShowOnlyRecent").on("change",toggleshowonlyrecent),d3.select("#sscontent").append("div").attr("id","teachersummary"),d3.select("#sscontent").append("div").attr("id","bigtable"),console.log(teacherl)})}function selectnewteacher(){if(0==document.getElementById("teacherSelector").selectedIndex);else{clearpage();var e=d3.select("#teacherSelector").property("value");teachersems=Object.keys(teacherl[e]).sort().reverse(),teachersems.unshift("Select a Semester"),d3.select("#teacherTermSelector").selectAll("option").remove(),d3.select("#teacherTermSelector").selectAll("option").data(teachersems).enter().append("option").text(function(e){return e}),document.getElementById("teacherTermSelector").selectedIndex=1,selectnewteachersemester()}}function selectnewteachersemester(){if(0==document.getElementById("teacherTermSelector").selectedIndex)clearpage();else{clearpage();var e=d3.select("#teacherSelector").property("value"),t=d3.select("#teacherTermSelector").property("value");d3.select("#bigtable").append("div").attr("id","teacherclassholder"),maketeachersummarybox(e,teacherl,t);for(let a of Object.keys(teacherl[e][t])){d3.select("#teacherclassholder").append("hr"),d3.select("#teacherclassholder").append("h3").attr("class","tclasstitle").text(a);for(let s of Object.keys(teacherl[e][t][a]))maketeacherclasstable(e,classl,t,a,s)}}}function maketeacherclasstable(e,t,a,s,r){var n="t".concat(e,a,s,r).replace(/[^A-Za-z0-9]/,"");n=n.replace(/[^A-Za-z0-9]/,""),d3.select("#teacherclassholder").append("div").attr("id",n),d3.select("#".concat(n)).append("span").attr("class","tsubjtitle").text(r),d3.select("#".concat(n)).append("div").attr("id","g".concat(n)).append("div").attr("id","g".concat(n,"grades")).attr("class","tgradeholder").selectAll("div").data(Object.keys(teacherl[e][a][s][r])).enter().append("div").attr("class",function(t){return"grade".concat(teacherl[e][a][s][r][t].grade)}).html(function(t){return teacherl[e][a][s][r][t].fname.concat(" ",teacherl[e][a][s][r][t].lname,"<br/><span class='tgradebig'>",gradenumtolet(teacherl[e][a][s][r][t].grade),"</span><br/><span class='tgradesmall'>",gradenumtolet(teacherl[e][a][s][r][t].prevgrade)," <br/>(change: ",gradechangeamount(teacherl[e][a][s][r][t].prevgrade,teacherl[e][a][s][r][t].grade),")</span>")}),d3.select("#g".concat(n)).append("div").attr("id","g".concat(n,"graphholder")).attr("class","tclasschartholder");var c=[0,0,0,0,0,0,0,0,0];for(let t of Object.keys(teacherl[e][a][s][r]))c[teacherl[e][a][s][r][t].grade]+=1;var l=[];for(let e of[5,4,3,2,1,6,7,8])l.push({y:c[e],x:gradenumtolet(e)});makegradebarchart(l,"#g".concat(n,"graphholder"),"#g".concat(n,"graph"))}function getsummaryboxstats(e,t,a,s,r,n,c,l,d,o,i,u){["7","8"].includes(e[t][a][s][r][n].grade)||l.push(e[t][a][s][r][n].grade%6),c[e[t][a][s][r][n].grade]+=1,isNaN(e[t][a][s][r][n].prevgrade)||["7","8",""].includes(e[t][a][s][r][n].prevgrade)||["7","8",""].includes(e[t][a][s][r][n].grade)||(d.push(e[t][a][s][r][n].grade%6-e[t][a][s][r][n].prevgrade%6),Math.abs(e[t][a][s][r][n].grade%6-e[t][a][s][r][n].prevgrade%6)>2&&o.push({class:s,subject:r,fname:e[t][a][s][r][n].fname,lname:e[t][a][s][r][n].lname,grade:e[t][a][s][r][n].grade,prevgrade:e[t][a][s][r][n].prevgrade})),6==e[t][a][s][r][n].grade&&i.push({class:s,subject:r,fname:e[t][a][s][r][n].fname,lname:e[t][a][s][r][n].lname}),[7,8,6,0].includes(e[t][a][s][r][n].prevgrade)&&["1","2","3","4","5"].includes(e[t][a][s][r][n].grade)&&u.push({class:s,subject:r,fname:e[t][a][s][r][n].fname,lname:e[t][a][s][r][n].lname,grade:e[t][a][s][r][n].grade})}function writesummarybox(e,t,a,s,r,n){var c=[];for(let t of[5,4,3,2,1,6,7,8])c.push({y:e[t],x:gradenumtolet(t)});var l=median(t),d=a.reduce((e,t)=>e+t,0)/a.length,o=d3.select("#teachersummary");o.append("div").attr("id","teachersummaryavgs").html("Median Grade: <b>".concat(gradenumtolet(l),"</b><br/>","Mean grade change: <b>",d.toFixed(2),"</b>")),o.append("div").attr("id","teacherbiggradechanges").html("<span onclick=teachersumtabletoggle('#tbgcarr','#tgradechangetable')>Grades changed by more than 2: <b>".concat(s.length,"</b> <span id='tbgcarr'>▼</span></span>")),d3.select("#teacherbiggradechanges").append("table").attr("id","tgradechangetable").attr("hidden",!0).selectAll("tr").data(s).enter().append("tr").each(function(e){d3.select(this).selectAll("td").data(["subject","class","fname","lname","grade","prevgrade"]).enter().append("td").text(function(t){return"grade"===t?"".concat(gradenumtolet(e[t]),"←"):"prevgrade"===t?gradenumtolet(e[t]):e[t]})}),o.append("div").attr("id","teacherstudentsfailing").html("<span onclick=teachersumtabletoggle('#tsfarr','#tstudentfailingtable')>Students failing: <b>".concat(r.length,"</b> <span id='tsfarr'>▼</span></span>")),d3.select("#teacherstudentsfailing").append("table").attr("id","tstudentfailingtable").attr("hidden",!0).selectAll("tr").data(r).enter().append("tr").each(function(e){d3.select(this).selectAll("td").data(["subject","class","fname","lname"]).enter().append("td").text(function(t){return e[t]})}),o.append("div").attr("id","teachernowpassing").html("<span onclick=teachersumtabletoggle('#tnparr','#tstudentpassingtable')>Students newly passing: <b>".concat(n.length,"</b> <span id='tnparr'>▼</span></span>")),d3.select("#teachernowpassing").append("table").attr("id","tstudentpassingtable").attr("hidden",!0).selectAll("tr").data(n).enter().append("tr").each(function(e){d3.select(this).selectAll("td").data(["subject","class","fname","lname","grade"]).enter().append("td").text(function(t){return"grade"==t?gradenumtolet(e[t]):e[t]})}),o.append("div").attr("id","sumbarchartcontainer"),makegradebarchart(c,"#sumbarchartcontainer","#sumbarchart")}function maketeachersummarybox(e,t,a){var s=[0,0,0,0,0,0,0,0,0],r=[],n=[],c=[],l=[],d=[];for(let o of Object.keys(t[e][a]))for(let i of Object.keys(t[e][a][o]))for(let u of Object.keys(t[e][a][o][i]))getsummaryboxstats(t,e,a,o,i,u,s,r,n,c,l,d);writesummarybox(s,r,n,c,l,d)}function teachersumtabletoggle(e,t){"▼"==d3.select(e).text()?(d3.select(e).html("▲"),d3.select(t).attr("hidden",null)):(d3.select(e).html("▼"),d3.select(t).attr("hidden",!0))}function makesummary(){new Promise(function(e,t){teacherl!={}&&generateteacherl(),e("1")}).then(function(){contents.html(""),selecttoptab("#sumtab"),contents.append("div").attr("id","summarytabs"),d3.select("#summarytabs").append("table").attr("id","summarytabstable").attr("class","tabs").html("<tr><td onclick='makesummaryprogress()' id='studentprogtab'>Student Progress</td>".concat("<td onclick='makesummaryabberations()' id='gradeoddtab'>Grade Oddities</td>","<td onclick='makesummaryteachers()' id='teachsummarytab'>Teacher Grades</td>")),contents.append("div").attr("id","summarySelector"),contents.append("div").attr("id","summaryContent")})}function getstudentswithgrade(e,t,a){var s={};for(let r of Object.keys(e))for(let n of Object.keys(e[r]))if(Object.keys(e[r][n].grades).includes(a))for(let c of Object.keys(e[r][n].grades[a]))t.includes(e[r][n].grades[a][c])&&(Object.keys(s).includes(e[r][n].name)?s[e[r][n].name].push([c,gradenumtolet(e[r][n].grades[a][c])]):s[e[r][n].name]=[r,[c,gradenumtolet(e[r][n].grades[a][c])]]);return s}function getstudentswithgradechange(e,t,a,s){if(![0,1,-1].includes(a))throw a+" is not a valid direction for getstudentswithgradechange";var r={};for(let c of Object.keys(e))if(Object.keys(e[c]).includes(s))for(let l of Object.keys(e[c][s]))for(let d of Object.keys(e[c][s][l]))for(let o of Object.keys(e[c][s][l][d]))if(!isNaN(e[c][s][l][d][o].prevgrade)&&!["7","8",""].includes(e[c][s][l][d][o].prevgrade)&&!["7","8",""].includes(e[c][s][l][d][o].grade)){var n=e[c][s][l][d][o].grade%6-e[c][s][l][d][o].prevgrade%6;(0!=a&&a*n>=t||0==a&&Math.abs(n)>=t)&&(Object.keys(r).includes(o)?r[o].changes[d]=[n,e[c][s][l][d][o].grade,e[c][s][l][d][o].prevgrade]:(r[o]={fname:e[c][s][l][d][o].fname,lname:e[c][s][l][d][o].lname,group:l,changes:{}},r[o].changes[d]=[n,e[c][s][l][d][o].grade,e[c][s][l][d][o].prevgrade]))}return r}function makestudentgradechangerow(e){var t="<td>";t+=e.fname+" "+e.lname+"</td><td>"+e.group+"</td>",subjs=Object.keys(e.changes).sort(sortsubjectorder);for(let a of subjs)t+="<td><b>"+a+"</b> ("+e.changes[a][0]+") "+gradenumtolet(e.changes[a][1])+"←"+gradenumtolet(e.changes[a][2])+"</td>";return t}function selectnewstudproggradechange(){var e=d3.select("#gradechangeamountselector").property("value"),t=document.getElementById("gradechangedirectionselector").selectedIndex-1,a=d3.select("#studprogsemesterselector").property("value");d3.select("#gradechangetable").remove();var s=getstudentswithgradechange(teacherl,e,t,a),r=d3.select("#summaryContent").append("table").attr("id","gradechangetable");for(let e of Object.keys(s).sort(function(e,t){return s[e].group<s[t].group?1:s[t].group<s[e].group?-1:s[e].fname<s[t].fname?-1:1}))r.append("tr").html(makestudentgradechangerow(s[e]))}function getstudentswithslope(e,t,a){if(![1,-1].includes(a))throw a+" is not a valid direction is getstudentswithslope";var s={};for(let r of Object.keys(e))for(let n of Object.keys(e[r]))(1==a&&e[r][n].advanced.linav>t||-1==a&&e[r][n].advanced.linav<t)&&(s[n]=[e[r][n].name,r,e[r][n].advanced.linav]);return s}function selectnewstudprogslope(){d3.select("#studprogslopetable").remove();var e=d3.select(slopenuminput).property("value"),t=document.getElementById("negslopeprogdirselector").selectedIndex;0==t&&(t=-1),studentlist=getstudentswithslope(classl,e,t);var a=d3.select("#summaryContent").append("table").attr("id","studprogslopetable");for(let e of Object.keys(studentlist).sort(function(e,a){return-t*(studentlist[e][2]-studentlist[a][2])}))a.append("tr").selectAll("td").data(studentlist[e]).enter().append("td").text(function(e){return isNaN(e)||(e=e.toFixed(4)),e})}var studprogoptions={missinggrades:{text:"Missing Grades",f:function(){document.getElementById("studprogsemesterselector")||(d3.select("#summarySelector").append("select").attr("id","studprogsemesterselector").selectAll("option").data(["Semester"].concat(totalsemesters)).enter().append("option").text(function(e){return e}),document.getElementById("studprogsemesterselector").selectedIndex=1),d3.select("#studprogsemesterselector").on("change",function(){var e=document.getElementById("studprogselector").selectedIndex;0!=e&&studprogoptions[Object.keys(studprogoptions)[e-1]].f()}),d3.select("#summaryContent").html(""),0==document.getElementById("studprogsemesterselector").selectedIndex&&(document.getElementById("studprogsemesterselector").selectedIndex=1);var e=d3.select("#studprogsemesterselector").property("value"),t=getstudentswithgrade(classl,[7,8],e),a=d3.select("#summaryContent").append("table").attr("id","missinggradestable");for(let e of Object.keys(t))a.append("tr").selectAll("td").data([e].concat(t[e])).enter().append("td").text(function(e){return"string"==typeof e?e:e.join(": ")})}},failing:{text:"Any Failing Grade",f:function(){document.getElementById("studprogsemesterselector")||(d3.select("#summarySelector").append("select").attr("id","studprogsemesterselector").selectAll("option").data(["Semester"].concat(totalsemesters)).enter().append("option").text(function(e){return e}),document.getElementById("studprogsemesterselector").selectedIndex=1),d3.select("#studprogsemesterselector").on("change",function(){var e=document.getElementById("studprogselector").selectedIndex;0!=e&&studprogoptions[Object.keys(studprogoptions)[e-1]].f()}),d3.select("#summaryContent").html(""),0==document.getElementById("studprogsemesterselector").selectedIndex&&(document.getElementById("studprogsemesterselector").selectedIndex=1);var e=d3.select("#studprogsemesterselector").property("value"),t=getstudentswithgrade(classl,[6],e),a=d3.select("#summaryContent").append("table").attr("id","failingstudentstable");for(let e of Object.keys(t))a.append("tr").selectAll("td").data([e].concat(t[e])).enter().append("td").text(function(e){return"string"==typeof e?e:e.join(": ")})}},gradechange:{text:"Significant Grade Changes",f:function(){document.getElementById("studprogsemesterselector")||(d3.select("#summarySelector").append("select").attr("id","studprogsemesterselector").selectAll("option").data(["Semester"].concat(totalsemesters)).enter().append("option").text(function(e){return e}),document.getElementById("studprogsemesterselector").selectedIndex=1),d3.select("#studprogsemesterselector").on("change",function(){0==document.getElementById("studprogsemesterselector").selectedIndex&&(document.getElementById("studprogsemesterselector").selectedIndex=1),selectnewstudproggradechange()}),d3.select("#summaryContent").html("");d3.select("#studprogsemesterselector").property("value");var e=d3.select("#summaryContent").append("div").attr("id","gradechangechoices");e.append("span").text("Show students with grades which ");var t=e.append("select").attr("id","gradechangedirectionselector");t.append("option").text("decreased"),t.append("option").text("changed"),t.append("option").text("increased"),e.append("span").text(" by at least ");e.append("select").attr("id","gradechangeamountselector").selectAll("option").data([1,2,3,4,5]).enter().append("option").text(function(e){return e});e.append("span").text(" letters."),document.getElementById("gradechangeamountselector").selectedIndex=1,d3.select("#gradechangedirectionselector").on("change",selectnewstudproggradechange),d3.select("#gradechangeamountselector").on("change",selectnewstudproggradechange),selectnewstudproggradechange()}},negtiveslope:{text:"Changing Grade Average",f:function(){d3.select("#studprogsemesterselector").remove(),d3.select("#summaryContent").html("");var e=d3.select("#summaryContent").append("div").attr("id","negslopeprogchoices");e.append("span").text("Show students with grade gradient "),e.append("select").attr("id","negslopeprogdirselector"),d3.select("#negslopeprogdirselector").append("option").text("less than"),d3.select("#negslopeprogdirselector").append("option").text("greater than"),e.append("input").attr("id","slopenuminput").attr("type","number").attr("size","5"),document.getElementById("slopenuminput").value="0.0",selectnewstudprogslope(),d3.select("#negslopeprogdirselector").on("change",selectnewstudprogslope),d3.select("#slopenuminput").on("change",selectnewstudprogslope)}},qualify:{text:"Doesn't Qualify for Course",f:function(){d3.select("#studprogsemesterselector").remove(),d3.select("#summaryContent").html("Coming Soon")}}};function selectnewstudprog(){var e=document.getElementById("studprogselector").selectedIndex;0!=e&&studprogoptions[Object.keys(studprogoptions)[e-1]].f()}function makesummaryprogress(){clearpage(),document.getElementById("studentprogtab").className="tabselected",document.getElementById("gradeoddtab").classList.remove("tabselected"),document.getElementById("teachsummarytab").classList.remove("tabselected"),d3.select("#summarySelector").append("select").attr("id","studprogselector").selectAll("option").data(["Show students with:"].concat(Object.keys(studprogoptions))).enter().append("option").text(function(e){return"Show students with:"!=e?studprogoptions[e].text:e}),d3.select("#studprogselector").on("change",selectnewstudprog)}function isMultimodal(e,t=.75){if(!Array.isArray(e)||e.some(isNaN)||e.some(e=>e<0))throw"Input to 'isBimodal' must be an array of positve values. Passed "+e;if(e.length<3)return!1;if(isNaN(t)||t<=0||t>=1)throw"Invalid sensitivity for 'isBimodal' Must be a positive number less than 1. Passed "+t;var a=[],s=[],r=!0,n=e[0];for(i=1;i<e.length;i++)if(e[i-1]<e[i])r=!0;else if(e[i-1]>e[i]){if(!0===r&&(a.push(e[i-1]),s.push(i-1),a.length>=2&&n<t*Math.min(...a.slice(a.length-2))))return!0;e[i]<n&&(n=e[i]),r=!1}return e[e.length-2]<e[e.length-1]&&(a.push(e[e.length-1]),s.push(e.length-1),a.length>=2&&n<t*Math.min(...a.slice(a.length-2)))}function isStudentMultimodal(e,t,a){if(!Object.keys(e.grades).includes(t))return!1;var s=[0,0,0,0,0,0,0,0,0];for(let a of Object.keys(e.grades[t]))notsubjects.includes(a)||(s[e.grades[t][a]]+=1);return isMultimodal(s=[5,4,3,2,1,6,7,8].map(e=>s[e]),a)}function getStudentVariance(e,t,a=0){if(![0,1].includes(a))throw"Invalid mode for getStudentVariance. Requires 0 or 1, passed: "+a;if(Object.keys(e.grades).includes(t)){var s=0,r=0,n=0;if(0==a){for(let a of Object.keys(e.grades[t]))!notsubjects.includes(a)&&e.grades[t][a]<7&&(s+=e.grades[t][a]%6+1,r+=1);if(r<2)return 0;s/=r;for(let a of Object.keys(e.grades[t]))!notsubjects.includes(a)&&e.grades[t][a]<7&&(n+=(e.grades[t][a]%6+1-s)**2)}else{for(let a of Object.keys(e.grades[t]))!notsubjects.includes(a)&&e.grades[t][a]<7&&(s+=gradetomerits(e.grades[t][a]),r+=1);if(r<2)return 0;s/=r;for(let a of Object.keys(e.grades[t]))!notsubjects.includes(a)&&e.grades[t][a]<7&&(n+=(gradetomerits(e.grades[t][a])-s)**2)}return[s,n/r]}return!1}function selectnewhgvvalue(){d3.select("#hgvabbertable").remove();var e=d3.select("#abbersemesterselector").property("value"),t=d3.select("#hgvnuminput").property("value"),a=0;1==d3.select("#hgvabbermodeselect").property("checked")&&(a=1);var s=[],r=0;for(let n of Object.keys(classl))for(let c of Object.keys(classl[n]))(r=getStudentVariance(classl[n][c],e,a))[1]>t&&s.push([classl[n][c].name,n,"<b>Mean:</b> ",r[0].toFixed(2),"<b>Variance: </b>",r[1].toFixed(2)]);d3.select("#summaryContent").append("table").attr("id","hgvabbertable");for(let e of s)d3.select("#hgvabbertable").append("tr").selectAll("td").data(e).enter().append("td").html(function(e){return e})}var abberationsoptions={fanda:{text:"Both F and A Grades",f:function(){document.getElementById("abbersemesterselector")||(d3.select("#summarySelector").append("select").attr("id","abbersemesterselector").selectAll("option").data(["Semester"].concat(totalsemesters)).enter().append("option").text(function(e){return e}),document.getElementById("abbersemesterselector").selectedIndex=1),d3.select("#abbersemesterselector").on("change",function(){var e=document.getElementById("studabberselector").selectedIndex;0!=e&&abberationsoptions[Object.keys(abberationsoptions)[e-1]].f()}),d3.select("#summaryContent").html(""),0==document.getElementById("abbersemesterselector").selectedIndex&&(document.getElementById("abbersemesterselector").selectedIndex=1);var e=d3.select("#abbersemesterselector").property("value"),t=getstudentswithgrade(classl,[5],e),a=getstudentswithgrade(classl,[6],e),s=getstudentswithgrade(classl,[5,6],e),r=Object.keys(t).filter(function(e){return Object.keys(a).indexOf(e)>-1}),n=d3.select("#summaryContent").append("table").attr("id","fandaabbertable");for(let e of r)n.append("tr").selectAll("td").data([e].concat(s[e])).enter().append("td").text(function(e){return"string"==typeof e?e:e.join(": ")})}},multimodal:{text:"Multimodal Grades",f:function(){document.getElementById("abbersemesterselector")||(d3.select("#summarySelector").append("select").attr("id","abbersemesterselector").selectAll("option").data(["Semester"].concat(totalsemesters)).enter().append("option").text(function(e){return e}),document.getElementById("abbersemesterselector").selectedIndex=1),d3.select("#abbersemesterselector").on("change",function(){var e=document.getElementById("studabberselector").selectedIndex;0!=e&&abberationsoptions[Object.keys(abberationsoptions)[e-1]].f()}),d3.select("#summaryContent").html(""),0==document.getElementById("abbersemesterselector").selectedIndex&&(document.getElementById("abbersemesterselector").selectedIndex=1);var e=d3.select("#abbersemesterselector").property("value");d3.select("#summaryContent").append("span").text("This test will miss students with particularly odd grade distibutions, (specifically: trimodal distributions in which the central high point is lower than the two outer). This is rare, but should be accounted for. (This may be fixed in a future version). ");d3.select("#summaryContent").append("table").attr("id","mmodabbertable");for(let t of Object.keys(classl))for(let a of Object.keys(classl[t]))isStudentMultimodal(classl[t][a],e,.75)&&d3.select("#mmodabbertable").append("tr").html("<td>"+t+"</td><td>"+classl[t][a].name)}},highvariance:{text:"High Grade Variance",f:function(){document.getElementById("abbersemesterselector")||(d3.select("#summarySelector").append("select").attr("id","abbersemesterselector").selectAll("option").data(["Semester"].concat(totalsemesters)).enter().append("option").text(function(e){return e}),document.getElementById("abbersemesterselector").selectedIndex=1),d3.select("#abbersemesterselector").on("change",function(){var e=document.getElementById("studabberselector").selectedIndex;0!=e&&abberationsoptions[Object.keys(abberationsoptions)[e-1]].f()}),d3.select("#summaryContent").html(""),0==document.getElementById("abbersemesterselector").selectedIndex&&(document.getElementById("abbersemesterselector").selectedIndex=1);var e=d3.select("#summaryContent").append("div").attr("id","hgvabberchoices");e.append("span").text("Show students with grade variance greater than "),e.append("input").attr("id","hgvnuminput").attr("type","number").attr("size","5"),e.append("br"),e.append("input").attr("type","checkbox").attr("id","hgvabbermodeselect"),e.append("span").text("Use merits to calculate variance (default is F=1, A=6)"),document.getElementById("hgvnuminput").value="2.5",selectnewhgvvalue(),d3.select("#hgvnuminput").on("change",selectnewhgvvalue),d3.select("#hgvabbermodeselect").on("change",function(){1==d3.select("#hgvabbermodeselect").property("checked")?document.getElementById("hgvnuminput").value="35":document.getElementById("hgvnuminput").value="2.5",selectnewhgvvalue()})}}};function makesummaryabberations(){clearpage(),document.getElementById("studentprogtab").classList.remove("tabselected"),document.getElementById("gradeoddtab").className="tabselected",document.getElementById("teachsummarytab").classList.remove("tabselected"),d3.select("#summarySelector").append("select").attr("id","studabberselector").selectAll("option").data(["Show students with:"].concat(Object.keys(abberationsoptions))).enter().append("option").text(function(e){return"Show students with:"!=e?abberationsoptions[e].text:e}),d3.select("#studabberselector").on("change",function(){var e=document.getElementById("studabberselector").selectedIndex;0!=e&&abberationsoptions[Object.keys(abberationsoptions)[e-1]].f()})}function getTeacherVariance(e,t,a=0){if(![0,1].includes(a))throw"Invalid mode for getTeacherVariance. Requires 0 or 1, passed: "+a;if(Object.keys(e).includes(t)){var s=0,r=0,n=0;if(0==a){for(let a of Object.keys(e[t]))for(let n of Object.keys(e[t][a]))for(let c of Object.keys(e[t][a][n]))!notsubjects.includes(n)&&e[t][a][n][c].grade<7&&(s+=parseInt(e[t][a][n][c].grade),r+=1);if(r<2)return[s/r,0];s/=r;for(let a of Object.keys(e[t]))for(let r of Object.keys(e[t][a]))for(let c of Object.keys(e[t][a][r]))!notsubjects.includes(r)&&e[t][a][r][c].grade<7&&(n+=(parseInt(e[t][a][r][c].grade)-s)**2)}else{for(let a of Object.keys(e[t]))for(let n of Object.keys(e[t][a]))for(let c of Object.keys(e[t][a][n]))!notsubjects.includes(n)&&e[t][a][n][c].grade<7&&(s+=gradetomerits(e[t][a][n][c].grade),r+=1);if(r<2)return[s/r,0];s/=r;for(let a of Object.keys(e[t]))for(let r of Object.keys(e[t][a]))for(let c of Object.keys(e[t][a][r]))!notsubjects.includes(r)&&e[t][a][r][c].grade<7&&(n+=(gradetomerits(e[t][a][r][c].grade)-s)**2)}return[s,n/r]}return[!1,0]}function selectnewtgvvalue(){d3.select("#tgvtable").remove();var e=d3.select("#teachgsemesterselector").property("value"),t=d3.select("#tgvnuminput").property("value"),a=0;1==d3.select("#tgvmodeselect").property("checked")&&(a=1);var s=[],r=0;for(let n of Object.keys(teacherl))(r=getTeacherVariance(teacherl[n],e,a))[1]<t&&r[0]&&s.push([n,"<b>Mean:</b> ",r[0].toFixed(2),"<b>Variance: </b>",r[1].toFixed(2)]);d3.select("#summaryContent").append("table").attr("id","tgvtable");for(let e of s)d3.select("#tgvtable").append("tr").selectAll("td").data(e).enter().append("td").html(function(e){return e})}function getteachermeangradechange(e,t){var a=0,s=0;if(Object.keys(e).includes(t)){for(let r of Object.keys(e[t]))for(let n of Object.keys(e[t][r]))for(let c of Object.keys(e[t][r][n]))isNaN(parseInt(e[t][r][n][c].prevgrade))||(s+=Math.abs(parseInt(e[t][r][n][c].prevgrade)-parseInt(e[t][r][n][c].grade)),a+=1);return[s/a,a]}return[!1,0]}function getteacherskew(e,t){var[a,s]=getTeacherVariance(e,t,0);if(0==a||0==s)return NaN;var r=[0,0,0,0,0,0],n=0;for(let a of Object.keys(e[t]))for(let s of Object.keys(e[t][a]))for(let c of Object.keys(e[t][a][s]))r[parseInt(e[t][a][s][c].grade)%6]+=1,n+=1;n/=2;for(var c=0;n>0;)n-=r[c],c+=1;return-(4-c)/Math.sqrt(s)}function selectnewskew(){d3.select("#skewtable").remove();var e=document.getElementById("skewselector").selectedIndex,t=d3.select("#teachgsemesterselector").property("value");d3.select("#summaryContent").append("table").attr("id","hmgctable");teacherlist=[];for(let s of Object.keys(teacherl)){var a=getteacherskew(teacherl[s],t);isNaN(a)||(2==e||1==e&&a>0||0==e&&a<0)&&teacherlist.push([s,a])}1!=e?teacherlist.sort(function(e,t){return e[1]-t[1]}):teacherlist.sort(function(e,t){return t[1]-e[1]});var s=d3.select("#summaryContent").append("table").attr("id","skewtable"),r=s.append("tr");r.append("th").text("Name"),r.append("th").text("Skew");for(let e of teacherlist)e[1]=e[1].toFixed(3),s.append("tr").selectAll("td").data(e).enter().append("td").text(function(e){return e})}var teachgradeoptions={lowvariance:{text:"Low Grading Variance",f:function(){document.getElementById("teachgsemesterselector")||(d3.select("#summarySelector").append("select").attr("id","teachgsemesterselector").selectAll("option").data(["Semester"].concat(totalsemesters)).enter().append("option").text(function(e){return e}),document.getElementById("teachgsemesterselector").selectedIndex=1),d3.select("#teachgsemesterselector").on("change",function(){var e=document.getElementById("teachgradeselector").selectedIndex;0!=e&&teachgradeoptions[Object.keys(teachgradeoptions)[e-1]].f()}),d3.select("#summaryContent").html(""),0==document.getElementById("teachgsemesterselector").selectedIndex&&(document.getElementById("teachgsemesterselector").selectedIndex=1);var e=d3.select("#summaryContent").append("div").attr("id","tgvchoices");e.append("span").text("Show teachers with grade variance less than "),e.append("input").attr("id","tgvnuminput").attr("type","number").attr("size","5"),e.append("br"),e.append("input").attr("type","checkbox").attr("id","tgvmodeselect"),e.append("span").text("Use merits to calculate variance (default is F=1, A=6)"),document.getElementById("tgvnuminput").value="1",selectnewtgvvalue(),d3.select("#tgvnuminput").on("change",selectnewtgvvalue),d3.select("#tgvmodeselect").on("change",function(){1==d3.select("#tgvmodeselect").property("checked")?document.getElementById("tgvnuminput").value="10":document.getElementById("tgvnuminput").value="1",selectnewtgvvalue()})}},skewedcurve:{text:"Skewed Grading Curve",f:function(){document.getElementById("teachgsemesterselector")||(d3.select("#summarySelector").append("select").attr("id","teachgsemesterselector").selectAll("option").data(["Semester"].concat(totalsemesters)).enter().append("option").text(function(e){return e}),document.getElementById("teachgsemesterselector").selectedIndex=1),d3.select("#teachgsemesterselector").on("change",function(){var e=document.getElementById("teachgradeselector").selectedIndex;0!=e&&teachgradeoptions[Object.keys(teachgradeoptions)[e-1]].f()}),d3.select("#summaryContent").html(""),0==document.getElementById("teachgsemesterselector").selectedIndex&&(document.getElementById("teachgsemesterselector").selectedIndex=1);var e=d3.select("#summaryContent").append("div").attr("id","skchoice");e.append("span").text("Show teachers with ");var t=e.append("select").attr("id","skewselector");t.append("option").text("negative"),t.append("option").text("positive"),t.append("option").text("any"),e.append("span").text(" skew. (Uses Pearson's 2nd Coefficient with mean C)"),e.on("change",selectnewskew),selectnewskew()}},highmeanchange:{text:"High Mean Grade Change",f:function(){document.getElementById("teachgsemesterselector")||(d3.select("#summarySelector").append("select").attr("id","teachgsemesterselector").selectAll("option").data(["Semester"].concat(totalsemesters)).enter().append("option").text(function(e){return e}),document.getElementById("teachgsemesterselector").selectedIndex=1),d3.select("#teachgsemesterselector").on("change",function(){var e=document.getElementById("teachgradeselector").selectedIndex;0!=e&&teachgradeoptions[Object.keys(teachgradeoptions)[e-1]].f()}),d3.select("#summaryContent").html(""),0==document.getElementById("teachgsemesterselector").selectedIndex&&(document.getElementById("teachgsemesterselector").selectedIndex=1);var e=d3.select("#teachgsemesterselector").property("value"),t=d3.select("#summaryContent").append("table").attr("id","hmgctable");teacherlist=[];for(let t of Object.keys(teacherl)){var a=getteachermeangradechange(teacherl[t],e);a[1]>0&&(a.unshift(t),teacherlist.push(a))}teacherlist.sort(function(e,t){return t[1]-e[1]}),t.append("tr").selectAll("th").data(["Teacher","Mean Change","Eligable Grades"]).enter().append("th").html(function(e){return"<b>"+e+"</d>"});for(let e of teacherlist)e[1]=e[1].toFixed(2),t.append("tr").selectAll("td").data(e).enter().append("td").text(function(e){return e})}}};function makesummaryteachers(){clearpage(),document.getElementById("studentprogtab").classList.remove("tabselected"),document.getElementById("gradeoddtab").classList.remove("tabselected"),document.getElementById("teachsummarytab").className="tabselected",d3.select("#summarySelector").append("select").attr("id","teachgradeselector").selectAll("option").data(["Show teachers with:"].concat(Object.keys(teachgradeoptions))).enter().append("option").text(function(e){return"Show teachers with:"!=e?teachgradeoptions[e].text:e}),d3.select("#teachgradeselector").on("change",function(){var e=document.getElementById("teachgradeselector").selectedIndex;0!=e&&teachgradeoptions[Object.keys(teachgradeoptions)[e-1]].f()})}function getsubjectsemesters(e,t){var a=[];for(let s of Object.keys(t))for(let r of Object.keys(t[s]))if(!a.includes(r))for(let n of Object.keys(t[s][r]))Object.keys(t[s][r][n]).includes(e)&&!a.includes(r)&&a.push(r);return a}function getsubjectyears(e,t,a){var s=[];for(let r of Object.keys(a))if(Object.keys(a[r]).includes(t))for(let n of Object.keys(a[r][t]))!s.includes(n.slice(0,1))&&Object.keys(a[r][t][n]).includes(e)&&s.push(n.slice(0,1));return s}function makesubject(){contents.html(""),selecttoptab("#subjtab"),new Promise(function(e,t){teacherl!={}&&generateteacherl(),e("1")}).then(function(){d3.select("#sscontent").append("div").attr("id","selectors"),d3.select("#selectors").append("select").attr("id","subjectSelector").selectAll("option").data(["Select Subject"].concat(subjects)).enter().append("option").text(function(e){return e});d3.select("#subjectSelector").on("change",selectnewsubject);d3.select("#selectors").append("select").attr("id","subjectSemesterSelector").selectAll("option").data(["Select Semester"]).enter().append("option").text(function(e){return e});d3.select("#subjectSemesterSelector").on("change",selectnewsubjectsemester);d3.select("#selectors").append("select").attr("id","subjectYearSelector").selectAll("option").data(["Overall Summary"]).enter().append("option").text(function(e){return e});d3.select("#subjectYearSelector").on("change",selectnewsubjectyear),d3.select("#sscontent").append("div").attr("id","teachersummary"),d3.select("#sscontent").append("div").attr("id","bigtable")})}function selectnewsubject(){if(0==document.getElementById("subjectSelector").selectedIndex);else{clearpage();var e=getsubjectsemesters(d3.select("#subjectSelector").property("value"),teacherl).sort();d3.select("#subjectSemesterSelector").selectAll("option").remove(),d3.select("#subjectSemesterSelector").selectAll("option").data(["Select Semester"].concat(e.reverse())).enter().append("option").text(function(e){return e}),document.getElementById("subjectSemesterSelector").selectedIndex=1,selectnewsubjectsemester()}}function selectnewsubjectsemester(){if(0==document.getElementById("subjectSemesterSelector").selectedIndex)clearpage();else{var e=d3.select("#subjectSemesterSelector").property("value"),t=getsubjectyears(d3.select("#subjectSelector").property("value"),e,teacherl);d3.select("#subjectYearSelector").selectAll("option").remove(),d3.select("#subjectYearSelector").selectAll("option").data(["Overall Summary"].concat(t.sort().reverse())).enter().append("option").text(function(e){return e}),selectnewsubjectyear()}}function teachertaughtsubjectinsemester(e,t,a,s,r){return!!(Object.keys(r).includes(e)&&Object.keys(r[e]).includes(a)&&Object.keys(r[e][a]).includes(t)&&Object.keys(r[e][a][t]).includes(s))}function selectnewsubjectyear(){var e=[];clearpage();var t=d3.select("#subjectSemesterSelector").property("value"),a=d3.select("#subjectSelector").property("value");if(d3.select("#bigtable").append("div").attr("id","teacherclassholder"),0==document.getElementById("subjectYearSelector").selectedIndex)makesubjectsummarybox(a,t,"s",teacherl,e);else{makesubjectsummarybox(a,t,d3.select("#subjectYearSelector").property("value"),teacherl,e);for(let s of e){d3.select("#teacherclassholder").append("hr"),d3.select("#teacherclassholder").append("h3").attr("class","tclasstitle").text(s);for(let e of Object.keys(teacherl))teachertaughtsubjectinsemester(e,s,t,a,teacherl)&&(d3.select("#teacherclassholder").append("h4").text(e),maketeacherclasstable(e,classl,t,s,a))}}}function makesubjectsummarybox(e,t,a,s,r){var n=[0,0,0,0,0,0,0,0,0],c=[],l=[],d=[],o=[],i=[],u=[];console.log(r);for(let m of Object.keys(s))if(Object.keys(s[m]).includes(t))for(let g of Object.keys(s[m][t]))if(("s"===a||g.slice(0,1)==a)&&(r.includes(g)||r.push(g),Object.keys(s[m][t][g]).includes(e)))for(let a of Object.keys(s[m][t][g][e]))u.includes(a)||(getsummaryboxstats(s,m,t,g,e,a,n,c,l,d,o,i),u.push(a));writesummarybox(n,c,l,d,o,i)}function getyearaverages(e,t){count=0;for(let s of Object.keys(e)){var a=s.slice(0,1);Object.keys(t[a].summary);for(let r of Object.keys(e[s]))for(let n of Object.keys(e[s][r].grades)){t[a][s].hasOwnProperty(n)||(t[a][s][n]={total:{},average:{},change:{}}),t[a].summary.hasOwnProperty(n)||(t[a].summary[n]={});for(let c of Object.keys(e[s][r].grades[n]))t[a][s][n].total.hasOwnProperty(c)||-1==gradetomerits(e[s][r].grades[n][c])?-1!=gradetomerits(e[s][r].grades[n][c])&&(count+=1,t[a][s][n].total[c]+=gradetomerits(e[s][r].grades[n][c]),t[a][s][n].average[c]+=1):(t[a][s][n].total[c]=gradetomerits(e[s][r].grades[n][c]),t[a][s][n].average[c]=1)}}for(let e of Object.keys(t))for(let a of Object.keys(t[e]))if("summary"!=a){for(let s of Object.keys(t[e][a]))if("summary"!=s)for(let r of Object.keys(t[e][a][s].total))notsubjects.includes(r)?(delete t[e][a][s].total[r],delete t[e][a][s].average[r]):t[e][a][s].average[r]=t[e][a][s].total[r]/t[e][a][s].average[r];for(let r of Object.keys(t[e][a])){if("summary"!=r)if(0!=(s=semesterbefore(t[e][a],r)))for(let n of Object.keys(t[e][a][r].average))t[e][a][s].average.hasOwnProperty(n)&&(t[e][a][r].change[n]=t[e][a][r].average[n]-t[e][a][s].average[n])}}for(let e of Object.keys(t))for(let a of Object.keys(t[e].summary).sort()){t[e].summary[a].average={},t[e].summary[a].count={},t[e].summary[a].change={};for(let s of Object.keys(t[e]))if("summary"!=s&&Object.keys(t[e][s]).includes(a))for(let r of Object.keys(t[e][s][a].average))t[e].summary[a].average.hasOwnProperty(r)?(t[e].summary[a].average[r]+=t[e][s][a].average[r],t[e].summary[a].count[r]+=1):(t[e].summary[a].average[r]=t[e][s][a].average[r]+0,t[e].summary[a].count[r]=1);var s=semesterbefore(t[e].summary,a);for(let r of Object.keys(t[e].summary[a].average)){t[e].summary[a].average[r]/=t[e].summary[a].count[r];0!=s&&null!=t[e].summary[s].average[r]?t[e].summary[a].change[r]=t[e].summary[a].average[r]-t[e].summary[s].average[r]:t[e].summary[a].change[r]=null}}}function sanitizenum(e,t=2){return isNaN(e)||null==e?"":e.toFixed(t)}function makeclasstable(e,t=sessionStorage.yTableDisplay){["0","1","2"].includes(t)||(t=0,sessionStorage.yTableDisplay=0),d3.select("#tablesettings").remove(),d3.select("#datasettings").append("table").attr("id","tablesettings").attr("class","tabs").html("<tr><td id='ts0' onclick='selectyeardatasetting(0)'>Display Average Merits</td>".concat("<td id='ts1' onclick='selectyeardatasetting(1)'>Display Merit Change</td>","<td id='ts2' onclick='selectyeardatasetting(2)'>Display Both</td></tr>")),document.getElementById("ts".concat(t)).className="tabselected";var a=getclasssubs(e);a.unshift("Semester"),d3.select("#bigtable").html("");var s=1;if(2==t){s=2;var r=[];for(let e of a)r.push(e),r.push(e.concat("1"))}d3.select("#bigtable").append("table").attr("id","yeartable").append("tr").attr("id","tableheader").selectAll("th").data(a).enter().append("th").text(function(e){return e.concat("\t")}).attr("colspan",s);var n=Object.keys(e).sort();n.pop(),n.unshift("0000"),0==t||1==t?d3.select("#yeartable").selectAll("tr").data(n.sort()).enter().append("tr").each(function(s){d3.select(this).selectAll("td").data(a).enter().append("td").html(function(a){if(0==t)r=sanitizenum(r=e[s].average[a]);else if(1==t){var r;r=sanitizenum(r=e[s].change[a])}return"Semester"==a?s:r}).attr("class",function(a){var r;return 0==t?null!=(r=e[s].average[a])?"grade".concat(merittonum(r)):"":1==t?null!=(r=e[s].change[a])?"change".concat(changelvls(r)):"blankcell":void(r="")})}):2==t&&d3.select("#yeartable").selectAll("tr").data(n.sort()).enter().append("tr").each(function(t){d3.select(this).selectAll("td").data(r).enter().append("td").html(function(a){if("1"!=a.slice(-1))var s=sanitizenum(e[t].average[a]);else s=sanitizenum(e[t].change[a.slice(0,-1)]);return"Semester"==a?t:s}).attr("class",function(a){if("1"!=a.slice(-1)){var s=sanitizenum(e[t].average[a]);return"grade".concat(merittonum(s))}s=sanitizenum(e[t].change[a.slice(0,-1)]);return"change".concat(changelvls(s))})})}function makeyeartable(e,t=sessionStorage.yTableDisplay){["0","1","2"].includes(t)||(t=0,sessionStorage.yTableDisplay=0),d3.select("#tablesettings").remove(),d3.select("#datasettings").append("table").attr("id","tablesettings").html("<tr><td id='ts0' onclick='selectyeardatasetting(0)'>Display Average Merits</td>".concat("<td id='ts1' onclick='selectyeardatasetting(1)'>Display Merit Change</td>","<td id='ts2' onclick='selectyeardatasetting(2)'>Display Both</td></tr>")),document.getElementById("ts".concat(t)).className="tabselected";var a=getyearsubs(e);a.unshift("Semester"),d3.select("#bigtable").html("");var s=1;if(2==t){s=2;var r=[];for(let e of a)r.push(e),r.push(e.concat("1"))}d3.select("#bigtable").append("table").attr("id","yeartable").append("tr").attr("id","tableheader").selectAll("th").data(a).enter().append("th").text(function(e){return e.concat("\t")}).attr("colspan",s);var n=Object.keys(e.summary);n.push("0000"),0==t||1==t?d3.select("#yeartable").selectAll("tr").data(n.sort()).enter().append("tr").each(function(s){d3.select(this).selectAll("td").data(a).enter().append("td").html(function(a){if(0==t)r=sanitizenum(r=e.summary[s].average[a]);else if(1==t){var r;r=sanitizenum(r=e.summary[s].change[a])}return"Semester"==a?s:r}).attr("class",function(a){var r;return 0==t?null!=(r=e.summary[s].average[a])?"grade".concat(merittonum(r)):"":1==t?null!=(r=e.summary[s].change[a])?"change".concat(changelvls(r)):"blankcell":void(r="")})}):2==t&&d3.select("#yeartable").selectAll("tr").data(n.sort()).enter().append("tr").each(function(t){d3.select(this).selectAll("td").data(r).enter().append("td").html(function(a){if("1"!=a.slice(-1))var s=sanitizenum(e.summary[t].average[a]);else s=sanitizenum(e.summary[t].change[a.slice(0,-1)]);return"Semester"==a?t:s}).attr("class",function(a){if("1"!=a.slice(-1)){var s=sanitizenum(e.summary[t].average[a]);return"grade".concat(merittonum(s))}s=sanitizenum(e.summary[t].change[a.slice(0,-1)]);return"change".concat(changelvls(s))})})}function changelvls(e){return e<-2?"m7":e<-1?"m6":e<-.5?"m5":e<-.3?"m4":e<-.2?"m3":e<-.1?"m2":e<0?"m1":0==e?0:e<.1?1:e<.2?2:e<.3?3:e<.5?4:e<1?5:e<2?6:7}function getfailingstudentsfromclass(e,t=null,a=null){var s=!1,r={};Object.keys(e);for(let l of Object.keys(e)){var n=!1;if(null==t||1==s){var c=Object.keys(e[l].grades).sort();t=c[c.length-1],s=!0}if(e[l].grades[t])for(let s of Object.keys(e[l].grades[t]))null!=a&&s!=a||[6,8].includes(e[l].grades[t][s])&&(n||(r[e[l].name]={class:e[l].grades[t].gradeclass},n=!0),r[e[l].name][s]=e[l].grades[t][s])}return r}function getfailingstudents(e,t,a=null,s=null){if(!["cohort","class"].includes(t))throw"Not a valid depth in getfailingstudents()";if("class"==t)var r=getfailingstudentsfromclass(e,a,s);else if("cohort"==t){r={};var n=Object.keys(e);for(let t of n){var c=getfailingstudentsfromclass(e[t],a,s);Object.keys(c).forEach(function(e){r[e]=c[e]})}}return r}function semesterbefore(e,t){return semesters=Object.keys(e),semesters.sort(),t!=semesters[0]&&semesters[semesters.indexOf(t)-1]}var checkclassl,contents="",tabs="";d3.select("#sstats").append("div").attr("id","dataentry").append("span").text("Paste in schoolsoft export:"),d3.select("#dataentry").append("textarea").attr("id","dataentryarea").attr("rows",10).attr("cols",100),d3.select("#dataentryarea").on("change",function(){studentobj=d3.tsvParse(d3.select("#dataentryarea").property("value")),students=new Promise(function(e,t){e(studentobj)}),d3.select("#dataentry").remove(),d3.select("#sstats").append("div").html("<p style='font-size:30px; color:red;'>WORK IN PROGRESS - email peter.brohan[at]gmail.com with suggestions</p>"),(tabs=d3.select("#sstats").append("div").attr("id","tabs")).append("table").attr("id","toptabs").html("<tr><td onclick='makestudents()' id='studenttab'>Student</td>".concat("<td onclick='makeyeargroup()' id='ygtab'>Year Group</td>","<td onclick='makesubject()' id='subjtab'>Subject</td>","<td onclick='maketeacher()' id='teachtab'>Teacher</td>","<td onclick='makesummary()' id='sumtab'>Summary</td></tr>")),contents=d3.select("#sstats").append("div").attr("id","sscontent"),checkclassl=new Promise(function(e,t){classl!={}&&makeclassl(),e(classl)})});