From 5f21b97c4757a6b3439d7bc67581b563615061fd Mon Sep 17 00:00:00 2001 From: Konrad Date: Sun, 10 Nov 2024 11:17:02 +0100 Subject: [PATCH] Create team ranking algorithm --- .../country_team_ranking_creator.dart | 39 ++++++++++++ .../jumper_in_ranking_tile.dart | 32 ++++++++++ .../team_jumpers_ranking_list.dart | 25 ++++++++ .../large/subscreens/__teams_screen.dart | 41 +++++++------ .../country_team_profile_widget.dart | 20 ++++++- .../country_team_profile_overview.dart | 59 +++++++++++++++++++ .../screens/simulation/simulation_route.dart | 2 +- 7 files changed, 194 insertions(+), 24 deletions(-) create mode 100644 lib/algorithms/jumpers_ranking/country_team_ranking_creator.dart create mode 100644 lib/ui/reusable_widgets/jumpers_ranking/jumper_in_ranking_tile.dart create mode 100644 lib/ui/reusable_widgets/jumpers_ranking/team_jumpers_ranking_list.dart rename lib/ui/screens/simulation/large/widgets/teams/{ => country_team_profile}/country_team_profile_widget.dart (74%) create mode 100644 lib/ui/screens/simulation/large/widgets/teams/country_team_profile/overview/country_team_profile_overview.dart diff --git a/lib/algorithms/jumpers_ranking/country_team_ranking_creator.dart b/lib/algorithms/jumpers_ranking/country_team_ranking_creator.dart new file mode 100644 index 00000000..388df77d --- /dev/null +++ b/lib/algorithms/jumpers_ranking/country_team_ranking_creator.dart @@ -0,0 +1,39 @@ +import 'package:sj_manager/models/simulation/flow/jumper_dynamic_params.dart'; +import 'package:sj_manager/models/user_db/jumper/jumper.dart'; + +class CountryTeamRankingCreator { + const CountryTeamRankingCreator({ + required this.jumpers, + required this.dynamicParams, + }); + + final List jumpers; + final Map dynamicParams; + + List create() { + final ratings = { + for (final jumper in jumpers) jumper: _calculateRating(jumper), + }; + final sorted = List.of(jumpers) + ..sort((first, second) { + return ratings[second]!.compareTo(ratings[first]!); + }); + return sorted; + } + + double _calculateRating(Jumper jumper) { + return (jumper.skills.takeoffQuality / 1) + + (jumper.skills.flightQuality / 1) + + (jumper.skills.landingQuality / 10) + + (dynamicParams[jumper]!.jumpsConsistency / 1.5) + + (dynamicParams[jumper]!.form * 2); + } +} + +/* +takeoff quality: 15 +flight quality: 15 +landing quality: 15 / 10 +jumps consistency: 14 / 1.5 +form: 10 * 2 +*/ diff --git a/lib/ui/reusable_widgets/jumpers_ranking/jumper_in_ranking_tile.dart b/lib/ui/reusable_widgets/jumpers_ranking/jumper_in_ranking_tile.dart new file mode 100644 index 00000000..deac26e5 --- /dev/null +++ b/lib/ui/reusable_widgets/jumpers_ranking/jumper_in_ranking_tile.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:sj_manager/models/user_db/jumper/jumper.dart'; +import 'package:sj_manager/ui/screens/simulation/large/widgets/simulation_jumper_image.dart'; + +class JumperInRankingTile extends StatelessWidget { + const JumperInRankingTile({ + super.key, + required this.jumper, + required this.position, + this.onTap, + }); + + final Jumper jumper; + final int position; + final VoidCallback? onTap; + + @override + Widget build(BuildContext context) { + return ListTile( + leading: Text( + position.toString(), + style: Theme.of(context).textTheme.bodyLarge, + ), + trailing: SimulationJumperImage( + jumper: jumper, + width: 25, + ), + title: Text(jumper.nameAndSurname()), + onTap: onTap, + ); + } +} diff --git a/lib/ui/reusable_widgets/jumpers_ranking/team_jumpers_ranking_list.dart b/lib/ui/reusable_widgets/jumpers_ranking/team_jumpers_ranking_list.dart new file mode 100644 index 00000000..6f0d80a4 --- /dev/null +++ b/lib/ui/reusable_widgets/jumpers_ranking/team_jumpers_ranking_list.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:sj_manager/models/user_db/jumper/jumper.dart'; +import 'package:sj_manager/ui/reusable_widgets/jumpers_ranking/jumper_in_ranking_tile.dart'; + +class TeamJumpersRankingList extends StatelessWidget { + const TeamJumpersRankingList({ + super.key, + required this.jumpers, + }); + + final List jumpers; + + @override + Widget build(BuildContext context) { + return ListView( + children: [ + for (var i = 0; i < jumpers.length; i++) + JumperInRankingTile( + jumper: jumpers[i], + position: i + 1, + ), + ], + ); + } +} diff --git a/lib/ui/screens/simulation/large/subscreens/__teams_screen.dart b/lib/ui/screens/simulation/large/subscreens/__teams_screen.dart index 5e7d61a3..56c8dbec 100644 --- a/lib/ui/screens/simulation/large/subscreens/__teams_screen.dart +++ b/lib/ui/screens/simulation/large/subscreens/__teams_screen.dart @@ -157,23 +157,26 @@ class _ListView extends StatelessWidget { await showDialog( context: context, builder: (context) { - return MultiProvider( - providers: [ - Provider.value(value: flagsRepo), - ], - child: Center( - child: ClipRRect( - borderRadius: BorderRadius.circular(15), - child: Container( - width: MediaQuery.of(context).size.width * 0.7, - height: MediaQuery.of(context).size.height * 0.8, - padding: const EdgeInsets.all(6), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainerHigh, - borderRadius: BorderRadius.circular(15), - ), - child: CountryTeamProfileWidget( - team: team, + return BlocProvider.value( + value: context.read(), + child: MultiProvider( + providers: [ + Provider.value(value: flagsRepo), + ], + child: Center( + child: ClipRRect( + borderRadius: BorderRadius.circular(15), + child: Container( + width: MediaQuery.of(context).size.width * 0.7, + height: MediaQuery.of(context).size.height * 0.8, + padding: const EdgeInsets.all(6), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceContainerHigh, + borderRadius: BorderRadius.circular(15), + ), + child: CountryTeamProfileWidget( + team: team, + ), ), ), ), @@ -187,7 +190,3 @@ class _ListView extends StatelessWidget { ); } } - -// francja -// musi zawierac f i r -// fr diff --git a/lib/ui/screens/simulation/large/widgets/teams/country_team_profile_widget.dart b/lib/ui/screens/simulation/large/widgets/teams/country_team_profile/country_team_profile_widget.dart similarity index 74% rename from lib/ui/screens/simulation/large/widgets/teams/country_team_profile_widget.dart rename to lib/ui/screens/simulation/large/widgets/teams/country_team_profile/country_team_profile_widget.dart index 02165881..a9602a3d 100644 --- a/lib/ui/screens/simulation/large/widgets/teams/country_team_profile_widget.dart +++ b/lib/ui/screens/simulation/large/widgets/teams/country_team_profile/country_team_profile_widget.dart @@ -3,6 +3,7 @@ import 'package:gap/gap.dart'; import 'package:material_symbols_icons/material_symbols_icons.dart'; import 'package:sj_manager/models/user_db/team/country_team/country_team.dart'; import 'package:sj_manager/ui/reusable_widgets/countries/country_flag.dart'; +import 'package:sj_manager/ui/screens/simulation/large/widgets/teams/country_team_profile/overview/country_team_profile_overview.dart'; import 'package:sj_manager/utils/icons.dart'; class CountryTeamProfileWidget extends StatefulWidget { @@ -42,7 +43,7 @@ class _CountryTeamProfileWidgetState extends State { length: 3, child: Column( children: [ - TabBar( + const TabBar( tabs: [ Tab( text: 'Przegląd', @@ -57,7 +58,22 @@ class _CountryTeamProfileWidgetState extends State { icon: Icon(Symbols.analytics), ), ], - ) + ), + const Gap(10), + Expanded( + child: Padding( + padding: const EdgeInsets.only(left: 5), + child: TabBarView( + children: [ + CountryTeamProfileOverview( + countryTeam: widget.team, + ), + const Placeholder(), + const Placeholder(), + ], + ), + ), + ), ], ), ), diff --git a/lib/ui/screens/simulation/large/widgets/teams/country_team_profile/overview/country_team_profile_overview.dart b/lib/ui/screens/simulation/large/widgets/teams/country_team_profile/overview/country_team_profile_overview.dart new file mode 100644 index 00000000..43051aed --- /dev/null +++ b/lib/ui/screens/simulation/large/widgets/teams/country_team_profile/overview/country_team_profile_overview.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:sj_manager/algorithms/jumpers_ranking/country_team_ranking_creator.dart'; +import 'package:sj_manager/bloc/simulation/simulation_database_cubit.dart'; +import 'package:sj_manager/models/user_db/jumper/jumper.dart'; +import 'package:sj_manager/models/user_db/team/country_team/country_team.dart'; +import 'package:sj_manager/ui/reusable_widgets/card_with_title.dart'; +import 'package:sj_manager/ui/reusable_widgets/jumpers_ranking/team_jumpers_ranking_list.dart'; + +class CountryTeamProfileOverview extends StatelessWidget { + const CountryTeamProfileOverview({ + super.key, + required this.countryTeam, + }); + + final CountryTeam countryTeam; + + @override + Widget build(BuildContext context) { + final database = context.watch().state; + final subteams = database.subteamJumpers.keys.where( + (subteam) => subteam.parentTeam == countryTeam, + ); + final unorderedJumpers = []; + for (var subteam in subteams) { + final jumperIds = database.subteamJumpers[subteam]!; + unorderedJumpers.addAll( + jumperIds.map((id) => database.idsRepo.get(id) as Jumper), + ); + } + final ranking = CountryTeamRankingCreator( + jumpers: unorderedJumpers, dynamicParams: database.jumperDynamicParams) + .create(); + + return Row( + children: [ + SizedBox( + width: 250, + child: CardWithTitle( + title: Text( + 'Ranking', + style: Theme.of(context).textTheme.headlineSmall, + ), + child: TeamJumpersRankingList( + jumpers: ranking, + ), + ), + ) + ], + ); + } +} + +// ranking skoczków +// perspektywa +// podstawowe rekordy (wygranych konkursow druż pś, wygranych konkursów ind pś) +// gwiazdki +// płeć na fladze +// diff --git a/lib/ui/screens/simulation/simulation_route.dart b/lib/ui/screens/simulation/simulation_route.dart index 7a30ca50..eb67a4b5 100644 --- a/lib/ui/screens/simulation/simulation_route.dart +++ b/lib/ui/screens/simulation/simulation_route.dart @@ -40,7 +40,7 @@ import 'package:sj_manager/ui/screens/simulation/large/widgets/team/team_screen/ import 'package:sj_manager/ui/screens/simulation/large/widgets/team/team_screen/team_screen_personal_coach_bottom_bar.dart'; import 'package:sj_manager/ui/screens/simulation/large/widgets/team/team_screen/team_summary_card.dart'; import 'package:sj_manager/ui/screens/simulation/large/widgets/teams/country_team_overview_list_tile.dart'; -import 'package:sj_manager/ui/screens/simulation/large/widgets/teams/country_team_profile_widget.dart'; +import 'package:sj_manager/ui/screens/simulation/large/widgets/teams/country_team_profile/country_team_profile_widget.dart'; import 'package:sj_manager/utils/filtering.dart'; import 'package:sj_manager/utils/show_dialog.dart'; import 'package:sj_manager/utils/translating.dart';