Permalink
Cannot retrieve contributors at this time
235 lines (191 sloc)
7.39 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| --- | |
| title: Coursework Calculator | |
| layout: page | |
| --- | |
| <p> | |
| <!-- I deliberately avoid saying "to pass" because there might be other reqs to pass --> | |
| If you want to see how much you need in your exam to get 40% overall, first: | |
| <ul> | |
| <li>Select your course.</li> | |
| <li>Click <button onclick="alert('not this one')">calculate me!</button> next to "Exam"</li> | |
| <li>Fill in how much you got in your coursework (in x%).</li> | |
| <li>Fill in <code>40</code> in the "Overall" field</li> | |
| <!-- | |
| <li>???</li> | |
| <li>PROFIT!</li> | |
| --> | |
| <li>The "Exam" field should now tell you how much you need in your exam to get 40% overall.</li> | |
| </ul> | |
| </p> | |
| <h3>Calculator</h3> | |
| <p> | |
| <strong>Select course:</strong> | |
| {% assign courses = site.data.courses.list %} | |
| <select id="course-list"> | |
| <option disabled selected>(select a course)</option> | |
| {% for course in courses %} | |
| <option data-acronym="{{ course[0] }}" value="{{ course[0] }}" | |
| {% unless course[1].cw_exam_ratio %} | |
| disabled="disabled" | |
| {% endunless %} | |
| >{{ course[0] }}: {{ course[1].name }}</option> | |
| {% endfor %} | |
| </select> | |
| <a href="#" id="course-descriptor" style="display: none">drps</a> | |
| <br><br> | |
| <p id="ccalc-error" style="color: red; font-weight: bold;"></p> | |
| <strong>Weighting</strong> (select course above to fill this in) | |
| <ul> | |
| <li> | |
| <strong>Coursework: </strong> | |
| <input data-cw-w8="cw" id="cw-w8-cw" style="width: 2rem"></input>% | |
| </li> | |
| <li> | |
| <strong>Exam: </strong> | |
| <input data-cw-w8="exam" id="cw-w8-exam" style="width: 2rem"></input>% | |
| </li> | |
| </ul> | |
| <br> | |
| <strong>Targets</strong> (lock one, fill other two) | |
| <ul> | |
| <li> | |
| Exam: | |
| <input data-cw-tar="exam" id="cw-tar-exam"></input>% <button data-cw-lock="exam" id="cw-lock-exam"></button> | |
| </li> | |
| <li> | |
| Coursework: | |
| <input data-cw-tar="cw" id="cw-tar-cw"></input>% <button data-cw-lock="cw" id="cw-lock-cw"></button> | |
| </li> | |
| <li> | |
| Overall: | |
| <input data-cw-tar="all" id="cw-tar-all" value="40"></input>% <button data-cw-lock="all" id="cw-lock-all"></button> | |
| </li> | |
| </ul> | |
| <br> | |
| <strong>Last updated from <a href="http://course.inf.ed.ac.uk">course.inf.ed.ac.uk</a>:</strong> {{ site.data.courses.last_update }} | |
| <small style="display: block;"> | |
| Don't forget to visit drps to double check the cw/exam weighting and | |
| check for any additional assessment info (such as a requirement to pass the exam) | |
| </small> | |
| </p> | |
| <script> | |
| const courseData = {{ courses | jsonify }}; | |
| const getEl = (type, target) => document.querySelector(`[data-cw-${type}="${target}"]`) | |
| function showCalculatorError(str) { | |
| if (str === "") { | |
| document.querySelector("#ccalc-error").innerText = ""; | |
| return; | |
| } | |
| document.querySelector('#ccalc-error').innerText = `Error: ${str}` | |
| } | |
| function updateCalculation() { | |
| showCalculatorError(''); | |
| const toSolve = document.querySelector('[data-cw-tar="' + document.querySelector('[data-cw-lock][disabled]').dataset.cwLock + '"]') | |
| console.log("Solving", toSolve.dataset.cwTar) | |
| toSolve.value = '' | |
| let overall = getEl('tar', 'all').value | |
| let exam = getEl('tar', 'exam').value | |
| let cw = getEl('tar', 'cw').value | |
| let ratio_cw = getEl('w8', 'cw').value | |
| let ratio_exam = getEl('w8', 'exam').value | |
| if ((overall != "") && (exam != "") && (cw != "")) { | |
| showCalculatorError("Only fill two of three targets"); | |
| return; | |
| } | |
| // If at least 2 are empty | |
| if ( | |
| ((overall == "") && (exam == "") && (cw == "")) | |
| || ((overall == "") && (exam == "") && (cw != "")) | |
| || ((overall != "") && (exam == "") && (cw == "")) | |
| || ((overall == "") && (exam != "") && (cw == "")) | |
| ) { | |
| console.log("At least 2 are empty.") | |
| return; | |
| } | |
| if (overall != "") { | |
| overall = parseInt(overall); | |
| } | |
| if (exam != "") { | |
| exam = parseInt(exam); | |
| } | |
| if (cw != "") { | |
| cw = parseInt(cw); | |
| } | |
| ratio_cw = parseInt(ratio_cw); | |
| ratio_exam = parseInt(ratio_exam); | |
| if (isNaN(ratio_cw) || isNaN(ratio_exam)) { | |
| showCalculatorError("Invalid cw/exam weightings"); | |
| return; | |
| } | |
| if (isNaN(overall) || isNaN(exam) || isNaN(cw)) { | |
| showCalculatorError("Numbers only please"); | |
| return; | |
| } | |
| ratio_cw /= 100; | |
| ratio_exam /= 100; | |
| const solveOverall = toSolve.dataset.cwTar === "all"; | |
| const solveExam = toSolve.dataset.cwTar === "exam"; | |
| const solveCw = toSolve.dataset.cwTar === "cw"; | |
| if (solveOverall) { | |
| // overall = (cw * ratio_cw) + (exam * ratio_exam); | |
| const result = (cw * ratio_cw) + (exam * ratio_exam); | |
| getEl('tar', 'all').value = result | |
| console.log("#cw-tar-all", result); | |
| } else if (solveExam || solveCw) { | |
| // exam = (overall - (cw * ratio_cw)) / ratio_exam | |
| // cw = (overall - (exam * ratio_exam)) / ratio_cw | |
| // obj = (overall - inner) / outer | |
| const inner = solveExam ? (cw * ratio_cw) : (exam * ratio_exam); | |
| const outer = solveExam ? ratio_exam : ratio_cw; | |
| const result = (overall - inner) / outer; | |
| getEl('tar', solveExam ? 'exam' : 'cw').value = result | |
| console.log(obj, result); | |
| } else { | |
| showCalculatorError("I can't into math.") | |
| } | |
| } | |
| const lockButtons = "#cw-lock-all, #cw-lock-cw, #cw-lock-exam" | |
| const targetInputs = lockButtons.replace(/lock/g, "tar"); | |
| function handleLock() { | |
| // Reset everything to normal | |
| document.querySelectorAll('[data-cw-lock]').forEach(el => { | |
| el.disabled = false | |
| el.innerText = 'calculate me!' | |
| }) | |
| document.querySelectorAll('[data-cw-tar]').forEach(el => el.disabled = false) | |
| const input = document.querySelector(`[data-cw-tar="${this.dataset.cwLock}"]`) | |
| input.disabled = true | |
| input.value = '' | |
| this.disabled = true | |
| this.innerText = 'calculated!' | |
| updateCalculation(); | |
| } | |
| function changeCourse() { | |
| const acronym = document.querySelector('#course-list').value | |
| const course = courseData[acronym]; | |
| const courseEl = document.querySelector('#course-descriptor') | |
| console.log('changed course') | |
| if (!course) { | |
| courseEl.style.display = 'none' | |
| return; | |
| } | |
| courseEl.style.display = null; | |
| courseEl.setAttribute('href', course.euclid_url) | |
| if (course.cw_exam_ratio === null) { | |
| showCalculatorError("course.inf.ed.ac.uk is missing a cw/exam ratio for this course"); | |
| return; | |
| } | |
| getEl('w8', 'cw').value = course.cw_exam_ratio[0] | |
| getEl('w8', 'exam').value = course.cw_exam_ratio[1] | |
| updateCalculation(); | |
| } | |
| function loadCourseCalculator() { | |
| document.querySelector('#course-list').addEventListener('change', changeCourse) | |
| document.querySelectorAll('[data-cw-tar]').forEach(el => el.addEventListener('input', updateCalculation)) | |
| document.querySelectorAll('[data-cw-w8]' ).forEach(el => el.addEventListener('input', updateCalculation)) | |
| document.querySelectorAll('[data-cw-lock]').forEach(el => el.addEventListener('click', handleLock)) | |
| // fire handler to initially populate the locks | |
| handleLock.bind(document.querySelector('[data-cw-lock]'))() | |
| } | |
| window.addEventListener('load', loadCourseCalculator) | |
| </script> |