Functional Weave
Code in Python

education.degree-classification@1.0.0

vectors.json

13,701 bytes · view raw

[
 {
  "name": "level 5 at 1 and level 6 at 2: 63 and 70.33 make 67.89, a 2:1 (credits alone would say 66.67)",
  "args": [
   [
    {
     "level": 5,
     "mark": 65,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 58,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 72,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 61,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 55,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 67,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 71,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 68,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 74,
     "credits": 40
    },
    {
     "level": 6,
     "mark": 66,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 69,
     "credits": 20
    }
   ],
   [
    {
     "level": 5,
     "weight": 1
    },
    {
     "level": 6,
     "weight": 2
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "average": {
    "numerator": 611,
    "denominator": 9
   },
   "scaled": 68,
   "decimals": 0,
   "classification": "upper-second",
   "label": "Upper second (2:1)",
   "countedCredits": 240
  }
 },
 {
  "name": "first-year modules are left out when level 4 is not weighted",
  "args": [
   [
    {
     "level": 4,
     "mark": 30,
     "credits": 120
    },
    {
     "level": 5,
     "mark": 65,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 58,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 72,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 61,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 55,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 67,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 71,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 68,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 74,
     "credits": 40
    },
    {
     "level": 6,
     "mark": 66,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 69,
     "credits": 20
    }
   ],
   [
    {
     "level": 5,
     "weight": 1
    },
    {
     "level": 6,
     "weight": 2
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "average": {
    "numerator": 611,
    "denominator": 9
   },
   "scaled": 68,
   "decimals": 0,
   "classification": "upper-second",
   "label": "Upper second (2:1)",
   "countedCredits": 240
  }
 },
 {
  "name": "50:50 in basis points",
  "args": [
   [
    {
     "level": 5,
     "mark": 65,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 58,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 72,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 61,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 55,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 67,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 71,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 68,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 74,
     "credits": 40
    },
    {
     "level": 6,
     "mark": 66,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 69,
     "credits": 20
    }
   ],
   [
    {
     "level": 5,
     "weight": 5000
    },
    {
     "level": 6,
     "weight": 5000
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "average": {
    "numerator": 200,
    "denominator": 3
   },
   "scaled": 67,
   "decimals": 0,
   "classification": "upper-second",
   "label": "Upper second (2:1)",
   "countedCredits": 240
  }
 },
 {
  "name": "final year only: a large module counts double its credits, 70.33 is a First",
  "args": [
   [
    {
     "level": 5,
     "mark": 65,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 58,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 72,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 61,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 55,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 67,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 71,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 68,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 74,
     "credits": 40
    },
    {
     "level": 6,
     "mark": 66,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 69,
     "credits": 20
    }
   ],
   [
    {
     "level": 5,
     "weight": 0
    },
    {
     "level": 6,
     "weight": 1
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "average": {
    "numerator": 211,
    "denominator": 3
   },
   "scaled": 70,
   "decimals": 0,
   "classification": "first",
   "label": "First",
   "countedCredits": 120
  }
 },
 {
  "name": "69.5 rounded to a whole mark is a First",
  "args": [
   [
    {
     "level": 6,
     "mark": 69,
     "credits": 60
    },
    {
     "level": 6,
     "mark": 70,
     "credits": 60
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "average": {
    "numerator": 139,
    "denominator": 2
   },
   "scaled": 70,
   "decimals": 0,
   "classification": "first",
   "label": "First",
   "countedCredits": 120
  }
 },
 {
  "name": "the same 69.5 rounded to one place stays a 2:1",
  "args": [
   [
    {
     "level": 6,
     "mark": 69,
     "credits": 60
    },
    {
     "level": 6,
     "mark": 70,
     "credits": 60
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    }
   ],
   1,
   "half-up"
  ],
  "expect": {
   "average": {
    "numerator": 139,
    "denominator": 2
   },
   "scaled": 695,
   "decimals": 1,
   "classification": "upper-second",
   "label": "Upper second (2:1)",
   "countedCredits": 120
  }
 },
 {
  "name": "the same 69.5 truncated stays a 2:1",
  "args": [
   [
    {
     "level": 6,
     "mark": 69,
     "credits": 60
    },
    {
     "level": 6,
     "mark": 70,
     "credits": 60
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    }
   ],
   0,
   "down"
  ],
  "expect": {
   "average": {
    "numerator": 139,
    "denominator": 2
   },
   "scaled": 69,
   "decimals": 0,
   "classification": "upper-second",
   "label": "Upper second (2:1)",
   "countedCredits": 120
  }
 },
 {
  "name": "exactly 60 is a 2:1",
  "args": [
   [
    {
     "level": 6,
     "mark": 60,
     "credits": 40
    },
    {
     "level": 6,
     "mark": 59,
     "credits": 40
    },
    {
     "level": 6,
     "mark": 61,
     "credits": 40
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "average": {
    "numerator": 60,
    "denominator": 1
   },
   "scaled": 60,
   "decimals": 0,
   "classification": "upper-second",
   "label": "Upper second (2:1)",
   "countedCredits": 120
  }
 },
 {
  "name": "exactly 50 is a 2:2",
  "args": [
   [
    {
     "level": 6,
     "mark": 50,
     "credits": 120
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "average": {
    "numerator": 50,
    "denominator": 1
   },
   "scaled": 50,
   "decimals": 0,
   "classification": "lower-second",
   "label": "Lower second (2:2)",
   "countedCredits": 120
  }
 },
 {
  "name": "exactly 40 is a Third",
  "args": [
   [
    {
     "level": 6,
     "mark": 40,
     "credits": 120
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "average": {
    "numerator": 40,
    "denominator": 1
   },
   "scaled": 40,
   "decimals": 0,
   "classification": "third",
   "label": "Third",
   "countedCredits": 120
  }
 },
 {
  "name": "39 is below a Third",
  "args": [
   [
    {
     "level": 6,
     "mark": 39,
     "credits": 120
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "average": {
    "numerator": 39,
    "denominator": 1
   },
   "scaled": 39,
   "decimals": 0,
   "classification": "unclassified",
   "label": "Unclassified",
   "countedCredits": 120
  }
 },
 {
  "name": "full marks",
  "args": [
   [
    {
     "level": 6,
     "mark": 100,
     "credits": 120
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "average": {
    "numerator": 100,
    "denominator": 1
   },
   "scaled": 100,
   "decimals": 0,
   "classification": "first",
   "label": "First",
   "countedCredits": 120
  }
 },
 {
  "name": "zero",
  "args": [
   [
    {
     "level": 6,
     "mark": 0,
     "credits": 120
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    }
   ],
   0,
   "half-up"
  ],
  "expect": {
   "average": {
    "numerator": 0,
    "denominator": 1
   },
   "scaled": 0,
   "decimals": 0,
   "classification": "unclassified",
   "label": "Unclassified",
   "countedCredits": 120
  }
 },
 {
  "name": "a mark above 100 is an error",
  "args": [
   [
    {
     "level": 6,
     "mark": 101,
     "credits": 120
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    }
   ],
   0,
   "half-up"
  ],
  "expectError": "mark must be a whole number from 0 to 100, received 101"
 },
 {
  "name": "a half mark is an error",
  "args": [
   [
    {
     "level": 6,
     "mark": 69.5,
     "credits": 120
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    }
   ],
   0,
   "half-up"
  ],
  "expectError": "mark must be a whole number from 0 to 100, received 69.5"
 },
 {
  "name": "zero credits is an error",
  "args": [
   [
    {
     "level": 6,
     "mark": 60,
     "credits": 0
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    }
   ],
   0,
   "half-up"
  ],
  "expectError": "credits must be a whole number of 1 or more, received 0"
 },
 {
  "name": "no level weights is an error",
  "args": [
   [
    {
     "level": 6,
     "mark": 71,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 68,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 74,
     "credits": 40
    },
    {
     "level": 6,
     "mark": 66,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 69,
     "credits": 20
    }
   ],
   [],
   0,
   "half-up"
  ],
  "expectError": "levelWeights must name at least one level"
 },
 {
  "name": "a level weighted twice is an error",
  "args": [
   [
    {
     "level": 6,
     "mark": 71,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 68,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 74,
     "credits": 40
    },
    {
     "level": 6,
     "mark": 66,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 69,
     "credits": 20
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    },
    {
     "level": 6,
     "weight": 2
    }
   ],
   0,
   "half-up"
  ],
  "expectError": "level 6 appears twice in levelWeights"
 },
 {
  "name": "a negative weight is an error",
  "args": [
   [
    {
     "level": 6,
     "mark": 71,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 68,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 74,
     "credits": 40
    },
    {
     "level": 6,
     "mark": 66,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 69,
     "credits": 20
    }
   ],
   [
    {
     "level": 6,
     "weight": -1
    }
   ],
   0,
   "half-up"
  ],
  "expectError": "weight must be a whole number of 0 or more, received -1 for level 6"
 },
 {
  "name": "all-zero weights are an error",
  "args": [
   [
    {
     "level": 6,
     "mark": 71,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 68,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 74,
     "credits": 40
    },
    {
     "level": 6,
     "mark": 66,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 69,
     "credits": 20
    }
   ],
   [
    {
     "level": 6,
     "weight": 0
    }
   ],
   0,
   "half-up"
  ],
  "expectError": "levelWeights must not all be zero"
 },
 {
  "name": "a weighted level with no modules is an error",
  "args": [
   [
    {
     "level": 5,
     "mark": 65,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 58,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 72,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 61,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 55,
     "credits": 20
    },
    {
     "level": 5,
     "mark": 67,
     "credits": 20
    }
   ],
   [
    {
     "level": 5,
     "weight": 1
    },
    {
     "level": 6,
     "weight": 2
    }
   ],
   0,
   "half-up"
  ],
  "expectError": "no modules at level 6, which levelWeights counts"
 },
 {
  "name": "seven decimal places is an error",
  "args": [
   [
    {
     "level": 6,
     "mark": 71,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 68,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 74,
     "credits": 40
    },
    {
     "level": 6,
     "mark": 66,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 69,
     "credits": 20
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    }
   ],
   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": [
   [
    {
     "level": 6,
     "mark": 71,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 68,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 74,
     "credits": 40
    },
    {
     "level": 6,
     "mark": 66,
     "credits": 20
    },
    {
     "level": 6,
     "mark": 69,
     "credits": 20
    }
   ],
   [
    {
     "level": 6,
     "weight": 1
    }
   ],
   0,
   "nearest"
  ],
  "expectError": "unknown rounding mode \"nearest\""
 }
]