Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
julien4215 committed Dec 11, 2024
1 parent c2c931f commit e948d04
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 47 deletions.
12 changes: 12 additions & 0 deletions lib/src/model/broadcast/broadcast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,18 @@ class BroadcastPlayerExtended with _$BroadcastPlayerExtended {
}) = _BroadcastPlayerExtended;
}

enum BroadcastPoints { one, half, zero }

@freezed
class BroadcastPlayerResult with _$BroadcastPlayerResult {
const factory BroadcastPlayerResult({
required Side color,
required BroadcastPoints? points,
required int? ratingDiff,
required BroadcastPlayer opponent,
}) = _BroadcastPlayerResult;
}

enum RoundStatus {
live,
finished,
Expand Down
12 changes: 12 additions & 0 deletions lib/src/model/broadcast/broadcast_providers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ Future<IList<BroadcastPlayerExtended>> broadcastPlayers(
);
}

@riverpod
Future<IList<BroadcastPlayerResult>> broadcastPlayerResult(
Ref ref,
BroadcastTournamentId broadcastTournamentId,
FideId fideId,
) {
return ref.withClient(
(client) => BroadcastRepository(client)
.getPlayerResults(broadcastTournamentId, fideId),
);
}

@Riverpod(keepAlive: true)
BroadcastImageWorkerFactory broadcastImageWorkerFactory(Ref ref) {
return const BroadcastImageWorkerFactory();
Expand Down
37 changes: 36 additions & 1 deletion lib/src/model/broadcast/broadcast_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ class BroadcastRepository {
mapper: _makePlayerFromJson,
);
}

Future<IList<BroadcastPlayerResult>> getPlayerResults(
BroadcastTournamentId tournamentId,
FideId fideId,
) {
return client.readJson(
Uri(path: 'broadcast/$tournamentId/players/$fideId'),
mapper: _makePlayerResultsFromJson,
);
}
}

BroadcastList _makeBroadcastResponseFromJson(
Expand All @@ -79,7 +89,7 @@ Broadcast _broadcastFromPick(RequiredPick pick) {
round: _roundFromPick(pick('round').required()),
group: pick('group').asStringOrNull(),
roundToLinkId:
pick('roundToLink', 'id').asBroadcastRoundIddOrNull() ?? roundId,
pick('roundToLink', 'id').asBroadcastRoundIdOrNull() ?? roundId,
);
}

Expand Down Expand Up @@ -221,3 +231,28 @@ BroadcastPlayerExtended _playerExtendedFromPick(RequiredPick pick) {
ratingDiff: pick('ratingDiff').asIntOrNull(),
);
}

IList<BroadcastPlayerResult> _makePlayerResultsFromJson(
Map<String, dynamic> json,
) {
return pick(json, 'games').asListOrThrow(_makePlayerResultFromPick).toIList();
}

BroadcastPlayerResult _makePlayerResultFromPick(RequiredPick pick) {
final pointsString = pick('points').asStringOrNull();
BroadcastPoints? points;
if (pointsString == '1') {
points = BroadcastPoints.one;
} else if (pointsString == '1/2') {
points = BroadcastPoints.half;
} else if (pointsString == '0') {
points = BroadcastPoints.zero;
}

return BroadcastPlayerResult(
color: pick('color').asSideOrThrow(),
ratingDiff: pick('ratingDiff').asIntOrNull(),
points: points,
opponent: _playerFromPick(pick('opponent').required()),
);
}
10 changes: 6 additions & 4 deletions lib/src/model/common/id.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ extension type const StringId(String value) {
bool startsWith(String prefix) => value.startsWith(prefix);
}

extension type const IntId(int value) {}

