<!doctype html> <html> <head> <meta charset='utf-8'> <title>grade calculator</title> <link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Averia+Serif+Libre'> <!-- <link rel='stylesheet' href='http://fonts.googleapis.com/css?family=Averia+Libre'> --> <link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Anonymous+Pro'> <script src='https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js'></script> <script src='https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js'></script> <style> body { background: #f9fcf9 0px 0px no-repeat url('/images/random_background.png'); padding: 0; color: black; width: 90%; margin: 1em auto; font-family: 'Averia Serif Libre', serif; font-size: 100%; } .heading {font-size:75%;} .description {width:20em;} .percent {width:3em;} .grade {width:3em;} .score {width:3em; font-size: 60%;} #componentcount {width:2em;} table {border:0; font-family: 'Anonymous Pro', sans-serif;} pre { font-family: 'Anonymous Pro', sans-serif; background-color:#f4f4f4; border: 1px solid black; padding: 0.25em; font-size: 75%; float: right; } .msg {padding: 0 0 0 1em} #overall {text-align: right} td {padding:0.5em;} #logo {float: right;} #main {padding: 0 1em;} #line hr {border:0; height:1px; color: grey; background-color: grey;} footer {border-top: 1px solid grey; clear:both;} footer div {float:right; padding: 0.5em; font-size:80%;} </style> <script> (function(){ var gradescores = { 'A': 4.0, 'A-': 3.666, 'B+': 3.333, 'B': 3.0, 'B-': 2.666, 'C+': 2.333, 'C': 2.0, 'C-': 1.666, 'D+': 1.333, 'D': 1.0, 'F': 0.00 }; var grade_boundary_threshold = 0.02; var display_decimals = 3; var score2grade = function(score){ /* Given a score (e.g. 3.9) return a grade (e.g. 'A'). If the score is close to a boundary (e.g. 3.833) return e.g. 'A/A-' */ if (score < 0.833){ return 'F'; } var grade_diffs = _.sortBy( _.map(_.keys(gradescores), function(g){return [g, Math.abs(gradescores[g] - score)]}), function(pair){return pair[1]}); if (Math.abs(grade_diffs[0][1] - grade_diffs[1][1]) < grade_boundary_threshold){ return grade_diffs[0][0] + '/' + grade_diffs[1][0]; } else { return grade_diffs[0][0]; } }; var add_n_components = function(){ /* Update the HTML display to show n plan components. */ $('.extracomponent').remove(); var n_extras = parseInt($('#componentcount').val(), 10) - 1; for (var i = 0; i < n_extras; i++){ $('.plancomponent:first').clone().addClass('extracomponent').insertBefore('#summary'); } update_calculate_triggers(); }; var update_summary = function(grade, score){ /* Modify the web page to show the given summary grade and score. */ if (_.isFinite(score)){ score = score.toFixed(display_decimals); } $('#overallgrade').text(grade); $('#overallscore').text(score); }; var recalculate = function(){ /* Calculate and display the overall grade from the component percentages and grades */ var score = 0.0; var valid_score = true; var process_component = function(index){ component = $(this); var percent = parseInt( component.find('.percent').val() ); var grade = component.find('.grade').val(); if (_.has(gradescores, grade)){ component.find('.score').text(gradescores[grade].toFixed(display_decimals)); } else { component.find('.score').text(''); } if (_.isFinite(percent) && (_.has(gradescores, grade))) { score += (percent/100) * gradescores[grade]; } else { valid_score = false; } }; $('.plancomponent').each(process_component); if (valid_score){ update_summary(score2grade(score), score); } else { update_summary('?', ''); } }; var update_calculate_triggers = function(){ $('.percent,.grade').change(recalculate); }; $(function(){ $('#componentcount').change(add_n_components); update_calculate_triggers(); }); })(); </script> </head> <body> <div id='logo'> <a href='https://www.marlboro.edu/'> <img src='/images/mc-logo.gif' alt='Marlboro College'> </a> </div> <h2>Grade Calculator</h2> <div id='main'> <form> <table> <tr class='heading'> <td colspan=2 class='msg'>number of components : <input type='text' id='componentcount'></td> <td class='msg'>grade</td> <td></td> </tr> <tr class='plancomponent'> <td><input type='text' class='description'></td> <td><input type='text' class='percent'> % </td> <td><input type='text' class='grade'></td> <td><div class='score'></div></td> </tr> <tr id='summary'> <td colspan=2 class='msg' id='overall'>overall</td> <td class='msg' id='overallgrade'>-</td> <td class='msg score' id='overallscore'></td> </tr> </table> </form> <pre> A 4.000 (3.833 - 4.000) A- 3.666 (3.500 - 3.833) B+ 3.333 (3.166 - 3.500) B 3.000 (2.833 - 3.166) B- 2.666 (2.500 - 2.833) C+ 2.333 (2.166 - 2.500) C 2.000 (1.833 - 2.166) C- 1.666 (1.500 - 1.833) D+ 1.333 (1.166 - 1.500) D 1.000 (0.833 - 1.166) F 0.000 (0.000 - 0.833) </pre> </div> <footer> <div> <a class='url fn' href='/'>Jim Mahoney</a> · <a rel='license' href='https://opensource.org/licenses/mit-license.php' >MIT License</a> · May 2013 </div> </footer> </body> </html>