Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 65 additions & 65 deletions lib/utils/checkout_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,40 +28,40 @@ abstract final class CheckoutHelper {
16: ['D8'],
17: ['S1', 'D8'],
18: ['D9'],
19: ['S3', 'D8'],
19: ['S1', 'D9'],
20: ['D10'],
21: ['S1', 'D10'],
22: ['D11'],
23: ['S7', 'D8'],
23: ['S1', 'D11'],
24: ['D12'],
25: ['S9', 'D8'],
25: ['S1', 'D12'],
26: ['D13'],
27: ['S3', 'D12'],
27: ['S1', 'D13'],
28: ['D14'],
29: ['S1', 'D14'],
30: ['D15'],
31: ['S7', 'D12'],
31: ['S1', 'D15'],
32: ['D16'],
33: ['S1', 'D16'],
34: ['D17'],
35: ['S3', 'D16'],
35: ['S1', 'D17'],
36: ['D18'],
37: ['S1', 'D18'],
38: ['D19'],
39: ['S7', 'D16'],
39: ['S1', 'D19'],
40: ['D20'],
41: ['S1', 'D20'],
42: ['D21'], // outer bull D21 doesn't exist — S10, D16
43: ['S3', 'D20'],
44: ['D22'], // S4, D20
45: ['S5', 'D20'],
41: ['S9', 'D16'],
42: ['S10', 'D16'],
43: ['S11', 'D16'],
44: ['S12', 'D16'],
45: ['S13', 'D16'],
46: ['S6', 'D20'],
47: ['S7', 'D20'],
48: ['D24'],
47: ['S15', 'D16'],
48: ['S8', 'D20'],
49: ['S9', 'D20'],
50: ['Bull'],
50: ['S10', 'D20'],
51: ['S11', 'D20'],
52: ['D16', 'D10'], // S12, D20
52: ['S12', 'D20'],
53: ['S13', 'D20'],
54: ['S14', 'D20'],
55: ['S15', 'D20'],
Expand All @@ -70,27 +70,27 @@ abstract final class CheckoutHelper {
58: ['S18', 'D20'],
59: ['S19', 'D20'],
60: ['S20', 'D20'],
61: ['S1', 'Bull'], // or T15, D8
62: ['S2', 'Bull'],
63: ['S3', 'Bull'], // or T13, D12
61: ['T15', 'D8'],
62: ['T10', 'D16'],
63: ['T17', 'D6'],
64: ['T16', 'D8'],
65: ['T15', 'D10'],
65: ['T11', 'D16'],
66: ['T10', 'D18'],
67: ['T17', 'D8'],
68: ['T12', 'D16'], // or T20, D4
69: ['T19', 'D6'], // or T15, D12
70: ['T18', 'D8'], // or T10, D20
67: ['T9', 'D20'],
68: ['T16', 'D10'],
69: ['T19', 'D6'],
70: ['T18', 'D8'],
71: ['T13', 'D16'],
72: ['T12', 'D18'], // or T16, D12
72: ['T16', 'D12'],
73: ['T19', 'D8'],
74: ['T14', 'D16'],
75: ['T17', 'D12'], // or T15, D15
76: ['T20', 'D8'],
77: ['T19', 'D10'], // or T7, D28 (not valid) — T15, D16
75: ['T17', 'D12'],
76: ['T16', 'D14'],
77: ['T19', 'D10'],
78: ['T18', 'D12'],
79: ['T13', 'D20'],
79: ['T19', 'D11'],
80: ['T20', 'D10'],
81: ['T19', 'D12'], // or T15, D18
81: ['T19', 'D12'],
82: ['T14', 'D20'],
83: ['T17', 'D16'],
84: ['T20', 'D12'],
Expand All @@ -108,50 +108,50 @@ abstract final class CheckoutHelper {
96: ['T20', 'D18'],
97: ['T19', 'D20'],
98: ['T20', 'D19'],
99: ['T19', 'D21'], // T19, S10, D16 — use T19, Bull
99: ['T19', 'S10', 'D16'],
100: ['T20', 'D20'],
101: ['T17', 'D25'], // T17, Bull
102: ['T20', 'D21'], // T20, S2, D20
103: ['T19', 'D23'], // T19, S6, D20
104: ['T18', 'D25'], // T18, Bull
105: ['T20', 'D22'], // T20, S5, D20
106: ['T20', 'D23'], // T20, S6, D20
107: ['T19', 'D25'], // T19, Bull
108: ['T20', 'D24'], // T20, S8, D20
109: ['T20', 'D24'], // T19, S12, D20
110: ['T20', 'D25'], // T20, Bull
111: ['T20', 'S11', 'D20'],
112: ['T20', 'S12', 'D20'],
113: ['T20', 'S13', 'D20'],
101: ['T20', 'S9', 'D16'],
102: ['T20', 'S10', 'D16'],
103: ['T19', 'S6', 'D20'],
104: ['T16', 'S16', 'D20'],
105: ['T19', 'S16', 'D16'],
106: ['T20', 'S6', 'D20'],
107: ['T20', 'S15', 'D16'],
108: ['T20', 'S16', 'D16'],
109: ['T20', 'S9', 'D20'],
110: ['T20', 'S10', 'D20'],
111: ['T19', 'S14', 'D20'],
112: ['T20', 'S20', 'D16'],
113: ['T19', 'S16', 'D20'],
114: ['T20', 'S14', 'D20'],
115: ['T20', 'S15', 'D20'],
116: ['T20', 'S16', 'D20'],
115: ['T19', 'S18', 'D20'],
116: ['T19', 'S19', 'D20'],
117: ['T20', 'S17', 'D20'],
118: ['T20', 'S18', 'D20'],
119: ['T20', 'S19', 'D20'],
119: ['T19', 'T12', 'D13'],
120: ['T20', 'S20', 'D20'],
121: ['T20', 'S11', 'Bull'],
122: ['T18', 'T16', 'D14'], // T18, S14, D20 — simplified
123: ['T19', 'S6', 'Bull'],
124: ['T20', 'T4', 'D20'], // T20, S4 = not quite right
125: ['T20', 'S5', 'Bull'], // T25 doesn't exist
126: ['T19', 'S9', 'Bull'],
127: ['T20', 'S7', 'Bull'],
121: ['T20', 'T11', 'D14'],
122: ['T18', 'T20', 'D4'],
123: ['T19', 'T16', 'D9'],
124: ['T20', 'T16', 'D8'],
125: ['T18', 'T13', 'D16'],
126: ['T19', 'T19', 'D6'],
127: ['T20', 'T17', 'D8'],
128: ['T18', 'T14', 'D16'],
129: ['T19', 'T12', 'D12'],
130: ['T20', 'T10', 'D20'],
131: ['T20', 'S11', 'Bull'], // duplicate of 121 — T19, T14, D12
132: ['T20', 'T16', 'D12'],
133: ['T20', 'T7', 'D24'], // T20, T19, D8
129: ['T19', 'T12', 'D18'],
130: ['T20', 'T20', 'D5'],
131: ['T20', 'T13', 'D16'],
132: ['Outer', 'T19', 'Bull'],
133: ['T20', 'T19', 'D8'],
134: ['T20', 'T14', 'D16'],
135: ['T20', 'T15', 'D15'],
136: ['T20', 'T16', 'D14'],
137: ['T20', 'T19', 'D10'], // T20, T15, D16
135: ['Outer', 'T20', 'Bull'],
136: ['T20', 'T20', 'D8'],
137: ['T20', 'T15', 'D16'],
138: ['T20', 'T18', 'D12'],
139: ['T19', 'T14', 'D20'],
140: ['T20', 'T20', 'D20'],
139: ['T20', 'T13', 'D20'],
140: ['T20', 'T20', 'D10'],
141: ['T20', 'T19', 'D12'],
142: ['T20', 'T18', 'D14'],
142: ['T20', 'T14', 'D20'],
143: ['T20', 'T17', 'D16'],
144: ['T20', 'T20', 'D12'],
145: ['T20', 'T19', 'D14'],
Expand Down
1 change: 0 additions & 1 deletion lib/utils/score_validator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ abstract final class ScoreValidator {
if (multiplierType == MultiplierType.outerBull) return 25;
if (multiplierType == MultiplierType.miss) return 0;
if (!isValidSector(rawValue)) return null;
if (multiplierType == MultiplierType.triple && rawValue == 25) return null; // no triple bull
return MultiplierType.computeScore(rawValue, multiplierType);
}

Expand Down
46 changes: 33 additions & 13 deletions test/game_logic_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ void main() {
expect(CheckoutHelper.getSuggestion(40), ['D20']);
});

test('Bull = 50', () {
expect(CheckoutHelper.getSuggestion(50), ['Bull']);
test('Bull = S10 D20', () {
expect(CheckoutHelper.getSuggestion(50), ['S10', 'D20']);
});

test('170 = T20 T20 Bull', () {
Expand All @@ -190,17 +190,37 @@ void main() {
expect(CheckoutHelper.getSuggestion(100), ['T20', 'D20']);
});

test('no checkout for 169', () {
expect(CheckoutHelper.getSuggestion(169), null);
});

test('no checkout for 1', () {
expect(CheckoutHelper.getSuggestion(1), null);
});

test('hasCheckout returns false for impossible scores', () {
expect(CheckoutHelper.hasCheckout(169), false);
expect(CheckoutHelper.hasCheckout(168), false);
test ('all suggestions are arithmetically correct, getSuggestion returns null and hasCheckout returns false for impossible scores', () {
for (int i = 1; i < 171; i++) {
List<String>? output = CheckoutHelper.getSuggestion(i);
bool checkoutAvailable = CheckoutHelper.hasCheckout(i);
if (i == 1 || i == 159 || i == 162 || i == 163 || i == 165 || i == 166 || i == 168 || i == 169) {
expect(output, null);
expect(checkoutAvailable, false);
} else if (output != null) {
int sum = 0;
for (var element in output) {
if (element == 'Bull') {
sum += 50;
} else if (element == 'Outer') {
sum += 25;
} else {
final type = element[0];
if (type == 'S') {
sum += int.parse((element.substring(1)));
} else if (type == 'D') {
sum += 2 * int.parse(element.substring(1));
} else if (type == 'T') {
sum += 3 * int.parse(element.substring(1));
}
}
}
expect(i, sum);
expect(checkoutAvailable, true);
} else {
fail('null checkout suggestion despite possible score, $i');
}
}
});
});

Expand Down