# Determine Beckett Grading Service (BGS) Final Grade

## Charcoal, ~~73~~ 71 bytes

```
≦⊗θ≔⌊θη≔⁻⌊Φθ⁻κ⌕θηηζＩ⊘⁺η∧ζ⎇⌕θη∨⎇⊖⌕θη∨›²ζ∨∧⁼²ζ‹¹⁶η∧⁼³⁻⌈θη›²⁰⌈θ›⁶ζ²⊕⌊⟦²÷ζ⁴
```

Try it online! Link is to verbose version of code. Takes input as an array of 4 values [Centring, Corners, Edges, Surface]. Explanation:

```
≦⊗θ
```

Double all the values so we're dealing in grade points rather than grades.

```
≔⌊θη
```

Find the worst grade.

```
≔⁻⌊Φθ⁻κ⌕θηηζ
```

Find the worst of the other grades, i.e. the second worst, and subtract the worst grade.

```
Ｉ⊘
```

Halve the final value and cast to string for display.

```
⁺η
```

Add the bonus to the minimum grade.

```
∧ζ
```

No bonus if the worst two grades are the same.

```
⎇⌕θη
```

Check whether the worst grade was for Centring.

```
∨⎇⊖⌕θη∨›²ζ∨∧⁼²ζ‹¹⁶η∧⁼³⁻⌈θη›²⁰⌈θ›⁶ζ²
```

If not then check whether only one bonus point should be awarded otherwise award two bonus points. (If the worst grade was for Corners then add a bonus point if the difference was less than 6 grade points or 2 if it was 6 or more. The calculation for Edges and Surface is longer but still only adds one or two bonus points.)

```
⊕⌊⟦²÷ζ⁴
```

If the worst grade was for Centring then add a bonus point for every 4 grade points between the worst two grades up to 2, plus a further bonus point.

## Perl 5 (`-ap`

), ~~157~~ 154 bytes

minor improvements `!$d?0:...`

inverted to `$d?...:0`

, `>=9.5`

changed to `>9.4`

and `!=10`

to `<10`

```
($w,$x,$y,$z)=sort{$b<=>$a}@F;$d=$y-$z;$_=$z+=$d?$z==$F[2]|$z==$F[3]?$d<1?.5:$d==1&$z+1>9.4|$w-$z==1.5&$w<10?.5:1:$z==$F[0]?$d<2?.5:$d<4?1:1.5:$d<3?.5:1:0
```

TIO

first answer was

```
($w,$x,$y,$z)=sort{$b<=>$a}@F;$d=$y-$z;$_=$z+=!$d?0:$z==$F[2]|$z==$F[3]?$d<1?.5:$d==1&$z+1>=9.5|$w-$z==1.5&$w!=10?.5:1:$z==$F[0]?$d<2?.5:$d<4?1:1.5:$d<3?.5:1
```

straight forward, ungolfed

```
!$d?0
:$z==$F[2]|$z==$F[3]?
$d<1?.5
:$d==1&$z+1>=9.5|$w-$z==1.5&$w!=10?.5
:1
:$z==$F[0]?
$d<2?.5
:$d<4?1
:1.5
:$d<3?.5
:1
```

TIO

## JavaScript (V8), ~~160 159 154~~ 151 bytes

```
s=>{[C,O,E,S]=[...s];[a,b,c,d]=s.sort((a,b)=>b-a);e=c-d;return(e?d==E|d==S?e<1?.5:(e==1&d>8.4)|(a-d==1.5&a<10)?.5:1:d-C?e<3?.5:1:e<2?.5:e<4?1:1.5:0)+d}
```

Try it online!

### A bit ungolfed:

```
function calculateScore(score) {
[center,corner,edge,surface] = [...score]; // makes a copy because sort is in-place
[first,second,third,fourth] = score.sort((a,b)=>b-a); // standard sort is alphabetically, this will sort by value
diff = third - fourth;
return fourth + (// Every final score is fourth + something else
diff != 0
? fourth == edge || fourth == surface
? diff < 1
? 0.5
: (diff == 1 && fourth >= 8.5) || (first-fourth == 1.5 && a < 10)
? 0.5
: 1
: fourth != corner
? diff < 3
? 0.5
: 1
: diff < 2
? 0.5
: diff < 4
? 1
: 1.5
: 0 // diff == 0
);
}
```

- -1:
`>=8.5`

->`>8.4`

- -5 thanks to @Kevin Cruijssen
- -3 for ES6 copying with
`[...s]`