extension type const GameAnyId._(String value) implements StringId {
GameAnyId(this.value) : assert(value.length == 8 || value.length == 12);
GameId get gameId => GameId(value.substring(0, 8));
Expand Down Expand Up @@ -65,7 +67,7 @@ extension type const StudyChapterId(String value) implements StringId {
StudyChapterId.fromJson(dynamic json) : this(json as String);
}

extension type const FideId(String value) implements StringId {}
extension type const FideId(int value) implements IntId {}

extension IDPick on Pick {
UserId asUserIdOrThrow() {
Expand Down Expand Up @@ -192,7 +194,7 @@ extension IDPick on Pick {
);
}

BroadcastRoundId? asBroadcastRoundIddOrNull() {
BroadcastRoundId? asBroadcastRoundIdOrNull() {
if (value == null) return null;
try {
return asBroadcastRoundIdOrThrow();
Expand All @@ -211,7 +213,7 @@ extension IDPick on Pick {
);
}

BroadcastGameId? asBroadcastGameIddOrNull() {
BroadcastGameId? asBroadcastGameIdOrNull() {
if (value == null) return null;
try {
return asBroadcastGameIdOrThrow();
Expand All @@ -232,7 +234,7 @@ extension IDPick on Pick {

FideId asFideIdOrThrow() {
final value = required().value;
if (value is String) {
if (value is int) {
return FideId(value);
}
throw PickException(
Expand Down
147 changes: 147 additions & 0 deletions lib/src/view/broadcast/broadcast_player_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import 'dart:math';

import 'package:dartchess/dartchess.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lichess_mobile/src/model/broadcast/broadcast.dart';
import 'package:lichess_mobile/src/model/broadcast/broadcast_providers.dart';
import 'package:lichess_mobile/src/model/common/id.dart';
import 'package:lichess_mobile/src/view/broadcast/broadcast_player_widget.dart';
import 'package:lichess_mobile/src/widgets/platform_scaffold.dart';
import 'package:lichess_mobile/src/widgets/progression_widget.dart';

class BroadcastPlayerScreen extends StatelessWidget {
final BroadcastTournamentId tournamentId;
final FideId fideId;
const BroadcastPlayerScreen(
this.tournamentId,
this.fideId,
);

@override
Widget build(BuildContext context) {
return PlatformScaffold(
appBar: const PlatformAppBar(
title: Text('Player details'),
),
body: _Body(tournamentId, fideId),
);
}
}

const _kTableRowPadding = EdgeInsets.symmetric(
vertical: 12.0,
);

class _Body extends ConsumerWidget {
final BroadcastTournamentId tournamentId;
final FideId fideId;

const _Body(this.tournamentId, this.fideId);

@override
Widget build(BuildContext context, WidgetRef ref) {
final playersResults =
ref.watch(broadcastPlayerResultProvider(tournamentId, fideId));

switch (playersResults) {
case AsyncData(value: final playerResults):
final indexWidth =
max(8.0 + playerResults.length.toString().length * 10.0, 28.0);

return ListView.builder(
itemCount: playerResults.length,
itemBuilder: (context, index) {
final playerResult = playerResults[index];
return ColoredBox(
color: index.isEven
? Theme.of(context).colorScheme.surfaceContainerLow
: Theme.of(context).colorScheme.surfaceContainerHigh,
child: Padding(
padding: _kTableRowPadding,
child: Row(
children: [
SizedBox(
width: indexWidth,
child: Center(child: Text((index + 1).toString())),
),
Expanded(
flex: 5,
child: BroadcastPlayerWidget(
federation: playerResult.opponent.federation,
title: playerResult.opponent.title,
name: playerResult.opponent.name,
),
),
Expanded(
flex: 3,
child: (playerResult.opponent.rating != null)
? Center(
child:
Text(playerResult.opponent.rating.toString()),
)
: const SizedBox.shrink(),
),
SizedBox(
width: 30,
child: Center(
child: Container(
width: 15,
height: 15,
decoration: BoxDecoration(
border: (Theme.of(context).brightness ==
Brightness.light &&
playerResult.color == Side.white ||
Theme.of(context).brightness ==
Brightness.dark &&
playerResult.color == Side.black)
? Border.all(
width: 2.0,
color:
Theme.of(context).colorScheme.outline,
)
: null,
shape: BoxShape.circle,
color: switch (playerResult.color) {
Side.white => Colors.white.withValues(alpha: 0.9),
Side.black => Colors.black.withValues(alpha: 0.9),
},
),
),
),
),
SizedBox(
width: 30,
child: Center(
child: Text(
switch (playerResult.points) {
BroadcastPoints.one => '1',
BroadcastPoints.half => '½',
BroadcastPoints.zero => '0',
_ => '*'
},
),
),
),
SizedBox(
width: 38,
child: (playerResult.ratingDiff != null)
? ProgressionWidget(
playerResult.ratingDiff!,
fontSize: 15,
)
: null,
),
],
),
),
);
},
);
case AsyncError(:final error):
return Text('Cannot load player data: $error');
case _:
return const CircularProgressIndicator.adaptive();
}
}
}
1 change: 0 additions & 1 deletion lib/src/view/broadcast/broadcast_player_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ class BroadcastPlayerWidget extends ConsumerWidget {
const SizedBox(width: 5),
Text(
rating.toString(),
style: const TextStyle(),
overflow: TextOverflow.ellipsis,
),
],
Expand Down
Loading

0 comments on commit e948d04

Please sign in to comment.