[
{
"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\""
}
]