<!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> &middot;
        <a rel='license' href='https://opensource.org/licenses/mit-license.php'
           >MIT License</a> &middot; 
        May 2013
      </div>
    </footer>
  </body>
</html>