Functional Weave
Code in TypeScript

education.weighted-grade@1.0.0

vectors.json

8,247 bytes · view raw

[
 {
  "name": "coursework 45/60 at 40% and exam 88/120 at 60% is exactly 74%",
  "args": [
   [
    {
     "name": "coursework",
     "mark": 45,
     "outOf": 60,
     "weightBasisPoints": 4000
    },
    {
     "name": "exam",
     "mark": 88,
     "outOf": 120,
     "weightBasisPoints": 6000
    }
   ],
   1,
   "half-up"
  ],
  "expect": {
   "percent": {
    "numerator": 74,
    "denominator": 1
   },
   "scaled": 740,
   "decimals": 1
  }
 },
 {
  "name": "equal-ish thirds with the extra basis point on the exam",
  "args": [
   [
    {
     "name": "essay",
     "mark": 50,
     "outOf": 100,
     "weightBasisPoints": 3333
    },
    {
     "name": "project",
     "mark": 60,
     "outOf": 100,
     "weightBasisPoints": 3333
    },
    {
     "name": "exam",
     "mark": 71,
     "outOf": 100,
     "weightBasisPoints": 3334
    }
   ],
   2,
   "half-up"
  ],
  "expect": {
   "percent": {
    "numerator": 37709,
    "denominator": 625
   },
   "scaled": 6033,
   "decimals": 2
  }
 },
 {
  "name": "an exact half rounds up under half-up",
  "args": [
   [
    {
     "name": "paper 1",
     "mark": 69,
     "outOf": 100,
     "weightBasisPoints": 5000
    },
    {
     "name": "paper 2",
     "mark": 70,
     "outOf": 100,
     "weightBasisPoints": 5000
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "percent": {
    "numerator": 139,
    "denominator": 2
   },
   "scaled": 70,
   "decimals": 0
  }
 },
 {
  "name": "the same half truncates under down",
  "args": [
   [
    {
     "name": "paper 1",
     "mark": 69,
     "outOf": 100,
     "weightBasisPoints": 5000
    },
    {
     "name": "paper 2",
     "mark": 70,
     "outOf": 100,
     "weightBasisPoints": 5000
    }
   ],
   0,
   "down"
  ],
  "expect": {
   "percent": {
    "numerator": 139,
    "denominator": 2
   },
   "scaled": 69,
   "decimals": 0
  }
 },
 {
  "name": "68.5 goes to the even 68 under half-even",
  "args": [
   [
    {
     "name": "paper 1",
     "mark": 68,
     "outOf": 100,
     "weightBasisPoints": 5000
    },
    {
     "name": "paper 2",
     "mark": 69,
     "outOf": 100,
     "weightBasisPoints": 5000
    }
   ],
   0,
   "half-even"
  ],
  "expect": {
   "percent": {
    "numerator": 137,
    "denominator": 2
   },
   "scaled": 68,
   "decimals": 0
  }
 },
 {
  "name": "68.5 goes to 69 under half-up",
  "args": [
   [
    {
     "name": "paper 1",
     "mark": 68,
     "outOf": 100,
     "weightBasisPoints": 5000
    },
    {
     "name": "paper 2",
     "mark": 69,
     "outOf": 100,
     "weightBasisPoints": 5000
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "percent": {
    "numerator": 137,
    "denominator": 2
   },
   "scaled": 69,
   "decimals": 0
  }
 },
 {
  "name": "10/30 and 29/300 at 50% each is exactly 21.5, which floats make 21.4999... and round to 21",
  "args": [
   [
    {
     "name": "quiz",
     "mark": 10,
     "outOf": 30,
     "weightBasisPoints": 5000
    },
    {
     "name": "lab",
     "mark": 29,
     "outOf": 300,
     "weightBasisPoints": 5000
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "percent": {
    "numerator": 43,
    "denominator": 2
   },
   "scaled": 22,
   "decimals": 0
  }
 },
 {
  "name": "a repeating two-thirds at two places, half-up",
  "args": [
   [
    {
     "name": "exam",
     "mark": 2,
     "outOf": 3,
     "weightBasisPoints": 10000
    }
   ],
   2,
   "half-up"
  ],
  "expect": {
   "percent": {
    "numerator": 200,
    "denominator": 3
   },
   "scaled": 6667,
   "decimals": 2
  }
 },
 {
  "name": "the same two-thirds cut down",
  "args": [
   [
    {
     "name": "exam",
     "mark": 2,
     "outOf": 3,
     "weightBasisPoints": 10000
    }
   ],
   2,
   "down"
  ],
  "expect": {
   "percent": {
    "numerator": 200,
    "denominator": 3
   },
   "scaled": 6666,
   "decimals": 2
  }
 },
 {
  "name": "the same two-thirds rounded up to whole marks",
  "args": [
   [
    {
     "name": "exam",
     "mark": 2,
     "outOf": 3,
     "weightBasisPoints": 10000
    }
   ],
   0,
   "up"
  ],
  "expect": {
   "percent": {
    "numerator": 200,
    "denominator": 3
   },
   "scaled": 67,
   "decimals": 0
  }
 },
 {
  "name": "no marks at all",
  "args": [
   [
    {
     "name": "exam",
     "mark": 0,
     "outOf": 50,
     "weightBasisPoints": 10000
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "percent": {
    "numerator": 0,
    "denominator": 1
   },
   "scaled": 0,
   "decimals": 0
  }
 },
 {
  "name": "full marks",
  "args": [
   [
    {
     "name": "exam",
     "mark": 50,
     "outOf": 50,
     "weightBasisPoints": 10000
    }
   ],
   1,
   "half-up"
  ],
  "expect": {
   "percent": {
    "numerator": 100,
    "denominator": 1
   },
   "scaled": 1000,
   "decimals": 1
  }
 },
 {
  "name": "a zero-weight formative piece adds nothing",
  "args": [
   [
    {
     "name": "formative",
     "mark": 0,
     "outOf": 10,
     "weightBasisPoints": 0
    },
    {
     "name": "exam",
     "mark": 80,
     "outOf": 100,
     "weightBasisPoints": 10000
    }
   ],
   1,
   "half-up"
  ],
  "expect": {
   "percent": {
    "numerator": 80,
    "denominator": 1
   },
   "scaled": 800,
   "decimals": 1
  }
 },
 {
  "name": "weights totalling 99.99% are an error",
  "args": [
   [
    {
     "name": "coursework",
     "mark": 45,
     "outOf": 60,
     "weightBasisPoints": 4000
    },
    {
     "name": "exam",
     "mark": 88,
     "outOf": 120,
     "weightBasisPoints": 5999
    }
   ],
   1,
   "half-up"
  ],
  "expectError": "weights must add up to 10000 basis points (100%), received 9999"
 },
 {
  "name": "a mark above outOf is an error",
  "args": [
   [
    {
     "name": "coursework",
     "mark": 61,
     "outOf": 60,
     "weightBasisPoints": 4000
    },
    {
     "name": "exam",
     "mark": 88,
     "outOf": 120,
     "weightBasisPoints": 6000
    }
   ],
   1,
   "half-up"
  ],
  "expectError": "mark must be a whole number from 0 to outOf (60), received 61"
 },
 {
  "name": "a half mark is an error",
  "args": [
   [
    {
     "name": "coursework",
     "mark": 44.5,
     "outOf": 60,
     "weightBasisPoints": 4000
    },
    {
     "name": "exam",
     "mark": 88,
     "outOf": 120,
     "weightBasisPoints": 6000
    }
   ],
   1,
   "half-up"
  ],
  "expectError": "mark must be a whole number from 0 to outOf (60), received 44.5"
 },
 {
  "name": "a negative mark is an error",
  "args": [
   [
    {
     "name": "coursework",
     "mark": -1,
     "outOf": 60,
     "weightBasisPoints": 4000
    },
    {
     "name": "exam",
     "mark": 88,
     "outOf": 120,
     "weightBasisPoints": 6000
    }
   ],
   1,
   "half-up"
  ],
  "expectError": "mark must be a whole number from 0 to outOf (60), received -1"
 },
 {
  "name": "outOf of zero is an error",
  "args": [
   [
    {
     "name": "exam",
     "mark": 0,
     "outOf": 0,
     "weightBasisPoints": 10000
    }
   ],
   1,
   "half-up"
  ],
  "expectError": "outOf must be a whole number of 1 or more, received 0"
 },
 {
  "name": "a negative weight is an error",
  "args": [
   [
    {
     "name": "coursework",
     "mark": 45,
     "outOf": 60,
     "weightBasisPoints": -1
    },
    {
     "name": "exam",
     "mark": 88,
     "outOf": 120,
     "weightBasisPoints": 10001
    }
   ],
   1,
   "half-up"
  ],
  "expectError": "weightBasisPoints must be a whole number of 0 or more, received -1"
 },
 {
  "name": "no components is an error",
  "args": [
   [],
   1,
   "half-up"
  ],
  "expectError": "components must not be empty"
 },
 {
  "name": "seven decimal places is an error",
  "args": [
   [
    {
     "name": "coursework",
     "mark": 45,
     "outOf": 60,
     "weightBasisPoints": 4000
    },
    {
     "name": "exam",
     "mark": 88,
     "outOf": 120,
     "weightBasisPoints": 6000
    }
   ],
   7,
   "half-up"
  ],
  "expectError": "decimals must be a whole number from 0 to 6, received 7"
 },
 {
  "name": "an unknown rounding mode is an error",
  "args": [
   [
    {
     "name": "coursework",
     "mark": 45,
     "outOf": 60,
     "weightBasisPoints": 4000
    },
    {
     "name": "exam",
     "mark": 88,
     "outOf": 120,
     "weightBasisPoints": 6000
    }
   ],
   1,
   "nearest"
  ],
  "expectError": "unknown rounding mode \"nearest\""
 }
]