From fea89a893043198566f9bda9052940308ae8ba20 Mon Sep 17 00:00:00 2001 From: August Date: Sun, 24 Mar 2024 22:50:19 +0100 Subject: [PATCH] feat: Basic support for API providers (#47) Contributes to #39 --- .../mocks/services/network/data_manager.dart | 6 + .../lib/provider/local_preferences.dart | 5 - .../provider/local_preferences_provider.dart | 37 -- .../local_preferences_provider.g.dart | 145 ----- .../lib/provider/network_provider.g.dart | 1 - .../lib/services/network/data_manager.dart | 2 + .../lib/services/network/remote/rest.dart | 10 + .../view/screens/edit/organization_edit.dart | 46 +- .../lib/view/screens/edit/person_edit.dart | 21 +- .../view/screens/edit/weight_class_edit.dart | 36 +- .../view/screens/more/settings/settings.dart | 76 +-- .../overview/organization_overview.dart | 25 +- .../team_match/team_match_overview.dart | 3 +- .../test/widget_test.dart | 3 +- .../lib/src/data/bout.dart | 13 +- .../lib/src/data/bout_action.dart | 11 +- .../lib/src/data/bout_config.dart | 8 +- .../lib/src/data/club.dart | 9 +- .../lib/src/data/club.freezed.dart | 57 +- .../lib/src/data/club.g.dart | 6 +- .../lib/src/data/competition/competition.dart | 15 +- .../data/competition/competition.freezed.dart | 60 +- .../src/data/competition/competition.g.dart | 5 + .../data/competition/competition_bout.dart | 10 +- .../data/competition/competition_person.dart | 11 +- .../competition_team_participation.dart | 10 +- .../lib/src/data/data_object.dart | 6 +- .../lib/src/data/lineup.dart | 21 +- .../lib/src/data/membership.dart | 11 +- .../lib/src/data/membership.freezed.dart | 68 ++- .../lib/src/data/membership.g.dart | 5 + .../lib/src/data/organization.dart | 18 + .../lib/src/data/organization.freezed.dart | 62 ++- .../lib/src/data/organization.g.dart | 13 + .../lib/src/data/participant_state.dart | 12 +- .../lib/src/data/participation.dart | 11 +- .../lib/src/data/person.dart | 13 +- .../lib/src/data/person.freezed.dart | 62 ++- .../lib/src/data/person.g.dart | 5 + .../lib/src/data/team.dart | 10 +- .../lib/src/data/team.freezed.dart | 66 ++- .../lib/src/data/team.g.dart | 5 + .../lib/src/data/team_match/division.dart | 11 +- .../src/data/team_match/division.freezed.dart | 98 ++-- .../lib/src/data/team_match/division.g.dart | 6 +- .../team_match/division_weight_class.dart | 11 +- .../lib/src/data/team_match/league.dart | 7 + .../src/data/team_match/league.freezed.dart | 79 ++- .../lib/src/data/team_match/league.g.dart | 5 + .../team_match/league_team_participation.dart | 10 +- .../lib/src/data/team_match/team_match.dart | 16 +- .../data/team_match/team_match.freezed.dart | 61 ++- .../lib/src/data/team_match/team_match.g.dart | 5 + .../src/data/team_match/team_match_bout.dart | 11 +- .../lib/src/data/weight_class.dart | 10 +- .../lib/src/data/wrestling_event.dart | 4 + .../lib/src/enums.dart | 3 +- .../lib/src/services/api.dart | 59 +- .../lib/src/services/apis/germany_nrw.dart | 415 ++++++++++++++ .../services/apis/mocks/competition.json.dart | 514 ++++++++++++++++++ .../apis/mocks/listCompetition.json.dart | 88 +++ .../services/apis/mocks/listLiga.json.dart | 286 ++++++++++ .../services/apis/mocks/listSaison.json.dart | 172 ++++++ .../services/apis/mocks/wrestler.json.dart | 35 ++ .../lib/src/services/auth/authorization.dart | 15 + .../lib/src/services/report.dart | 6 +- .../lib/src/services/reports/germany_nrw.dart | 5 + .../lib/src/util/data_wrapper.dart | 12 +- wrestling_scoreboard_common/pubspec.yaml | 2 + .../test/services/apis_test.dart | 368 +++++++++++++ .../test/services/reports_test.dart | 9 +- .../test/services/shared.dart | 4 + .../PostgreSQL-wrestling_scoreboard-dump.sql | 291 ++++++---- .../lib/controllers/database_controller.dart | 2 +- .../lib/controllers/entity_controller.dart | 58 +- .../controllers/organization_controller.dart | 88 +++ .../lib/controllers/websocket_handler.dart | 14 +- .../lib/routes/api_route.dart | 7 +- wrestling_scoreboard_server/lib/server.dart | 1 + wrestling_scoreboard_server/pubspec.lock | 28 +- 80 files changed, 3214 insertions(+), 621 deletions(-) create mode 100644 wrestling_scoreboard_common/lib/src/services/apis/germany_nrw.dart create mode 100644 wrestling_scoreboard_common/lib/src/services/apis/mocks/competition.json.dart create mode 100644 wrestling_scoreboard_common/lib/src/services/apis/mocks/listCompetition.json.dart create mode 100644 wrestling_scoreboard_common/lib/src/services/apis/mocks/listLiga.json.dart create mode 100644 wrestling_scoreboard_common/lib/src/services/apis/mocks/listSaison.json.dart create mode 100644 wrestling_scoreboard_common/lib/src/services/apis/mocks/wrestler.json.dart create mode 100644 wrestling_scoreboard_common/lib/src/services/auth/authorization.dart create mode 100644 wrestling_scoreboard_common/test/services/apis_test.dart create mode 100644 wrestling_scoreboard_common/test/services/shared.dart diff --git a/wrestling_scoreboard_client/lib/mocks/services/network/data_manager.dart b/wrestling_scoreboard_client/lib/mocks/services/network/data_manager.dart index d5f13320..615b664d 100644 --- a/wrestling_scoreboard_client/lib/mocks/services/network/data_manager.dart +++ b/wrestling_scoreboard_client/lib/mocks/services/network/data_manager.dart @@ -432,6 +432,12 @@ class MockDataManager extends DataManager { // TODO: implement restoreDatabase throw UnimplementedError(); } + + @override + Future organizationImport(int id) { + // TODO: implement organizationImport + throw UnimplementedError(); + } } class MockWebSocketManager implements WebSocketManager { diff --git a/wrestling_scoreboard_client/lib/provider/local_preferences.dart b/wrestling_scoreboard_client/lib/provider/local_preferences.dart index cfb9814c..a970dd05 100644 --- a/wrestling_scoreboard_client/lib/provider/local_preferences.dart +++ b/wrestling_scoreboard_client/lib/provider/local_preferences.dart @@ -2,15 +2,12 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:wrestling_scoreboard_common/common.dart'; class Preferences { static const keyLocale = 'locale'; static const keyThemeMode = 'theme-mode'; static const keyApiUrl = 'api-url'; static const keyWsUrl = 'ws-url'; - static const keyApiProvider = 'api-provider'; - static const keyReportProvider = 'report-provider'; /// Network timeout in milliseconds. static const keyNetworkTimeout = 'network-timeout'; @@ -22,8 +19,6 @@ class Preferences { static final StreamController onChangeThemeMode = StreamController.broadcast(); static final StreamController onChangeApiUrl = StreamController.broadcast(); static final StreamController onChangeWsUrlWebSocket = StreamController.broadcast(); - static final StreamController onChangeApiProvider = StreamController.broadcast(); - static final StreamController onChangeReportProvider = StreamController.broadcast(); static final StreamController onChangeNetworkTimeout = StreamController.broadcast(); static final StreamController onChangeBellSound = StreamController.broadcast(); static final StreamController onChangeFontFamily = StreamController.broadcast(); diff --git a/wrestling_scoreboard_client/lib/provider/local_preferences_provider.dart b/wrestling_scoreboard_client/lib/provider/local_preferences_provider.dart index 1758cb51..4082dc28 100644 --- a/wrestling_scoreboard_client/lib/provider/local_preferences_provider.dart +++ b/wrestling_scoreboard_client/lib/provider/local_preferences_provider.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:wrestling_scoreboard_client/provider/local_preferences.dart'; import 'package:wrestling_scoreboard_client/utils/environment.dart'; -import 'package:wrestling_scoreboard_common/common.dart'; part 'local_preferences_provider.g.dart'; @@ -96,42 +95,6 @@ class ApiUrlNotifier extends _$ApiUrlNotifier { } } -@riverpod -class ApiProviderNotifier extends _$ApiProviderNotifier { - @override - Raw> build() async { - Preferences.onChangeApiProvider.stream.distinct().listen((event) { - state = Future.value(event); - }); - final apiProviderStr = await Preferences.getString(Preferences.keyApiProvider); - final WrestlingApiProvider? apiProvider; - if (apiProviderStr != null) { - apiProvider = WrestlingApiProvider.values.byName(apiProviderStr); - } else { - apiProvider = null; - } - return apiProvider; - } -} - -@riverpod -class ReportProviderNotifier extends _$ReportProviderNotifier { - @override - Raw> build() async { - Preferences.onChangeReportProvider.stream.distinct().listen((event) { - state = Future.value(event); - }); - final apiProviderStr = await Preferences.getString(Preferences.keyReportProvider); - final WrestlingReportProvider? apiProvider; - if (apiProviderStr != null) { - apiProvider = WrestlingReportProvider.values.byName(apiProviderStr); - } else { - apiProvider = null; - } - return apiProvider; - } -} - @Riverpod(keepAlive: true) class BellSoundNotifier extends _$BellSoundNotifier { @override diff --git a/wrestling_scoreboard_client/lib/provider/local_preferences_provider.g.dart b/wrestling_scoreboard_client/lib/provider/local_preferences_provider.g.dart index 7524f19b..abe4e650 100644 --- a/wrestling_scoreboard_client/lib/provider/local_preferences_provider.g.dart +++ b/wrestling_scoreboard_client/lib/provider/local_preferences_provider.g.dart @@ -70,7 +70,6 @@ String _$localeNotifierHash() => r'e1e390bd02d18a8474b484ee33bc40edca7e9c3d'; abstract class _$LocaleNotifier extends $Notifier>> { Raw> build(); - @$internal @override Raw> runBuild() => build(); @@ -137,7 +136,6 @@ String _$themeModeNotifierHash() => r'29aedc145964f8e32034ab495a26ee3ccedfed82'; abstract class _$ThemeModeNotifier extends $Notifier>> { Raw> build(); - @$internal @override Raw> runBuild() => build(); @@ -204,7 +202,6 @@ String _$fontFamilyNotifierHash() => r'38c577d6ba358636b04947a2d8d33bb02f7a8bfc' abstract class _$FontFamilyNotifier extends $Notifier>> { Raw> build(); - @$internal @override Raw> runBuild() => build(); @@ -271,7 +268,6 @@ String _$webSocketUrlNotifierHash() => r'3e384b28903aca1717d43fa65ace0651b39b668 abstract class _$WebSocketUrlNotifier extends $Notifier>> { Raw> build(); - @$internal @override Raw> runBuild() => build(); @@ -338,7 +334,6 @@ String _$networkTimeoutNotifierHash() => r'2c6a26f2904896d01c9ddd31fd4ae7637030a abstract class _$NetworkTimeoutNotifier extends $Notifier>> { Raw> build(); - @$internal @override Raw> runBuild() => build(); @@ -405,150 +400,11 @@ String _$apiUrlNotifierHash() => r'8c063b9ec135234c56970345957760282a21fbde'; abstract class _$ApiUrlNotifier extends $Notifier>> { Raw> build(); - @$internal @override Raw> runBuild() => build(); } -@ProviderFor(ApiProviderNotifier) -const apiProviderNotifierProvider = ApiProviderNotifierProvider._(); - -final class ApiProviderNotifierProvider - extends $NotifierProvider>> { - const ApiProviderNotifierProvider._({super.runNotifierBuildOverride, ApiProviderNotifier Function()? create}) - : _createCb = create, - super( - from: null, - argument: null, - name: r'apiProviderNotifierProvider', - isAutoDispose: true, - dependencies: null, - allTransitiveDependencies: null, - ); - - final ApiProviderNotifier Function()? _createCb; - - @override - String debugGetCreateSourceHash() => _$apiProviderNotifierHash(); - - /// {@macro riverpod.override_with_value} - Override overrideWithValue(Raw> value) { - return $ProviderOverride( - origin: this, - providerOverride: $ValueProvider>>(value), - ); - } - - @$internal - @override - ApiProviderNotifier create() => _createCb?.call() ?? ApiProviderNotifier(); - - @$internal - @override - ApiProviderNotifierProvider $copyWithCreate( - ApiProviderNotifier Function() create, - ) { - return ApiProviderNotifierProvider._(create: create); - } - - @$internal - @override - ApiProviderNotifierProvider $copyWithBuild( - Raw> Function( - Ref>>, - ApiProviderNotifier, - ) build, - ) { - return ApiProviderNotifierProvider._(runNotifierBuildOverride: build); - } - - @$internal - @override - $NotifierProviderElement>> $createElement( - ProviderContainer container) => - $NotifierProviderElement(this, container); -} - -String _$apiProviderNotifierHash() => r'f44b0c800a10b30fda681d7b30ff5ffedf40301d'; - -abstract class _$ApiProviderNotifier extends $Notifier>> { - Raw> build(); - - @$internal - @override - Raw> runBuild() => build(); -} - -@ProviderFor(ReportProviderNotifier) -const reportProviderNotifierProvider = ReportProviderNotifierProvider._(); - -final class ReportProviderNotifierProvider - extends $NotifierProvider>> { - const ReportProviderNotifierProvider._({super.runNotifierBuildOverride, ReportProviderNotifier Function()? create}) - : _createCb = create, - super( - from: null, - argument: null, - name: r'reportProviderNotifierProvider', - isAutoDispose: true, - dependencies: null, - allTransitiveDependencies: null, - ); - - final ReportProviderNotifier Function()? _createCb; - - @override - String debugGetCreateSourceHash() => _$reportProviderNotifierHash(); - - /// {@macro riverpod.override_with_value} - Override overrideWithValue(Raw> value) { - return $ProviderOverride( - origin: this, - providerOverride: $ValueProvider>>(value), - ); - } - - @$internal - @override - ReportProviderNotifier create() => _createCb?.call() ?? ReportProviderNotifier(); - - @$internal - @override - ReportProviderNotifierProvider $copyWithCreate( - ReportProviderNotifier Function() create, - ) { - return ReportProviderNotifierProvider._(create: create); - } - - @$internal - @override - ReportProviderNotifierProvider $copyWithBuild( - Raw> Function( - Ref>>, - ReportProviderNotifier, - ) build, - ) { - return ReportProviderNotifierProvider._(runNotifierBuildOverride: build); - } - - @$internal - @override - $NotifierProviderElement>> $createElement( - ProviderContainer container) => - $NotifierProviderElement(this, container); -} - -String _$reportProviderNotifierHash() => r'03af15f0301c652c2af440e19bf176af7624a618'; - -abstract class _$ReportProviderNotifier extends $Notifier>> { - Raw> build(); - - @$internal - @override - Raw> runBuild() => build(); -} - @ProviderFor(BellSoundNotifier) const bellSoundNotifierProvider = BellSoundNotifierProvider._(); @@ -610,7 +466,6 @@ String _$bellSoundNotifierHash() => r'1c9d805977f6f32cd7b44e7bd1ecfecd15447ddd'; abstract class _$BellSoundNotifier extends $Notifier>> { Raw> build(); - @$internal @override Raw> runBuild() => build(); diff --git a/wrestling_scoreboard_client/lib/provider/network_provider.g.dart b/wrestling_scoreboard_client/lib/provider/network_provider.g.dart index aa344987..5409314b 100644 --- a/wrestling_scoreboard_client/lib/provider/network_provider.g.dart +++ b/wrestling_scoreboard_client/lib/provider/network_provider.g.dart @@ -67,7 +67,6 @@ String _$dataManagerNotifierHash() => r'ca415c0257cc0041067af426ad3887c4353f72e2 abstract class _$DataManagerNotifier extends $Notifier>> { Raw> build(); - @$internal @override Raw> runBuild() => build(); diff --git a/wrestling_scoreboard_client/lib/services/network/data_manager.dart b/wrestling_scoreboard_client/lib/services/network/data_manager.dart index 41534114..940d9917 100644 --- a/wrestling_scoreboard_client/lib/services/network/data_manager.dart +++ b/wrestling_scoreboard_client/lib/services/network/data_manager.dart @@ -79,6 +79,8 @@ abstract class DataManager { Future resetDatabase(); + Future organizationImport(int id); + final Map> _singleStreamControllers = {}; final Map>>> _manyStreamControllers = {}; final Map>> _singleRawStreamControllers = {}; diff --git a/wrestling_scoreboard_client/lib/services/network/remote/rest.dart b/wrestling_scoreboard_client/lib/services/network/remote/rest.dart index 1c37fda0..9bb4abbe 100644 --- a/wrestling_scoreboard_client/lib/services/network/remote/rest.dart +++ b/wrestling_scoreboard_client/lib/services/network/remote/rest.dart @@ -145,6 +145,16 @@ class RestDataManager extends DataManager { set webSocketManager(WebSocketManager manager) { _webSocketManager = manager; } + + @override + Future organizationImport(int id) async { + final uri = Uri.parse('$_apiUrl/organization/$id/api/import'); + final response = await http.post(uri); + if (response.statusCode != 200) { + throw Exception( + 'Failed to import from organization $id: ${response.reasonPhrase ?? response.statusCode.toString()}'); + } + } } class RestException implements Exception { diff --git a/wrestling_scoreboard_client/lib/view/screens/edit/organization_edit.dart b/wrestling_scoreboard_client/lib/view/screens/edit/organization_edit.dart index b322f069..9c16258a 100644 --- a/wrestling_scoreboard_client/lib/view/screens/edit/organization_edit.dart +++ b/wrestling_scoreboard_client/lib/view/screens/edit/organization_edit.dart @@ -23,10 +23,14 @@ class _OrganizationEditState extends ConsumerState { String? _name; String? _abbreviation; Organization? _parent; + WrestlingApiProvider? _apiProvider; + WrestlingReportProvider? _reportProvider; @override void initState() { _parent = widget.organization?.parent ?? widget.initialParent; + _apiProvider = widget.organization?.apiProvider; + _reportProvider = widget.organization?.reportProvider; super.initState(); } @@ -73,7 +77,7 @@ class _OrganizationEditState extends ConsumerState { onSaved: (Organization? value) => setState(() { _parent = value; }), - allowEmpty: false, + allowEmpty: true, itemAsString: (u) => u.name, onFind: (String? filter) async { _availableOrganizations ??= @@ -85,6 +89,44 @@ class _OrganizationEditState extends ConsumerState { }, ), ), + ListTile( + leading: const Icon(Icons.api), + title: ButtonTheme( + alignedDropdown: true, + child: SimpleDropdown( + isNullable: true, + hint: localizations.apiProvider, + isExpanded: true, + options: WrestlingApiProvider.values.map((value) => MapEntry( + value, + Text(value.name), + )), + selected: _apiProvider, + onChange: (newValue) => setState(() { + _apiProvider = newValue; + }), + ), + ), + ), + ListTile( + leading: const Icon(Icons.description), + title: ButtonTheme( + alignedDropdown: true, + child: SimpleDropdown( + isNullable: true, + hint: localizations.apiProvider, + isExpanded: true, + options: WrestlingReportProvider.values.map((value) => MapEntry( + value, + Text(value.name), + )), + selected: _reportProvider, + onChange: (newValue) => setState(() { + _reportProvider = newValue; + }), + ), + ), + ), ]; return Form( @@ -106,6 +148,8 @@ class _OrganizationEditState extends ConsumerState { name: _name!, abbreviation: _abbreviation, parent: _parent, + reportProvider: _reportProvider, + apiProvider: _apiProvider, )); navigator.pop(); } diff --git a/wrestling_scoreboard_client/lib/view/screens/edit/person_edit.dart b/wrestling_scoreboard_client/lib/view/screens/edit/person_edit.dart index 78b41d6b..00e0e0e0 100644 --- a/wrestling_scoreboard_client/lib/view/screens/edit/person_edit.dart +++ b/wrestling_scoreboard_client/lib/view/screens/edit/person_edit.dart @@ -106,18 +106,17 @@ abstract class PersonEditState extends ConsumerState im leading: const Icon(Icons.transgender), title: ButtonTheme( alignedDropdown: true, - child: DropdownButton( - hint: Text(localizations.gender), + child: SimpleDropdown( + isNullable: true, + hint: localizations.gender, isExpanded: true, - items: Gender.values.map((Gender value) { - return DropdownMenuItem( - value: value, - child: Text(value.localize(context)), - ); - }).toList(), - value: _gender, - onChanged: (newValue) => setState(() { - _gender = newValue!; + options: Gender.values.map((Gender value) => MapEntry( + value, + Text(value.localize(context)), + )), + selected: _gender, + onChange: (newValue) => setState(() { + _gender = newValue; }), ), ), diff --git a/wrestling_scoreboard_client/lib/view/screens/edit/weight_class_edit.dart b/wrestling_scoreboard_client/lib/view/screens/edit/weight_class_edit.dart index 66b440b8..a5032c65 100644 --- a/wrestling_scoreboard_client/lib/view/screens/edit/weight_class_edit.dart +++ b/wrestling_scoreboard_client/lib/view/screens/edit/weight_class_edit.dart @@ -5,6 +5,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:wrestling_scoreboard_client/localization/wrestling_style.dart'; import 'package:wrestling_scoreboard_client/provider/network_provider.dart'; import 'package:wrestling_scoreboard_client/view/screens/edit/common.dart'; +import 'package:wrestling_scoreboard_client/view/widgets/dropdown.dart'; import 'package:wrestling_scoreboard_client/view/widgets/edit.dart'; import 'package:wrestling_scoreboard_client/view/widgets/formatter.dart'; import 'package:wrestling_scoreboard_common/common.dart'; @@ -62,17 +63,17 @@ abstract class WeightClassEditState extends ConsumerS leading: const Icon(Icons.style), title: ButtonTheme( alignedDropdown: true, - child: DropdownButton( - hint: Text(localizations.wrestlingStyle), + child: SimpleDropdown( + hint: localizations.wrestlingStyle, isExpanded: true, - items: WrestlingStyle.values.map((WrestlingStyle style) { - return DropdownMenuItem( - value: style, - child: Text('${style.localize(context)} (${style.abbreviation(context)})'), + options: WrestlingStyle.values.map((WrestlingStyle style) { + return MapEntry( + style, + Text('${style.localize(context)} (${style.abbreviation(context)})'), ); - }).toList(), - value: _wrestlingStyle, - onChanged: (newValue) => setState(() { + }), + selected: _wrestlingStyle, + onChange: (newValue) => setState(() { _wrestlingStyle = newValue!; }), ), @@ -82,17 +83,14 @@ abstract class WeightClassEditState extends ConsumerS leading: const Icon(Icons.straighten), title: ButtonTheme( alignedDropdown: true, - child: DropdownButton( - hint: Text(localizations.weightUnit), + child: SimpleDropdown( + hint: localizations.weightUnit, isExpanded: true, - items: WeightUnit.values.map((WeightUnit value) { - return DropdownMenuItem( - value: value, - child: Text(value.toAbbr()), - ); - }).toList(), - value: _unit, - onChanged: (newValue) => setState(() { + options: WeightUnit.values.map((WeightUnit value) { + return MapEntry(value, Text(value.toAbbr())); + }), + selected: _unit, + onChange: (newValue) => setState(() { _unit = newValue!; }), ), diff --git a/wrestling_scoreboard_client/lib/view/screens/more/settings/settings.dart b/wrestling_scoreboard_client/lib/view/screens/more/settings/settings.dart index 85b68360..4449b5e9 100644 --- a/wrestling_scoreboard_client/lib/view/screens/more/settings/settings.dart +++ b/wrestling_scoreboard_client/lib/view/screens/more/settings/settings.dart @@ -17,7 +17,6 @@ import 'package:wrestling_scoreboard_client/utils/environment.dart'; import 'package:wrestling_scoreboard_client/view/widgets/dialogs.dart'; import 'package:wrestling_scoreboard_client/view/widgets/loading_builder.dart'; import 'package:wrestling_scoreboard_client/view/widgets/responsive_container.dart'; -import 'package:wrestling_scoreboard_common/common.dart'; class CustomSettingsScreen extends ConsumerWidget { const CustomSettingsScreen({super.key}); @@ -331,73 +330,14 @@ class CustomSettingsScreen extends ConsumerWidget { ); }, ), - LoadingBuilder( - future: ref.watch(apiProviderNotifierProvider), - builder: (context, apiProvider) { - return LoadingBuilder( - future: ref.watch(reportProviderNotifierProvider), - builder: (context, reportProvider) { - return SettingsSection( - title: localizations.services, - action: TextButton( - onPressed: () { - Preferences.setString(Preferences.keyApiProvider, null); - Preferences.onChangeApiProvider.add(null); - - Preferences.setString(Preferences.keyReportProvider, null); - Preferences.onChangeReportProvider.add(null); - }, - child: Text(localizations.reset), - ), - children: [ - ListTile( - leading: const Icon(Icons.api), - title: Text(localizations.apiProvider), - subtitle: Text(apiProvider?.name ?? localizations.noneSelected), - onTap: () async { - final val = await showDialog( - context: context, - builder: (BuildContext context) { - final List> providerValues = - WrestlingApiProvider.values.map((provider) { - return MapEntry(provider, provider.name); - }).toList(); - providerValues.insert(0, MapEntry(null, localizations.noneSelected)); - return RadioDialog( - values: providerValues, initialValue: apiProvider); - }, - ); - Preferences.onChangeApiProvider.add(val); - await Preferences.setString(Preferences.keyApiProvider, val?.name); - }, - ), - ListTile( - leading: const Icon(Icons.description), - title: Text(localizations.reportProvider), - subtitle: Text(reportProvider?.name ?? localizations.noneSelected), - onTap: () async { - final val = await showDialog( - context: context, - builder: (BuildContext context) { - final List> providerValues = - WrestlingReportProvider.values.map((provider) { - return MapEntry(provider, provider.name); - }).toList(); - providerValues.insert(0, MapEntry(null, localizations.noneSelected)); - return RadioDialog( - values: providerValues, initialValue: reportProvider); - }, - ); - Preferences.onChangeReportProvider.add(val); - await Preferences.setString(Preferences.keyReportProvider, val?.name); - }, - ), - ], - ); - }, - ); - }, - ), + // SettingsSection( + // title: localizations.services, + // action: TextButton( + // onPressed: () {}, + // child: Text(localizations.reset), + // ), + // children: [], + // ), SettingsSection( title: localizations.database, children: [ diff --git a/wrestling_scoreboard_client/lib/view/screens/overview/organization_overview.dart b/wrestling_scoreboard_client/lib/view/screens/overview/organization_overview.dart index 9ad8cf62..e16f54d5 100644 --- a/wrestling_scoreboard_client/lib/view/screens/overview/organization_overview.dart +++ b/wrestling_scoreboard_client/lib/view/screens/overview/organization_overview.dart @@ -10,6 +10,7 @@ import 'package:wrestling_scoreboard_client/view/screens/overview/club_overview. import 'package:wrestling_scoreboard_client/view/screens/overview/common.dart'; import 'package:wrestling_scoreboard_client/view/screens/overview/team_match/division_overview.dart'; import 'package:wrestling_scoreboard_client/view/widgets/consumer.dart'; +import 'package:wrestling_scoreboard_client/view/widgets/dialogs.dart'; import 'package:wrestling_scoreboard_client/view/widgets/grouped_list.dart'; import 'package:wrestling_scoreboard_client/view/widgets/info.dart'; import 'package:wrestling_scoreboard_common/common.dart'; @@ -47,12 +48,30 @@ class OrganizationOverview extends ConsumerWidget { subtitle: localizations.abbreviation, icon: Icons.short_text, ), + ContentItem( + title: data.apiProvider?.name ?? '-', + subtitle: localizations.apiProvider, + icon: Icons.api, + ), + ContentItem( + title: data.reportProvider?.name ?? '-', + subtitle: localizations.reportProvider, + icon: Icons.description, + ), ], ); return Scaffold( - appBar: AppBar( - title: AppBarTitle(label: localizations.organization, details: data.name), - ), + appBar: AppBar(title: AppBarTitle(label: localizations.organization, details: data.name), actions: [ + IconButton( + onPressed: () => catchAsync(context, () async { + final dataManager = await ref.read(dataManagerNotifierProvider); + await dataManager.organizationImport(id); + if (context.mounted) { + await showOkDialog(context: context, child: Text(localizations.actionSuccessful)); + } + }), + icon: const Icon(Icons.api)), + ]), body: GroupedList(items: [ description, ManyConsumer( diff --git a/wrestling_scoreboard_client/lib/view/screens/overview/team_match/team_match_overview.dart b/wrestling_scoreboard_client/lib/view/screens/overview/team_match/team_match_overview.dart index 0a770395..8f57301b 100644 --- a/wrestling_scoreboard_client/lib/view/screens/overview/team_match/team_match_overview.dart +++ b/wrestling_scoreboard_client/lib/view/screens/overview/team_match/team_match_overview.dart @@ -10,7 +10,6 @@ import 'package:wrestling_scoreboard_client/localization/bout_utils.dart'; import 'package:wrestling_scoreboard_client/localization/date_time.dart'; import 'package:wrestling_scoreboard_client/localization/season.dart'; import 'package:wrestling_scoreboard_client/provider/data_provider.dart'; -import 'package:wrestling_scoreboard_client/provider/local_preferences_provider.dart'; import 'package:wrestling_scoreboard_client/provider/network_provider.dart'; import 'package:wrestling_scoreboard_client/services/network/data_manager.dart'; import 'package:wrestling_scoreboard_client/view/screens/display/match/match_display.dart'; @@ -52,7 +51,7 @@ class TeamMatchOverview extends ConsumerWidget { // TODO: replace with file_save when https://github.com/flutter/flutter/issues/102560 is merged, also replace in settings. IconButton( onPressed: () async { - final reporter = (await ref.read(reportProviderNotifierProvider))?.reporter; + final reporter = match.organization?.getReporter(); if (reporter != null) { final fileNameBuilder = [ match.date.toIso8601String().substring(0, 10), diff --git a/wrestling_scoreboard_client/test/widget_test.dart b/wrestling_scoreboard_client/test/widget_test.dart index 9840b957..e163bf65 100644 --- a/wrestling_scoreboard_client/test/widget_test.dart +++ b/wrestling_scoreboard_client/test/widget_test.dart @@ -10,9 +10,10 @@ void main() { testWidgets('App launched', (WidgetTester tester) async { // Build our app and trigger a frame. await tester.pumpWidget(mockProviderScope); - await tester.pump(); + await tester.pumpAndSettle(); expect(find.byIcon(Icons.home), findsOneWidget); + expect(find.byIcon(Icons.explore), findsOneWidget); expect(find.byIcon(Icons.more_horiz), findsOneWidget); // Tap more icon. diff --git a/wrestling_scoreboard_common/lib/src/data/bout.dart b/wrestling_scoreboard_common/lib/src/data/bout.dart index 17809f67..6ea9211b 100644 --- a/wrestling_scoreboard_common/lib/src/data/bout.dart +++ b/wrestling_scoreboard_common/lib/src/data/bout.dart @@ -1,11 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import '../enums/bout_result.dart'; -import '../enums/bout_role.dart'; -import 'data_object.dart'; -import 'bout_action.dart'; -import 'participant_state.dart'; -import 'weight_class.dart'; +import '../../common.dart'; part 'bout.freezed.dart'; part 'bout.g.dart'; @@ -185,4 +180,10 @@ class Bout with _$Bout implements DataObject { Bout copyWithId(int? id) { return copyWith(id: id); } + + @override + String? get orgSyncId => throw UnimplementedError(); + + @override + Organization? get organization => throw UnimplementedError(); } diff --git a/wrestling_scoreboard_common/lib/src/data/bout_action.dart b/wrestling_scoreboard_common/lib/src/data/bout_action.dart index 9643c7b0..b8d3d733 100644 --- a/wrestling_scoreboard_common/lib/src/data/bout_action.dart +++ b/wrestling_scoreboard_common/lib/src/data/bout_action.dart @@ -1,9 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import '../enums/bout_action_type.dart'; -import '../enums/bout_role.dart'; -import 'bout.dart'; -import 'data_object.dart'; +import '../../common.dart'; part 'bout_action.freezed.dart'; part 'bout_action.g.dart'; @@ -69,4 +66,10 @@ class BoutAction with _$BoutAction implements DataObject { BoutAction copyWithId(int? id) { return copyWith(id: id); } + + @override + String? get orgSyncId => throw UnimplementedError(); + + @override + Organization? get organization => throw UnimplementedError(); } diff --git a/wrestling_scoreboard_common/lib/src/data/bout_config.dart b/wrestling_scoreboard_common/lib/src/data/bout_config.dart index df70f3df..ef67c793 100644 --- a/wrestling_scoreboard_common/lib/src/data/bout_config.dart +++ b/wrestling_scoreboard_common/lib/src/data/bout_config.dart @@ -1,6 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import 'data_object.dart'; +import '../../common.dart'; part 'bout_config.freezed.dart'; part 'bout_config.g.dart'; @@ -64,4 +64,10 @@ class BoutConfig with _$BoutConfig implements DataObject { BoutConfig copyWithId(int? id) { return copyWith(id: id); } + + @override + String? get orgSyncId => throw UnimplementedError(); + + @override + Organization? get organization => throw UnimplementedError(); } diff --git a/wrestling_scoreboard_common/lib/src/data/club.dart b/wrestling_scoreboard_common/lib/src/data/club.dart index 6ca880bb..23c37e09 100644 --- a/wrestling_scoreboard_common/lib/src/data/club.dart +++ b/wrestling_scoreboard_common/lib/src/data/club.dart @@ -12,8 +12,9 @@ class Club with _$Club implements DataObject { const factory Club({ int? id, - required String name, + String? orgSyncId, required Organization organization, + required String name, String? no, // Club-ID }) = _Club; @@ -23,17 +24,19 @@ class Club with _$Club implements DataObject { Map toRaw() { return { if (id != null) 'id': id, + if (orgSyncId != null) 'org_sync_id': orgSyncId, + 'organization_id': organization.id, 'no': no, 'name': name, - 'organization_id': organization.id, }; } static Future fromRaw(Map e, GetSingleOfTypeCallback getSingle) async => Club( id: e['id'] as int?, + orgSyncId: e['org_sync_id'] as String?, + organization: (await getSingle(e['organization_id'] as int)), no: e['no'] as String?, name: e['name'] as String, - organization: (await getSingle(e['organization_id'] as int)), ); @override diff --git a/wrestling_scoreboard_common/lib/src/data/club.freezed.dart b/wrestling_scoreboard_common/lib/src/data/club.freezed.dart index 2bda5173..9e4e4e71 100644 --- a/wrestling_scoreboard_common/lib/src/data/club.freezed.dart +++ b/wrestling_scoreboard_common/lib/src/data/club.freezed.dart @@ -21,8 +21,9 @@ Club _$ClubFromJson(Map json) { /// @nodoc mixin _$Club { int? get id => throw _privateConstructorUsedError; - String get name => throw _privateConstructorUsedError; + String? get orgSyncId => throw _privateConstructorUsedError; Organization get organization => throw _privateConstructorUsedError; + String get name => throw _privateConstructorUsedError; String? get no => throw _privateConstructorUsedError; Map toJson() => throw _privateConstructorUsedError; @@ -34,7 +35,7 @@ mixin _$Club { abstract class $ClubCopyWith<$Res> { factory $ClubCopyWith(Club value, $Res Function(Club) then) = _$ClubCopyWithImpl<$Res, Club>; @useResult - $Res call({int? id, String name, Organization organization, String? no}); + $Res call({int? id, String? orgSyncId, Organization organization, String name, String? no}); $OrganizationCopyWith<$Res> get organization; } @@ -52,8 +53,9 @@ class _$ClubCopyWithImpl<$Res, $Val extends Club> implements $ClubCopyWith<$Res> @override $Res call({ Object? id = freezed, - Object? name = null, + Object? orgSyncId = freezed, Object? organization = null, + Object? name = null, Object? no = freezed, }) { return _then(_value.copyWith( @@ -61,14 +63,18 @@ class _$ClubCopyWithImpl<$Res, $Val extends Club> implements $ClubCopyWith<$Res> ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, - name: null == name - ? _value.name - : name // ignore: cast_nullable_to_non_nullable - as String, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, organization: null == organization ? _value.organization : organization // ignore: cast_nullable_to_non_nullable as Organization, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, no: freezed == no ? _value.no : no // ignore: cast_nullable_to_non_nullable @@ -90,7 +96,7 @@ abstract class _$$ClubImplCopyWith<$Res> implements $ClubCopyWith<$Res> { factory _$$ClubImplCopyWith(_$ClubImpl value, $Res Function(_$ClubImpl) then) = __$$ClubImplCopyWithImpl<$Res>; @override @useResult - $Res call({int? id, String name, Organization organization, String? no}); + $Res call({int? id, String? orgSyncId, Organization organization, String name, String? no}); @override $OrganizationCopyWith<$Res> get organization; @@ -104,8 +110,9 @@ class __$$ClubImplCopyWithImpl<$Res> extends _$ClubCopyWithImpl<$Res, _$ClubImpl @override $Res call({ Object? id = freezed, - Object? name = null, + Object? orgSyncId = freezed, Object? organization = null, + Object? name = null, Object? no = freezed, }) { return _then(_$ClubImpl( @@ -113,14 +120,18 @@ class __$$ClubImplCopyWithImpl<$Res> extends _$ClubCopyWithImpl<$Res, _$ClubImpl ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, - name: null == name - ? _value.name - : name // ignore: cast_nullable_to_non_nullable - as String, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, organization: null == organization ? _value.organization : organization // ignore: cast_nullable_to_non_nullable as Organization, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, no: freezed == no ? _value.no : no // ignore: cast_nullable_to_non_nullable @@ -132,22 +143,24 @@ class __$$ClubImplCopyWithImpl<$Res> extends _$ClubCopyWithImpl<$Res, _$ClubImpl /// @nodoc @JsonSerializable() class _$ClubImpl extends _Club { - const _$ClubImpl({this.id, required this.name, required this.organization, this.no}) : super._(); + const _$ClubImpl({this.id, this.orgSyncId, required this.organization, required this.name, this.no}) : super._(); factory _$ClubImpl.fromJson(Map json) => _$$ClubImplFromJson(json); @override final int? id; @override - final String name; + final String? orgSyncId; @override final Organization organization; @override + final String name; + @override final String? no; @override String toString() { - return 'Club(id: $id, name: $name, organization: $organization, no: $no)'; + return 'Club(id: $id, orgSyncId: $orgSyncId, organization: $organization, name: $name, no: $no)'; } @override @@ -156,14 +169,15 @@ class _$ClubImpl extends _Club { (other.runtimeType == runtimeType && other is _$ClubImpl && (identical(other.id, id) || other.id == id) && - (identical(other.name, name) || other.name == name) && + (identical(other.orgSyncId, orgSyncId) || other.orgSyncId == orgSyncId) && (identical(other.organization, organization) || other.organization == organization) && + (identical(other.name, name) || other.name == name) && (identical(other.no, no) || other.no == no)); } @JsonKey(ignore: true) @override - int get hashCode => Object.hash(runtimeType, id, name, organization, no); + int get hashCode => Object.hash(runtimeType, id, orgSyncId, organization, name, no); @JsonKey(ignore: true) @override @@ -181,8 +195,9 @@ class _$ClubImpl extends _Club { abstract class _Club extends Club { const factory _Club( {final int? id, - required final String name, + final String? orgSyncId, required final Organization organization, + required final String name, final String? no}) = _$ClubImpl; const _Club._() : super._(); @@ -191,10 +206,12 @@ abstract class _Club extends Club { @override int? get id; @override - String get name; + String? get orgSyncId; @override Organization get organization; @override + String get name; + @override String? get no; @override @JsonKey(ignore: true) diff --git a/wrestling_scoreboard_common/lib/src/data/club.g.dart b/wrestling_scoreboard_common/lib/src/data/club.g.dart index 230deea1..63f0856e 100644 --- a/wrestling_scoreboard_common/lib/src/data/club.g.dart +++ b/wrestling_scoreboard_common/lib/src/data/club.g.dart @@ -8,14 +8,16 @@ part of 'club.dart'; _$ClubImpl _$$ClubImplFromJson(Map json) => _$ClubImpl( id: json['id'] as int?, - name: json['name'] as String, + orgSyncId: json['orgSyncId'] as String?, organization: Organization.fromJson(json['organization'] as Map), + name: json['name'] as String, no: json['no'] as String?, ); Map _$$ClubImplToJson(_$ClubImpl instance) => { 'id': instance.id, - 'name': instance.name, + 'orgSyncId': instance.orgSyncId, 'organization': instance.organization.toJson(), + 'name': instance.name, 'no': instance.no, }; diff --git a/wrestling_scoreboard_common/lib/src/data/competition/competition.dart b/wrestling_scoreboard_common/lib/src/data/competition/competition.dart index ff157ef1..4a782218 100644 --- a/wrestling_scoreboard_common/lib/src/data/competition/competition.dart +++ b/wrestling_scoreboard_common/lib/src/data/competition/competition.dart @@ -1,11 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import '../bout_config.dart'; -import '../data_object.dart'; -import '../bout.dart'; -import '../participation.dart'; -import '../weight_class.dart'; -import '../wrestling_event.dart'; +import '../../../common.dart'; part 'competition.freezed.dart'; part 'competition.g.dart'; @@ -17,6 +12,8 @@ class Competition extends WrestlingEvent with _$Competition { const factory Competition({ int? id, + String? orgSyncId, + Organization? organization, required String name, required BoutConfig boutConfig, String? location, @@ -30,9 +27,12 @@ class Competition extends WrestlingEvent with _$Competition { static Future fromRaw(Map e, GetSingleOfTypeCallback getSingle) async { final boutConfig = await getSingle(e['bout_config_id'] as int); - // TODO fetch lineups, referees, weightClasses, etc. + final organizationId = e['organization_id'] as int?; + // TODO: fetch lineups, referees, weightClasses, etc. return Competition( id: e['id'] as int?, + orgSyncId: e['org_sync_id'] as String?, + organization: organizationId == null ? null : await getSingle(organizationId), name: e['name'], location: e['location'] as String?, date: e['date'] as DateTime, @@ -46,7 +46,6 @@ class Competition extends WrestlingEvent with _$Competition { Map toRaw() { return super.toRaw() ..addAll({ - if (id != null) 'id': id, 'name': name, 'bout_config_id': boutConfig.id, }); diff --git a/wrestling_scoreboard_common/lib/src/data/competition/competition.freezed.dart b/wrestling_scoreboard_common/lib/src/data/competition/competition.freezed.dart index e7de8043..46c71c91 100644 --- a/wrestling_scoreboard_common/lib/src/data/competition/competition.freezed.dart +++ b/wrestling_scoreboard_common/lib/src/data/competition/competition.freezed.dart @@ -21,6 +21,8 @@ Competition _$CompetitionFromJson(Map json) { /// @nodoc mixin _$Competition { int? get id => throw _privateConstructorUsedError; + String? get orgSyncId => throw _privateConstructorUsedError; + Organization? get organization => throw _privateConstructorUsedError; String get name => throw _privateConstructorUsedError; BoutConfig get boutConfig => throw _privateConstructorUsedError; String? get location => throw _privateConstructorUsedError; @@ -41,6 +43,8 @@ abstract class $CompetitionCopyWith<$Res> { @useResult $Res call( {int? id, + String? orgSyncId, + Organization? organization, String name, BoutConfig boutConfig, String? location, @@ -49,6 +53,7 @@ abstract class $CompetitionCopyWith<$Res> { int? visitorsCount, String? comment}); + $OrganizationCopyWith<$Res>? get organization; $BoutConfigCopyWith<$Res> get boutConfig; } @@ -65,6 +70,8 @@ class _$CompetitionCopyWithImpl<$Res, $Val extends Competition> implements $Comp @override $Res call({ Object? id = freezed, + Object? orgSyncId = freezed, + Object? organization = freezed, Object? name = null, Object? boutConfig = null, Object? location = freezed, @@ -78,6 +85,14 @@ class _$CompetitionCopyWithImpl<$Res, $Val extends Competition> implements $Comp ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, + organization: freezed == organization + ? _value.organization + : organization // ignore: cast_nullable_to_non_nullable + as Organization?, name: null == name ? _value.name : name // ignore: cast_nullable_to_non_nullable @@ -109,6 +124,18 @@ class _$CompetitionCopyWithImpl<$Res, $Val extends Competition> implements $Comp ) as $Val); } + @override + @pragma('vm:prefer-inline') + $OrganizationCopyWith<$Res>? get organization { + if (_value.organization == null) { + return null; + } + + return $OrganizationCopyWith<$Res>(_value.organization!, (value) { + return _then(_value.copyWith(organization: value) as $Val); + }); + } + @override @pragma('vm:prefer-inline') $BoutConfigCopyWith<$Res> get boutConfig { @@ -126,6 +153,8 @@ abstract class _$$CompetitionImplCopyWith<$Res> implements $CompetitionCopyWith< @useResult $Res call( {int? id, + String? orgSyncId, + Organization? organization, String name, BoutConfig boutConfig, String? location, @@ -134,6 +163,8 @@ abstract class _$$CompetitionImplCopyWith<$Res> implements $CompetitionCopyWith< int? visitorsCount, String? comment}); + @override + $OrganizationCopyWith<$Res>? get organization; @override $BoutConfigCopyWith<$Res> get boutConfig; } @@ -148,6 +179,8 @@ class __$$CompetitionImplCopyWithImpl<$Res> extends _$CompetitionCopyWithImpl<$R @override $Res call({ Object? id = freezed, + Object? orgSyncId = freezed, + Object? organization = freezed, Object? name = null, Object? boutConfig = null, Object? location = freezed, @@ -161,6 +194,14 @@ class __$$CompetitionImplCopyWithImpl<$Res> extends _$CompetitionCopyWithImpl<$R ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, + organization: freezed == organization + ? _value.organization + : organization // ignore: cast_nullable_to_non_nullable + as Organization?, name: null == name ? _value.name : name // ignore: cast_nullable_to_non_nullable @@ -198,6 +239,8 @@ class __$$CompetitionImplCopyWithImpl<$Res> extends _$CompetitionCopyWithImpl<$R class _$CompetitionImpl extends _Competition { const _$CompetitionImpl( {this.id, + this.orgSyncId, + this.organization, required this.name, required this.boutConfig, this.location, @@ -212,6 +255,10 @@ class _$CompetitionImpl extends _Competition { @override final int? id; @override + final String? orgSyncId; + @override + final Organization? organization; + @override final String name; @override final BoutConfig boutConfig; @@ -228,7 +275,7 @@ class _$CompetitionImpl extends _Competition { @override String toString() { - return 'Competition(id: $id, name: $name, boutConfig: $boutConfig, location: $location, date: $date, no: $no, visitorsCount: $visitorsCount, comment: $comment)'; + return 'Competition(id: $id, orgSyncId: $orgSyncId, organization: $organization, name: $name, boutConfig: $boutConfig, location: $location, date: $date, no: $no, visitorsCount: $visitorsCount, comment: $comment)'; } @override @@ -237,6 +284,8 @@ class _$CompetitionImpl extends _Competition { (other.runtimeType == runtimeType && other is _$CompetitionImpl && (identical(other.id, id) || other.id == id) && + (identical(other.orgSyncId, orgSyncId) || other.orgSyncId == orgSyncId) && + (identical(other.organization, organization) || other.organization == organization) && (identical(other.name, name) || other.name == name) && (identical(other.boutConfig, boutConfig) || other.boutConfig == boutConfig) && (identical(other.location, location) || other.location == location) && @@ -248,7 +297,8 @@ class _$CompetitionImpl extends _Competition { @JsonKey(ignore: true) @override - int get hashCode => Object.hash(runtimeType, id, name, boutConfig, location, date, no, visitorsCount, comment); + int get hashCode => Object.hash( + runtimeType, id, orgSyncId, organization, name, boutConfig, location, date, no, visitorsCount, comment); @JsonKey(ignore: true) @override @@ -267,6 +317,8 @@ class _$CompetitionImpl extends _Competition { abstract class _Competition extends Competition { const factory _Competition( {final int? id, + final String? orgSyncId, + final Organization? organization, required final String name, required final BoutConfig boutConfig, final String? location, @@ -281,6 +333,10 @@ abstract class _Competition extends Competition { @override int? get id; @override + String? get orgSyncId; + @override + Organization? get organization; + @override String get name; @override BoutConfig get boutConfig; diff --git a/wrestling_scoreboard_common/lib/src/data/competition/competition.g.dart b/wrestling_scoreboard_common/lib/src/data/competition/competition.g.dart index 7e5f920a..cb3e88d8 100644 --- a/wrestling_scoreboard_common/lib/src/data/competition/competition.g.dart +++ b/wrestling_scoreboard_common/lib/src/data/competition/competition.g.dart @@ -8,6 +8,9 @@ part of 'competition.dart'; _$CompetitionImpl _$$CompetitionImplFromJson(Map json) => _$CompetitionImpl( id: json['id'] as int?, + orgSyncId: json['orgSyncId'] as String?, + organization: + json['organization'] == null ? null : Organization.fromJson(json['organization'] as Map), name: json['name'] as String, boutConfig: BoutConfig.fromJson(json['boutConfig'] as Map), location: json['location'] as String?, @@ -19,6 +22,8 @@ _$CompetitionImpl _$$CompetitionImplFromJson(Map json) => _$Com Map _$$CompetitionImplToJson(_$CompetitionImpl instance) => { 'id': instance.id, + 'orgSyncId': instance.orgSyncId, + 'organization': instance.organization?.toJson(), 'name': instance.name, 'boutConfig': instance.boutConfig.toJson(), 'location': instance.location, diff --git a/wrestling_scoreboard_common/lib/src/data/competition/competition_bout.dart b/wrestling_scoreboard_common/lib/src/data/competition/competition_bout.dart index 749a81d6..d3afa7ed 100644 --- a/wrestling_scoreboard_common/lib/src/data/competition/competition_bout.dart +++ b/wrestling_scoreboard_common/lib/src/data/competition/competition_bout.dart @@ -1,8 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import '../data_object.dart'; -import '../bout.dart'; -import 'competition.dart'; +import '../../../common.dart'; part 'competition_bout.freezed.dart'; part 'competition_bout.g.dart'; @@ -46,4 +44,10 @@ class CompetitionBout with _$CompetitionBout implements DataObject { CompetitionBout copyWithId(int? id) { return copyWith(id: id); } + + @override + String? get orgSyncId => throw UnimplementedError(); + + @override + Organization? get organization => throw UnimplementedError(); } diff --git a/wrestling_scoreboard_common/lib/src/data/competition/competition_person.dart b/wrestling_scoreboard_common/lib/src/data/competition/competition_person.dart index c6b06fd6..9d005b0d 100644 --- a/wrestling_scoreboard_common/lib/src/data/competition/competition_person.dart +++ b/wrestling_scoreboard_common/lib/src/data/competition/competition_person.dart @@ -1,9 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import '../../enums/person_role.dart'; -import '../data_object.dart'; -import '../person.dart'; -import 'competition.dart'; +import '../../../common.dart'; part 'competition_person.freezed.dart'; part 'competition_person.g.dart'; @@ -47,4 +44,10 @@ class CompetitionPerson with _$CompetitionPerson implements DataObject { CompetitionPerson copyWithId(int? id) { return copyWith(id: id); } + + @override + String? get orgSyncId => throw UnimplementedError(); + + @override + Organization? get organization => throw UnimplementedError(); } diff --git a/wrestling_scoreboard_common/lib/src/data/competition/competition_team_participation.dart b/wrestling_scoreboard_common/lib/src/data/competition/competition_team_participation.dart index bc346b13..56dc512c 100644 --- a/wrestling_scoreboard_common/lib/src/data/competition/competition_team_participation.dart +++ b/wrestling_scoreboard_common/lib/src/data/competition/competition_team_participation.dart @@ -1,8 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import '../data_object.dart'; -import '../team.dart'; -import 'competition.dart'; +import '../../../common.dart'; part 'competition_team_participation.freezed.dart'; part 'competition_team_participation.g.dart'; @@ -45,4 +43,10 @@ class CompetitionTeamParticipation with _$CompetitionTeamParticipation implement CompetitionTeamParticipation copyWithId(int? id) { return copyWith(id: id); } + + @override + String? get orgSyncId => throw UnimplementedError(); + + @override + Organization? get organization => throw UnimplementedError(); } diff --git a/wrestling_scoreboard_common/lib/src/data/data_object.dart b/wrestling_scoreboard_common/lib/src/data/data_object.dart index 94e3c1e7..1fccb48d 100644 --- a/wrestling_scoreboard_common/lib/src/data/data_object.dart +++ b/wrestling_scoreboard_common/lib/src/data/data_object.dart @@ -6,6 +6,10 @@ typedef GetSingleOfTypeCallback = Future Function(int i abstract class DataObject { int? get id; + String? get orgSyncId => null; + + Organization? get organization => null; + Map toJson(); Map toRaw(); @@ -94,7 +98,7 @@ abstract class DataObject { case const (ParticipantState): return (await ParticipantState.fromRaw(raw, getSingle)) as T; case const (Person): - return (await Person.fromRaw(raw)) as T; + return (await Person.fromRaw(raw, getSingle)) as T; case const (Team): return (await Team.fromRaw(raw, getSingle)) as T; case const (TeamMatch): diff --git a/wrestling_scoreboard_common/lib/src/data/lineup.dart b/wrestling_scoreboard_common/lib/src/data/lineup.dart index cf6b9e4c..71a0215e 100644 --- a/wrestling_scoreboard_common/lib/src/data/lineup.dart +++ b/wrestling_scoreboard_common/lib/src/data/lineup.dart @@ -1,8 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import 'data_object.dart'; -import 'membership.dart'; -import 'team.dart'; +import '../../common.dart'; part 'lineup.freezed.dart'; part 'lineup.g.dart'; @@ -22,13 +20,14 @@ class Lineup with _$Lineup implements DataObject { factory Lineup.fromJson(Map json) => _$LineupFromJson(json); static Future fromRaw(Map e, GetSingleOfTypeCallback getSingle) async { - final id = e['id'] as int?; - final team = await getSingle(e['team_id'] as int); final leaderId = e['leader_id'] as int?; - final leader = leaderId == null ? null : await getSingle(leaderId); final coachId = e['coach_id'] as int?; - final coach = coachId == null ? null : await getSingle(coachId); - return Lineup(id: id, team: team, leader: leader, coach: coach); + return Lineup( + id: e['id'] as int?, + team: await getSingle(e['team_id'] as int), + leader: leaderId == null ? null : await getSingle(leaderId), + coach: coachId == null ? null : await getSingle(coachId), + ); } @override @@ -48,4 +47,10 @@ class Lineup with _$Lineup implements DataObject { Lineup copyWithId(int? id) { return copyWith(id: id); } + + @override + String? get orgSyncId => throw UnimplementedError(); + + @override + Organization? get organization => throw UnimplementedError(); } diff --git a/wrestling_scoreboard_common/lib/src/data/membership.dart b/wrestling_scoreboard_common/lib/src/data/membership.dart index 53046c9e..2427af54 100644 --- a/wrestling_scoreboard_common/lib/src/data/membership.dart +++ b/wrestling_scoreboard_common/lib/src/data/membership.dart @@ -1,8 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import 'club.dart'; -import 'data_object.dart'; -import 'person.dart'; +import '../../common.dart'; part 'membership.freezed.dart'; part 'membership.g.dart'; @@ -14,6 +12,8 @@ class Membership with _$Membership implements DataObject { const factory Membership({ int? id, + String? orgSyncId, + Organization? organization, String? no, // Vereinsnummer required Club club, required Person person, @@ -24,8 +24,11 @@ class Membership with _$Membership implements DataObject { static Future fromRaw(Map e, GetSingleOfTypeCallback getSingle) async { final person = await getSingle(e['person_id'] as int); final club = await getSingle(e['club_id'] as int); + final organizationId = e['organization_id'] as int?; return Membership( id: e['id'] as int?, + orgSyncId: e['org_sync_id'] as String?, + organization: organizationId == null ? null : await getSingle(organizationId), no: e['no'] as String?, person: person, club: club, @@ -36,6 +39,8 @@ class Membership with _$Membership implements DataObject { Map toRaw() { return { if (id != null) 'id': id, + if (orgSyncId != null) 'org_sync_id': orgSyncId, + if (organization != null) 'organization_id': organization?.id, 'person_id': person.id, 'club_id': club.id, 'no': no, diff --git a/wrestling_scoreboard_common/lib/src/data/membership.freezed.dart b/wrestling_scoreboard_common/lib/src/data/membership.freezed.dart index d620fa2f..6ddb4d19 100644 --- a/wrestling_scoreboard_common/lib/src/data/membership.freezed.dart +++ b/wrestling_scoreboard_common/lib/src/data/membership.freezed.dart @@ -21,6 +21,8 @@ Membership _$MembershipFromJson(Map json) { /// @nodoc mixin _$Membership { int? get id => throw _privateConstructorUsedError; + String? get orgSyncId => throw _privateConstructorUsedError; + Organization? get organization => throw _privateConstructorUsedError; String? get no => throw _privateConstructorUsedError; // Vereinsnummer Club get club => throw _privateConstructorUsedError; Person get person => throw _privateConstructorUsedError; @@ -35,8 +37,9 @@ abstract class $MembershipCopyWith<$Res> { factory $MembershipCopyWith(Membership value, $Res Function(Membership) then) = _$MembershipCopyWithImpl<$Res, Membership>; @useResult - $Res call({int? id, String? no, Club club, Person person}); + $Res call({int? id, String? orgSyncId, Organization? organization, String? no, Club club, Person person}); + $OrganizationCopyWith<$Res>? get organization; $ClubCopyWith<$Res> get club; $PersonCopyWith<$Res> get person; } @@ -54,6 +57,8 @@ class _$MembershipCopyWithImpl<$Res, $Val extends Membership> implements $Member @override $Res call({ Object? id = freezed, + Object? orgSyncId = freezed, + Object? organization = freezed, Object? no = freezed, Object? club = null, Object? person = null, @@ -63,6 +68,14 @@ class _$MembershipCopyWithImpl<$Res, $Val extends Membership> implements $Member ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, + organization: freezed == organization + ? _value.organization + : organization // ignore: cast_nullable_to_non_nullable + as Organization?, no: freezed == no ? _value.no : no // ignore: cast_nullable_to_non_nullable @@ -78,6 +91,18 @@ class _$MembershipCopyWithImpl<$Res, $Val extends Membership> implements $Member ) as $Val); } + @override + @pragma('vm:prefer-inline') + $OrganizationCopyWith<$Res>? get organization { + if (_value.organization == null) { + return null; + } + + return $OrganizationCopyWith<$Res>(_value.organization!, (value) { + return _then(_value.copyWith(organization: value) as $Val); + }); + } + @override @pragma('vm:prefer-inline') $ClubCopyWith<$Res> get club { @@ -101,8 +126,10 @@ abstract class _$$MembershipImplCopyWith<$Res> implements $MembershipCopyWith<$R __$$MembershipImplCopyWithImpl<$Res>; @override @useResult - $Res call({int? id, String? no, Club club, Person person}); + $Res call({int? id, String? orgSyncId, Organization? organization, String? no, Club club, Person person}); + @override + $OrganizationCopyWith<$Res>? get organization; @override $ClubCopyWith<$Res> get club; @override @@ -118,6 +145,8 @@ class __$$MembershipImplCopyWithImpl<$Res> extends _$MembershipCopyWithImpl<$Res @override $Res call({ Object? id = freezed, + Object? orgSyncId = freezed, + Object? organization = freezed, Object? no = freezed, Object? club = null, Object? person = null, @@ -127,6 +156,14 @@ class __$$MembershipImplCopyWithImpl<$Res> extends _$MembershipCopyWithImpl<$Res ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, + organization: freezed == organization + ? _value.organization + : organization // ignore: cast_nullable_to_non_nullable + as Organization?, no: freezed == no ? _value.no : no // ignore: cast_nullable_to_non_nullable @@ -146,13 +183,19 @@ class __$$MembershipImplCopyWithImpl<$Res> extends _$MembershipCopyWithImpl<$Res /// @nodoc @JsonSerializable() class _$MembershipImpl extends _Membership { - const _$MembershipImpl({this.id, this.no, required this.club, required this.person}) : super._(); + const _$MembershipImpl( + {this.id, this.orgSyncId, this.organization, this.no, required this.club, required this.person}) + : super._(); factory _$MembershipImpl.fromJson(Map json) => _$$MembershipImplFromJson(json); @override final int? id; @override + final String? orgSyncId; + @override + final Organization? organization; + @override final String? no; // Vereinsnummer @override @@ -162,7 +205,7 @@ class _$MembershipImpl extends _Membership { @override String toString() { - return 'Membership(id: $id, no: $no, club: $club, person: $person)'; + return 'Membership(id: $id, orgSyncId: $orgSyncId, organization: $organization, no: $no, club: $club, person: $person)'; } @override @@ -171,6 +214,8 @@ class _$MembershipImpl extends _Membership { (other.runtimeType == runtimeType && other is _$MembershipImpl && (identical(other.id, id) || other.id == id) && + (identical(other.orgSyncId, orgSyncId) || other.orgSyncId == orgSyncId) && + (identical(other.organization, organization) || other.organization == organization) && (identical(other.no, no) || other.no == no) && (identical(other.club, club) || other.club == club) && (identical(other.person, person) || other.person == person)); @@ -178,7 +223,7 @@ class _$MembershipImpl extends _Membership { @JsonKey(ignore: true) @override - int get hashCode => Object.hash(runtimeType, id, no, club, person); + int get hashCode => Object.hash(runtimeType, id, orgSyncId, organization, no, club, person); @JsonKey(ignore: true) @override @@ -195,8 +240,13 @@ class _$MembershipImpl extends _Membership { } abstract class _Membership extends Membership { - const factory _Membership({final int? id, final String? no, required final Club club, required final Person person}) = - _$MembershipImpl; + const factory _Membership( + {final int? id, + final String? orgSyncId, + final Organization? organization, + final String? no, + required final Club club, + required final Person person}) = _$MembershipImpl; const _Membership._() : super._(); factory _Membership.fromJson(Map json) = _$MembershipImpl.fromJson; @@ -204,6 +254,10 @@ abstract class _Membership extends Membership { @override int? get id; @override + String? get orgSyncId; + @override + Organization? get organization; + @override String? get no; @override // Vereinsnummer Club get club; diff --git a/wrestling_scoreboard_common/lib/src/data/membership.g.dart b/wrestling_scoreboard_common/lib/src/data/membership.g.dart index 85889f66..814d6051 100644 --- a/wrestling_scoreboard_common/lib/src/data/membership.g.dart +++ b/wrestling_scoreboard_common/lib/src/data/membership.g.dart @@ -8,6 +8,9 @@ part of 'membership.dart'; _$MembershipImpl _$$MembershipImplFromJson(Map json) => _$MembershipImpl( id: json['id'] as int?, + orgSyncId: json['orgSyncId'] as String?, + organization: + json['organization'] == null ? null : Organization.fromJson(json['organization'] as Map), no: json['no'] as String?, club: Club.fromJson(json['club'] as Map), person: Person.fromJson(json['person'] as Map), @@ -15,6 +18,8 @@ _$MembershipImpl _$$MembershipImplFromJson(Map json) => _$Membe Map _$$MembershipImplToJson(_$MembershipImpl instance) => { 'id': instance.id, + 'orgSyncId': instance.orgSyncId, + 'organization': instance.organization?.toJson(), 'no': instance.no, 'club': instance.club.toJson(), 'person': instance.person.toJson(), diff --git a/wrestling_scoreboard_common/lib/src/data/organization.dart b/wrestling_scoreboard_common/lib/src/data/organization.dart index 7d5f07bb..e393c83e 100644 --- a/wrestling_scoreboard_common/lib/src/data/organization.dart +++ b/wrestling_scoreboard_common/lib/src/data/organization.dart @@ -15,6 +15,8 @@ class Organization with _$Organization implements DataObject { required String name, String? abbreviation, Organization? parent, + WrestlingApiProvider? apiProvider, + WrestlingReportProvider? reportProvider, }) = _Organization; factory Organization.fromJson(Map json) => _$OrganizationFromJson(json); @@ -22,10 +24,14 @@ class Organization with _$Organization implements DataObject { static Future fromRaw(Map e, GetSingleOfTypeCallback getSingle) async { final parentId = e['parent_id'] as int?; final parent = parentId == null ? null : await getSingle(parentId); + final apiProviderStr = e['api_provider'] as String?; + final reportProviderStr = e['report_provider'] as String?; return Organization( id: e['id'] as int?, name: e['name'] as String, abbreviation: e['abbreviation'] as String?, + apiProvider: apiProviderStr == null ? null : WrestlingApiProvider.values.byName(apiProviderStr), + reportProvider: reportProviderStr == null ? null : WrestlingReportProvider.values.byName(reportProviderStr), parent: parent, ); } @@ -37,6 +43,8 @@ class Organization with _$Organization implements DataObject { 'name': name, 'abbreviation': abbreviation, 'parent_id': parent?.id, + 'api_provider': apiProvider?.name, + 'report_provider': reportProvider?.name, }; } @@ -45,8 +53,18 @@ class Organization with _$Organization implements DataObject { String get fullname => '$name ($abbreviation)'; + WrestlingApi? getApi(GetSingleOfOrg getSingle) => apiProvider?.getApi(this, getSingleOfOrg: getSingle); + + WrestlingReporter? getReporter() => reportProvider?.getReporter(this); + @override Organization copyWithId(int? id) { return copyWith(id: id); } + + @override + String? get orgSyncId => throw UnimplementedError(); + + @override + Organization? get organization => throw UnimplementedError(); } diff --git a/wrestling_scoreboard_common/lib/src/data/organization.freezed.dart b/wrestling_scoreboard_common/lib/src/data/organization.freezed.dart index 5f2c6411..fbcc3601 100644 --- a/wrestling_scoreboard_common/lib/src/data/organization.freezed.dart +++ b/wrestling_scoreboard_common/lib/src/data/organization.freezed.dart @@ -24,6 +24,8 @@ mixin _$Organization { String get name => throw _privateConstructorUsedError; String? get abbreviation => throw _privateConstructorUsedError; Organization? get parent => throw _privateConstructorUsedError; + WrestlingApiProvider? get apiProvider => throw _privateConstructorUsedError; + WrestlingReportProvider? get reportProvider => throw _privateConstructorUsedError; Map toJson() => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -35,7 +37,13 @@ abstract class $OrganizationCopyWith<$Res> { factory $OrganizationCopyWith(Organization value, $Res Function(Organization) then) = _$OrganizationCopyWithImpl<$Res, Organization>; @useResult - $Res call({int? id, String name, String? abbreviation, Organization? parent}); + $Res call( + {int? id, + String name, + String? abbreviation, + Organization? parent, + WrestlingApiProvider? apiProvider, + WrestlingReportProvider? reportProvider}); $OrganizationCopyWith<$Res>? get parent; } @@ -56,6 +64,8 @@ class _$OrganizationCopyWithImpl<$Res, $Val extends Organization> implements $Or Object? name = null, Object? abbreviation = freezed, Object? parent = freezed, + Object? apiProvider = freezed, + Object? reportProvider = freezed, }) { return _then(_value.copyWith( id: freezed == id @@ -74,6 +84,14 @@ class _$OrganizationCopyWithImpl<$Res, $Val extends Organization> implements $Or ? _value.parent : parent // ignore: cast_nullable_to_non_nullable as Organization?, + apiProvider: freezed == apiProvider + ? _value.apiProvider + : apiProvider // ignore: cast_nullable_to_non_nullable + as WrestlingApiProvider?, + reportProvider: freezed == reportProvider + ? _value.reportProvider + : reportProvider // ignore: cast_nullable_to_non_nullable + as WrestlingReportProvider?, ) as $Val); } @@ -96,7 +114,13 @@ abstract class _$$OrganizationImplCopyWith<$Res> implements $OrganizationCopyWit __$$OrganizationImplCopyWithImpl<$Res>; @override @useResult - $Res call({int? id, String name, String? abbreviation, Organization? parent}); + $Res call( + {int? id, + String name, + String? abbreviation, + Organization? parent, + WrestlingApiProvider? apiProvider, + WrestlingReportProvider? reportProvider}); @override $OrganizationCopyWith<$Res>? get parent; @@ -115,6 +139,8 @@ class __$$OrganizationImplCopyWithImpl<$Res> extends _$OrganizationCopyWithImpl< Object? name = null, Object? abbreviation = freezed, Object? parent = freezed, + Object? apiProvider = freezed, + Object? reportProvider = freezed, }) { return _then(_$OrganizationImpl( id: freezed == id @@ -133,6 +159,14 @@ class __$$OrganizationImplCopyWithImpl<$Res> extends _$OrganizationCopyWithImpl< ? _value.parent : parent // ignore: cast_nullable_to_non_nullable as Organization?, + apiProvider: freezed == apiProvider + ? _value.apiProvider + : apiProvider // ignore: cast_nullable_to_non_nullable + as WrestlingApiProvider?, + reportProvider: freezed == reportProvider + ? _value.reportProvider + : reportProvider // ignore: cast_nullable_to_non_nullable + as WrestlingReportProvider?, )); } } @@ -140,7 +174,9 @@ class __$$OrganizationImplCopyWithImpl<$Res> extends _$OrganizationCopyWithImpl< /// @nodoc @JsonSerializable() class _$OrganizationImpl extends _Organization { - const _$OrganizationImpl({this.id, required this.name, this.abbreviation, this.parent}) : super._(); + const _$OrganizationImpl( + {this.id, required this.name, this.abbreviation, this.parent, this.apiProvider, this.reportProvider}) + : super._(); factory _$OrganizationImpl.fromJson(Map json) => _$$OrganizationImplFromJson(json); @@ -152,10 +188,14 @@ class _$OrganizationImpl extends _Organization { final String? abbreviation; @override final Organization? parent; + @override + final WrestlingApiProvider? apiProvider; + @override + final WrestlingReportProvider? reportProvider; @override String toString() { - return 'Organization(id: $id, name: $name, abbreviation: $abbreviation, parent: $parent)'; + return 'Organization(id: $id, name: $name, abbreviation: $abbreviation, parent: $parent, apiProvider: $apiProvider, reportProvider: $reportProvider)'; } @override @@ -166,12 +206,14 @@ class _$OrganizationImpl extends _Organization { (identical(other.id, id) || other.id == id) && (identical(other.name, name) || other.name == name) && (identical(other.abbreviation, abbreviation) || other.abbreviation == abbreviation) && - (identical(other.parent, parent) || other.parent == parent)); + (identical(other.parent, parent) || other.parent == parent) && + (identical(other.apiProvider, apiProvider) || other.apiProvider == apiProvider) && + (identical(other.reportProvider, reportProvider) || other.reportProvider == reportProvider)); } @JsonKey(ignore: true) @override - int get hashCode => Object.hash(runtimeType, id, name, abbreviation, parent); + int get hashCode => Object.hash(runtimeType, id, name, abbreviation, parent, apiProvider, reportProvider); @JsonKey(ignore: true) @override @@ -192,7 +234,9 @@ abstract class _Organization extends Organization { {final int? id, required final String name, final String? abbreviation, - final Organization? parent}) = _$OrganizationImpl; + final Organization? parent, + final WrestlingApiProvider? apiProvider, + final WrestlingReportProvider? reportProvider}) = _$OrganizationImpl; const _Organization._() : super._(); factory _Organization.fromJson(Map json) = _$OrganizationImpl.fromJson; @@ -206,6 +250,10 @@ abstract class _Organization extends Organization { @override Organization? get parent; @override + WrestlingApiProvider? get apiProvider; + @override + WrestlingReportProvider? get reportProvider; + @override @JsonKey(ignore: true) _$$OrganizationImplCopyWith<_$OrganizationImpl> get copyWith => throw _privateConstructorUsedError; } diff --git a/wrestling_scoreboard_common/lib/src/data/organization.g.dart b/wrestling_scoreboard_common/lib/src/data/organization.g.dart index 207a6ea0..64617e92 100644 --- a/wrestling_scoreboard_common/lib/src/data/organization.g.dart +++ b/wrestling_scoreboard_common/lib/src/data/organization.g.dart @@ -11,6 +11,8 @@ _$OrganizationImpl _$$OrganizationImplFromJson(Map json) => _$O name: json['name'] as String, abbreviation: json['abbreviation'] as String?, parent: json['parent'] == null ? null : Organization.fromJson(json['parent'] as Map), + apiProvider: $enumDecodeNullable(_$WrestlingApiProviderEnumMap, json['apiProvider']), + reportProvider: $enumDecodeNullable(_$WrestlingReportProviderEnumMap, json['reportProvider']), ); Map _$$OrganizationImplToJson(_$OrganizationImpl instance) => { @@ -18,4 +20,15 @@ Map _$$OrganizationImplToJson(_$OrganizationImpl instance) => < 'name': instance.name, 'abbreviation': instance.abbreviation, 'parent': instance.parent?.toJson(), + 'apiProvider': _$WrestlingApiProviderEnumMap[instance.apiProvider], + 'reportProvider': _$WrestlingReportProviderEnumMap[instance.reportProvider], }; + +const _$WrestlingApiProviderEnumMap = { + WrestlingApiProvider.deNwRingenApi: 'deNwRingenApi', + WrestlingApiProvider.deByRingenApi: 'deByRingenApi', +}; + +const _$WrestlingReportProviderEnumMap = { + WrestlingReportProvider.deNwRdb274: 'deNwRdb274', +}; diff --git a/wrestling_scoreboard_common/lib/src/data/participant_state.dart b/wrestling_scoreboard_common/lib/src/data/participant_state.dart index a95bf0bf..0a1e3ed8 100644 --- a/wrestling_scoreboard_common/lib/src/data/participant_state.dart +++ b/wrestling_scoreboard_common/lib/src/data/participant_state.dart @@ -1,10 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import '../enums/bout_action_type.dart'; -import '../enums/bout_role.dart'; -import 'data_object.dart'; -import 'bout_action.dart'; -import 'participation.dart'; +import '../../common.dart'; part 'participant_state.freezed.dart'; part 'participant_state.g.dart'; @@ -59,4 +55,10 @@ class ParticipantState with _$ParticipantState implements DataObject { ParticipantState copyWithId(int? id) { return copyWith(id: id); } + + @override + String? get orgSyncId => throw UnimplementedError(); + + @override + Organization? get organization => throw UnimplementedError(); } diff --git a/wrestling_scoreboard_common/lib/src/data/participation.dart b/wrestling_scoreboard_common/lib/src/data/participation.dart index 98a03580..8ef61e3b 100644 --- a/wrestling_scoreboard_common/lib/src/data/participation.dart +++ b/wrestling_scoreboard_common/lib/src/data/participation.dart @@ -1,9 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import 'data_object.dart'; -import 'lineup.dart'; -import 'membership.dart'; -import 'weight_class.dart'; +import '../../common.dart'; part 'participation.freezed.dart'; part 'participation.g.dart'; @@ -61,4 +58,10 @@ class Participation with _$Participation implements DataObject { Participation copyWithId(int? id) { return copyWith(id: id); } + + @override + String? get orgSyncId => throw UnimplementedError(); + + @override + Organization? get organization => throw UnimplementedError(); } diff --git a/wrestling_scoreboard_common/lib/src/data/person.dart b/wrestling_scoreboard_common/lib/src/data/person.dart index ba846041..99f35ea3 100644 --- a/wrestling_scoreboard_common/lib/src/data/person.dart +++ b/wrestling_scoreboard_common/lib/src/data/person.dart @@ -1,9 +1,7 @@ import 'package:country/country.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import '../enums/gender.dart'; -import '../util.dart'; -import 'data_object.dart'; +import '../../common.dart'; part 'person.freezed.dart'; part 'person.g.dart'; @@ -25,6 +23,8 @@ class Person with _$Person implements DataObject { const factory Person({ int? id, + String? orgSyncId, + Organization? organization, required String prename, required String surname, Gender? gender, @@ -34,11 +34,14 @@ class Person with _$Person implements DataObject { factory Person.fromJson(Map json) => _$PersonFromJson(json); - static Future fromRaw(Map e) async { + static Future fromRaw(Map e, GetSingleOfTypeCallback getSingle) async { final gender = e['gender'] as String?; final nationality = e['nationality'] as String?; + final organizationId = e['organization_id'] as int?; return Person( id: e['id'] as int?, + orgSyncId: e['org_sync_id'] as String?, + organization: organizationId == null ? null : await getSingle(organizationId), prename: e['prename'] as String, surname: e['surname'] as String, gender: gender == null ? null : Gender.values.byName(gender), @@ -51,6 +54,8 @@ class Person with _$Person implements DataObject { Map toRaw() { return { if (id != null) 'id': id, + if (orgSyncId != null) 'org_sync_id': orgSyncId, + if (organization != null) 'organization_id': organization?.id, 'prename': prename, 'surname': surname, 'gender': gender?.name, diff --git a/wrestling_scoreboard_common/lib/src/data/person.freezed.dart b/wrestling_scoreboard_common/lib/src/data/person.freezed.dart index 80793861..a05fa2b2 100644 --- a/wrestling_scoreboard_common/lib/src/data/person.freezed.dart +++ b/wrestling_scoreboard_common/lib/src/data/person.freezed.dart @@ -21,6 +21,8 @@ Person _$PersonFromJson(Map json) { /// @nodoc mixin _$Person { int? get id => throw _privateConstructorUsedError; + String? get orgSyncId => throw _privateConstructorUsedError; + Organization? get organization => throw _privateConstructorUsedError; String get prename => throw _privateConstructorUsedError; String get surname => throw _privateConstructorUsedError; Gender? get gender => throw _privateConstructorUsedError; @@ -39,11 +41,15 @@ abstract class $PersonCopyWith<$Res> { @useResult $Res call( {int? id, + String? orgSyncId, + Organization? organization, String prename, String surname, Gender? gender, DateTime? birthDate, @CountryJsonConverter() Country? nationality}); + + $OrganizationCopyWith<$Res>? get organization; } /// @nodoc @@ -59,6 +65,8 @@ class _$PersonCopyWithImpl<$Res, $Val extends Person> implements $PersonCopyWith @override $Res call({ Object? id = freezed, + Object? orgSyncId = freezed, + Object? organization = freezed, Object? prename = null, Object? surname = null, Object? gender = freezed, @@ -70,6 +78,14 @@ class _$PersonCopyWithImpl<$Res, $Val extends Person> implements $PersonCopyWith ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, + organization: freezed == organization + ? _value.organization + : organization // ignore: cast_nullable_to_non_nullable + as Organization?, prename: null == prename ? _value.prename : prename // ignore: cast_nullable_to_non_nullable @@ -92,6 +108,18 @@ class _$PersonCopyWithImpl<$Res, $Val extends Person> implements $PersonCopyWith as Country?, ) as $Val); } + + @override + @pragma('vm:prefer-inline') + $OrganizationCopyWith<$Res>? get organization { + if (_value.organization == null) { + return null; + } + + return $OrganizationCopyWith<$Res>(_value.organization!, (value) { + return _then(_value.copyWith(organization: value) as $Val); + }); + } } /// @nodoc @@ -102,11 +130,16 @@ abstract class _$$PersonImplCopyWith<$Res> implements $PersonCopyWith<$Res> { @useResult $Res call( {int? id, + String? orgSyncId, + Organization? organization, String prename, String surname, Gender? gender, DateTime? birthDate, @CountryJsonConverter() Country? nationality}); + + @override + $OrganizationCopyWith<$Res>? get organization; } /// @nodoc @@ -118,6 +151,8 @@ class __$$PersonImplCopyWithImpl<$Res> extends _$PersonCopyWithImpl<$Res, _$Pers @override $Res call({ Object? id = freezed, + Object? orgSyncId = freezed, + Object? organization = freezed, Object? prename = null, Object? surname = null, Object? gender = freezed, @@ -129,6 +164,14 @@ class __$$PersonImplCopyWithImpl<$Res> extends _$PersonCopyWithImpl<$Res, _$Pers ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, + organization: freezed == organization + ? _value.organization + : organization // ignore: cast_nullable_to_non_nullable + as Organization?, prename: null == prename ? _value.prename : prename // ignore: cast_nullable_to_non_nullable @@ -158,6 +201,8 @@ class __$$PersonImplCopyWithImpl<$Res> extends _$PersonCopyWithImpl<$Res, _$Pers class _$PersonImpl extends _Person { const _$PersonImpl( {this.id, + this.orgSyncId, + this.organization, required this.prename, required this.surname, this.gender, @@ -170,6 +215,10 @@ class _$PersonImpl extends _Person { @override final int? id; @override + final String? orgSyncId; + @override + final Organization? organization; + @override final String prename; @override final String surname; @@ -183,7 +232,7 @@ class _$PersonImpl extends _Person { @override String toString() { - return 'Person(id: $id, prename: $prename, surname: $surname, gender: $gender, birthDate: $birthDate, nationality: $nationality)'; + return 'Person(id: $id, orgSyncId: $orgSyncId, organization: $organization, prename: $prename, surname: $surname, gender: $gender, birthDate: $birthDate, nationality: $nationality)'; } @override @@ -192,6 +241,8 @@ class _$PersonImpl extends _Person { (other.runtimeType == runtimeType && other is _$PersonImpl && (identical(other.id, id) || other.id == id) && + (identical(other.orgSyncId, orgSyncId) || other.orgSyncId == orgSyncId) && + (identical(other.organization, organization) || other.organization == organization) && (identical(other.prename, prename) || other.prename == prename) && (identical(other.surname, surname) || other.surname == surname) && (identical(other.gender, gender) || other.gender == gender) && @@ -201,7 +252,8 @@ class _$PersonImpl extends _Person { @JsonKey(ignore: true) @override - int get hashCode => Object.hash(runtimeType, id, prename, surname, gender, birthDate, nationality); + int get hashCode => + Object.hash(runtimeType, id, orgSyncId, organization, prename, surname, gender, birthDate, nationality); @JsonKey(ignore: true) @override @@ -219,6 +271,8 @@ class _$PersonImpl extends _Person { abstract class _Person extends Person { const factory _Person( {final int? id, + final String? orgSyncId, + final Organization? organization, required final String prename, required final String surname, final Gender? gender, @@ -231,6 +285,10 @@ abstract class _Person extends Person { @override int? get id; @override + String? get orgSyncId; + @override + Organization? get organization; + @override String get prename; @override String get surname; diff --git a/wrestling_scoreboard_common/lib/src/data/person.g.dart b/wrestling_scoreboard_common/lib/src/data/person.g.dart index 242bb197..677fed2e 100644 --- a/wrestling_scoreboard_common/lib/src/data/person.g.dart +++ b/wrestling_scoreboard_common/lib/src/data/person.g.dart @@ -8,6 +8,9 @@ part of 'person.dart'; _$PersonImpl _$$PersonImplFromJson(Map json) => _$PersonImpl( id: json['id'] as int?, + orgSyncId: json['orgSyncId'] as String?, + organization: + json['organization'] == null ? null : Organization.fromJson(json['organization'] as Map), prename: json['prename'] as String, surname: json['surname'] as String, gender: $enumDecodeNullable(_$GenderEnumMap, json['gender']), @@ -17,6 +20,8 @@ _$PersonImpl _$$PersonImplFromJson(Map json) => _$PersonImpl( Map _$$PersonImplToJson(_$PersonImpl instance) => { 'id': instance.id, + 'orgSyncId': instance.orgSyncId, + 'organization': instance.organization?.toJson(), 'prename': instance.prename, 'surname': instance.surname, 'gender': _$GenderEnumMap[instance.gender], diff --git a/wrestling_scoreboard_common/lib/src/data/team.dart b/wrestling_scoreboard_common/lib/src/data/team.dart index 71ee6e8c..8a544696 100644 --- a/wrestling_scoreboard_common/lib/src/data/team.dart +++ b/wrestling_scoreboard_common/lib/src/data/team.dart @@ -1,7 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import 'club.dart'; -import 'data_object.dart'; +import '../../common.dart'; part 'team.freezed.dart'; part 'team.g.dart'; @@ -13,6 +12,8 @@ class Team with _$Team implements DataObject { const factory Team({ int? id, + String? orgSyncId, + Organization? organization, required String name, required Club club, String? description, @@ -22,8 +23,11 @@ class Team with _$Team implements DataObject { static Future fromRaw(Map e, GetSingleOfTypeCallback getSingle) async { final club = await getSingle(e['club_id'] as int); + final organizationId = e['organization_id'] as int?; return Team( id: e['id'] as int?, + orgSyncId: e['org_sync_id'] as String?, + organization: organizationId == null ? null : await getSingle(organizationId), name: e['name'] as String, club: club, description: e['description'] as String?, @@ -34,6 +38,8 @@ class Team with _$Team implements DataObject { Map toRaw() { return { if (id != null) 'id': id, + if (orgSyncId != null) 'org_sync_id': orgSyncId, + if (organization != null) 'organization_id': organization?.id, 'name': name, 'description': description, 'club_id': club.id, diff --git a/wrestling_scoreboard_common/lib/src/data/team.freezed.dart b/wrestling_scoreboard_common/lib/src/data/team.freezed.dart index b5be94cf..41a934f0 100644 --- a/wrestling_scoreboard_common/lib/src/data/team.freezed.dart +++ b/wrestling_scoreboard_common/lib/src/data/team.freezed.dart @@ -21,6 +21,8 @@ Team _$TeamFromJson(Map json) { /// @nodoc mixin _$Team { int? get id => throw _privateConstructorUsedError; + String? get orgSyncId => throw _privateConstructorUsedError; + Organization? get organization => throw _privateConstructorUsedError; String get name => throw _privateConstructorUsedError; Club get club => throw _privateConstructorUsedError; String? get description => throw _privateConstructorUsedError; @@ -34,8 +36,9 @@ mixin _$Team { abstract class $TeamCopyWith<$Res> { factory $TeamCopyWith(Team value, $Res Function(Team) then) = _$TeamCopyWithImpl<$Res, Team>; @useResult - $Res call({int? id, String name, Club club, String? description}); + $Res call({int? id, String? orgSyncId, Organization? organization, String name, Club club, String? description}); + $OrganizationCopyWith<$Res>? get organization; $ClubCopyWith<$Res> get club; } @@ -52,6 +55,8 @@ class _$TeamCopyWithImpl<$Res, $Val extends Team> implements $TeamCopyWith<$Res> @override $Res call({ Object? id = freezed, + Object? orgSyncId = freezed, + Object? organization = freezed, Object? name = null, Object? club = null, Object? description = freezed, @@ -61,6 +66,14 @@ class _$TeamCopyWithImpl<$Res, $Val extends Team> implements $TeamCopyWith<$Res> ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, + organization: freezed == organization + ? _value.organization + : organization // ignore: cast_nullable_to_non_nullable + as Organization?, name: null == name ? _value.name : name // ignore: cast_nullable_to_non_nullable @@ -76,6 +89,18 @@ class _$TeamCopyWithImpl<$Res, $Val extends Team> implements $TeamCopyWith<$Res> ) as $Val); } + @override + @pragma('vm:prefer-inline') + $OrganizationCopyWith<$Res>? get organization { + if (_value.organization == null) { + return null; + } + + return $OrganizationCopyWith<$Res>(_value.organization!, (value) { + return _then(_value.copyWith(organization: value) as $Val); + }); + } + @override @pragma('vm:prefer-inline') $ClubCopyWith<$Res> get club { @@ -90,8 +115,10 @@ abstract class _$$TeamImplCopyWith<$Res> implements $TeamCopyWith<$Res> { factory _$$TeamImplCopyWith(_$TeamImpl value, $Res Function(_$TeamImpl) then) = __$$TeamImplCopyWithImpl<$Res>; @override @useResult - $Res call({int? id, String name, Club club, String? description}); + $Res call({int? id, String? orgSyncId, Organization? organization, String name, Club club, String? description}); + @override + $OrganizationCopyWith<$Res>? get organization; @override $ClubCopyWith<$Res> get club; } @@ -104,6 +131,8 @@ class __$$TeamImplCopyWithImpl<$Res> extends _$TeamCopyWithImpl<$Res, _$TeamImpl @override $Res call({ Object? id = freezed, + Object? orgSyncId = freezed, + Object? organization = freezed, Object? name = null, Object? club = null, Object? description = freezed, @@ -113,6 +142,14 @@ class __$$TeamImplCopyWithImpl<$Res> extends _$TeamCopyWithImpl<$Res, _$TeamImpl ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, + organization: freezed == organization + ? _value.organization + : organization // ignore: cast_nullable_to_non_nullable + as Organization?, name: null == name ? _value.name : name // ignore: cast_nullable_to_non_nullable @@ -132,13 +169,19 @@ class __$$TeamImplCopyWithImpl<$Res> extends _$TeamCopyWithImpl<$Res, _$TeamImpl /// @nodoc @JsonSerializable() class _$TeamImpl extends _Team { - const _$TeamImpl({this.id, required this.name, required this.club, this.description}) : super._(); + const _$TeamImpl( + {this.id, this.orgSyncId, this.organization, required this.name, required this.club, this.description}) + : super._(); factory _$TeamImpl.fromJson(Map json) => _$$TeamImplFromJson(json); @override final int? id; @override + final String? orgSyncId; + @override + final Organization? organization; + @override final String name; @override final Club club; @@ -147,7 +190,7 @@ class _$TeamImpl extends _Team { @override String toString() { - return 'Team(id: $id, name: $name, club: $club, description: $description)'; + return 'Team(id: $id, orgSyncId: $orgSyncId, organization: $organization, name: $name, club: $club, description: $description)'; } @override @@ -156,6 +199,8 @@ class _$TeamImpl extends _Team { (other.runtimeType == runtimeType && other is _$TeamImpl && (identical(other.id, id) || other.id == id) && + (identical(other.orgSyncId, orgSyncId) || other.orgSyncId == orgSyncId) && + (identical(other.organization, organization) || other.organization == organization) && (identical(other.name, name) || other.name == name) && (identical(other.club, club) || other.club == club) && (identical(other.description, description) || other.description == description)); @@ -163,7 +208,7 @@ class _$TeamImpl extends _Team { @JsonKey(ignore: true) @override - int get hashCode => Object.hash(runtimeType, id, name, club, description); + int get hashCode => Object.hash(runtimeType, id, orgSyncId, organization, name, club, description); @JsonKey(ignore: true) @override @@ -180,7 +225,12 @@ class _$TeamImpl extends _Team { abstract class _Team extends Team { const factory _Team( - {final int? id, required final String name, required final Club club, final String? description}) = _$TeamImpl; + {final int? id, + final String? orgSyncId, + final Organization? organization, + required final String name, + required final Club club, + final String? description}) = _$TeamImpl; const _Team._() : super._(); factory _Team.fromJson(Map json) = _$TeamImpl.fromJson; @@ -188,6 +238,10 @@ abstract class _Team extends Team { @override int? get id; @override + String? get orgSyncId; + @override + Organization? get organization; + @override String get name; @override Club get club; diff --git a/wrestling_scoreboard_common/lib/src/data/team.g.dart b/wrestling_scoreboard_common/lib/src/data/team.g.dart index 6c13cfb3..1a1f0ef2 100644 --- a/wrestling_scoreboard_common/lib/src/data/team.g.dart +++ b/wrestling_scoreboard_common/lib/src/data/team.g.dart @@ -8,6 +8,9 @@ part of 'team.dart'; _$TeamImpl _$$TeamImplFromJson(Map json) => _$TeamImpl( id: json['id'] as int?, + orgSyncId: json['orgSyncId'] as String?, + organization: + json['organization'] == null ? null : Organization.fromJson(json['organization'] as Map), name: json['name'] as String, club: Club.fromJson(json['club'] as Map), description: json['description'] as String?, @@ -15,6 +18,8 @@ _$TeamImpl _$$TeamImplFromJson(Map json) => _$TeamImpl( Map _$$TeamImplToJson(_$TeamImpl instance) => { 'id': instance.id, + 'orgSyncId': instance.orgSyncId, + 'organization': instance.organization?.toJson(), 'name': instance.name, 'club': instance.club.toJson(), 'description': instance.description, diff --git a/wrestling_scoreboard_common/lib/src/data/team_match/division.dart b/wrestling_scoreboard_common/lib/src/data/team_match/division.dart index 8a82e51a..3476af30 100644 --- a/wrestling_scoreboard_common/lib/src/data/team_match/division.dart +++ b/wrestling_scoreboard_common/lib/src/data/team_match/division.dart @@ -13,13 +13,14 @@ class Division with _$Division implements DataObject { const factory Division({ int? id, + String? orgSyncId, + required Organization organization, required String name, required DateTime startDate, required DateTime endDate, required BoutConfig boutConfig, required int seasonPartitions, Division? parent, - required Organization organization, }) = _Division; factory Division.fromJson(Map json) => _$DivisionFromJson(json); @@ -30,13 +31,14 @@ class Division with _$Division implements DataObject { final parent = parentId == null ? null : await getSingle(parentId); return Division( id: e['id'] as int?, + orgSyncId: e['org_sync_id'] as String?, + organization: await getSingle(e['organization_id'] as int), name: e['name'] as String, startDate: e['start_date'] as DateTime, endDate: e['end_date'] as DateTime, seasonPartitions: e['season_partitions'] as int, boutConfig: boutConfig, parent: parent, - organization: await getSingle(e['organization_id'] as int), ); } @@ -44,20 +46,21 @@ class Division with _$Division implements DataObject { Map toRaw() { return { if (id != null) 'id': id, + if (orgSyncId != null) 'org_sync_id': orgSyncId, + 'organization_id': organization.id, 'name': name, 'start_date': startDate, 'end_date': endDate, 'bout_config_id': boutConfig.id, 'season_partitions': seasonPartitions, 'parent_id': parent?.id, - 'organization_id': organization.id, }; } @override String get tableName => 'division'; - String get fullname => '${parent != null ? (parent!.fullname) : organization.name}, $name'; + String get fullname => parent != null ? '${parent?.fullname}, $name' : name; @override Division copyWithId(int? id) { diff --git a/wrestling_scoreboard_common/lib/src/data/team_match/division.freezed.dart b/wrestling_scoreboard_common/lib/src/data/team_match/division.freezed.dart index e32865a3..b9659c14 100644 --- a/wrestling_scoreboard_common/lib/src/data/team_match/division.freezed.dart +++ b/wrestling_scoreboard_common/lib/src/data/team_match/division.freezed.dart @@ -21,13 +21,14 @@ Division _$DivisionFromJson(Map json) { /// @nodoc mixin _$Division { int? get id => throw _privateConstructorUsedError; + String? get orgSyncId => throw _privateConstructorUsedError; + Organization get organization => throw _privateConstructorUsedError; String get name => throw _privateConstructorUsedError; DateTime get startDate => throw _privateConstructorUsedError; DateTime get endDate => throw _privateConstructorUsedError; BoutConfig get boutConfig => throw _privateConstructorUsedError; int get seasonPartitions => throw _privateConstructorUsedError; Division? get parent => throw _privateConstructorUsedError; - Organization get organization => throw _privateConstructorUsedError; Map toJson() => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -40,17 +41,18 @@ abstract class $DivisionCopyWith<$Res> { @useResult $Res call( {int? id, + String? orgSyncId, + Organization organization, String name, DateTime startDate, DateTime endDate, BoutConfig boutConfig, int seasonPartitions, - Division? parent, - Organization organization}); + Division? parent}); + $OrganizationCopyWith<$Res> get organization; $BoutConfigCopyWith<$Res> get boutConfig; $DivisionCopyWith<$Res>? get parent; - $OrganizationCopyWith<$Res> get organization; } /// @nodoc @@ -66,19 +68,28 @@ class _$DivisionCopyWithImpl<$Res, $Val extends Division> implements $DivisionCo @override $Res call({ Object? id = freezed, + Object? orgSyncId = freezed, + Object? organization = null, Object? name = null, Object? startDate = null, Object? endDate = null, Object? boutConfig = null, Object? seasonPartitions = null, Object? parent = freezed, - Object? organization = null, }) { return _then(_value.copyWith( id: freezed == id ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, + organization: null == organization + ? _value.organization + : organization // ignore: cast_nullable_to_non_nullable + as Organization, name: null == name ? _value.name : name // ignore: cast_nullable_to_non_nullable @@ -103,13 +114,17 @@ class _$DivisionCopyWithImpl<$Res, $Val extends Division> implements $DivisionCo ? _value.parent : parent // ignore: cast_nullable_to_non_nullable as Division?, - organization: null == organization - ? _value.organization - : organization // ignore: cast_nullable_to_non_nullable - as Organization, ) as $Val); } + @override + @pragma('vm:prefer-inline') + $OrganizationCopyWith<$Res> get organization { + return $OrganizationCopyWith<$Res>(_value.organization, (value) { + return _then(_value.copyWith(organization: value) as $Val); + }); + } + @override @pragma('vm:prefer-inline') $BoutConfigCopyWith<$Res> get boutConfig { @@ -129,14 +144,6 @@ class _$DivisionCopyWithImpl<$Res, $Val extends Division> implements $DivisionCo return _then(_value.copyWith(parent: value) as $Val); }); } - - @override - @pragma('vm:prefer-inline') - $OrganizationCopyWith<$Res> get organization { - return $OrganizationCopyWith<$Res>(_value.organization, (value) { - return _then(_value.copyWith(organization: value) as $Val); - }); - } } /// @nodoc @@ -147,20 +154,21 @@ abstract class _$$DivisionImplCopyWith<$Res> implements $DivisionCopyWith<$Res> @useResult $Res call( {int? id, + String? orgSyncId, + Organization organization, String name, DateTime startDate, DateTime endDate, BoutConfig boutConfig, int seasonPartitions, - Division? parent, - Organization organization}); + Division? parent}); + @override + $OrganizationCopyWith<$Res> get organization; @override $BoutConfigCopyWith<$Res> get boutConfig; @override $DivisionCopyWith<$Res>? get parent; - @override - $OrganizationCopyWith<$Res> get organization; } /// @nodoc @@ -172,19 +180,28 @@ class __$$DivisionImplCopyWithImpl<$Res> extends _$DivisionCopyWithImpl<$Res, _$ @override $Res call({ Object? id = freezed, + Object? orgSyncId = freezed, + Object? organization = null, Object? name = null, Object? startDate = null, Object? endDate = null, Object? boutConfig = null, Object? seasonPartitions = null, Object? parent = freezed, - Object? organization = null, }) { return _then(_$DivisionImpl( id: freezed == id ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, + organization: null == organization + ? _value.organization + : organization // ignore: cast_nullable_to_non_nullable + as Organization, name: null == name ? _value.name : name // ignore: cast_nullable_to_non_nullable @@ -209,10 +226,6 @@ class __$$DivisionImplCopyWithImpl<$Res> extends _$DivisionCopyWithImpl<$Res, _$ ? _value.parent : parent // ignore: cast_nullable_to_non_nullable as Division?, - organization: null == organization - ? _value.organization - : organization // ignore: cast_nullable_to_non_nullable - as Organization, )); } } @@ -222,13 +235,14 @@ class __$$DivisionImplCopyWithImpl<$Res> extends _$DivisionCopyWithImpl<$Res, _$ class _$DivisionImpl extends _Division { const _$DivisionImpl( {this.id, + this.orgSyncId, + required this.organization, required this.name, required this.startDate, required this.endDate, required this.boutConfig, required this.seasonPartitions, - this.parent, - required this.organization}) + this.parent}) : super._(); factory _$DivisionImpl.fromJson(Map json) => _$$DivisionImplFromJson(json); @@ -236,6 +250,10 @@ class _$DivisionImpl extends _Division { @override final int? id; @override + final String? orgSyncId; + @override + final Organization organization; + @override final String name; @override final DateTime startDate; @@ -247,12 +265,10 @@ class _$DivisionImpl extends _Division { final int seasonPartitions; @override final Division? parent; - @override - final Organization organization; @override String toString() { - return 'Division(id: $id, name: $name, startDate: $startDate, endDate: $endDate, boutConfig: $boutConfig, seasonPartitions: $seasonPartitions, parent: $parent, organization: $organization)'; + return 'Division(id: $id, orgSyncId: $orgSyncId, organization: $organization, name: $name, startDate: $startDate, endDate: $endDate, boutConfig: $boutConfig, seasonPartitions: $seasonPartitions, parent: $parent)'; } @override @@ -261,19 +277,20 @@ class _$DivisionImpl extends _Division { (other.runtimeType == runtimeType && other is _$DivisionImpl && (identical(other.id, id) || other.id == id) && + (identical(other.orgSyncId, orgSyncId) || other.orgSyncId == orgSyncId) && + (identical(other.organization, organization) || other.organization == organization) && (identical(other.name, name) || other.name == name) && (identical(other.startDate, startDate) || other.startDate == startDate) && (identical(other.endDate, endDate) || other.endDate == endDate) && (identical(other.boutConfig, boutConfig) || other.boutConfig == boutConfig) && (identical(other.seasonPartitions, seasonPartitions) || other.seasonPartitions == seasonPartitions) && - (identical(other.parent, parent) || other.parent == parent) && - (identical(other.organization, organization) || other.organization == organization)); + (identical(other.parent, parent) || other.parent == parent)); } @JsonKey(ignore: true) @override - int get hashCode => - Object.hash(runtimeType, id, name, startDate, endDate, boutConfig, seasonPartitions, parent, organization); + int get hashCode => Object.hash( + runtimeType, id, orgSyncId, organization, name, startDate, endDate, boutConfig, seasonPartitions, parent); @JsonKey(ignore: true) @override @@ -292,13 +309,14 @@ class _$DivisionImpl extends _Division { abstract class _Division extends Division { const factory _Division( {final int? id, + final String? orgSyncId, + required final Organization organization, required final String name, required final DateTime startDate, required final DateTime endDate, required final BoutConfig boutConfig, required final int seasonPartitions, - final Division? parent, - required final Organization organization}) = _$DivisionImpl; + final Division? parent}) = _$DivisionImpl; const _Division._() : super._(); factory _Division.fromJson(Map json) = _$DivisionImpl.fromJson; @@ -306,6 +324,10 @@ abstract class _Division extends Division { @override int? get id; @override + String? get orgSyncId; + @override + Organization get organization; + @override String get name; @override DateTime get startDate; @@ -318,8 +340,6 @@ abstract class _Division extends Division { @override Division? get parent; @override - Organization get organization; - @override @JsonKey(ignore: true) _$$DivisionImplCopyWith<_$DivisionImpl> get copyWith => throw _privateConstructorUsedError; } diff --git a/wrestling_scoreboard_common/lib/src/data/team_match/division.g.dart b/wrestling_scoreboard_common/lib/src/data/team_match/division.g.dart index 605f5c8a..1cd1cebe 100644 --- a/wrestling_scoreboard_common/lib/src/data/team_match/division.g.dart +++ b/wrestling_scoreboard_common/lib/src/data/team_match/division.g.dart @@ -8,22 +8,24 @@ part of 'division.dart'; _$DivisionImpl _$$DivisionImplFromJson(Map json) => _$DivisionImpl( id: json['id'] as int?, + orgSyncId: json['orgSyncId'] as String?, + organization: Organization.fromJson(json['organization'] as Map), name: json['name'] as String, startDate: DateTime.parse(json['startDate'] as String), endDate: DateTime.parse(json['endDate'] as String), boutConfig: BoutConfig.fromJson(json['boutConfig'] as Map), seasonPartitions: json['seasonPartitions'] as int, parent: json['parent'] == null ? null : Division.fromJson(json['parent'] as Map), - organization: Organization.fromJson(json['organization'] as Map), ); Map _$$DivisionImplToJson(_$DivisionImpl instance) => { 'id': instance.id, + 'orgSyncId': instance.orgSyncId, + 'organization': instance.organization.toJson(), 'name': instance.name, 'startDate': instance.startDate.toIso8601String(), 'endDate': instance.endDate.toIso8601String(), 'boutConfig': instance.boutConfig.toJson(), 'seasonPartitions': instance.seasonPartitions, 'parent': instance.parent?.toJson(), - 'organization': instance.organization.toJson(), }; diff --git a/wrestling_scoreboard_common/lib/src/data/team_match/division_weight_class.dart b/wrestling_scoreboard_common/lib/src/data/team_match/division_weight_class.dart index 5ec54ec1..75581c11 100644 --- a/wrestling_scoreboard_common/lib/src/data/team_match/division_weight_class.dart +++ b/wrestling_scoreboard_common/lib/src/data/team_match/division_weight_class.dart @@ -1,8 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import '../data_object.dart'; -import '../weight_class.dart'; -import 'division.dart'; +import '../../../common.dart'; part 'division_weight_class.freezed.dart'; part 'division_weight_class.g.dart'; @@ -11,6 +9,7 @@ part 'division_weight_class.g.dart'; class DivisionWeightClass with _$DivisionWeightClass implements DataObject { const DivisionWeightClass._(); + /// The [seasonPartition] is started counting at 0. const factory DivisionWeightClass({ int? id, required int pos, @@ -48,4 +47,10 @@ class DivisionWeightClass with _$DivisionWeightClass implements DataObject { DivisionWeightClass copyWithId(int? id) { return copyWith(id: id); } + + @override + String? get orgSyncId => throw UnimplementedError(); + + @override + Organization? get organization => throw UnimplementedError(); } diff --git a/wrestling_scoreboard_common/lib/src/data/team_match/league.dart b/wrestling_scoreboard_common/lib/src/data/team_match/league.dart index ad9ce799..c9a438e2 100644 --- a/wrestling_scoreboard_common/lib/src/data/team_match/league.dart +++ b/wrestling_scoreboard_common/lib/src/data/team_match/league.dart @@ -13,6 +13,8 @@ class League with _$League implements DataObject { const factory League({ int? id, + String? orgSyncId, + Organization? organization, required String name, required DateTime startDate, required DateTime endDate, @@ -23,8 +25,11 @@ class League with _$League implements DataObject { static Future fromRaw(Map e, GetSingleOfTypeCallback getSingle) async { final division = await getSingle(e['division_id'] as int); + final organizationId = e['organization_id'] as int?; return League( id: e['id'] as int?, + orgSyncId: e['org_sync_id'] as String?, + organization: organizationId == null ? null : await getSingle(organizationId), name: e['name'] as String, startDate: e['start_date'] as DateTime, endDate: e['end_date'] as DateTime, @@ -36,6 +41,8 @@ class League with _$League implements DataObject { Map toRaw() { return { if (id != null) 'id': id, + if (orgSyncId != null) 'org_sync_id': orgSyncId, + if (organization != null) 'organization_id': organization?.id, 'name': name, 'start_date': startDate, 'end_date': endDate, diff --git a/wrestling_scoreboard_common/lib/src/data/team_match/league.freezed.dart b/wrestling_scoreboard_common/lib/src/data/team_match/league.freezed.dart index 35a1a969..e94cb4bc 100644 --- a/wrestling_scoreboard_common/lib/src/data/team_match/league.freezed.dart +++ b/wrestling_scoreboard_common/lib/src/data/team_match/league.freezed.dart @@ -21,6 +21,8 @@ League _$LeagueFromJson(Map json) { /// @nodoc mixin _$League { int? get id => throw _privateConstructorUsedError; + String? get orgSyncId => throw _privateConstructorUsedError; + Organization? get organization => throw _privateConstructorUsedError; String get name => throw _privateConstructorUsedError; DateTime get startDate => throw _privateConstructorUsedError; DateTime get endDate => throw _privateConstructorUsedError; @@ -35,8 +37,16 @@ mixin _$League { abstract class $LeagueCopyWith<$Res> { factory $LeagueCopyWith(League value, $Res Function(League) then) = _$LeagueCopyWithImpl<$Res, League>; @useResult - $Res call({int? id, String name, DateTime startDate, DateTime endDate, Division division}); + $Res call( + {int? id, + String? orgSyncId, + Organization? organization, + String name, + DateTime startDate, + DateTime endDate, + Division division}); + $OrganizationCopyWith<$Res>? get organization; $DivisionCopyWith<$Res> get division; } @@ -53,6 +63,8 @@ class _$LeagueCopyWithImpl<$Res, $Val extends League> implements $LeagueCopyWith @override $Res call({ Object? id = freezed, + Object? orgSyncId = freezed, + Object? organization = freezed, Object? name = null, Object? startDate = null, Object? endDate = null, @@ -63,6 +75,14 @@ class _$LeagueCopyWithImpl<$Res, $Val extends League> implements $LeagueCopyWith ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, + organization: freezed == organization + ? _value.organization + : organization // ignore: cast_nullable_to_non_nullable + as Organization?, name: null == name ? _value.name : name // ignore: cast_nullable_to_non_nullable @@ -82,6 +102,18 @@ class _$LeagueCopyWithImpl<$Res, $Val extends League> implements $LeagueCopyWith ) as $Val); } + @override + @pragma('vm:prefer-inline') + $OrganizationCopyWith<$Res>? get organization { + if (_value.organization == null) { + return null; + } + + return $OrganizationCopyWith<$Res>(_value.organization!, (value) { + return _then(_value.copyWith(organization: value) as $Val); + }); + } + @override @pragma('vm:prefer-inline') $DivisionCopyWith<$Res> get division { @@ -97,8 +129,17 @@ abstract class _$$LeagueImplCopyWith<$Res> implements $LeagueCopyWith<$Res> { __$$LeagueImplCopyWithImpl<$Res>; @override @useResult - $Res call({int? id, String name, DateTime startDate, DateTime endDate, Division division}); + $Res call( + {int? id, + String? orgSyncId, + Organization? organization, + String name, + DateTime startDate, + DateTime endDate, + Division division}); + @override + $OrganizationCopyWith<$Res>? get organization; @override $DivisionCopyWith<$Res> get division; } @@ -112,6 +153,8 @@ class __$$LeagueImplCopyWithImpl<$Res> extends _$LeagueCopyWithImpl<$Res, _$Leag @override $Res call({ Object? id = freezed, + Object? orgSyncId = freezed, + Object? organization = freezed, Object? name = null, Object? startDate = null, Object? endDate = null, @@ -122,6 +165,14 @@ class __$$LeagueImplCopyWithImpl<$Res> extends _$LeagueCopyWithImpl<$Res, _$Leag ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, + organization: freezed == organization + ? _value.organization + : organization // ignore: cast_nullable_to_non_nullable + as Organization?, name: null == name ? _value.name : name // ignore: cast_nullable_to_non_nullable @@ -146,7 +197,13 @@ class __$$LeagueImplCopyWithImpl<$Res> extends _$LeagueCopyWithImpl<$Res, _$Leag @JsonSerializable() class _$LeagueImpl extends _League { const _$LeagueImpl( - {this.id, required this.name, required this.startDate, required this.endDate, required this.division}) + {this.id, + this.orgSyncId, + this.organization, + required this.name, + required this.startDate, + required this.endDate, + required this.division}) : super._(); factory _$LeagueImpl.fromJson(Map json) => _$$LeagueImplFromJson(json); @@ -154,6 +211,10 @@ class _$LeagueImpl extends _League { @override final int? id; @override + final String? orgSyncId; + @override + final Organization? organization; + @override final String name; @override final DateTime startDate; @@ -164,7 +225,7 @@ class _$LeagueImpl extends _League { @override String toString() { - return 'League(id: $id, name: $name, startDate: $startDate, endDate: $endDate, division: $division)'; + return 'League(id: $id, orgSyncId: $orgSyncId, organization: $organization, name: $name, startDate: $startDate, endDate: $endDate, division: $division)'; } @override @@ -173,6 +234,8 @@ class _$LeagueImpl extends _League { (other.runtimeType == runtimeType && other is _$LeagueImpl && (identical(other.id, id) || other.id == id) && + (identical(other.orgSyncId, orgSyncId) || other.orgSyncId == orgSyncId) && + (identical(other.organization, organization) || other.organization == organization) && (identical(other.name, name) || other.name == name) && (identical(other.startDate, startDate) || other.startDate == startDate) && (identical(other.endDate, endDate) || other.endDate == endDate) && @@ -181,7 +244,7 @@ class _$LeagueImpl extends _League { @JsonKey(ignore: true) @override - int get hashCode => Object.hash(runtimeType, id, name, startDate, endDate, division); + int get hashCode => Object.hash(runtimeType, id, orgSyncId, organization, name, startDate, endDate, division); @JsonKey(ignore: true) @override @@ -199,6 +262,8 @@ class _$LeagueImpl extends _League { abstract class _League extends League { const factory _League( {final int? id, + final String? orgSyncId, + final Organization? organization, required final String name, required final DateTime startDate, required final DateTime endDate, @@ -210,6 +275,10 @@ abstract class _League extends League { @override int? get id; @override + String? get orgSyncId; + @override + Organization? get organization; + @override String get name; @override DateTime get startDate; diff --git a/wrestling_scoreboard_common/lib/src/data/team_match/league.g.dart b/wrestling_scoreboard_common/lib/src/data/team_match/league.g.dart index 7e1499cc..e0cf1c62 100644 --- a/wrestling_scoreboard_common/lib/src/data/team_match/league.g.dart +++ b/wrestling_scoreboard_common/lib/src/data/team_match/league.g.dart @@ -8,6 +8,9 @@ part of 'league.dart'; _$LeagueImpl _$$LeagueImplFromJson(Map json) => _$LeagueImpl( id: json['id'] as int?, + orgSyncId: json['orgSyncId'] as String?, + organization: + json['organization'] == null ? null : Organization.fromJson(json['organization'] as Map), name: json['name'] as String, startDate: DateTime.parse(json['startDate'] as String), endDate: DateTime.parse(json['endDate'] as String), @@ -16,6 +19,8 @@ _$LeagueImpl _$$LeagueImplFromJson(Map json) => _$LeagueImpl( Map _$$LeagueImplToJson(_$LeagueImpl instance) => { 'id': instance.id, + 'orgSyncId': instance.orgSyncId, + 'organization': instance.organization?.toJson(), 'name': instance.name, 'startDate': instance.startDate.toIso8601String(), 'endDate': instance.endDate.toIso8601String(), diff --git a/wrestling_scoreboard_common/lib/src/data/team_match/league_team_participation.dart b/wrestling_scoreboard_common/lib/src/data/team_match/league_team_participation.dart index 460a0f90..e24c9f2e 100644 --- a/wrestling_scoreboard_common/lib/src/data/team_match/league_team_participation.dart +++ b/wrestling_scoreboard_common/lib/src/data/team_match/league_team_participation.dart @@ -1,8 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import '../data_object.dart'; -import '../team.dart'; -import 'league.dart'; +import '../../../common.dart'; part 'league_team_participation.freezed.dart'; part 'league_team_participation.g.dart'; @@ -43,4 +41,10 @@ class LeagueTeamParticipation with _$LeagueTeamParticipation implements DataObje LeagueTeamParticipation copyWithId(int? id) { return copyWith(id: id); } + + @override + String? get orgSyncId => throw UnimplementedError(); + + @override + Organization? get organization => throw UnimplementedError(); } diff --git a/wrestling_scoreboard_common/lib/src/data/team_match/team_match.dart b/wrestling_scoreboard_common/lib/src/data/team_match/team_match.dart index 130b84e7..e769144d 100644 --- a/wrestling_scoreboard_common/lib/src/data/team_match/team_match.dart +++ b/wrestling_scoreboard_common/lib/src/data/team_match/team_match.dart @@ -1,14 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import '../data_object.dart'; -import '../bout.dart'; -import '../lineup.dart'; -import '../participant_state.dart'; -import '../participation.dart'; -import '../person.dart'; -import '../weight_class.dart'; -import '../wrestling_event.dart'; -import 'league.dart'; +import '../../../common.dart'; part 'team_match.freezed.dart'; part 'team_match.g.dart'; @@ -19,8 +11,11 @@ class TeamMatch extends WrestlingEvent with _$TeamMatch { // TODO add missing stewards to extra table const TeamMatch._(); + /// The [seasonPartition] is started counting at 0. const factory TeamMatch({ int? id, + String? orgSyncId, + Organization? organization, required Lineup home, required Lineup guest, League? league, @@ -48,6 +43,7 @@ class TeamMatch extends WrestlingEvent with _$TeamMatch { final int? timeKeeperId = e['time_keeper_id']; final int? transcriptWriterId = e['transcript_writer_id']; final int? leagueId = e['league_id']; + final organizationId = e['organization_id'] as int?; // TODO ditch weightclasses, always handle at client // final weightClasses = home != null && home.team.league != null // ? await LeagueController().getWeightClasses(home.team.league!.id.toString()) @@ -56,6 +52,8 @@ class TeamMatch extends WrestlingEvent with _$TeamMatch { return TeamMatch( id: e['id'] as int?, + orgSyncId: e['org_sync_id'] as String?, + organization: organizationId == null ? null : await getSingle(organizationId), no: e['no'] as String?, location: e['location'] as String?, date: e['date'] as DateTime, diff --git a/wrestling_scoreboard_common/lib/src/data/team_match/team_match.freezed.dart b/wrestling_scoreboard_common/lib/src/data/team_match/team_match.freezed.dart index 855249fb..eaf6d7e3 100644 --- a/wrestling_scoreboard_common/lib/src/data/team_match/team_match.freezed.dart +++ b/wrestling_scoreboard_common/lib/src/data/team_match/team_match.freezed.dart @@ -21,6 +21,8 @@ TeamMatch _$TeamMatchFromJson(Map json) { /// @nodoc mixin _$TeamMatch { int? get id => throw _privateConstructorUsedError; + String? get orgSyncId => throw _privateConstructorUsedError; + Organization? get organization => throw _privateConstructorUsedError; Lineup get home => throw _privateConstructorUsedError; Lineup get guest => throw _privateConstructorUsedError; League? get league => throw _privateConstructorUsedError; @@ -47,6 +49,8 @@ abstract class $TeamMatchCopyWith<$Res> { @useResult $Res call( {int? id, + String? orgSyncId, + Organization? organization, Lineup home, Lineup guest, League? league, @@ -62,6 +66,7 @@ abstract class $TeamMatchCopyWith<$Res> { int? visitorsCount, String? comment}); + $OrganizationCopyWith<$Res>? get organization; $LineupCopyWith<$Res> get home; $LineupCopyWith<$Res> get guest; $LeagueCopyWith<$Res>? get league; @@ -85,6 +90,8 @@ class _$TeamMatchCopyWithImpl<$Res, $Val extends TeamMatch> implements $TeamMatc @override $Res call({ Object? id = freezed, + Object? orgSyncId = freezed, + Object? organization = freezed, Object? home = null, Object? guest = null, Object? league = freezed, @@ -105,6 +112,14 @@ class _$TeamMatchCopyWithImpl<$Res, $Val extends TeamMatch> implements $TeamMatc ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, + organization: freezed == organization + ? _value.organization + : organization // ignore: cast_nullable_to_non_nullable + as Organization?, home: null == home ? _value.home : home // ignore: cast_nullable_to_non_nullable @@ -164,6 +179,18 @@ class _$TeamMatchCopyWithImpl<$Res, $Val extends TeamMatch> implements $TeamMatc ) as $Val); } + @override + @pragma('vm:prefer-inline') + $OrganizationCopyWith<$Res>? get organization { + if (_value.organization == null) { + return null; + } + + return $OrganizationCopyWith<$Res>(_value.organization!, (value) { + return _then(_value.copyWith(organization: value) as $Val); + }); + } + @override @pragma('vm:prefer-inline') $LineupCopyWith<$Res> get home { @@ -261,6 +288,8 @@ abstract class _$$TeamMatchImplCopyWith<$Res> implements $TeamMatchCopyWith<$Res @useResult $Res call( {int? id, + String? orgSyncId, + Organization? organization, Lineup home, Lineup guest, League? league, @@ -276,6 +305,8 @@ abstract class _$$TeamMatchImplCopyWith<$Res> implements $TeamMatchCopyWith<$Res int? visitorsCount, String? comment}); + @override + $OrganizationCopyWith<$Res>? get organization; @override $LineupCopyWith<$Res> get home; @override @@ -303,6 +334,8 @@ class __$$TeamMatchImplCopyWithImpl<$Res> extends _$TeamMatchCopyWithImpl<$Res, @override $Res call({ Object? id = freezed, + Object? orgSyncId = freezed, + Object? organization = freezed, Object? home = null, Object? guest = null, Object? league = freezed, @@ -323,6 +356,14 @@ class __$$TeamMatchImplCopyWithImpl<$Res> extends _$TeamMatchCopyWithImpl<$Res, ? _value.id : id // ignore: cast_nullable_to_non_nullable as int?, + orgSyncId: freezed == orgSyncId + ? _value.orgSyncId + : orgSyncId // ignore: cast_nullable_to_non_nullable + as String?, + organization: freezed == organization + ? _value.organization + : organization // ignore: cast_nullable_to_non_nullable + as Organization?, home: null == home ? _value.home : home // ignore: cast_nullable_to_non_nullable @@ -388,6 +429,8 @@ class __$$TeamMatchImplCopyWithImpl<$Res> extends _$TeamMatchCopyWithImpl<$Res, class _$TeamMatchImpl extends _TeamMatch { const _$TeamMatchImpl( {this.id, + this.orgSyncId, + this.organization, required this.home, required this.guest, this.league, @@ -409,6 +452,10 @@ class _$TeamMatchImpl extends _TeamMatch { @override final int? id; @override + final String? orgSyncId; + @override + final Organization? organization; + @override final Lineup home; @override final Lineup guest; @@ -439,7 +486,7 @@ class _$TeamMatchImpl extends _TeamMatch { @override String toString() { - return 'TeamMatch(id: $id, home: $home, guest: $guest, league: $league, seasonPartition: $seasonPartition, matChairman: $matChairman, referee: $referee, judge: $judge, timeKeeper: $timeKeeper, transcriptWriter: $transcriptWriter, no: $no, location: $location, date: $date, visitorsCount: $visitorsCount, comment: $comment)'; + return 'TeamMatch(id: $id, orgSyncId: $orgSyncId, organization: $organization, home: $home, guest: $guest, league: $league, seasonPartition: $seasonPartition, matChairman: $matChairman, referee: $referee, judge: $judge, timeKeeper: $timeKeeper, transcriptWriter: $transcriptWriter, no: $no, location: $location, date: $date, visitorsCount: $visitorsCount, comment: $comment)'; } @override @@ -448,6 +495,8 @@ class _$TeamMatchImpl extends _TeamMatch { (other.runtimeType == runtimeType && other is _$TeamMatchImpl && (identical(other.id, id) || other.id == id) && + (identical(other.orgSyncId, orgSyncId) || other.orgSyncId == orgSyncId) && + (identical(other.organization, organization) || other.organization == organization) && (identical(other.home, home) || other.home == home) && (identical(other.guest, guest) || other.guest == guest) && (identical(other.league, league) || other.league == league) && @@ -466,8 +515,8 @@ class _$TeamMatchImpl extends _TeamMatch { @JsonKey(ignore: true) @override - int get hashCode => Object.hash(runtimeType, id, home, guest, league, seasonPartition, matChairman, referee, judge, - timeKeeper, transcriptWriter, no, location, date, visitorsCount, comment); + int get hashCode => Object.hash(runtimeType, id, orgSyncId, organization, home, guest, league, seasonPartition, + matChairman, referee, judge, timeKeeper, transcriptWriter, no, location, date, visitorsCount, comment); @JsonKey(ignore: true) @override @@ -486,6 +535,8 @@ class _$TeamMatchImpl extends _TeamMatch { abstract class _TeamMatch extends TeamMatch { const factory _TeamMatch( {final int? id, + final String? orgSyncId, + final Organization? organization, required final Lineup home, required final Lineup guest, final League? league, @@ -507,6 +558,10 @@ abstract class _TeamMatch extends TeamMatch { @override int? get id; @override + String? get orgSyncId; + @override + Organization? get organization; + @override Lineup get home; @override Lineup get guest; diff --git a/wrestling_scoreboard_common/lib/src/data/team_match/team_match.g.dart b/wrestling_scoreboard_common/lib/src/data/team_match/team_match.g.dart index 332c6538..ee90843d 100644 --- a/wrestling_scoreboard_common/lib/src/data/team_match/team_match.g.dart +++ b/wrestling_scoreboard_common/lib/src/data/team_match/team_match.g.dart @@ -8,6 +8,9 @@ part of 'team_match.dart'; _$TeamMatchImpl _$$TeamMatchImplFromJson(Map json) => _$TeamMatchImpl( id: json['id'] as int?, + orgSyncId: json['orgSyncId'] as String?, + organization: + json['organization'] == null ? null : Organization.fromJson(json['organization'] as Map), home: Lineup.fromJson(json['home'] as Map), guest: Lineup.fromJson(json['guest'] as Map), league: json['league'] == null ? null : League.fromJson(json['league'] as Map), @@ -27,6 +30,8 @@ _$TeamMatchImpl _$$TeamMatchImplFromJson(Map json) => _$TeamMat Map _$$TeamMatchImplToJson(_$TeamMatchImpl instance) => { 'id': instance.id, + 'orgSyncId': instance.orgSyncId, + 'organization': instance.organization?.toJson(), 'home': instance.home.toJson(), 'guest': instance.guest.toJson(), 'league': instance.league?.toJson(), diff --git a/wrestling_scoreboard_common/lib/src/data/team_match/team_match_bout.dart b/wrestling_scoreboard_common/lib/src/data/team_match/team_match_bout.dart index e22d27d1..b0be5a6a 100644 --- a/wrestling_scoreboard_common/lib/src/data/team_match/team_match_bout.dart +++ b/wrestling_scoreboard_common/lib/src/data/team_match/team_match_bout.dart @@ -1,11 +1,8 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import '../data_object.dart'; -import '../bout.dart'; -import 'team_match.dart'; +import '../../../common.dart'; part 'team_match_bout.freezed.dart'; - part 'team_match_bout.g.dart'; @freezed @@ -50,4 +47,10 @@ class TeamMatchBout with _$TeamMatchBout implements DataObject { TeamMatchBout copyWithId(int? id) { return copyWith(id: id); } + + @override + String? get orgSyncId => throw UnimplementedError(); + + @override + Organization? get organization => throw UnimplementedError(); } diff --git a/wrestling_scoreboard_common/lib/src/data/weight_class.dart b/wrestling_scoreboard_common/lib/src/data/weight_class.dart index e5074baa..3389f3d5 100644 --- a/wrestling_scoreboard_common/lib/src/data/weight_class.dart +++ b/wrestling_scoreboard_common/lib/src/data/weight_class.dart @@ -1,8 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import '../enums/weight_unit.dart'; -import '../enums/wrestling_style.dart'; -import 'data_object.dart'; +import '../../common.dart'; part 'weight_class.freezed.dart'; part 'weight_class.g.dart'; @@ -61,4 +59,10 @@ class WeightClass with _$WeightClass implements DataObject { WeightClass copyWithId(int? id) { return copyWith(id: id); } + + @override + String? get orgSyncId => throw UnimplementedError(); + + @override + Organization? get organization => throw UnimplementedError(); } diff --git a/wrestling_scoreboard_common/lib/src/data/wrestling_event.dart b/wrestling_scoreboard_common/lib/src/data/wrestling_event.dart index 52866a42..0687aaa5 100644 --- a/wrestling_scoreboard_common/lib/src/data/wrestling_event.dart +++ b/wrestling_scoreboard_common/lib/src/data/wrestling_event.dart @@ -18,6 +18,8 @@ abstract class WrestlingEvent implements DataObject { // static Future fromRaw(Map e) async => WrestlingEvent( // id: e['id'] as int?, + // orgSyncId: e['org_sync_id'] as String?, + // organization: organizationId == null ? null : await getSingle(organizationId), // location: e['location'] as String?, // date: e['date'] as DateTime?, // visitorsCount: e['visitors_count'] as int?, @@ -28,6 +30,8 @@ abstract class WrestlingEvent implements DataObject { Map toRaw() { return { if (id != null) 'id': id, + if (orgSyncId != null) 'org_sync_id': orgSyncId, + if (organization != null) 'organization_id': organization?.id, 'no': no, 'location': location, 'date': date, diff --git a/wrestling_scoreboard_common/lib/src/enums.dart b/wrestling_scoreboard_common/lib/src/enums.dart index 4ce2f8d1..dd28cfe0 100644 --- a/wrestling_scoreboard_common/lib/src/enums.dart +++ b/wrestling_scoreboard_common/lib/src/enums.dart @@ -1,7 +1,8 @@ -export 'enums/crud.dart'; export 'enums/bout_action_type.dart'; export 'enums/bout_result.dart'; export 'enums/bout_role.dart'; +export 'enums/crud.dart'; export 'enums/gender.dart'; +export 'enums/person_role.dart'; export 'enums/weight_unit.dart'; export 'enums/wrestling_style.dart'; diff --git a/wrestling_scoreboard_common/lib/src/services/api.dart b/wrestling_scoreboard_common/lib/src/services/api.dart index 916e7c88..37933b41 100644 --- a/wrestling_scoreboard_common/lib/src/services/api.dart +++ b/wrestling_scoreboard_common/lib/src/services/api.dart @@ -1,15 +1,64 @@ -export 'reports/germany_nrw.dart'; +import '../../common.dart'; +import 'auth/authorization.dart'; + +export 'apis/germany_nrw.dart'; + +typedef GetSingleOfOrg = Future Function(String orgSyncId, {required int orgId}); enum WrestlingApiProvider { - deNwRingenApi; + deNwRingenApi, + deByRingenApi; - WrestlingApi get api { + String get name => toString().split('.').last; + + WrestlingApi getApi( + Organization organization, { + required GetSingleOfOrg getSingleOfOrg, + AuthService? authService, + }) { switch (this) { case WrestlingApiProvider.deNwRingenApi: - throw UnimplementedError(); + return NrwGermanyWrestlingApi( + organization, + getSingleOfOrg: getSingleOfOrg, + apiUrl: 'https://www.brv-ringen.de/Api/v1/cs/', + authService: authService as BasicAuthService, + ); + case WrestlingApiProvider.deByRingenApi: + if (authService != null && authService is! BasicAuthService) { + throw 'Auth service is not valid for this API provider'; + } + return NrwGermanyWrestlingApi( + organization, + getSingleOfOrg: getSingleOfOrg, + apiUrl: 'https://www.brv-ringen.de/Api/v1/cs/', + authService: authService as BasicAuthService, + ); } } } /// Abstraction for providing an api interface. -abstract class WrestlingApi {} +abstract class WrestlingApi { + set isMock(bool isMock); + + Organization get organization; + + GetSingleOfOrg get getSingleOfOrg; + + AuthService? get authService; + + Future> importDivisions({DateTime? minDate, DateTime? maxDate}); + + Future> importDivisionWeightClasses({required Division division}); + + Future> importClubs(); + + Future> importMemberships({required Club club}); + + Future> importTeams({required Club club}); + + Future> importLeagues({required Division division}); + + Future> importTeamMatches({required League league}); +} diff --git a/wrestling_scoreboard_common/lib/src/services/apis/germany_nrw.dart b/wrestling_scoreboard_common/lib/src/services/apis/germany_nrw.dart new file mode 100644 index 00000000..d289dd20 --- /dev/null +++ b/wrestling_scoreboard_common/lib/src/services/apis/germany_nrw.dart @@ -0,0 +1,415 @@ +import 'dart:convert'; + +import 'package:collection/collection.dart'; +import 'package:country/country.dart'; +import 'package:http/http.dart' as http; + +import '../../../common.dart'; +import '../auth/authorization.dart'; +import 'mocks/competition.json.dart'; +import 'mocks/listCompetition.json.dart'; +import 'mocks/listLiga.json.dart'; +import 'mocks/listSaison.json.dart'; +import 'mocks/wrestler.json.dart'; + +class NrwGermanyWrestlingApi extends WrestlingApi { + final String apiUrl; + + @override + final BasicAuthService? authService; + + bool isMock = false; + + @override + final Organization organization; + + @override + GetSingleOfOrg getSingleOfOrg; + + late Future Function(String orgSyncId) _getSingleBySyncId; + + NrwGermanyWrestlingApi( + this.organization, { + required this.getSingleOfOrg, + this.apiUrl = 'https://www.brv-ringen.de/Api/v1/cs/', + this.authService, + }) { + _getSingleBySyncId = + (String orgSyncId) => getSingleOfOrg(orgSyncId, orgId: organization.id!); + } + + @override + Future> importDivisions({DateTime? minDate, DateTime? maxDate}) async { + final json = await _getLeagueList(seasonId: minDate?.year.toString()); + final year = minDate?.year ?? int.parse(json['year']); // FIXME: year not matching the request. + final divisionList = json['ligaList']; + if (divisionList is Map) { + return await Future.wait(divisionList.entries.map( + (entry) async => Division( + organization: organization, + name: entry.key, + startDate: DateTime(year), + endDate: DateTime(year + 1), + boutConfig: BoutConfig(), + // TODO: get from "boutSchemeId" inside league list + seasonPartitions: 2, + orgSyncId: '${year}_${entry.key}', + ), + )); + } + return []; + } + + @override + Future> importDivisionWeightClasses({required Division division}) async { + final leagues = await importLeagues(division: division); + final competitions = await importTeamMatches(league: leagues.first); + final json = await _getCompetition( + seasonId: division.startDate.year.toString(), competitionId: competitions.first.orgSyncId!); + final List boutList = json['competition']['_boutList']; + final weightClassCount = boutList.length; + final weightClassesPartitition1 = boutList.asMap().entries.map((e) { + final Map item = e.value; + final String weightClassStr = item['weightClass']; + final intInStr = RegExp(r'^\d+'); + final weightStr = intInStr.firstMatch(weightClassStr)!.group(0)!; + final suffix = weightClassStr.replaceFirst(weightStr, '').trim(); + return DivisionWeightClass( + // Alter order of weightclasses + pos: e.key < (weightClassCount / 2) ? e.key * 2 : (weightClassCount - e.key - 1) * 2 + 1, + seasonPartition: 0, + division: division, + weightClass: WeightClass( + style: item['style'] == 'GR' ? WrestlingStyle.greco : WrestlingStyle.free, + weight: int.parse(weightStr), + suffix: suffix.isEmpty ? null : suffix, + unit: WeightUnit.kilogram, + ), + ); + }); + final weightClassesPartition2 = weightClassesPartitition1.map((e) => e.copyWith( + seasonPartition: 1, + weightClass: e.weightClass.copyWith( + style: e.weightClass.style == WrestlingStyle.greco ? WrestlingStyle.free : WrestlingStyle.greco, + ))); + return [...weightClassesPartitition1, ...weightClassesPartition2]; + } + + @override + Future> importClubs() async { + final divisions = await importDivisions(); + final leagues = (await Future.wait(divisions.map((e) => importLeagues(division: e)))).expand((element) => element); + final clubs = (await Future.wait(leagues.map((league) async { + final json = await _getCompetitionList( + ligaId: league.division.name, + regionId: league.name, + seasonId: league.startDate.year.toString(), + ); + + final Map competitionList = json['competitionList']; + final listHome = await Future.wait(competitionList.entries.map((entry) async { + final Map values = entry.value; + return Club( + name: values['homeTeamName'], + organization: organization, + orgSyncId: values['homeTeamName'], + // TODO: read 'no' from endpoint, when available + no: null, + ); + })); + + final listGuest = await Future.wait(competitionList.entries.map((entry) async { + final Map values = entry.value; + return Club( + name: values['opponentTeamName'], + organization: organization, + orgSyncId: values['opponentTeamName'], + // TODO: read 'no' from endpoint, when available + no: null, + ); + })); + + return [...listHome, ...listGuest]; + }))) + .expand((element) => element); + return clubs.toSet(); + } + + @override + Future> importMemberships({required Club club}) async { + final divisions = await importDivisions(minDate: DateTime(DateTime.now().year - 1)); + final leagues = (await Future.wait(divisions.map((e) => importLeagues(division: e)))).expand((element) => element); + final teamMatches = + (await Future.wait(leagues.map((e) => importTeamMatches(league: e)))).expand((element) => element); + final memberships = (await Future.wait( + teamMatches.map((teamMatch) async { + final json = await _getCompetition( + seasonId: teamMatch.league!.startDate.year.toString(), competitionId: teamMatch.orgSyncId!); + final List boutList = json['competition']['_boutList']; + + final homeLicenseIds = boutList.map((boutJson) => int.tryParse(boutJson['homeWrestlerLicId'] ?? '')); + final opponentLicenseIds = boutList.map((boutJson) => int.tryParse(boutJson['homeWrestlerLicId'] ?? '')); + final licenseIds = [...homeLicenseIds, ...opponentLicenseIds].whereNotNull(); + final memberships = await Future.wait(licenseIds.map((e) async { + final json = await _getSaisonWrestler(passCode: e); + final wrestlerJson = json['wrestler']; + if (wrestlerJson == null || wrestlerJson['clubCode'] != club.no) { + // FIXME: comparison may not is correct! + return null; + } + return Membership( + club: club, + organization: organization, + no: json['passcode'], + orgSyncId: '${wrestlerJson['clubCode']}-${json['passcode']}', + person: _copyPersonWithOrg(Person( + prename: wrestlerJson['givenname'], + surname: wrestlerJson['name'], + gender: wrestlerJson['gender'] == 'm' + ? Gender.male + : (wrestlerJson['gender'] == 'w' ? Gender.female : Gender.other), + birthDate: DateTime.parse(wrestlerJson['birthday']), + nationality: Countries.values + .singleWhereOrNull((element) => element.unofficialNames.contains(wrestlerJson['nationality'])), + )), + ); + })); + + return memberships.whereNotNull().toSet(); + }), + )) + .expand((element) => element); + return memberships.toSet(); + } + + @override + Future> importTeams({required Club club}) async { + final divisions = await importDivisions(); + final leagues = (await Future.wait(divisions.map((e) => importLeagues(division: e)))).expand((element) => element); + final teams = (await Future.wait(leagues.map((league) async { + final json = await _getCompetitionList( + ligaId: league.division.name, + regionId: league.name, + seasonId: league.startDate.year.toString(), + ); + + final Map competitionList = json['competitionList']; + Future> getTeamOfCompetition(String key) async { + return (await Future.wait(competitionList.entries.map((entry) async { + final Map values = entry.value; + final teamName = values[key]; + if (teamName != club.name) return null; + return Team( + name: teamName, + club: await _getSingleBySyncId(teamName), + orgSyncId: teamName, + organization: organization, + ); + }))) + .whereNotNull() + .toList(); + } + + final listHome = await getTeamOfCompetition('homeTeamName'); + final listGuest = await getTeamOfCompetition('opponentTeamName'); + + listHome.addAll(listGuest); + return listHome; + }))) + .expand((element) => element); + return teams.toSet().where((element) => element.club == club); + } + + @override + Future> importLeagues({required Division division}) async { + final json = await _getLeagueList(seasonId: division.startDate.year.toString()); + + final leagueList = json['ligaList'][division.name]; + if (leagueList is Map) { + return await Future.wait( + leagueList.entries.map( + (entry) async => League( + name: entry.key, + startDate: division.startDate, + endDate: division.endDate, + division: division, + orgSyncId: '${division.orgSyncId}_${entry.key}', + organization: organization, + ), + ), + ); + } + return []; + } + + @override + Future> importTeamMatches({required League league}) async { + final json = await _getCompetitionList( + ligaId: league.division.name, + regionId: league.name, + seasonId: league.startDate.year.toString(), + ); + + final competitionList = json['competitionList']; + if (competitionList is Map) { + final teamMatches = await Future.wait(competitionList.entries.map((entry) async { + final Map values = entry.value; + final refereePrename = values['refereeGivenname'].toString().trim(); + final refereeSurname = values['refereeName'].toString().trim(); + final referee = refereePrename.isNotEmpty && refereeSurname.isNotEmpty + ? _copyPersonWithOrg(Person( + prename: refereePrename, + surname: refereeSurname, + )) + : null; + return TeamMatch( + home: Lineup( + team: await _getSingleBySyncId(values['homeTeamName']), + ), + guest: Lineup( + team: await _getSingleBySyncId(values['opponentTeamName']), + ), + date: DateTime.parse(values['boutDate'] + ' ' + values['scaleTime']), + visitorsCount: int.tryParse(values['audience']), + location: values['location'], + referee: referee, + comment: values['editorComment'], + league: league, + no: entry.key, + // TODO: Save number of boutdays in league, and use them here. + seasonPartition: double.parse(values['boutday']) / 16 < 0.5 ? 1 : 2, + organization: organization, + orgSyncId: entry.key, + ); + })); + return teamMatches.toSet(); + } + return []; + } + + Person _copyPersonWithOrg(Person person) { + return person.copyWith(orgSyncId: '${person.fullName}_${person.birthDate}', organization: organization); + } + + /// Get all seasons + // ignore: unused_element + Future> _getSeasonList() async { + final uri = Uri.parse(apiUrl).replace(queryParameters: { + 'op': 'listSaison', + }); + + String body; + if (!isMock) { + final response = await http.get(uri); + if (response.statusCode != 200) { + throw Exception('Failed to get the saison list: ${response.reasonPhrase ?? response.statusCode.toString()}'); + } + body = response.body; + } else { + body = listSaisonJson; + } + final Map json = jsonDecode(body); + final Map competitionList = json['ligaList']; + return await Future.wait(competitionList.entries.map((entry) async => entry.value.toString())); + } + + /// Get leagues of a season + Future> _getLeagueList({ + String? seasonId, + }) async { + seasonId ??= DateTime.now().year.toString(); + final uri = Uri.parse(apiUrl).replace(queryParameters: { + 'op': 'listLiga', + 'sid': seasonId, + }); + String body; + if (!isMock) { + final response = await http.get(uri); + if (response.statusCode != 200) { + throw Exception( + 'Failed to get the liga list (seasonId: $seasonId): ${response.reasonPhrase ?? response.statusCode.toString()}'); + } + body = response.body; + } else { + body = listLigaJson; + } + return jsonDecode(body); + } + + /// Get team matches of a league + Future> _getCompetitionList({ + required String seasonId, + required String ligaId, + required String regionId, + }) async { + final uri = Uri.parse(apiUrl).replace(queryParameters: { + 'op': 'listCompetition', + 'sid': seasonId, + 'ligaId': ligaId, + 'rid': regionId, + }); + + String body; + if (!isMock) { + final response = await http.get(uri); + if (response.statusCode != 200) { + throw Exception( + 'Failed to get the competition list (seasonId: $seasonId, ligaId: $ligaId, rid: $regionId): ${response.reasonPhrase ?? response.statusCode.toString()}'); + } + body = response.body; + } else { + body = listCompetitionJson; + } + return jsonDecode(body); + } + + Future> _getCompetition({ + required String seasonId, + required String competitionId, + }) async { + final uri = Uri.parse(apiUrl).replace(queryParameters: { + 'op': 'getCompetition', + 'sid': seasonId, + 'cid': competitionId, + }); + + String body; + if (!isMock) { + final response = await http.get(uri); + if (response.statusCode != 200) { + throw Exception( + 'Failed to get the competition list (seasonId: $seasonId, competitionId: $competitionId): ${response.reasonPhrase ?? response.statusCode.toString()}'); + } + body = response.body; + } else { + body = competitionJson; + } + return jsonDecode(body); + } + + Future> _getSaisonWrestler({ + required int passCode, + }) async { + final uri = Uri.parse(apiUrl).replace(queryParameters: { + 'op': 'getSaisonWrestler', + 'passcode': passCode.toString(), + }); + + String body; + if (!isMock) { + if (authService == null) { + print('No credentials given. Operation `getSaisonWrestler` skipped.'); + return {}; + } + final response = await http.get(uri, headers: authService?.header); + if (response.statusCode != 200) { + throw Exception( + 'Failed to get the competition list (passcode: $passCode): ${response.reasonPhrase ?? response.statusCode.toString()}'); + } + body = response.body; + } else { + body = wrestlerJson; + } + return jsonDecode(body); + } +} diff --git a/wrestling_scoreboard_common/lib/src/services/apis/mocks/competition.json.dart b/wrestling_scoreboard_common/lib/src/services/apis/mocks/competition.json.dart new file mode 100644 index 00000000..18a2da36 --- /dev/null +++ b/wrestling_scoreboard_common/lib/src/services/apis/mocks/competition.json.dart @@ -0,0 +1,514 @@ +final competitionJson = r''' +{ + "rpcid": null, + "rc": "ok", + "api": { + "rdb": "3.0.8 \\\/ 3.0.9", + "jrcs": "1.0.3" + }, + "year": "2021", + "sid": "2019", + "cid": "001006a", + "flags": 0, + "competition": { + "saisonId": "2019", + "competitionId": "001006a", + "ligaId": "Oberliga", + "tableId": "Nord", + "status": "3", + "scheme": "", + "manualInput": "1", + "inTable": "1", + "inStatistics": "0", + "invalidated": "0", + "planned": "0", + "boutday": "5", + "homeTeamName": "TSV Burgebrach I", + "opponentTeamName": "RSV Schonungen ", + "homePoints": "21", + "opponentPoints": "8", + "boutDate": "2019-10-05", + "scaleTime": "19:00:00", + "audience": "305", + "location": "Windeckhalle, Grasmanndorf Str. 2b, 96138 Burgebrach", + "editorName": "burgebrach", + "editorComment": "61KG RSV Schonungen 07 Khachik Gaspariyan mit 56,9kg Untergewicht; ", + "refereeName": "Rankl", + "refereeGivenname": "Konrad", + "lastModified": "2019-10-06 11:25:31", + "editedAt": "2019-10-06 11:03:02", + "editedBy": "j.heinz@brv-ringen.de", + "editedIpAddr": "87.166.225.222", + "controlledAt": "2019-10-06 11:03:41", + "controlledBy": "j.heinz@brv-ringen.de", + "controllerComment": "", + "validatedHomePoints": "21", + "validatedOpponentPoints": "8", + "decision": "home", + "_boutList": [ + { + "saisonId": "2019", + "competitionId": "001006a", + "order": "1", + "weightClass": "57", + "style": "LL", + "homeWrestlerId": "4354", + "homeWrestlerLicId": "0", + "homeWrestlerName": "Engelhardt", + "homeWrestlerGivenname": "Johann", + "opponentWrestlerId": "6237", + "opponentWrestlerLicId": "259", + "opponentWrestlerName": "Mandica", + "opponentWrestlerGivenname": "Alexandru-Vasile", + "homeWrestlerPoints": "0", + "homeWrestlerFlags": "0", + "opponentWrestlerPoints": "2", + "opponentWrestlerFlags": "0", + "result": "PS", + "round1": "2:7 ", + "round2": "", + "round3": "", + "round4": "", + "round5": "", + "homeWrestlerStatus": "J", + "opponentWrestlerStatus": "N", + "annotation": { + "1": { + "points": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "1", + "round": "1", + "type": "points", + "value": "1b39,1b67,Pr75,1b101,Ar124,1b148,1b197,2b294,2r355" + }, + "duration": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "1", + "round": "1", + "type": "duration", + "value": "360" + } + } + } + }, + { + "saisonId": "2019", + "competitionId": "001006a", + "order": "2", + "weightClass": "61", + "style": "GR", + "homeWrestlerId": "2063", + "homeWrestlerLicId": "158", + "homeWrestlerName": "Cimpanu", + "homeWrestlerGivenname": "Dragos Florin", + "opponentWrestlerId": "", + "opponentWrestlerLicId": "0", + "opponentWrestlerName": "", + "opponentWrestlerGivenname": "", + "homeWrestlerPoints": "4", + "homeWrestlerFlags": "0", + "opponentWrestlerPoints": "0", + "opponentWrestlerFlags": "0", + "result": "KL", + "round1": " ", + "round2": "", + "round3": "", + "round4": "", + "round5": "", + "homeWrestlerStatus": "", + "opponentWrestlerStatus": "", + "annotation": { + "1": { + "duration": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "2", + "round": "1", + "type": "duration", + "value": "0" + } + } + } + }, + { + "saisonId": "2019", + "competitionId": "001006a", + "order": "3", + "weightClass": "66", + "style": "LL", + "homeWrestlerId": "2798", + "homeWrestlerLicId": "0", + "homeWrestlerName": "Rippl", + "homeWrestlerGivenname": "Christopher", + "opponentWrestlerId": "968", + "opponentWrestlerLicId": "0", + "opponentWrestlerName": "Klein", + "opponentWrestlerGivenname": "Gabriel Gamsat", + "homeWrestlerPoints": "0", + "homeWrestlerFlags": "0", + "opponentWrestlerPoints": "4", + "opponentWrestlerFlags": "0", + "result": "T\u00dc", + "round1": "0:16 ", + "round2": "", + "round3": "", + "round4": "", + "round5": "", + "homeWrestlerStatus": "", + "opponentWrestlerStatus": "", + "annotation": { + "1": { + "points": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "3", + "round": "1", + "type": "points", + "value": "2b60,2b79,Pr98,2b107,2b112,2b130,2b139,2b151,2b160" + }, + "duration": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "3", + "round": "1", + "type": "duration", + "value": "161" + } + } + } + }, + { + "saisonId": "2019", + "competitionId": "001006a", + "order": "4", + "weightClass": "71", + "style": "GR", + "homeWrestlerId": "7459", + "homeWrestlerLicId": "0", + "homeWrestlerName": "Vancza", + "homeWrestlerGivenname": "Istvan", + "opponentWrestlerId": "859", + "opponentWrestlerLicId": "0", + "opponentWrestlerName": "Schwanke", + "opponentWrestlerGivenname": "Rudolf", + "homeWrestlerPoints": "4", + "homeWrestlerFlags": "0", + "opponentWrestlerPoints": "0", + "opponentWrestlerFlags": "0", + "result": "T\u00dc", + "round1": "15:0 ", + "round2": "", + "round3": "", + "round4": "", + "round5": "", + "homeWrestlerStatus": "", + "opponentWrestlerStatus": "", + "annotation": { + "1": { + "points": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "4", + "round": "1", + "type": "points", + "value": "4r21,2r28,2r57,Pb88,1r88,2r101,4r151" + }, + "duration": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "4", + "round": "1", + "type": "duration", + "value": "152" + } + } + } + }, + { + "saisonId": "2019", + "competitionId": "001006a", + "order": "5", + "weightClass": "75 A", + "style": "LL", + "homeWrestlerId": "3446", + "homeWrestlerLicId": "0", + "homeWrestlerName": "Giehl", + "homeWrestlerGivenname": "Josef", + "opponentWrestlerId": "2141", + "opponentWrestlerLicId": "0", + "opponentWrestlerName": "Gelaschanov", + "opponentWrestlerGivenname": "Machs", + "homeWrestlerPoints": "2", + "homeWrestlerFlags": "0", + "opponentWrestlerPoints": "0", + "opponentWrestlerFlags": "0", + "result": "PS", + "round1": "6:1 ", + "round2": "", + "round3": "", + "round4": "", + "round5": "", + "homeWrestlerStatus": "", + "opponentWrestlerStatus": "N6", + "annotation": { + "1": { + "points": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "5", + "round": "1", + "type": "points", + "value": "1b31,Pr105,Ar148,2r160,2r180,2r285" + }, + "duration": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "5", + "round": "1", + "type": "duration", + "value": "360" + } + } + } + }, + { + "saisonId": "2019", + "competitionId": "001006a", + "order": "6", + "weightClass": "75 B", + "style": "GR", + "homeWrestlerId": "2797", + "homeWrestlerLicId": "0", + "homeWrestlerName": "Pflauger", + "homeWrestlerGivenname": "Felix", + "opponentWrestlerId": "1406", + "opponentWrestlerLicId": "0", + "opponentWrestlerName": "Hofmann", + "opponentWrestlerGivenname": "Tobias", + "homeWrestlerPoints": "0", + "homeWrestlerFlags": "0", + "opponentWrestlerPoints": "1", + "opponentWrestlerFlags": "0", + "result": "PS", + "round1": "4:6 ", + "round2": "", + "round3": "", + "round4": "", + "round5": "", + "homeWrestlerStatus": "", + "opponentWrestlerStatus": "", + "annotation": { + "1": { + "points": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "6", + "round": "1", + "type": "points", + "value": "Pr96,1b96,2b115,2r130,2r151,1b220,1b256,1b348" + }, + "duration": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "6", + "round": "1", + "type": "duration", + "value": "360" + } + } + } + }, + { + "saisonId": "2019", + "competitionId": "001006a", + "order": "7", + "weightClass": "80", + "style": "LL", + "homeWrestlerId": "7063", + "homeWrestlerLicId": "155", + "homeWrestlerName": "Castillo-Silveira", + "homeWrestlerGivenname": "Yunier", + "opponentWrestlerId": "2527", + "opponentWrestlerLicId": "0", + "opponentWrestlerName": "H\u00fcmpfer", + "opponentWrestlerGivenname": "Andreas", + "homeWrestlerPoints": "4", + "homeWrestlerFlags": "0", + "opponentWrestlerPoints": "0", + "opponentWrestlerFlags": "0", + "result": "T\u00dc", + "round1": "18:3 ", + "round2": "", + "round3": "", + "round4": "", + "round5": "", + "homeWrestlerStatus": "", + "opponentWrestlerStatus": "", + "annotation": { + "1": { + "points": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "7", + "round": "1", + "type": "points", + "value": "1b54,4r88,2r108,2r125,2r175,2r199,2b219,2r249,2r266,2r286" + }, + "duration": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "7", + "round": "1", + "type": "duration", + "value": "286" + } + } + } + }, + { + "saisonId": "2019", + "competitionId": "001006a", + "order": "8", + "weightClass": "86", + "style": "GR", + "homeWrestlerId": "2796", + "homeWrestlerLicId": "0", + "homeWrestlerName": "Winkler", + "homeWrestlerGivenname": "Dominik", + "opponentWrestlerId": "2724", + "opponentWrestlerLicId": "0", + "opponentWrestlerName": "Full", + "opponentWrestlerGivenname": "Felix", + "homeWrestlerPoints": "3", + "homeWrestlerFlags": "0", + "opponentWrestlerPoints": "0", + "opponentWrestlerFlags": "0", + "result": "PS", + "round1": "11:0 ", + "round2": "", + "round3": "", + "round4": "", + "round5": "", + "homeWrestlerStatus": "", + "opponentWrestlerStatus": "", + "annotation": { + "1": { + "points": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "8", + "round": "1", + "type": "points", + "value": "Pb92,1r92,Pb231,1r231,1r274,0b292,2r292,2r308,1r316,0b334,2r334,1r350" + }, + "duration": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "8", + "round": "1", + "type": "duration", + "value": "360" + } + } + } + }, + { + "saisonId": "2019", + "competitionId": "001006a", + "order": "9", + "weightClass": "98", + "style": "LL", + "homeWrestlerId": "1082", + "homeWrestlerLicId": "0", + "homeWrestlerName": "Z\u00fcrl", + "homeWrestlerGivenname": "Markus", + "opponentWrestlerId": "807", + "opponentWrestlerLicId": "0", + "opponentWrestlerName": "Sch\u00e4fer", + "opponentWrestlerGivenname": "Markus", + "homeWrestlerPoints": "0", + "homeWrestlerFlags": "0", + "opponentWrestlerPoints": "1", + "opponentWrestlerFlags": "0", + "result": "PS", + "round1": "1:3 ", + "round2": "", + "round3": "", + "round4": "", + "round5": "", + "homeWrestlerStatus": "", + "opponentWrestlerStatus": "", + "annotation": { + "1": { + "points": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "9", + "round": "1", + "type": "points", + "value": "Pr68,1r75,Ar116,1b149,2b239" + }, + "duration": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "9", + "round": "1", + "type": "duration", + "value": "360" + } + } + } + }, + { + "saisonId": "2019", + "competitionId": "001006a", + "order": "10", + "weightClass": "130", + "style": "GR", + "homeWrestlerId": "3175", + "homeWrestlerLicId": "0", + "homeWrestlerName": "Brosowski", + "homeWrestlerGivenname": "Jens", + "opponentWrestlerId": "2757", + "opponentWrestlerLicId": "0", + "opponentWrestlerName": "Doile", + "opponentWrestlerGivenname": "Florian", + "homeWrestlerPoints": "4", + "homeWrestlerFlags": "0", + "opponentWrestlerPoints": "0", + "opponentWrestlerFlags": "0", + "result": "T\u00dc", + "round1": "16:0 ", + "round2": "", + "round3": "", + "round4": "", + "round5": "", + "homeWrestlerStatus": "J", + "opponentWrestlerStatus": "", + "annotation": { + "1": { + "points": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "10", + "round": "1", + "type": "points", + "value": "4r100,Pb121,1r121,2r132,2r135,Pb243,1r243,2r253,2r256,2r281" + }, + "duration": { + "saisonId": "2019", + "competitionId": "001006a", + "order": "10", + "round": "1", + "type": "duration", + "value": "281" + } + } + } + } + ] + } +} +'''; diff --git a/wrestling_scoreboard_common/lib/src/services/apis/mocks/listCompetition.json.dart b/wrestling_scoreboard_common/lib/src/services/apis/mocks/listCompetition.json.dart new file mode 100644 index 00000000..e53b2e57 --- /dev/null +++ b/wrestling_scoreboard_common/lib/src/services/apis/mocks/listCompetition.json.dart @@ -0,0 +1,88 @@ +final listCompetitionJson = r''' +{ + "rpcid": null, + "rc": "ok", + "api": { + "rdb": "3.0.8 \\\/ 3.0.9", + "jrcs": "1.0.3" + }, + "year": "2021", + "sid": "2021", + "lid": "Gruppenliga", + "rid": "S\u00fcd", + "competitionList": { + "106109j": { + "saisonId": "2021", + "competitionId": "106109j", + "ligaId": "Gruppenliga", + "tableId": "S\u00fcd", + "status": "3", + "scheme": "", + "manualInput": "1", + "inTable": "1", + "inStatistics": "0", + "invalidated": "0", + "planned": "0", + "boutday": "4", + "homeTeamName": "TV Geiselh\u00f6ring II", + "opponentTeamName": "TV Feldkirchen", + "homePoints": "46", + "opponentPoints": "8", + "boutDate": "2021-09-25", + "scaleTime": "17:45:00", + "audience": "100", + "location": "Geiselh\u00f6ringer Hof, Straubinger Str. 5, 94333 Geiselh\u00f6ring", + "editorName": "geiselhoering", + "editorComment": "fair", + "refereeName": "Steinberger ", + "refereeGivenname": "Johannes", + "lastModified": "2021-09-26 12:27:39", + "editedAt": "2021-09-26 12:13:31", + "editedBy": "j.heinz@brv-ringen.de", + "editedIpAddr": "87.172.196.211", + "controlledAt": "2021-09-26 12:13:45", + "controlledBy": "j.heinz@brv-ringen.de", + "controllerComment": "", + "validatedHomePoints": "46", + "validatedOpponentPoints": "8", + "decision": "home" + }, + "035106j": { + "saisonId": "2021", + "competitionId": "035106j", + "ligaId": "Gruppenliga", + "tableId": "S\u00fcd", + "status": "3", + "scheme": "", + "manualInput": "1", + "inTable": "1", + "inStatistics": "0", + "invalidated": "0", + "planned": "0", + "boutday": "5", + "homeTeamName": "AC Bad Reichenhall", + "opponentTeamName": "TV Geiselh\u00f6ring II", + "homePoints": "23", + "opponentPoints": "32", + "boutDate": "2021-10-02", + "scaleTime": "19:00:00", + "audience": "", + "location": "Mehrzweckturnhalle in Karlstein, Schmalschl\u00e4gerstr. 5, 83435 Bad Reichenhall \/ Karlstein", + "editorName": "reichenhall", + "editorComment": "AC 57, 61 kg unbesetzt, TVGII 98,130kg unbesetzt", + "refereeName": "", + "refereeGivenname": "", + "lastModified": "2021-10-03 09:41:46", + "editedAt": "2021-10-03 09:41:12", + "editedBy": "j.heinz@brv-ringen.de", + "editedIpAddr": "87.172.196.211", + "controlledAt": "2021-10-03 09:41:31", + "controlledBy": "j.heinz@brv-ringen.de", + "controllerComment": "", + "validatedHomePoints": "23", + "validatedOpponentPoints": "32", + "decision": "opponent" + } + } +} +'''; diff --git a/wrestling_scoreboard_common/lib/src/services/apis/mocks/listLiga.json.dart b/wrestling_scoreboard_common/lib/src/services/apis/mocks/listLiga.json.dart new file mode 100644 index 00000000..f354d89f --- /dev/null +++ b/wrestling_scoreboard_common/lib/src/services/apis/mocks/listLiga.json.dart @@ -0,0 +1,286 @@ +final listLigaJson = r''' +{ + "rpcid": null, + "rc": "ok", + "api": { + "rdb": "3.0.8 \\\/ 3.0.9", + "jrcs": "1.0.3" + }, + "year": "2021", + "sid": "2023", + "ligaList": { + "(S) Bezirksliga": { + "Grenzlandliga": { + "saisonId": "2023", + "ligaId": "(S) Bezirksliga", + "fid": "BZL", + "type": "amorphous", + "tableId": "Grenzlandliga", + "systemId": "S", + "status": "3", + "order": "5", + "indicator": "k", + "extId": "", + "boutSchemeId": "1101", + "wrestlerMissed": "3", + "noOfBoutDays": "14", + "sumOfLigaBoutDays": "0", + "lastUpdate": "2023-12-10 09:28:48", + "moveUpRank": "0", + "dropDownRank": "0", + "cntl": "" + }, + "Mittelfranken": { + "saisonId": "2023", + "ligaId": "(S) Bezirksliga", + "fid": "BZL", + "type": "amorphous", + "tableId": "Mittelfranken", + "systemId": "S", + "status": "3", + "order": "5", + "indicator": "g", + "extId": "", + "boutSchemeId": "1016", + "wrestlerMissed": "9", + "noOfBoutDays": "16", + "sumOfLigaBoutDays": "0", + "lastUpdate": "2023-12-11 18:51:52", + "moveUpRank": "0", + "dropDownRank": "0", + "cntl": "" + }, + "Niederbayern\/Oberpfalz": { + "saisonId": "2023", + "ligaId": "(S) Bezirksliga", + "fid": "BZL", + "type": "amorphous", + "tableId": "Niederbayern\/Oberpfalz", + "systemId": "S", + "status": "3", + "order": "5", + "indicator": "l", + "extId": "", + "boutSchemeId": "1050", + "wrestlerMissed": "4", + "noOfBoutDays": "14", + "sumOfLigaBoutDays": "0", + "lastUpdate": "2023-12-11 13:20:56", + "moveUpRank": "0", + "dropDownRank": "0", + "cntl": "" + }, + "Oberbayern\/Schwaben Gr. A": { + "saisonId": "2023", + "ligaId": "(S) Bezirksliga", + "fid": "BZL", + "type": "amorphous", + "tableId": "Oberbayern\/Schwaben Gr. A", + "systemId": "S", + "status": "2", + "order": "5", + "indicator": "j", + "extId": "", + "boutSchemeId": "1100", + "wrestlerMissed": "2", + "noOfBoutDays": "14", + "sumOfLigaBoutDays": "0", + "lastUpdate": "2023-12-09 17:03:15", + "moveUpRank": "0", + "dropDownRank": "0", + "cntl": "" + }, + "Oberbayern\/Schwaben Gr. B": { + "saisonId": "2023", + "ligaId": "(S) Bezirksliga", + "fid": "BZL", + "type": "amorphous", + "tableId": "Oberbayern\/Schwaben Gr. B", + "systemId": "S", + "status": "2", + "order": "5", + "indicator": "i", + "extId": "", + "boutSchemeId": "1100", + "wrestlerMissed": "2", + "noOfBoutDays": "14", + "sumOfLigaBoutDays": "0", + "lastUpdate": "2023-12-17 20:14:42", + "moveUpRank": "0", + "dropDownRank": "0", + "cntl": "" + } + }, + "(S) Finalrunde": { + "": { + "saisonId": "2023", + "ligaId": "(S) Finalrunde", + "fid": "SF", + "type": "amorphous", + "tableId": "", + "systemId": "S", + "status": "2", + "order": "6", + "indicator": "n", + "extId": "", + "boutSchemeId": "1102", + "wrestlerMissed": "8", + "noOfBoutDays": "4", + "sumOfLigaBoutDays": "0", + "lastUpdate": "2023-12-18 11:13:19", + "moveUpRank": "0", + "dropDownRank": "0", + "cntl": "" + } + }, + "Bayernliga": { + "Nord": { + "saisonId": "2023", + "ligaId": "Bayernliga", + "fid": "BL", + "type": "utable", + "tableId": "Nord", + "systemId": "M", + "status": "3", + "order": "2", + "indicator": "b", + "extId": "764,2", + "boutSchemeId": "1053", + "wrestlerMissed": "2", + "noOfBoutDays": "18", + "sumOfLigaBoutDays": "0", + "lastUpdate": "2023-12-10 18:40:36", + "moveUpRank": "1", + "dropDownRank": "1", + "cntl": "" + }, + "S\u00c3\u00bcd": { + "saisonId": "2023", + "ligaId": "Bayernliga", + "fid": "BL", + "type": "utable", + "tableId": "S\u00fcd", + "systemId": "M", + "status": "3", + "order": "2", + "indicator": "c", + "extId": "764,3", + "boutSchemeId": "1053", + "wrestlerMissed": "2", + "noOfBoutDays": "18", + "sumOfLigaBoutDays": "0", + "lastUpdate": "2023-12-10 18:40:51", + "moveUpRank": "1", + "dropDownRank": "1", + "cntl": "" + } + }, + "Gruppenoberliga": { + "Nord": { + "saisonId": "2023", + "ligaId": "Gruppenoberliga", + "fid": "GOL", + "type": "utable", + "tableId": "Nord", + "systemId": "M", + "status": "3", + "order": "4", + "indicator": "f", + "extId": "765,3", + "boutSchemeId": "1051", + "wrestlerMissed": "8", + "noOfBoutDays": "14", + "sumOfLigaBoutDays": "0", + "lastUpdate": "2024-02-09 18:17:20", + "moveUpRank": "1", + "dropDownRank": "8", + "cntl": "" + }, + "S\u00c3\u00bcd": { + "saisonId": "2023", + "ligaId": "Gruppenoberliga", + "fid": "GOL", + "type": "utable", + "tableId": "S\u00fcd", + "systemId": "M", + "status": "3", + "order": "4", + "indicator": "e", + "extId": "765,4", + "boutSchemeId": "1051", + "wrestlerMissed": "8", + "noOfBoutDays": "18", + "sumOfLigaBoutDays": "0", + "lastUpdate": "2023-12-10 18:42:02", + "moveUpRank": "1", + "dropDownRank": "10", + "cntl": "" + } + }, + "Landesliga": { + "Nord": { + "saisonId": "2023", + "ligaId": "Landesliga", + "fid": "LL", + "type": "utable", + "tableId": "Nord", + "systemId": "M", + "status": "3", + "order": "3", + "indicator": "d", + "extId": "765,1", + "boutSchemeId": "1051", + "wrestlerMissed": "8", + "noOfBoutDays": "14", + "sumOfLigaBoutDays": "0", + "lastUpdate": "2023-12-15 12:53:29", + "moveUpRank": "1", + "dropDownRank": "8", + "cntl": "" + }, + "S\u00c3\u00bcd": { + "saisonId": "2023", + "ligaId": "Landesliga", + "fid": "LL", + "type": "utable", + "tableId": "S\u00fcd", + "systemId": "M", + "status": "3", + "order": "3", + "indicator": "h", + "extId": "765,2", + "boutSchemeId": "1051", + "wrestlerMissed": "8", + "noOfBoutDays": "14", + "sumOfLigaBoutDays": "0", + "lastUpdate": "2023-12-12 14:24:53", + "moveUpRank": "1", + "dropDownRank": "8", + "cntl": "status=\"1\"" + } + }, + "Oberliga": { + "": { + "saisonId": "2023", + "ligaId": "Oberliga", + "fid": "OL", + "type": "utable", + "tableId": "", + "systemId": "M", + "status": "3", + "order": "1", + "indicator": "a", + "extId": "764,1", + "boutSchemeId": "1053", + "wrestlerMissed": "2", + "noOfBoutDays": "18", + "sumOfLigaBoutDays": "0", + "lastUpdate": "2023-12-10 18:40:07", + "moveUpRank": "1", + "dropDownRank": "2", + "cntl": "" + } + } + } +} +'''; diff --git a/wrestling_scoreboard_common/lib/src/services/apis/mocks/listSaison.json.dart b/wrestling_scoreboard_common/lib/src/services/apis/mocks/listSaison.json.dart new file mode 100644 index 00000000..a051b032 --- /dev/null +++ b/wrestling_scoreboard_common/lib/src/services/apis/mocks/listSaison.json.dart @@ -0,0 +1,172 @@ +final listSaisonJson = r''' +{ + "rpcid": null, + "rc": "ok", + "api": { + "rdb": "3.0.8 \\\/ 3.0.9", + "jrcs": "1.0.3" + }, + "saisonList": { + "2009": { + "saisonId": "2009", + "active": "1", + "controllerName": "Stefan Dammert", + "description": "Ligen des BRV", + "noOfBoutDays": "14", + "teamIdSize": "2", + "noOfSystems": "1", + "ruleType": "0" + }, + "2010": { + "saisonId": "2010", + "active": "1", + "controllerName": "Stefan Dammert", + "description": "Ligen des BRV", + "noOfBoutDays": "14", + "teamIdSize": "2", + "noOfSystems": "2", + "ruleType": "0" + }, + "2011": { + "saisonId": "2011", + "active": "1", + "controllerName": "Stefan Dammert", + "description": "Ligen des BRV", + "noOfBoutDays": "14", + "teamIdSize": "2", + "noOfSystems": "2", + "ruleType": "0" + }, + "2012": { + "saisonId": "2012", + "active": "1", + "controllerName": "Stefan Dammert", + "description": "Ligen des BRV", + "noOfBoutDays": "14", + "teamIdSize": "3", + "noOfSystems": "2", + "ruleType": "0" + }, + "2013": { + "saisonId": "2013", + "active": "1", + "controllerName": "Stefan Dammert", + "description": "Ligen des BRV", + "noOfBoutDays": "16", + "teamIdSize": "3", + "noOfSystems": "2", + "ruleType": "1" + }, + "0000": { + "saisonId": "0000", + "active": "1", + "controllerName": "hosting system", + "description": "rdb free regime system", + "noOfBoutDays": "0", + "teamIdSize": "0", + "noOfSystems": "0", + "ruleType": "2" + }, + "2014": { + "saisonId": "2014", + "active": "1", + "controllerName": "Jan Oertli", + "description": "Ligen des BRV", + "noOfBoutDays": "16", + "teamIdSize": "3", + "noOfSystems": "2", + "ruleType": "2" + }, + "2015": { + "saisonId": "2015", + "active": "1", + "controllerName": "Jan Oertli", + "description": "Ligen des BRV", + "noOfBoutDays": "16", + "teamIdSize": "3", + "noOfSystems": "2", + "ruleType": "2" + }, + "2016": { + "saisonId": "2016", + "active": "1", + "controllerName": "Florian Geiger", + "description": "Ligen des BRV", + "noOfBoutDays": "16", + "teamIdSize": "3", + "noOfSystems": "2", + "ruleType": "2" + }, + "2017": { + "saisonId": "2017", + "active": "1", + "controllerName": "Natascha Sch\u00e4fer", + "description": "Ligen des BRV", + "noOfBoutDays": "18", + "teamIdSize": "3", + "noOfSystems": "2", + "ruleType": "2" + }, + "2018": { + "saisonId": "2018", + "active": "1", + "controllerName": "Natascha Sch\u00e4fer", + "description": "Ligen des BRV", + "noOfBoutDays": "16", + "teamIdSize": "3", + "noOfSystems": "2", + "ruleType": "2" + }, + "2019": { + "saisonId": "2019", + "active": "1", + "controllerName": "Jens Heinz", + "description": "Ligen des BRV", + "noOfBoutDays": "16", + "teamIdSize": "3", + "noOfSystems": "2", + "ruleType": "2" + }, + "2020": { + "saisonId": "2020", + "active": "1", + "controllerName": "Jens Heinz", + "description": "", + "noOfBoutDays": "14", + "teamIdSize": "3", + "noOfSystems": "1", + "ruleType": "0" + }, + "2021": { + "saisonId": "2021", + "active": "1", + "controllerName": "Jens Heinz", + "description": "", + "noOfBoutDays": "16", + "teamIdSize": "3", + "noOfSystems": "2", + "ruleType": "2" + }, + "2022": { + "saisonId": "2022", + "active": "1", + "controllerName": "Jens Heinz", + "description": "", + "noOfBoutDays": "16", + "teamIdSize": "3", + "noOfSystems": "2", + "ruleType": "2" + }, + "2023": { + "saisonId": "2023", + "active": "1", + "controllerName": "Jens Heinz", + "description": "", + "noOfBoutDays": "18", + "teamIdSize": "3", + "noOfSystems": "2", + "ruleType": "2" + } + } +} +'''; diff --git a/wrestling_scoreboard_common/lib/src/services/apis/mocks/wrestler.json.dart b/wrestling_scoreboard_common/lib/src/services/apis/mocks/wrestler.json.dart new file mode 100644 index 00000000..273a30ff --- /dev/null +++ b/wrestling_scoreboard_common/lib/src/services/apis/mocks/wrestler.json.dart @@ -0,0 +1,35 @@ +final wrestlerJson = r''' +{ + "rpcid": null, + "rc": "ok", + "api": { + "rdb": "3.0.8 \\\/ 3.0.9", + "jrcs": "1.0.3" + }, + "year": "2021", + "sid": "2021", + "passcode": "4440", + "nationCode": "GER", + "authCode": "BRV", + "wrestler": { + "name": "Scheffler", + "givenname": "Georg", + "gender": "m", + "birthday": "2002-05-27", + "licenceCode": null, + "authRating": null, + "clubCode": null, + "nationality": "Deutschland", + "passCode": null, + "nationCode": null, + "authCode": null, + "id": "rdb.4440", + "active": "0", + "persId": "4633", + "licId": "0", + "status": "", + "clubId": "11472", + "birthplace": "Neuss" + } +} +'''; diff --git a/wrestling_scoreboard_common/lib/src/services/auth/authorization.dart b/wrestling_scoreboard_common/lib/src/services/auth/authorization.dart new file mode 100644 index 00000000..7f1764a5 --- /dev/null +++ b/wrestling_scoreboard_common/lib/src/services/auth/authorization.dart @@ -0,0 +1,15 @@ +import 'dart:convert'; + +abstract class AuthService {} + +class BasicAuthService extends AuthService { + final String username; + final String password; + + BasicAuthService({required this.username, required this.password}); + + Map get header { + String basicAuth = 'Basic ${base64.encode(utf8.encode('$username:$password'))}'; + return {'authorization': basicAuth}; + } +} diff --git a/wrestling_scoreboard_common/lib/src/services/report.dart b/wrestling_scoreboard_common/lib/src/services/report.dart index b54302c9..f8ccaef9 100644 --- a/wrestling_scoreboard_common/lib/src/services/report.dart +++ b/wrestling_scoreboard_common/lib/src/services/report.dart @@ -7,16 +7,18 @@ export 'reports/germany_nrw.dart'; enum WrestlingReportProvider { deNwRdb274; // NRW, RDB 2.7.4 für Mannschaftskämpfe - WrestlingReporter get reporter { + WrestlingReporter getReporter(Organization organization) { switch (this) { case WrestlingReportProvider.deNwRdb274: - return NrwGermanyWrestlingReporter(); + return NrwGermanyWrestlingReporter(organization); } } } /// Abstraction for importing and exporting file reports. abstract class WrestlingReporter { + Organization get organization; + String exportTeamMatchReport(TeamMatch teamMatch, Map> boutMap); (TeamMatch teamMatch, Map> boutMap) importTeamMatchReport(String report); diff --git a/wrestling_scoreboard_common/lib/src/services/reports/germany_nrw.dart b/wrestling_scoreboard_common/lib/src/services/reports/germany_nrw.dart index b4c35372..5c232ac0 100644 --- a/wrestling_scoreboard_common/lib/src/services/reports/germany_nrw.dart +++ b/wrestling_scoreboard_common/lib/src/services/reports/germany_nrw.dart @@ -52,6 +52,11 @@ extension GerBoutResultAbbreviation on BoutResult { class NrwGermanyWrestlingReporter extends WrestlingReporter { static const HtmlEscape _htmlEscape = HtmlEscape(HtmlEscapeMode(escapeLtGt: true)); + @override + final Organization organization; + + NrwGermanyWrestlingReporter(this.organization); + /// Comments must be HTML escaped and must be longer than 200 characters. String _handleComment(String comment) { bool isSubstring = false; diff --git a/wrestling_scoreboard_common/lib/src/util/data_wrapper.dart b/wrestling_scoreboard_common/lib/src/util/data_wrapper.dart index 7855c08e..d71bf49c 100644 --- a/wrestling_scoreboard_common/lib/src/util/data_wrapper.dart +++ b/wrestling_scoreboard_common/lib/src/util/data_wrapper.dart @@ -309,23 +309,25 @@ Type getTypeFromTableName(String tableName) { } } -/// Hierarchically ordered data types +/// Hierarchically ordered data types. final dataTypes = [ BoutAction, ParticipantState, TeamMatchBout, Bout, - LeagueTeamParticipation, Participation, TeamMatch, - DivisionWeightClass, - BoutConfig, + Competition, Lineup, + LeagueTeamParticipation, + League, + BoutConfig, Membership, Person, Team, Club, + DivisionWeightClass, Division, WeightClass, - Competition, + Organization, ]; diff --git a/wrestling_scoreboard_common/pubspec.yaml b/wrestling_scoreboard_common/pubspec.yaml index dd318820..3e4e6976 100644 --- a/wrestling_scoreboard_common/pubspec.yaml +++ b/wrestling_scoreboard_common/pubspec.yaml @@ -10,6 +10,8 @@ dependencies: json_annotation: ^4.8.1 freezed_annotation: ^2.4.1 country: ^4.1.3 + http: ^1.2.1 + collection: ^1.18.0 dev_dependencies: build_runner: ^2.3.0 diff --git a/wrestling_scoreboard_common/test/services/apis_test.dart b/wrestling_scoreboard_common/test/services/apis_test.dart new file mode 100644 index 00000000..2eded488 --- /dev/null +++ b/wrestling_scoreboard_common/test/services/apis_test.dart @@ -0,0 +1,368 @@ +import 'package:test/test.dart'; +import 'package:wrestling_scoreboard_common/common.dart'; +import 'package:wrestling_scoreboard_common/src/services/auth/authorization.dart'; + +import 'shared.dart'; + +void main() { + late WrestlingApi wrestlingApi; + + final testDivision = Division( + name: '(S) Bezirksliga', + startDate: DateTime(2023), + endDate: DateTime(2024), + boutConfig: BoutConfig(), + seasonPartitions: 2, + organization: organizationNRW, + orgSyncId: '2023_(S) Bezirksliga', + ); + + final testLeague = League( + name: 'Grenzlandliga', + startDate: testDivision.startDate, + endDate: testDivision.endDate, + division: testDivision, + organization: organizationNRW, + orgSyncId: '2023_(S) Bezirksliga_Grenzlandliga', + ); + + final testClub = Club(name: 'TV Geiselhöring II', organization: organizationNRW, orgSyncId: 'TV Geiselhöring II'); + + setUp(() { + wrestlingApi = WrestlingApiProvider.deNwRingenApi.getApi( + organizationNRW, + authService: BasicAuthService(username: '', password: ''), + getSingleOfOrg: (String orgSyncId, {required int orgId}) async { + switch (T) { + case const (Club): + return Club(name: orgSyncId, organization: organizationNRW, orgSyncId: orgSyncId) as T; + case const (Team): + return Team( + name: orgSyncId, + club: Club(name: orgSyncId, organization: organizationNRW, orgSyncId: orgSyncId), + orgSyncId: orgSyncId, + organization: organizationNRW, + ) as T; + default: + throw UnimplementedError(); + } + }, + ); + wrestlingApi.isMock = true; + }); + + group('APIs', () { + group('Germany, NRW', () { + test('Divisions', () async { + final divisions = await wrestlingApi.importDivisions(minDate: DateTime(2023)); + expect(divisions, [ + testDivision, + Division( + name: '(S) Finalrunde', + startDate: DateTime(2023), + endDate: DateTime(2024), + boutConfig: BoutConfig(), + seasonPartitions: 2, + organization: organizationNRW, + orgSyncId: '2023_(S) Finalrunde', + ), + Division( + name: 'Bayernliga', + startDate: DateTime(2023), + endDate: DateTime(2024), + boutConfig: BoutConfig(), + seasonPartitions: 2, + organization: organizationNRW, + orgSyncId: '2023_Bayernliga', + ), + Division( + name: 'Gruppenoberliga', + startDate: DateTime(2023), + endDate: DateTime(2024), + boutConfig: BoutConfig(), + seasonPartitions: 2, + organization: organizationNRW, + orgSyncId: '2023_Gruppenoberliga', + ), + Division( + name: 'Landesliga', + startDate: DateTime(2023), + endDate: DateTime(2024), + boutConfig: BoutConfig(), + seasonPartitions: 2, + organization: organizationNRW, + orgSyncId: '2023_Landesliga', + ), + Division( + name: 'Oberliga', + startDate: DateTime(2023), + endDate: DateTime(2024), + boutConfig: BoutConfig(), + seasonPartitions: 2, + organization: organizationNRW, + orgSyncId: '2023_Oberliga', + ), + ]); + }); + + test('DivisionWeightClasses', () async { + final divisionWeightClasses = await wrestlingApi.importDivisionWeightClasses(division: testDivision); + expect(divisionWeightClasses, [ + // Season partition 1 + DivisionWeightClass( + pos: 0, + seasonPartition: 0, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.free, weight: 57, suffix: null, unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 2, + seasonPartition: 0, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.greco, weight: 61, suffix: null, unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 4, + seasonPartition: 0, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.free, weight: 66, suffix: null, unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 6, + seasonPartition: 0, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.greco, weight: 71, suffix: null, unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 8, + seasonPartition: 0, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.free, weight: 75, suffix: 'A', unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 9, + seasonPartition: 0, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.greco, weight: 75, suffix: 'B', unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 7, + seasonPartition: 0, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.free, weight: 80, suffix: null, unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 5, + seasonPartition: 0, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.greco, weight: 86, suffix: null, unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 3, + seasonPartition: 0, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.free, weight: 98, suffix: null, unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 1, + seasonPartition: 0, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.greco, weight: 130, suffix: null, unit: WeightUnit.kilogram), + ), + // Season partition 2 + DivisionWeightClass( + pos: 0, + seasonPartition: 1, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.greco, weight: 57, suffix: null, unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 2, + seasonPartition: 1, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.free, weight: 61, suffix: null, unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 4, + seasonPartition: 1, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.greco, weight: 66, suffix: null, unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 6, + seasonPartition: 1, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.free, weight: 71, suffix: null, unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 8, + seasonPartition: 1, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.greco, weight: 75, suffix: 'A', unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 9, + seasonPartition: 1, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.free, weight: 75, suffix: 'B', unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 7, + seasonPartition: 1, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.greco, weight: 80, suffix: null, unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 5, + seasonPartition: 1, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.free, weight: 86, suffix: null, unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 3, + seasonPartition: 1, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.greco, weight: 98, suffix: null, unit: WeightUnit.kilogram), + ), + DivisionWeightClass( + pos: 1, + seasonPartition: 1, + division: testDivision, + weightClass: WeightClass(style: WrestlingStyle.free, weight: 130, suffix: null, unit: WeightUnit.kilogram), + ), + ]); + }); + + test('Leagues', () async { + final leagues = await wrestlingApi.importLeagues(division: testDivision); + expect(leagues, [ + testLeague, + League( + name: 'Mittelfranken', + startDate: testDivision.startDate, + endDate: testDivision.endDate, + division: testDivision, + organization: organizationNRW, + orgSyncId: '2023_(S) Bezirksliga_Mittelfranken', + ), + League( + name: 'Niederbayern/Oberpfalz', + startDate: testDivision.startDate, + endDate: testDivision.endDate, + division: testDivision, + organization: organizationNRW, + orgSyncId: '2023_(S) Bezirksliga_Niederbayern/Oberpfalz', + ), + League( + name: 'Oberbayern/Schwaben Gr. A', + startDate: testDivision.startDate, + endDate: testDivision.endDate, + division: testDivision, + organization: organizationNRW, + orgSyncId: '2023_(S) Bezirksliga_Oberbayern/Schwaben Gr. A', + ), + League( + name: 'Oberbayern/Schwaben Gr. B', + startDate: testDivision.startDate, + endDate: testDivision.endDate, + division: testDivision, + organization: organizationNRW, + orgSyncId: '2023_(S) Bezirksliga_Oberbayern/Schwaben Gr. B', + ), + ]); + }); + + test('Clubs', () async { + final clubs = await wrestlingApi.importClubs(); + expect(clubs, [ + testClub, + Club(name: 'AC Bad Reichenhall', organization: organizationNRW, orgSyncId: 'AC Bad Reichenhall'), + Club(name: 'TV Feldkirchen', organization: organizationNRW, orgSyncId: 'TV Feldkirchen'), + ]); + }); + + // TODO: enable when endpoint for clubs is available. + /*test('Memberships', () async { + final memberships = await wrestlingApi.importMemberships(club: testClub); + expect(memberships, []); + });*/ + + test('Teams', () async { + final teams = await wrestlingApi.importTeams(club: testClub); + expect(teams, [ + Team( + name: 'TV Geiselhöring II', + club: testClub, + orgSyncId: 'TV Geiselhöring II', + organization: organizationNRW, + ), + ]); + }); + + test('TeamMatches', () async { + final teamMatches = await wrestlingApi.importTeamMatches(league: testLeague); + expect(teamMatches, [ + TeamMatch( + home: Lineup( + team: Team( + name: 'TV Geiselhöring II', + club: testClub, + organization: organizationNRW, + orgSyncId: 'TV Geiselhöring II'), + ), + guest: Lineup( + team: Team( + name: 'TV Feldkirchen', + club: Club(name: 'TV Feldkirchen', organization: organizationNRW, orgSyncId: 'TV Feldkirchen'), + orgSyncId: 'TV Feldkirchen', + organization: organizationNRW, + ), + ), + date: DateTime(2021, 9, 25, 17, 45), + visitorsCount: 100, + location: 'Geiselhöringer Hof, Straubinger Str. 5, 94333 Geiselhöring', + referee: Person( + prename: 'Johannes', + surname: 'Steinberger', + orgSyncId: 'Johannes Steinberger_null', + organization: organizationNRW, + ), + comment: 'fair', + league: testLeague, + no: '106109j', + seasonPartition: 1, + organization: organizationNRW, + orgSyncId: '106109j', + ), + TeamMatch( + home: Lineup( + team: Team( + name: 'AC Bad Reichenhall', + club: Club(name: 'AC Bad Reichenhall', organization: organizationNRW, orgSyncId: 'AC Bad Reichenhall'), + orgSyncId: 'AC Bad Reichenhall', + organization: organizationNRW, + ), + ), + guest: Lineup( + team: Team( + name: 'TV Geiselhöring II', + club: testClub, + organization: organizationNRW, + orgSyncId: 'TV Geiselhöring II'), + ), + date: DateTime(2021, 10, 02, 19), + visitorsCount: null, + location: 'Mehrzweckturnhalle in Karlstein, Schmalschlägerstr. 5, 83435 Bad Reichenhall / Karlstein', + referee: null, + comment: 'AC 57, 61 kg unbesetzt, TVGII 98,130kg unbesetzt', + league: testLeague, + no: '035106j', + seasonPartition: 1, + organization: organizationNRW, + orgSyncId: '035106j', + ), + ]); + }); + }); + }); +} diff --git a/wrestling_scoreboard_common/test/services/reports_test.dart b/wrestling_scoreboard_common/test/services/reports_test.dart index 1039794e..d1481dc0 100644 --- a/wrestling_scoreboard_common/test/services/reports_test.dart +++ b/wrestling_scoreboard_common/test/services/reports_test.dart @@ -2,8 +2,9 @@ import 'package:country/country.dart'; import 'package:test/test.dart'; import 'package:wrestling_scoreboard_common/common.dart'; +import 'shared.dart'; + void main() { - final organization = Organization(name: 'Deutscher Ringer Bund', abbreviation: 'DRB'); final division = Division( name: 'Test Division', startDate: DateTime(1999), @@ -20,8 +21,8 @@ void main() { endDate: DateTime(2000), division: division, ); - final clubA = Club(name: 'Club A', organization: organization); - final clubB = Club(name: 'Club B', organization: organization); + final clubA = Club(name: 'Club A', organization: organizationNRW); + final clubB = Club(name: 'Club B', organization: organizationDRB); final lineupA = Lineup(team: Team(name: 'Team A', club: clubA)); final lineupB = Lineup(team: Team(name: 'Team B', club: clubB)); final teamMatch = TeamMatch( @@ -80,7 +81,7 @@ void main() { group('Reports', () { test('Germany, NRW', () { - final wrestlingReport = NrwGermanyWrestlingReporter(); + final wrestlingReport = WrestlingReportProvider.deNwRdb274.getReporter(organizationNRW); final report = wrestlingReport.exportTeamMatchReport( teamMatch, { diff --git a/wrestling_scoreboard_common/test/services/shared.dart b/wrestling_scoreboard_common/test/services/shared.dart new file mode 100644 index 00000000..a0eeb766 --- /dev/null +++ b/wrestling_scoreboard_common/test/services/shared.dart @@ -0,0 +1,4 @@ +import 'package:wrestling_scoreboard_common/common.dart'; + +final organizationNRW = Organization(id: 1, name: 'Ringerverband Nordrhein-Westfalen e.V.', abbreviation: 'RV NRW'); +final organizationDRB = Organization(id: 2, name: 'Deutscher Ringer Bund', abbreviation: 'DRB'); diff --git a/wrestling_scoreboard_server/database/dump/PostgreSQL-wrestling_scoreboard-dump.sql b/wrestling_scoreboard_server/database/dump/PostgreSQL-wrestling_scoreboard-dump.sql index f070dc13..6b985b3d 100644 --- a/wrestling_scoreboard_server/database/dump/PostgreSQL-wrestling_scoreboard-dump.sql +++ b/wrestling_scoreboard_server/database/dump/PostgreSQL-wrestling_scoreboard-dump.sql @@ -32,6 +32,18 @@ ALTER SCHEMA public OWNER TO wrestling; COMMENT ON SCHEMA public IS 'standard public schema'; +-- +-- Name: api_provider; Type: TYPE; Schema: public; Owner: wrestling +-- + +CREATE TYPE public.api_provider AS ENUM ( + 'deNwRingenApi', + 'deByRingenApi' +); + + +ALTER TYPE public.api_provider OWNER TO wrestling; + -- -- Name: bout_action_type; Type: TYPE; Schema: public; Owner: wrestling -- @@ -107,6 +119,17 @@ CREATE TYPE public.person_role AS ENUM ( ALTER TYPE public.person_role OWNER TO wrestling; +-- +-- Name: report_provider; Type: TYPE; Schema: public; Owner: wrestling +-- + +CREATE TYPE public.report_provider AS ENUM ( + 'deNwRdb274' +); + + +ALTER TYPE public.report_provider OWNER TO wrestling; + -- -- Name: weight_unit; Type: TYPE; Schema: public; Owner: wrestling -- @@ -146,7 +169,8 @@ CREATE TABLE public.bout ( weight_class_id integer, winner_role public.bout_role, bout_result public.bout_result, - duration_millis integer + duration_millis integer, + org_sync_id character varying(127) ); @@ -258,7 +282,8 @@ CREATE TABLE public.club ( id integer NOT NULL, no character varying(8), name character varying(255) NOT NULL, - organization_id integer NOT NULL + organization_id integer NOT NULL, + org_sync_id character varying(127) ); @@ -296,7 +321,9 @@ CREATE TABLE public.wrestling_event ( location character varying(100), visitors_count integer, comment text, - no character varying(16) + no character varying(16), + organization_id integer, + org_sync_id character varying(127) ); @@ -308,8 +335,7 @@ ALTER TABLE public.wrestling_event OWNER TO wrestling; CREATE TABLE public.competition ( name character varying(127), - bout_config_id integer NOT NULL, - organization_id integer + bout_config_id integer NOT NULL ) INHERITS (public.wrestling_event); @@ -399,7 +425,8 @@ CREATE TABLE public.division ( bout_config_id integer NOT NULL, season_partitions integer DEFAULT 1 NOT NULL, parent_id integer, - organization_id integer NOT NULL + organization_id integer NOT NULL, + org_sync_id character varying(127) ); @@ -495,7 +522,9 @@ CREATE TABLE public.league ( name character varying(127) NOT NULL, start_date date NOT NULL, end_date date NOT NULL, - division_id integer NOT NULL + division_id integer NOT NULL, + org_sync_id character varying(127), + organization_id integer ); @@ -602,7 +631,9 @@ CREATE TABLE public.membership ( id integer NOT NULL, person_id integer NOT NULL, club_id integer NOT NULL, - no character varying(55) + no character varying(55), + org_sync_id character varying(127), + organization_id integer ); @@ -638,7 +669,9 @@ CREATE TABLE public.organization ( id integer NOT NULL, name character varying(255) NOT NULL, abbreviation character varying(64), - parent_id integer + parent_id integer, + api_provider public.api_provider, + report_provider public.report_provider ); @@ -748,7 +781,9 @@ CREATE TABLE public.person ( surname character varying(100) NOT NULL, birth_date date, gender public.gender, - nationality character(3) DEFAULT NULL::bpchar + nationality character(3) DEFAULT NULL::bpchar, + org_sync_id character varying(127), + organization_id integer ); @@ -784,7 +819,9 @@ CREATE TABLE public.team ( id integer NOT NULL, name character varying(100) NOT NULL, description character varying(255), - club_id integer NOT NULL + club_id integer NOT NULL, + org_sync_id character varying(127), + organization_id integer ); @@ -1112,21 +1149,21 @@ ALTER TABLE ONLY public.wrestling_event ALTER COLUMN id SET DEFAULT nextval('pub -- Data for Name: bout; Type: TABLE DATA; Schema: public; Owner: wrestling -- -COPY public.bout (id, red_id, blue_id, weight_class_id, winner_role, bout_result, duration_millis) FROM stdin; -27 31 32 19 \N \N 0 -28 33 34 20 \N \N 0 -29 35 36 21 \N \N 0 -32 40 41 22 \N \N 0 -34 44 45 23 \N \N 0 -35 46 47 24 \N \N 0 -37 50 51 25 \N \N 0 -38 52 53 26 \N \N 0 -40 56 57 27 \N \N 0 -43 62 \N 28 \N \N 0 -45 65 66 29 \N \N 0 -47 69 70 30 \N \N 0 -49 73 74 31 \N \N 0 -50 75 76 32 \N \N 0 +COPY public.bout (id, red_id, blue_id, weight_class_id, winner_role, bout_result, duration_millis, org_sync_id) FROM stdin; +28 33 34 20 \N \N 0 \N +29 35 36 21 \N \N 0 \N +32 40 41 22 \N \N 0 \N +34 44 45 23 \N \N 0 \N +35 46 47 24 \N \N 0 \N +37 50 51 25 \N \N 0 \N +38 52 53 26 \N \N 0 \N +40 56 57 27 \N \N 0 \N +43 62 \N 28 \N \N 0 \N +45 65 66 29 \N \N 0 \N +47 69 70 30 \N \N 0 \N +49 73 74 31 \N \N 0 \N +50 75 76 32 \N \N 0 \N +27 31 32 19 \N \N 0 \N \. @@ -1151,9 +1188,9 @@ COPY public.bout_config (id, period_duration_secs, break_duration_secs, activity -- Data for Name: club; Type: TABLE DATA; Schema: public; Owner: wrestling -- -COPY public.club (id, no, name, organization_id) FROM stdin; -2 12345 Springfield Wrestlers 1 -1 05432 Quahog Hunters 1 +COPY public.club (id, no, name, organization_id, org_sync_id) FROM stdin; +2 12345 Springfield Wrestlers 1 \N +1 05432 Quahog Hunters 1 \N \. @@ -1161,8 +1198,8 @@ COPY public.club (id, no, name, organization_id) FROM stdin; -- Data for Name: competition; Type: TABLE DATA; Schema: public; Owner: wrestling -- -COPY public.competition (id, date, location, visitors_count, comment, no, name, bout_config_id, organization_id) FROM stdin; -1 2021-07-17 Quahog 15 \N \N The Griffin-Simpson Competition 1 \N +COPY public.competition (id, date, location, visitors_count, comment, no, organization_id, org_sync_id, name, bout_config_id) FROM stdin; +1 2021-07-17 Quahog 15 \N \N \N \N The Griffin-Simpson Competition 1 \. @@ -1186,9 +1223,9 @@ COPY public.competition_person (id, competition_id, person_id, person_role) FROM -- Data for Name: division; Type: TABLE DATA; Schema: public; Owner: wrestling -- -COPY public.division (id, name, start_date, end_date, bout_config_id, season_partitions, parent_id, organization_id) FROM stdin; -1 National League 2024-01-01 2025-01-01 1 2 \N 1 -2 National League Junior 2024-01-01 2025-01-01 1 2 \N 1 +COPY public.division (id, name, start_date, end_date, bout_config_id, season_partitions, parent_id, organization_id, org_sync_id) FROM stdin; +1 National League 2024-01-01 2025-01-01 1 2 \N 1 \N +2 National League Junior 2024-01-01 2025-01-01 1 2 \N 1 \N \. @@ -1233,10 +1270,10 @@ COPY public.division_weight_class (id, division_id, weight_class_id, pos, season -- Data for Name: league; Type: TABLE DATA; Schema: public; Owner: wrestling -- -COPY public.league (id, name, start_date, end_date, division_id) FROM stdin; -3 North 2021-10-01 2022-10-01 1 -1 South 2021-10-01 2022-10-01 1 -2 North Jn 2021-10-01 2022-10-01 2 +COPY public.league (id, name, start_date, end_date, division_id, org_sync_id, organization_id) FROM stdin; +3 North 2021-10-01 2022-10-01 1 \N \N +1 South 2021-10-01 2022-10-01 1 \N \N +2 North Jn 2021-10-01 2022-10-01 2 \N \N \. @@ -1269,29 +1306,29 @@ COPY public.lineup (id, team_id, leader_id, coach_id) FROM stdin; -- Data for Name: membership; Type: TABLE DATA; Schema: public; Owner: wrestling -- -COPY public.membership (id, person_id, club_id, no) FROM stdin; -2 2 2 \N -3 3 2 \N -4 4 2 \N -7 7 1 \N -8 8 1 \N -10 11 1 \N -11 12 1 \N -5 5 1 1234 -9 10 1 \N -12 13 1 \N -13 14 1 \N -14 15 1 \N -15 16 1 \N -16 17 2 \N -17 18 2 \N -18 19 2 \N -19 20 2 \N -20 21 2 \N -21 22 2 \N -22 23 2 \N -6 6 1 \N -1 1 2 \N +COPY public.membership (id, person_id, club_id, no, org_sync_id, organization_id) FROM stdin; +2 2 2 \N \N \N +3 3 2 \N \N \N +4 4 2 \N \N \N +7 7 1 \N \N \N +8 8 1 \N \N \N +10 11 1 \N \N \N +11 12 1 \N \N \N +5 5 1 1234 \N \N +9 10 1 \N \N \N +12 13 1 \N \N \N +13 14 1 \N \N \N +14 15 1 \N \N \N +15 16 1 \N \N \N +16 17 2 \N \N \N +17 18 2 \N \N \N +18 19 2 \N \N \N +19 20 2 \N \N \N +20 21 2 \N \N \N +21 22 2 \N \N \N +22 23 2 \N \N \N +6 6 1 \N \N \N +1 1 2 \N \N \N \. @@ -1299,8 +1336,8 @@ COPY public.membership (id, person_id, club_id, no) FROM stdin; -- Data for Name: organization; Type: TABLE DATA; Schema: public; Owner: wrestling -- -COPY public.organization (id, name, abbreviation, parent_id) FROM stdin; -1 United World Wrestling UWW \N +COPY public.organization (id, name, abbreviation, parent_id, api_provider, report_provider) FROM stdin; +1 United World Wrestling UWW \N deByRingenApi deNwRdb274 \. @@ -1379,30 +1416,30 @@ COPY public.participation (id, membership_id, lineup_id, weight_class_id, weight -- Data for Name: person; Type: TABLE DATA; Schema: public; Owner: wrestling -- -COPY public.person (id, prename, surname, birth_date, gender, nationality) FROM stdin; -2 Bart Simpson 2007-07-08 male \N -3 March Simpson 1980-07-08 female \N -4 Homer Simpson 1975-07-08 male \N -7 Lois Griffin 1979-03-08 female \N -8 Peter Griffin 1975-03-08 male \N -9 Mr Referee \N other \N -11 Brian Griffin 2000-03-07 male \N -12 Joe Swanson 1976-03-08 male \N -5 Chris Griffin 2005-03-08 male \N -10 Glenn Quagmire 1982-03-08 male \N -13 Cleveland Brown 1985-03-08 male \N -14 Stewie Griffin 2021-03-07 male \N -15 Adam West 1967-03-08 male \N -16 Bonnie Swanson 1991-03-08 female \N -17 Mr. Burns 1925-03-08 male \N -18 Ned Flanders 1964-03-08 male \N -19 Milhouse Van Houten 2004-03-07 male \N -20 Krusty Clown 1983-03-08 male \N -21 Moe Szyslak 1981-03-08 male \N -22 Maggie Simpson 2020-03-07 female \N -23 Nelson Muntz \N male \N -6 Meg Griffin 2007-03-08 female \N -1 Lisa Simpson 2010-07-08 female USA +COPY public.person (id, prename, surname, birth_date, gender, nationality, org_sync_id, organization_id) FROM stdin; +2 Bart Simpson 2007-07-08 male \N \N \N +3 March Simpson 1980-07-08 female \N \N \N +4 Homer Simpson 1975-07-08 male \N \N \N +7 Lois Griffin 1979-03-08 female \N \N \N +8 Peter Griffin 1975-03-08 male \N \N \N +9 Mr Referee \N other \N \N \N +11 Brian Griffin 2000-03-07 male \N \N \N +12 Joe Swanson 1976-03-08 male \N \N \N +5 Chris Griffin 2005-03-08 male \N \N \N +10 Glenn Quagmire 1982-03-08 male \N \N \N +13 Cleveland Brown 1985-03-08 male \N \N \N +14 Stewie Griffin 2021-03-07 male \N \N \N +15 Adam West 1967-03-08 male \N \N \N +16 Bonnie Swanson 1991-03-08 female \N \N \N +17 Mr. Burns 1925-03-08 male \N \N \N +18 Ned Flanders 1964-03-08 male \N \N \N +19 Milhouse Van Houten 2004-03-07 male \N \N \N +20 Krusty Clown 1983-03-08 male \N \N \N +21 Moe Szyslak 1981-03-08 male \N \N \N +22 Maggie Simpson 2020-03-07 female \N \N \N +23 Nelson Muntz \N male \N \N \N +6 Meg Griffin 2007-03-08 female \N \N \N +1 Lisa Simpson 2010-07-08 female USA \N \N \. @@ -1410,10 +1447,10 @@ COPY public.person (id, prename, surname, birth_date, gender, nationality) FROM -- Data for Name: team; Type: TABLE DATA; Schema: public; Owner: wrestling -- -COPY public.team (id, name, description, club_id) FROM stdin; -1 Springfield Wrestlers 1. Team Men 2 -2 Springfield Wrestlers Jn Juniors 2 -3 Quahog Hunters II 2. Team Men 1 +COPY public.team (id, name, description, club_id, org_sync_id, organization_id) FROM stdin; +1 Springfield Wrestlers 1. Team Men 2 \N \N +2 Springfield Wrestlers Jn Juniors 2 \N \N +3 Quahog Hunters II 2. Team Men 1 \N \N \. @@ -1421,8 +1458,8 @@ COPY public.team (id, name, description, club_id) FROM stdin; -- Data for Name: team_match; Type: TABLE DATA; Schema: public; Owner: wrestling -- -COPY public.team_match (id, date, location, visitors_count, comment, no, home_id, guest_id, referee_id, transcript_writer_id, time_keeper_id, mat_chairman_id, league_id, judge_id, season_partition) FROM stdin; -1 2021-07-10 Springfield \N \N 1 2 \N \N \N \N 1 \N 1 +COPY public.team_match (id, date, location, visitors_count, comment, no, organization_id, org_sync_id, home_id, guest_id, referee_id, transcript_writer_id, time_keeper_id, mat_chairman_id, league_id, judge_id, season_partition) FROM stdin; +1 2021-07-10 Springfield \N \N \N \N 1 2 \N \N \N \N 1 \N 1 \. @@ -1492,7 +1529,7 @@ COPY public.weight_class (id, suffix, weight, style, unit) FROM stdin; -- Data for Name: wrestling_event; Type: TABLE DATA; Schema: public; Owner: wrestling -- -COPY public.wrestling_event (id, date, location, visitors_count, comment, no) FROM stdin; +COPY public.wrestling_event (id, date, location, visitors_count, comment, no, organization_id, org_sync_id) FROM stdin; \. @@ -1535,14 +1572,14 @@ SELECT pg_catalog.setval('public.competition_bout_id_seq', 1, false); -- Name: competition_id_seq; Type: SEQUENCE SET; Schema: public; Owner: wrestling -- -SELECT pg_catalog.setval('public.competition_id_seq', 1, false); +SELECT pg_catalog.setval('public.competition_id_seq', 1, true); -- -- Name: division_id_seq; Type: SEQUENCE SET; Schema: public; Owner: wrestling -- -SELECT pg_catalog.setval('public.division_id_seq', 1, false); +SELECT pg_catalog.setval('public.division_id_seq', 2, true); -- @@ -1563,14 +1600,14 @@ SELECT pg_catalog.setval('public.event_person_id_seq', 1, false); -- Name: league_id_seq; Type: SEQUENCE SET; Schema: public; Owner: wrestling -- -SELECT pg_catalog.setval('public.league_id_seq', 7, true); +SELECT pg_catalog.setval('public.league_id_seq', 3, true); -- -- Name: league_team_participation_id_seq; Type: SEQUENCE SET; Schema: public; Owner: wrestling -- -SELECT pg_catalog.setval('public.league_team_participation_id_seq', 1, false); +SELECT pg_catalog.setval('public.league_team_participation_id_seq', 5, true); -- @@ -1591,7 +1628,7 @@ SELECT pg_catalog.setval('public.membership_id_seq', 22, true); -- Name: organization_id_seq; Type: SEQUENCE SET; Schema: public; Owner: wrestling -- -SELECT pg_catalog.setval('public.organization_id_seq', 1, false); +SELECT pg_catalog.setval('public.organization_id_seq', 1, true); -- @@ -1738,6 +1775,14 @@ ALTER TABLE ONLY public.league_team_participation ADD CONSTRAINT league_team_participation_pk PRIMARY KEY (id); +-- +-- Name: league_team_participation league_team_participation_pk2; Type: CONSTRAINT; Schema: public; Owner: wrestling +-- + +ALTER TABLE ONLY public.league_team_participation + ADD CONSTRAINT league_team_participation_pk2 UNIQUE (league_id, team_id); + + -- -- Name: lineup lineup_pk; Type: CONSTRAINT; Schema: public; Owner: wrestling -- @@ -1940,14 +1985,6 @@ ALTER TABLE ONLY public.competition ADD CONSTRAINT competition_bout_config_id_fk FOREIGN KEY (bout_config_id) REFERENCES public.bout_config(id) ON DELETE CASCADE; --- --- Name: competition competition_organization_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: wrestling --- - -ALTER TABLE ONLY public.competition - ADD CONSTRAINT competition_organization_id_fk FOREIGN KEY (organization_id) REFERENCES public.organization(id); - - -- -- Name: division division_bout_config_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: wrestling -- @@ -2012,6 +2049,14 @@ ALTER TABLE ONLY public.league ADD CONSTRAINT league_division_id_fk FOREIGN KEY (division_id) REFERENCES public.division(id); +-- +-- Name: league league_organization_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: wrestling +-- + +ALTER TABLE ONLY public.league + ADD CONSTRAINT league_organization_id_fk FOREIGN KEY (organization_id) REFERENCES public.organization(id); + + -- -- Name: league_team_participation league_team_participation_league_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: wrestling -- @@ -2052,6 +2097,14 @@ ALTER TABLE ONLY public.membership ADD CONSTRAINT membership_club_id_fk FOREIGN KEY (club_id) REFERENCES public.club(id); +-- +-- Name: membership membership_organization_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: wrestling +-- + +ALTER TABLE ONLY public.membership + ADD CONSTRAINT membership_organization_id_fk FOREIGN KEY (organization_id) REFERENCES public.organization(id); + + -- -- Name: membership membership_person_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: wrestling -- @@ -2100,6 +2153,14 @@ ALTER TABLE ONLY public.participation ADD CONSTRAINT participation_weight_class_id_fk FOREIGN KEY (weight_class_id) REFERENCES public.weight_class(id) ON DELETE CASCADE; +-- +-- Name: person person_organization_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: wrestling +-- + +ALTER TABLE ONLY public.person + ADD CONSTRAINT person_organization_id_fk FOREIGN KEY (organization_id) REFERENCES public.organization(id); + + -- -- Name: team team_club_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: wrestling -- @@ -2188,6 +2249,22 @@ ALTER TABLE ONLY public.team_match ADD CONSTRAINT team_match_person_id_fk_5 FOREIGN KEY (judge_id) REFERENCES public.person(id) ON DELETE CASCADE; +-- +-- Name: team team_organization_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: wrestling +-- + +ALTER TABLE ONLY public.team + ADD CONSTRAINT team_organization_id_fk FOREIGN KEY (organization_id) REFERENCES public.organization(id); + + +-- +-- Name: wrestling_event wrestling_event_organization_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: wrestling +-- + +ALTER TABLE ONLY public.wrestling_event + ADD CONSTRAINT wrestling_event_organization_id_fk FOREIGN KEY (organization_id) REFERENCES public.organization(id); + + -- -- Name: SCHEMA public; Type: ACL; Schema: -; Owner: wrestling -- diff --git a/wrestling_scoreboard_server/lib/controllers/database_controller.dart b/wrestling_scoreboard_server/lib/controllers/database_controller.dart index 6ac13a78..27eb3fb3 100644 --- a/wrestling_scoreboard_server/lib/controllers/database_controller.dart +++ b/wrestling_scoreboard_server/lib/controllers/database_controller.dart @@ -10,7 +10,7 @@ class DatabaseController { // TODO: migration should be handled automatically at server start. /// Reset all tables - Future reset(Request request) async { + Future reset([Request? request]) async { try { await _restoreDefault(); Iterable entityControllers = diff --git a/wrestling_scoreboard_server/lib/controllers/entity_controller.dart b/wrestling_scoreboard_server/lib/controllers/entity_controller.dart index 76602580..722d2707 100644 --- a/wrestling_scoreboard_server/lib/controllers/entity_controller.dart +++ b/wrestling_scoreboard_server/lib/controllers/entity_controller.dart @@ -9,13 +9,13 @@ import 'package:wrestling_scoreboard_server/controllers/bout_config_controller.d import 'package:wrestling_scoreboard_server/controllers/bout_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/club_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/competition_controller.dart'; -import 'package:wrestling_scoreboard_server/controllers/organization_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/division_controller.dart'; +import 'package:wrestling_scoreboard_server/controllers/division_weight_class_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/league_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/league_team_participation_controller.dart'; -import 'package:wrestling_scoreboard_server/controllers/division_weight_class_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/lineup_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/membership_controller.dart'; +import 'package:wrestling_scoreboard_server/controllers/organization_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/participant_state_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/participation_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/person_controller.dart'; @@ -79,13 +79,30 @@ abstract class EntityController { return DataObject.fromRaw(single, getSingleFromDataType); } + /// Get a single data object via a foreign id (sync id), given by an organization. + Future getSingleOfOrg(String orgSyncId, {required int orgId}) async { + final single = await getSingleOfOrgRaw(orgSyncId, orgId: orgId); + return DataObject.fromRaw(single, getSingleFromDataType); + } + late final getSingleRawStmt = PostgresDb().connection.prepare(psql.Sql.named('SELECT * FROM $tableName WHERE $primaryKeyName = @id;')); Future> getSingleRaw(int id) async { final resStream = (await getSingleRawStmt).bind({'id': id}); final many = await resStream.toColumnMap().toList(); - if (many.isEmpty) throw Exception('$T with id "$id" not found'); + if (many.isEmpty) throw InvalidParameterException('$T with id "$id" not found'); + return many.first; + } + + late final getSingleOfOrgRawStmt = PostgresDb() + .connection + .prepare(psql.Sql.named('SELECT * FROM $tableName WHERE organization_id = @orgId AND org_sync_id = @orgSyncId;')); + + Future> getSingleOfOrgRaw(String orgSyncId, {required int orgId}) async { + final resStream = (await getSingleOfOrgRawStmt).bind({'orgSyncId': orgSyncId, 'orgId': orgId}); + final many = await resStream.toColumnMap().toList(); + if (many.isEmpty) throw InvalidParameterException('$T with id "$orgSyncId" not found'); return many.first; } @@ -114,6 +131,37 @@ abstract class EntityController { } } + Future createSingleReturn(T dataObject) async { + return dataObject.copyWithId(await createSingle(dataObject)) as T; + } + + Future getOrCreateSingleOfOrg(T dataObject) async { + if (dataObject.id != null) { + throw Exception('Data object already has an id: $dataObject'); + } + if (dataObject.organization?.id == null || dataObject.orgSyncId == null) { + throw Exception('Organization id and sync id must not be null: $dataObject'); + } + try { + final single = await getSingleOfOrg(dataObject.orgSyncId!, orgId: dataObject.organization!.id!); + return single; + } on InvalidParameterException catch (_) { + return createSingleReturn(dataObject); + } + } + + Future> createMany(List dataObjects) async { + return await Future.wait(dataObjects.map((element) => createSingle(element))); + } + + Future> createManyReturn(List dataObjects) async { + return await Future.wait(dataObjects.map((element) => createSingleReturn(element))); + } + + Future> getOrCreateManyOfOrg(List dataObjects) async { + return await Future.wait(dataObjects.map((element) => getOrCreateSingleOfOrg(element))); + } + Future updateSingle(T dataObject) async { return updateSingleRaw(dataObject.toRaw()); } @@ -306,6 +354,10 @@ abstract class EntityController { return getControllerFromDataType(T).getSingle(id) as Future; } + static Future getSingleFromDataTypeOfOrg(String orgSyncId, {required int orgId}) { + return getControllerFromDataType(T).getSingleOfOrg(orgSyncId, orgId: orgId) as Future; + } + static Future> getManyFromDataType( {List? conditions, Conjunction conjunction = Conjunction.and, Map? substitutionValues}) { return getControllerFromDataType(T).getMany( diff --git a/wrestling_scoreboard_server/lib/controllers/organization_controller.dart b/wrestling_scoreboard_server/lib/controllers/organization_controller.dart index 545aae3d..76ed8fe5 100644 --- a/wrestling_scoreboard_server/lib/controllers/organization_controller.dart +++ b/wrestling_scoreboard_server/lib/controllers/organization_controller.dart @@ -3,7 +3,17 @@ import 'package:wrestling_scoreboard_common/common.dart'; import 'package:wrestling_scoreboard_server/controllers/club_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/competition_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/division_controller.dart'; +import 'package:wrestling_scoreboard_server/controllers/division_weight_class_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/entity_controller.dart'; +import 'package:wrestling_scoreboard_server/controllers/league_team_participation_controller.dart'; +import 'package:wrestling_scoreboard_server/controllers/lineup_controller.dart'; +import 'package:wrestling_scoreboard_server/controllers/person_controller.dart'; +import 'package:wrestling_scoreboard_server/controllers/team_controller.dart'; +import 'package:wrestling_scoreboard_server/controllers/team_match_controller.dart'; +import 'package:wrestling_scoreboard_server/controllers/weight_class_controller.dart'; + +import 'bout_config_controller.dart'; +import 'league_controller.dart'; class OrganizationController extends EntityController { static final OrganizationController _singleton = OrganizationController._internal(); @@ -33,4 +43,82 @@ class OrganizationController extends EntityController { return EntityController.handleRequestManyOfController(OrganizationController(), isRaw: isRaw(request), conditions: ['parent_id = @id'], substitutionValues: {'id': id}); } + + Future import(Request request, String id) async { + try { + final organization = await getSingle(int.parse(id)); + final apiProvider = organization.getApi(EntityController.getSingleFromDataTypeOfOrg); + if (apiProvider == null) { + return Response.notFound('No API provider selected'); + } + apiProvider.isMock = true; + + final clubs = await apiProvider.importClubs(); + await Future.forEach(clubs, (club) async { + club = await ClubController().getOrCreateSingleOfOrg(club); + + final teams = await apiProvider.importTeams(club: club); + await TeamController().getOrCreateManyOfOrg(teams.toList()); + }); + + final divisions = await apiProvider.importDivisions(minDate: DateTime(DateTime.now().year)); + await Future.forEach(divisions, (division) async { + // TODO: Don't create bout config or delete old one, if division already exists. + final boutConfig = await BoutConfigController().createSingleReturn(division.boutConfig); + division = division.copyWith(boutConfig: boutConfig); + division = await DivisionController().getOrCreateSingleOfOrg(division); + + // TODO: Don't create (division) weight classes or delete old ones, if division already exists. + final divisionWeightClasses = await apiProvider.importDivisionWeightClasses(division: division); + await Future.forEach(divisionWeightClasses, (divisionWeightClass) async { + final weightClass = await WeightClassController().createSingleReturn(divisionWeightClass.weightClass); + divisionWeightClass = divisionWeightClass.copyWith(weightClass: weightClass); + divisionWeightClass = await DivisionWeightClassController().createSingleReturn(divisionWeightClass); + }); + + var leagues = await apiProvider.importLeagues(division: division); + leagues = await LeagueController().getOrCreateManyOfOrg(leagues.toList()); + + await Future.forEach(leagues, (league) async { + final teamMatchs = await apiProvider.importTeamMatches(league: league); + + await Future.forEach(teamMatchs, (teamMatch) async { + teamMatch = teamMatch.copyWith( + // TODO: Don't create lineup or delete old one, if match already exists. + home: await LineupController().createSingleReturn(teamMatch.home), + guest: await LineupController().createSingleReturn(teamMatch.guest), + referee: teamMatch.referee == null + ? null + : await PersonController().getOrCreateSingleOfOrg(teamMatch.referee!), + judge: teamMatch.judge == null ? null : await PersonController().getOrCreateSingleOfOrg(teamMatch.judge!), + matChairman: teamMatch.matChairman == null + ? null + : await PersonController().getOrCreateSingleOfOrg(teamMatch.matChairman!), + transcriptWriter: teamMatch.transcriptWriter == null + ? null + : await PersonController().getOrCreateSingleOfOrg(teamMatch.transcriptWriter!), + timeKeeper: teamMatch.timeKeeper == null + ? null + : await PersonController().getOrCreateSingleOfOrg(teamMatch.timeKeeper!), + ); + teamMatch = await TeamMatchController().getOrCreateSingleOfOrg(teamMatch); + + // TODO: may do this in a separate import call for the participating teams: + try { + await LeagueTeamParticipationController() + .createSingle(LeagueTeamParticipation(league: league, team: teamMatch.home.team)); + await LeagueTeamParticipationController() + .createSingle(LeagueTeamParticipation(league: league, team: teamMatch.guest.team)); + } on InvalidParameterException catch (_) { + // Do not add teams multiple times. + } + }); + }); + }); + + return Response.ok('{"status": "success"}'); + } catch (err, stackTrace) { + return Response.internalServerError(body: '{"err": "$err", "stackTrace": "$stackTrace"}'); + } + } } diff --git a/wrestling_scoreboard_server/lib/controllers/websocket_handler.dart b/wrestling_scoreboard_server/lib/controllers/websocket_handler.dart index 96866a57..d298d105 100644 --- a/wrestling_scoreboard_server/lib/controllers/websocket_handler.dart +++ b/wrestling_scoreboard_server/lib/controllers/websocket_handler.dart @@ -7,9 +7,9 @@ import 'package:wrestling_scoreboard_common/common.dart'; import 'package:wrestling_scoreboard_server/controllers/bout_action_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/club_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/division_weight_class_controller.dart'; -import 'package:wrestling_scoreboard_server/controllers/league_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/lineup_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/membership_controller.dart'; +import 'package:wrestling_scoreboard_server/controllers/organization_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/participation_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/team_controller.dart'; import 'package:wrestling_scoreboard_server/controllers/team_match_bout_controller.dart'; @@ -43,12 +43,12 @@ void broadcastSingle(T single) async { filterType: Bout, filterId: single.bout.id))); } else if (single is Organization) { - // TODO + // SpecialCase: the full Organization list has to be updated with no filter, shouldn't occur often + broadcast( + jsonEncode(manyToJson(await OrganizationController().getMany(), Organization, CRUD.update, isRaw: false))); } else if (single is Division) { // TODO } else if (single is League) { - // SpecialCase: the full League list has to be updated, shouldn't occur often - broadcast(jsonEncode(manyToJson(await LeagueController().getMany(), League, CRUD.update, isRaw: false))); } else if (single is DivisionWeightClass) { broadcast(jsonEncode(manyToJson( await DivisionWeightClassController() @@ -162,12 +162,12 @@ void broadcastSingleRaw(Map single) async filterType: Bout, filterId: single['bout_id']))); } else if (T == Organization) { - // TODO + // SpecialCase: the full Organization list has to be updated with no filter, shouldn't occur often + broadcast( + jsonEncode(manyToJson(await OrganizationController().getManyRaw(), Organization, CRUD.update, isRaw: true))); } else if (T == Division) { // TODO } else if (T == League) { - // SpecialCase: the full League list has to be updated, shouldn't occur often - broadcast(jsonEncode(manyToJson(await LeagueController().getManyRaw(), League, CRUD.update, isRaw: true))); } else if (T == DivisionWeightClass) { broadcast(jsonEncode(manyToJson( await DivisionWeightClassController() diff --git a/wrestling_scoreboard_server/lib/routes/api_route.dart b/wrestling_scoreboard_server/lib/routes/api_route.dart index 35d7b939..79ea94f6 100644 --- a/wrestling_scoreboard_server/lib/routes/api_route.dart +++ b/wrestling_scoreboard_server/lib/routes/api_route.dart @@ -1,8 +1,5 @@ import 'package:shelf/shelf.dart'; import 'package:shelf_router/shelf_router.dart'; -import 'package:wrestling_scoreboard_server/controllers/database_controller.dart'; -import 'package:wrestling_scoreboard_server/controllers/league_team_participation_controller.dart'; -import 'package:wrestling_scoreboard_server/controllers/division_weight_class_controller.dart'; import '../controllers/bout_action_controller.dart'; import '../controllers/bout_config_controller.dart'; @@ -10,9 +7,12 @@ import '../controllers/bout_controller.dart'; import '../controllers/club_controller.dart'; import '../controllers/competition_bout_controller.dart'; import '../controllers/competition_controller.dart'; +import '../controllers/database_controller.dart'; +import '../controllers/division_weight_class_controller.dart'; import '../controllers/organization_controller.dart'; import '../controllers/division_controller.dart'; import '../controllers/league_controller.dart'; +import '../controllers/league_team_participation_controller.dart'; import '../controllers/lineup_controller.dart'; import '../controllers/membership_controller.dart'; import '../controllers/participant_state_controller.dart'; @@ -60,6 +60,7 @@ class ApiRoute { router.get('/bout_action/', boutActionController.requestSingle); final organizationController = OrganizationController(); + router.post('/organization//api/import', organizationController.import); router.post('/organization', organizationController.postSingle); router.get('/organizations', organizationController.requestMany); router.get('/organization/', organizationController.requestSingle); diff --git a/wrestling_scoreboard_server/lib/server.dart b/wrestling_scoreboard_server/lib/server.dart index da8fed89..b649ee3d 100644 --- a/wrestling_scoreboard_server/lib/server.dart +++ b/wrestling_scoreboard_server/lib/server.dart @@ -48,6 +48,7 @@ Future init() async { await PostgresDb().open(); final serverUrl = 'http://${server.address.host}:${server.port}'; + print('Serving at $serverUrl'); print('Serving API at $serverUrl/api'); print('Serving Websocket at $serverUrl/ws'); } diff --git a/wrestling_scoreboard_server/pubspec.lock b/wrestling_scoreboard_server/pubspec.lock index 3c88afd3..3cd947bc 100644 --- a/wrestling_scoreboard_server/pubspec.lock +++ b/wrestling_scoreboard_server/pubspec.lock @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: buffer - sha256: "94f60815065a8f0fd4f05be51faf86cf86519327e039d5c2aac72e1d1cc1dad4" + sha256: "389da2ec2c16283c8787e0adaede82b1842102f8c8aae2f49003a766c5c6b3d1" url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "1.2.3" charcode: dependency: transitive description: @@ -137,6 +137,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + http: + dependency: transitive + description: + name: http + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + url: "https://pub.dev" + source: hosted + version: "1.2.1" http_methods: dependency: transitive description: @@ -213,10 +221,10 @@ packages: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.12.0" mime: dependency: transitive description: @@ -269,10 +277,10 @@ packages: dependency: "direct main" description: name: postgres - sha256: f669831dd73e50978fa8ea9bd5023818deb03b5c932d1d694cd7434ecd9fde70 + sha256: "69c93e9a7c69033eab766ba254f8266b417e3047d278ef6bc7aff01d58010c37" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.2" pub_semver: dependency: transitive description: @@ -437,10 +445,10 @@ packages: dependency: transitive description: name: vm_service - sha256: a2662fb1f114f4296cf3f5a50786a2d888268d7776cf681aa17d660ffa23b246 + sha256: a75f83f14ad81d5fe4b3319710b90dec37da0e22612326b696c9e1b8f34bbf48 url: "https://pub.dev" source: hosted - version: "14.0.0" + version: "14.2.0" watcher: dependency: transitive description: @@ -453,10 +461,10 @@ packages: dependency: transitive description: name: web - sha256: "1d9158c616048c38f712a6646e317a3426da10e884447626167240d45209cbad" + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.5.1" web_socket_channel: dependency: "direct main" description: