Skip to content

Commit 246b885

Browse files
committed
Write the tests for StandingsRepo and fix its bugs. Change the way of sorting items in positions map creators.
1 parent 294d538 commit 246b885

File tree

3 files changed

+153
-16
lines changed

3 files changed

+153
-16
lines changed

lib/models/db/event_series/standings/standings_positions_map_creator/standings_positions_with_ex_aequos_creator.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ class StandingsPositionsWithExAequosCreator<T extends StandingsRecord>
1313
}
1414

1515
void _sortRecords() {
16-
_records.sort((a, b) => b.compareTo(a));
16+
_records.sort((a, b) {
17+
if (a.score > b.score) return -1;
18+
if (a.score < b.score) return 1;
19+
return 0; // Maintain original order if scores are equal
20+
});
1721
}
1822

1923
Map<int, List<T>> _generatePositionsMap() {

lib/models/db/event_series/standings/standings_repo.dart

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class StandingsRepo<E, S extends Score, R extends StandingsRecord<E, S>>
88
implements ValueRepo<Map<int, List<R>>> {
99
StandingsRepo({required this.positionsCreator, List<R>? initialRecords}) {
1010
if (initialRecords != null) {
11-
_records = initialRecords;
11+
_records = List.of(initialRecords);
1212
_updateStandings();
1313
set(_standings);
1414
}
@@ -28,12 +28,18 @@ class StandingsRepo<E, S extends Score, R extends StandingsRecord<E, S>>
2828
}
2929
}
3030

31-
if (recordToChange != null) {
32-
throw StateError('Standings does not have the entiy (${newRecord.entity})');
31+
if (recordToChange == null) {
32+
_records.add(newRecord);
33+
} else {
34+
_records[_records.indexOf(recordToChange)] = newRecord;
3335
}
3436

35-
_records[_records.indexOf(recordToChange!)] = newRecord;
37+
_updateStandings();
38+
set(_standings);
39+
}
3640

41+
void remove({required R record}) {
42+
_records.remove(record);
3743
_updateStandings();
3844
set(_standings);
3945
}
@@ -42,6 +48,10 @@ class StandingsRepo<E, S extends Score, R extends StandingsRecord<E, S>>
4248
_standings = positionsCreator.create(_records);
4349
}
4450

51+
List<R> get leaders {
52+
return atPosition(1);
53+
}
54+
4555
List<R> atPosition(int position) {
4656
if (!_standings.containsKey(position)) {
4757
throw StateError('Standings does not have any entity at $position position');
@@ -50,28 +60,40 @@ class StandingsRepo<E, S extends Score, R extends StandingsRecord<E, S>>
5060
}
5161

5262
int positionOf(E entity) {
53-
int? toReturn;
54-
_standings.forEach((position, entities) {
55-
if (entities.contains(entity)) {
56-
toReturn = position;
63+
for (var entry in _standings.entries) {
64+
bool hasRecordWithEntity =
65+
entry.value.where((record) => record.entity == entity).length == 1;
66+
if (hasRecordWithEntity) {
67+
return entry.key;
5768
}
58-
});
59-
if (toReturn == null) {
60-
throw StateError('The entity ($entity) is not contained by standings');
6169
}
62-
return toReturn!;
70+
throw _notContainEntityError(entity);
6371
}
6472

65-
S? scoreOf(E entity) {
73+
S scoreOf(E entity) {
6674
for (var record in _records) {
6775
if (record.entity == entity) {
6876
return record.score;
6977
}
7078
}
71-
return null;
79+
throw _notContainEntityError(entity);
7280
}
7381

74-
int get length => last.length;
82+
Error _notContainEntityError(E entity) {
83+
return StateError('The entity ($entity) is not contained by standings');
84+
}
85+
86+
int get length => _records.length;
87+
88+
int get lastPosition {
89+
return _standings.keys.reduce((first, second) {
90+
if (second > first) {
91+
return second;
92+
} else {
93+
return first;
94+
}
95+
});
96+
}
7597

7698
bool containsEntity(E entity) {
7799
return _records.where((record) => record.entity == entity).isNotEmpty;
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:sj_manager/models/db/event_series/standings/score/basic_score_types.dart';
3+
import 'package:sj_manager/models/db/event_series/standings/standings_positions_map_creator/standings_positions_with_ex_aequos_creator.dart';
4+
import 'package:sj_manager/models/db/event_series/standings/standings_record.dart';
5+
import 'package:sj_manager/models/db/event_series/standings/standings_repo.dart';
6+
7+
void main() {
8+
group(StandingsRepo, () {
9+
late StandingsRepo<String, PointsScore, StandingsRecord<String, PointsScore>> repo;
10+
11+
test('Adding, editing and removing; updating standings', () {
12+
const stoch = StandingsRecord(entity: 'Kamil Stoch', score: PointsScore(315.5));
13+
const kubacki = StandingsRecord(entity: 'Dawid Kubacki', score: PointsScore(333.4));
14+
const zyla = StandingsRecord(entity: 'Piotr Żyła', score: PointsScore(315.5));
15+
const geiger = StandingsRecord(entity: 'Karl Geiger', score: PointsScore(330.0));
16+
const eisenbichler =
17+
StandingsRecord(entity: 'Markus Eisenbichler', score: PointsScore(350.1));
18+
19+
repo = StandingsRepo(
20+
positionsCreator: StandingsPositionsWithExAequosCreator(),
21+
initialRecords: const [stoch, kubacki, zyla],
22+
);
23+
24+
repo.update(newRecord: geiger);
25+
repo.update(newRecord: eisenbichler);
26+
expect(repo.leaders.single, eisenbichler);
27+
expect(repo.last.values.last, [stoch, zyla]); // Records at last position
28+
expect(repo.length, 5);
29+
repo.remove(record: eisenbichler);
30+
expect(repo.leaders.single, kubacki);
31+
expect(repo.length, 4);
32+
expect(repo.containsEntity('Markus Eisenbichler'), false);
33+
repo.update(newRecord: stoch.copyWith(score: const PointsScore(441.4)));
34+
expect(repo.leaders.single.entity, 'Kamil Stoch');
35+
expect(repo.length, 4);
36+
37+
repo.dispose();
38+
});
39+
40+
group('Repo view utilities', () {
41+
const kot = StandingsRecord(entity: 'Maciej Kot', score: PointsScore(116.4));
42+
const hula = StandingsRecord(entity: 'Stefan Hula', score: PointsScore(116.4));
43+
const kobayashi =
44+
StandingsRecord(entity: 'Ryoyu Kobayashi', score: PointsScore(137.8));
45+
const danielHuber =
46+
StandingsRecord(entity: 'Daniel Huber', score: PointsScore(137.8));
47+
const stefanHuber =
48+
StandingsRecord(entity: 'Stefan Huber', score: PointsScore(120.1));
49+
const wohlgenannt =
50+
StandingsRecord(entity: 'Ulrich Wohlgenannt', score: PointsScore(111.5));
51+
const kos = StandingsRecord(entity: 'Lovro Kos', score: PointsScore(127.5));
52+
const prevc = StandingsRecord(entity: 'Domen Prevc', score: PointsScore(114.9));
53+
const peier = StandingsRecord(entity: 'Killian Peier', score: PointsScore(110.8));
54+
55+
setUpAll(() {
56+
repo = StandingsRepo(
57+
positionsCreator: StandingsPositionsWithExAequosCreator(),
58+
initialRecords: const [
59+
kot,
60+
hula,
61+
kobayashi,
62+
danielHuber,
63+
stefanHuber,
64+
wohlgenannt,
65+
kos,
66+
prevc,
67+
peier,
68+
],
69+
);
70+
});
71+
72+
test('leaders', () {
73+
expect(repo.leaders, [kobayashi, danielHuber]);
74+
expect(() => repo.leaders.single, throwsA(isA<StateError>()));
75+
});
76+
77+
test('records by position', () {
78+
expect(repo.leaders, repo.atPosition(1));
79+
expect(repo.atPosition(4), [stefanHuber]);
80+
expect(() => repo.atPosition(0), throwsA(isA<StateError>()));
81+
expect(() => repo.atPosition(18), throwsA(isA<StateError>()));
82+
});
83+
84+
test('position by entity', () {
85+
expect(repo.positionOf('Ulrich Wohlgenannt'), 8);
86+
expect(repo.positionOf('Stefan Huber'), 4);
87+
expect(() => repo.positionOf('Karol Wojtyła'), throwsA(isA<StateError>()));
88+
});
89+
90+
test('score by entity', () {
91+
expect(repo.scoreOf('Domen Prevc'), const PointsScore(114.9));
92+
expect(repo.scoreOf('Daniel Huber'), const PointsScore(137.8));
93+
expect(() => repo.scoreOf('Peter Prevc'), throwsA(isA<StateError>()));
94+
});
95+
96+
test('length', () {
97+
expect(repo.length, 9);
98+
});
99+
100+
test('whether contains an entity', () {
101+
expect(repo.containsEntity('Stefan Hula'), true);
102+
expect(repo.containsEntity('Stefan Huber'), true);
103+
expect(repo.containsEntity('Junshiro Kobayashi'), false);
104+
});
105+
106+
tearDownAll(() {
107+
repo.dispose();
108+
});
109+
});
110+
});
111+
}

0 commit comments

Comments
 (0)