From 0fd0ad1ac836869f6a115a3bdb74a182910948b4 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Fri, 15 Apr 2022 11:50:09 -0400 Subject: [PATCH 01/40] Deleting a bunch of stuff, it's time to start fresh. --- .gitignore | 14 +- .../PocketLeagueiOS.xcodeproj/project.pbxproj | 624 ------------------ .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcschemes/xcschememanagement.plist | 14 - .../AccentColor.colorset/Contents.json | 11 - .../AppIcon.appiconset/Contents.json | 98 --- .../Assets.xcassets/Contents.json | 6 - .../PocketLeagueiOS/ContentView.swift | 53 -- .../EventSummaryDisplayModel.swift | 17 - .../EventSummaryListItem.swift | 38 -- .../PocketLeagueiOS/PocketLeagueiOSApp.swift | 17 - .../Preview Assets.xcassets/Contents.json | 6 - .../PocketLeagueiOSTests.swift | 36 - .../PocketLeagueiOSUITests.swift | 42 -- .../PocketLeagueiOSUITestsLaunchTests.swift | 32 - android-design-system/build.gradle.kts | 1 - app/build.gradle.kts | 29 - .../ui/BracketSeriesOverviewItemTest.kt | 54 -- .../ui/EventOverviewContentTest.kt | 107 --- .../fakes/FakeSeriesOverviewDisplayModel.kt | 14 - .../fakes/FakeTeamOverviewDisplayModel.kt | 11 - .../pocketleague/EventOverviewQuery.graphql | 62 -- .../EventSummaryListQuery.graphql | 27 - .../pocketleague/PageInfo.graphql | 5 - .../pocketleague/PhaseDetailQuery.graphql | 41 -- .../TournamentDetailQuery.graphql | 47 -- .../com/adammcneilly/pocketleague/schema.json | 1 - .../ExcludeFromJacocoGeneratedReport.kt | 14 - .../adammcneilly/pocketleague/MainActivity.kt | 13 +- .../bracket/ui/BracketPhaseContent.kt | 87 --- .../bracket/ui/BracketPhaseDisplayModel.kt | 8 - .../bracket/ui/BracketRoundDisplayModel.kt | 11 - .../bracket/ui/BracketRoundList.kt | 84 --- .../bracket/ui/BracketSeriesOverviewItem.kt | 142 ---- .../SmashGGAuthorizationInterceptor.kt | 22 - .../data/remote/smashgg/SmashGGModelMapper.kt | 158 ----- .../pocketleague/core/di/DataModule.kt | 43 -- .../pocketleague/core/di/RemoteModule.kt | 65 -- .../pocketleague/core/di/UseCaseModule.kt | 59 -- .../pocketleague/core/di/UtilModule.kt | 43 -- .../pocketleague/core/html/HTMLDocument.kt | 15 - .../pocketleague/core/html/HTMLElement.kt | 36 - .../pocketleague/core/html/HTMLParser.kt | 20 - .../core/html/JSoupHTMLDocument.kt | 25 - .../core/html/JSoupHTMLElement.kt | 38 -- .../pocketleague/core/html/JSoupHTMLParser.kt | 20 - .../core/ui/FlagKitFlagResProvider.kt | 16 - .../pocketleague/core/ui/FlagResProvider.kt | 12 - .../pocketleague/core/ui/Material3Card.kt | 22 - .../ui/Material3CircularProgressIndicator.kt | 41 -- .../pocketleague/core/ui/Material3Divider.kt | 21 - .../pocketleague/core/ui/PocketLeagueImage.kt | 39 -- .../pocketleague/core/ui/TextCard.kt | 60 -- .../pocketleague/core/ui/WindowSize.kt | 63 -- .../pocketleague/core/utils/DateTimeHelper.kt | 18 - .../pocketleague/core/utils/DateUtils.kt | 28 - .../pocketleague/event/ui/EventContent.kt | 33 - .../pocketleague/event/ui/EventScreen.kt | 23 - .../pocketleague/event/ui/EventViewModel.kt | 16 - .../pocketleague/event/ui/EventViewState.kt | 14 - .../eventoverview/ui/EventOverviewContent.kt | 232 ------- .../eventoverview/ui/EventOverviewHeader.kt | 38 -- .../eventoverview/ui/EventOverviewNavArgs.kt | 8 - .../eventoverview/ui/EventOverviewScreen.kt | 45 -- .../ui/EventOverviewViewModel.kt | 56 -- .../eventsummary/ui/EventSummaryList.kt | 89 --- .../ui/EventSummaryListContent.kt | 46 -- .../eventsummary/ui/EventSummaryListItem.kt | 147 ----- .../eventsummary/ui/EventSummaryListScreen.kt | 45 -- .../ui/EventSummaryListViewModel.kt | 62 -- .../gameresult/ui/GameResultDisplayModel.kt | 23 - .../gameresult/ui/GameResultList.kt | 88 --- .../gameresult/ui/GameResultListItem.kt | 105 --- .../phase/ui/PhaseDetailContent.kt | 24 - .../phase/ui/PhaseDetailNavArgs.kt | 8 - .../phase/ui/PhaseDetailScreen.kt | 26 - .../phase/ui/PhaseDetailViewModel.kt | 35 - .../pocketleague/phase/ui/PhaseList.kt | 74 --- .../pocketleague/phase/ui/PhaseListItem.kt | 111 ---- .../player/ui/PlayerDisplayModel.kt | 36 - .../pocketleague/player/ui/PlayerList.kt | 100 --- .../pocketleague/player/ui/PlayerListItem.kt | 133 ---- .../player/ui/PlayerOverviewDisplayModel.kt | 8 - .../seriesdetail/ui/SeriesDetailContent.kt | 140 ---- .../ui/SeriesDetailDisplayModel.kt | 29 - .../domain/models/SeriesOverview.kt | 13 - .../ui/SeriesOverviewDisplayModel.kt | 35 - .../standings/ui/StandingsList.kt | 63 -- .../ui/StandingsPlacementListItem.kt | 138 ---- .../swiss/domain/models/SwissRound.kt | 14 - .../swiss/domain/models/SwissStage.kt | 10 - .../swiss/ui/SwissRoundDisplayModel.kt | 25 - .../pocketleague/swiss/ui/SwissRoundList.kt | 122 ---- .../swiss/ui/SwissSeriesOverviewItem.kt | 196 ------ .../swiss/ui/SwissStageDisplayModel.kt | 21 - .../teamdetail/ui/TeamDetailContent.kt | 130 ---- .../teamdetail/ui/TeamDetailDisplayModel.kt | 33 - .../teamlist/data/TeamListService.kt | 25 - .../domain/models/FetchTeamListResult.kt | 18 - .../domain/usecases/FetchAllTeamsUseCase.kt | 13 - .../usecases/FetchAllTeamsUseCaseImpl.kt | 27 - .../teamlist/ui/TeamListContent.kt | 30 - .../teamlist/ui/TeamListScreen.kt | 23 - .../teamlist/ui/TeamListViewModel.kt | 59 -- .../teamlist/ui/TeamListViewState.kt | 13 - .../ui/TeamOverviewDisplayModel.kt | 45 -- .../teamoverview/ui/TeamOverviewList.kt | 28 - .../teamoverview/ui/TeamOverviewListItem.kt | 98 --- .../ui/ToggleableTeamOverviewListItem.kt | 30 - .../core/ui/FakeFlagResProvider.kt | 16 - .../pocketleague/core/utils/DateUtilsTest.kt | 22 - .../core/utils/FakeDateTimeHelper.kt | 24 - .../player/ui/PlayerDisplayModelTest.kt | 58 -- .../ui/TeamDetailDisplayModelTest.kt | 42 -- .../teamlist/data/FakeTeamListService.kt | 18 - .../usecases/FetchAllTeamsUseCaseImplTest.kt | 45 -- core-data/README.md | 3 - core-data/build.gradle.kts | 56 -- core-data/src/androidMain/AndroidManifest.xml | 2 - .../pocketleague/core/data/DataResult.kt | 21 - core-datetime/build.gradle.kts | 66 -- .../src/androidMain/AndroidManifest.xml | 2 - .../core/datetime/DateTimeFormatter.kt | 23 - .../core/datetime/DateTimeFormatter.kt | 19 - .../core/datetime/DateTimeParser.kt | 26 - .../core/datetime/DateTimeFormatter.kt | 31 - core-models/README.md | 3 - core-models/build.gradle.kts | 60 -- .../src/androidMain/AndroidManifest.xml | 2 - .../pocketleague/core/models/BracketType.kt | 11 - .../pocketleague/core/models/EventOverview.kt | 15 - .../pocketleague/core/models/EventSet.kt | 13 - .../pocketleague/core/models/EventSummary.kt | 29 - .../pocketleague/core/models/Game.kt | 12 - .../pocketleague/core/models/PhaseDetail.kt | 16 - .../pocketleague/core/models/PhaseOverview.kt | 15 - .../pocketleague/core/models/Player.kt | 11 - .../pocketleague/core/models/SetSlot.kt | 9 - .../pocketleague/core/models/Standings.kt | 8 - .../core/models/StandingsPlacement.kt | 9 - .../pocketleague/core/models/Team.kt | 11 - event-api/README.md | 3 - event-api/build.gradle.kts | 62 -- event-api/src/androidMain/AndroidManifest.xml | 2 - .../pocketleague/event/api/EventRepository.kt | 23 - event-implementation/README.md | 3 - event-implementation/build.gradle.kts | 96 --- .../src/androidMain/AndroidManifest.xml | 2 - .../graphql/EventOverviewQuery.graphql | 62 -- .../graphql/EventSummaryListQuery.graphql | 33 - .../graphql/PhaseDetailQuery.graphql | 45 -- .../src/commonMain/graphql/schema.json | 1 - .../octanegg/OctaneGGEventService.kt | 46 -- .../smashgg/SmashGGApolloClient.kt | 11 - .../SmashGGAuthorizationInterceptor.kt | 27 - .../smashgg/SmashGGEventService.kt | 67 -- .../smashgg/mappers/BracketTypeMapper.kt | 17 - .../smashgg/mappers/EventEntrantMapper.kt | 19 - .../smashgg/mappers/EventOverviewMapper.kt | 37 -- .../smashgg/mappers/EventPlayerMapper.kt | 15 - .../smashgg/mappers/EventSummaryMapper.kt | 28 - .../smashgg/mappers/PhaseGroupMapper.kt | 23 - .../mappers/StandingsPlacementMapper.kt | 16 - feature-eventsummarylist/build.gradle.kts | 64 -- .../src/androidMain/AndroidManifest.xml | 2 - .../eventsummarylist/EventSummaryListSort.kt | 17 - .../domain/GetEventSummariesUseCase.kt | 42 -- .../domain/GetEventSummariesUseCaseImpl.kt | 31 - .../state/EventSummaryListAction.kt | 36 - .../state/EventSummaryListStateMutator.kt | 148 ----- .../state/EventSummaryListViewState.kt | 15 - .../ui/EventSummaryListItemDisplayModel.kt | 18 - settings.gradle | 11 +- shared/build.gradle.kts | 93 --- shared/src/androidMain/AndroidManifest.xml | 2 - .../graphql/EventOverviewQuery.graphql | 62 -- .../graphql/EventSummaryListQuery.graphql | 33 - .../graphql/PhaseDetailQuery.graphql | 45 -- shared/src/commonMain/graphql/schema.json | 1 - .../pocketleague/shared/core/ui/UIImage.kt | 17 - .../pocketleague/shared/core/ui/UIText.kt | 16 - .../pocketleague/shared/data/Result.kt | 21 - .../shared/data/event/EventListRequestBody.kt | 14 - .../shared/data/event/EventRepository.kt | 26 - .../remote/smashgg/SmashGGEventService.kt | 165 ----- .../shared/data/phase/PhaseRepository.kt | 15 - .../remote/smashgg/SmashGGPhaseService.kt | 85 --- .../shared/data/smashgg/SmashGGAPI.kt | 11 - .../SmashGGAuthorizationInterceptor.kt | 27 - .../data/smashgg/mappers/BracketTypeMapper.kt | 17 - .../smashgg/mappers/EventEntrantMapper.kt | 19 - .../data/smashgg/mappers/EventPlayerMapper.kt | 15 - .../domain/GetEventOverviewUseCase.kt | 31 - .../domain/GetEventOverviewUseCaseImpl.kt | 28 - .../state/EventOverviewAction.kt | 25 - .../state/EventOverviewStateMutator.kt | 164 ----- .../state/EventOverviewViewState.kt | 14 - .../ui/EventOverviewDisplayModel.kt | 19 - .../ui/EventOverviewPhaseDisplayModel.kt | 14 - .../domain/GetPhaseDetailUseCase.kt | 35 - .../domain/GetPhaseDetailUseCaseImpl.kt | 32 - .../phasedetail/state/PhaseDetailAction.kt | 13 - .../state/PhaseDetailStateMutator.kt | 88 --- .../phasedetail/state/PhaseDetailViewState.kt | 13 - .../phasedetail/ui/PhaseDetailDisplayModel.kt | 8 - .../shared/standings/StandingsDisplayModel.kt | 8 - .../StandingsPlacementDisplayModel.kt | 13 - team-api/build.gradle.kts | 62 -- team-api/src/androidMain/AndroidManifest.xml | 2 - .../pocketleague/team/api/TeamRepository.kt | 17 - team-implementation/build.gradle.kts | 66 -- .../src/androidMain/AndroidManifest.xml | 2 - .../octanegg/OctaneGGAPIClient.kt | 46 -- .../octanegg/OctaneGGTeamService.kt | 38 -- .../octanegg/dtos/AccountDTO.kt | 15 - .../implementation/octanegg/dtos/PlayerDTO.kt | 31 - .../implementation/octanegg/dtos/TeamDTO.kt | 15 - .../octanegg/dtos/TeamListResponseDTO.kt | 19 - .../octanegg/dtos/TeamOverviewDTO.kt | 23 - .../octanegg/mappers/PlayerMapper.kt | 15 - .../octanegg/mappers/TeamMapper.kt | 17 - 222 files changed, 4 insertions(+), 8921 deletions(-) delete mode 100644 PocketLeagueiOS/PocketLeagueiOS.xcodeproj/project.pbxproj delete mode 100644 PocketLeagueiOS/PocketLeagueiOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 PocketLeagueiOS/PocketLeagueiOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 PocketLeagueiOS/PocketLeagueiOS.xcodeproj/xcuserdata/amcneilly.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 PocketLeagueiOS/PocketLeagueiOS/Assets.xcassets/AccentColor.colorset/Contents.json delete mode 100644 PocketLeagueiOS/PocketLeagueiOS/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 PocketLeagueiOS/PocketLeagueiOS/Assets.xcassets/Contents.json delete mode 100644 PocketLeagueiOS/PocketLeagueiOS/ContentView.swift delete mode 100644 PocketLeagueiOS/PocketLeagueiOS/EventSummaryDisplayModel.swift delete mode 100644 PocketLeagueiOS/PocketLeagueiOS/EventSummaryListItem.swift delete mode 100644 PocketLeagueiOS/PocketLeagueiOS/PocketLeagueiOSApp.swift delete mode 100644 PocketLeagueiOS/PocketLeagueiOS/Preview Content/Preview Assets.xcassets/Contents.json delete mode 100644 PocketLeagueiOS/PocketLeagueiOSTests/PocketLeagueiOSTests.swift delete mode 100644 PocketLeagueiOS/PocketLeagueiOSUITests/PocketLeagueiOSUITests.swift delete mode 100644 PocketLeagueiOS/PocketLeagueiOSUITests/PocketLeagueiOSUITestsLaunchTests.swift delete mode 100644 app/src/androidTest/java/com/adammcneilly/pocketleague/bracket/ui/BracketSeriesOverviewItemTest.kt delete mode 100644 app/src/androidTest/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewContentTest.kt delete mode 100644 app/src/androidTest/java/com/adammcneilly/pocketleague/fakes/FakeSeriesOverviewDisplayModel.kt delete mode 100644 app/src/androidTest/java/com/adammcneilly/pocketleague/fakes/FakeTeamOverviewDisplayModel.kt delete mode 100644 app/src/main/graphql/com/adammcneilly/pocketleague/EventOverviewQuery.graphql delete mode 100644 app/src/main/graphql/com/adammcneilly/pocketleague/EventSummaryListQuery.graphql delete mode 100644 app/src/main/graphql/com/adammcneilly/pocketleague/PageInfo.graphql delete mode 100644 app/src/main/graphql/com/adammcneilly/pocketleague/PhaseDetailQuery.graphql delete mode 100644 app/src/main/graphql/com/adammcneilly/pocketleague/TournamentDetailQuery.graphql delete mode 100644 app/src/main/graphql/com/adammcneilly/pocketleague/schema.json delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ExcludeFromJacocoGeneratedReport.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketPhaseContent.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketPhaseDisplayModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketRoundDisplayModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketRoundList.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketSeriesOverviewItem.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/data/remote/smashgg/SmashGGAuthorizationInterceptor.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/data/remote/smashgg/SmashGGModelMapper.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/di/DataModule.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/di/RemoteModule.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/di/UseCaseModule.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/di/UtilModule.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/html/HTMLDocument.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/html/HTMLElement.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/html/HTMLParser.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/html/JSoupHTMLDocument.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/html/JSoupHTMLElement.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/html/JSoupHTMLParser.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/ui/FlagKitFlagResProvider.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/ui/FlagResProvider.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/ui/Material3Card.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/ui/Material3CircularProgressIndicator.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/ui/Material3Divider.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/ui/PocketLeagueImage.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/ui/TextCard.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/ui/WindowSize.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/utils/DateTimeHelper.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/core/utils/DateUtils.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventContent.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventScreen.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventViewModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventViewState.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewContent.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewHeader.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewNavArgs.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewScreen.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewViewModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryList.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListContent.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListItem.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListScreen.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListViewModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/gameresult/ui/GameResultDisplayModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/gameresult/ui/GameResultList.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/gameresult/ui/GameResultListItem.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailContent.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailNavArgs.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailScreen.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailViewModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseList.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseListItem.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerDisplayModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerList.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerListItem.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerOverviewDisplayModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/seriesdetail/ui/SeriesDetailContent.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/seriesdetail/ui/SeriesDetailDisplayModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/seriesoverview/domain/models/SeriesOverview.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/seriesoverview/ui/SeriesOverviewDisplayModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/standings/ui/StandingsList.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/standings/ui/StandingsPlacementListItem.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/swiss/domain/models/SwissRound.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/swiss/domain/models/SwissStage.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissRoundDisplayModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissRoundList.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissSeriesOverviewItem.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissStageDisplayModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/teamdetail/ui/TeamDetailContent.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/teamdetail/ui/TeamDetailDisplayModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/teamlist/data/TeamListService.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/teamlist/domain/models/FetchTeamListResult.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/teamlist/domain/usecases/FetchAllTeamsUseCase.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/teamlist/domain/usecases/FetchAllTeamsUseCaseImpl.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListContent.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListScreen.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListViewModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListViewState.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/TeamOverviewDisplayModel.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/TeamOverviewList.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/TeamOverviewListItem.kt delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/ToggleableTeamOverviewListItem.kt delete mode 100644 app/src/test/java/com/adammcneilly/pocketleague/core/ui/FakeFlagResProvider.kt delete mode 100644 app/src/test/java/com/adammcneilly/pocketleague/core/utils/DateUtilsTest.kt delete mode 100644 app/src/test/java/com/adammcneilly/pocketleague/core/utils/FakeDateTimeHelper.kt delete mode 100644 app/src/test/java/com/adammcneilly/pocketleague/player/ui/PlayerDisplayModelTest.kt delete mode 100644 app/src/test/java/com/adammcneilly/pocketleague/teamdetail/ui/TeamDetailDisplayModelTest.kt delete mode 100644 app/src/test/java/com/adammcneilly/pocketleague/teamlist/data/FakeTeamListService.kt delete mode 100644 app/src/test/java/com/adammcneilly/pocketleague/teamlist/domain/usecases/FetchAllTeamsUseCaseImplTest.kt delete mode 100644 core-data/README.md delete mode 100644 core-data/build.gradle.kts delete mode 100644 core-data/src/androidMain/AndroidManifest.xml delete mode 100644 core-data/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/data/DataResult.kt delete mode 100644 core-datetime/build.gradle.kts delete mode 100644 core-datetime/src/androidMain/AndroidManifest.xml delete mode 100644 core-datetime/src/androidMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeFormatter.kt delete mode 100644 core-datetime/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeFormatter.kt delete mode 100644 core-datetime/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeParser.kt delete mode 100644 core-datetime/src/iosMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeFormatter.kt delete mode 100644 core-models/README.md delete mode 100644 core-models/build.gradle.kts delete mode 100644 core-models/src/androidMain/AndroidManifest.xml delete mode 100644 core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/BracketType.kt delete mode 100644 core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/EventOverview.kt delete mode 100644 core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/EventSet.kt delete mode 100644 core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/EventSummary.kt delete mode 100644 core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Game.kt delete mode 100644 core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/PhaseDetail.kt delete mode 100644 core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/PhaseOverview.kt delete mode 100644 core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Player.kt delete mode 100644 core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/SetSlot.kt delete mode 100644 core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Standings.kt delete mode 100644 core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/StandingsPlacement.kt delete mode 100644 core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Team.kt delete mode 100644 event-api/README.md delete mode 100644 event-api/build.gradle.kts delete mode 100644 event-api/src/androidMain/AndroidManifest.xml delete mode 100644 event-api/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/api/EventRepository.kt delete mode 100644 event-implementation/README.md delete mode 100644 event-implementation/build.gradle.kts delete mode 100644 event-implementation/src/androidMain/AndroidManifest.xml delete mode 100644 event-implementation/src/commonMain/graphql/EventOverviewQuery.graphql delete mode 100644 event-implementation/src/commonMain/graphql/EventSummaryListQuery.graphql delete mode 100644 event-implementation/src/commonMain/graphql/PhaseDetailQuery.graphql delete mode 100644 event-implementation/src/commonMain/graphql/schema.json delete mode 100644 event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/octanegg/OctaneGGEventService.kt delete mode 100644 event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/SmashGGApolloClient.kt delete mode 100644 event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/SmashGGAuthorizationInterceptor.kt delete mode 100644 event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/SmashGGEventService.kt delete mode 100644 event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/BracketTypeMapper.kt delete mode 100644 event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventEntrantMapper.kt delete mode 100644 event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventOverviewMapper.kt delete mode 100644 event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventPlayerMapper.kt delete mode 100644 event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventSummaryMapper.kt delete mode 100644 event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/PhaseGroupMapper.kt delete mode 100644 event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/StandingsPlacementMapper.kt delete mode 100644 feature-eventsummarylist/build.gradle.kts delete mode 100644 feature-eventsummarylist/src/androidMain/AndroidManifest.xml delete mode 100644 feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/EventSummaryListSort.kt delete mode 100644 feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/domain/GetEventSummariesUseCase.kt delete mode 100644 feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/domain/GetEventSummariesUseCaseImpl.kt delete mode 100644 feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/state/EventSummaryListAction.kt delete mode 100644 feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/state/EventSummaryListStateMutator.kt delete mode 100644 feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/state/EventSummaryListViewState.kt delete mode 100644 feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/ui/EventSummaryListItemDisplayModel.kt delete mode 100644 shared/build.gradle.kts delete mode 100644 shared/src/androidMain/AndroidManifest.xml delete mode 100644 shared/src/commonMain/graphql/EventOverviewQuery.graphql delete mode 100644 shared/src/commonMain/graphql/EventSummaryListQuery.graphql delete mode 100644 shared/src/commonMain/graphql/PhaseDetailQuery.graphql delete mode 100644 shared/src/commonMain/graphql/schema.json delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/core/ui/UIImage.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/core/ui/UIText.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Result.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/event/EventListRequestBody.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/event/EventRepository.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/event/remote/smashgg/SmashGGEventService.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/phase/PhaseRepository.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/phase/remote/smashgg/SmashGGPhaseService.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/SmashGGAPI.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/SmashGGAuthorizationInterceptor.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/mappers/BracketTypeMapper.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/mappers/EventEntrantMapper.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/mappers/EventPlayerMapper.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/domain/GetEventOverviewUseCase.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/domain/GetEventOverviewUseCaseImpl.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/state/EventOverviewAction.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/state/EventOverviewStateMutator.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/state/EventOverviewViewState.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/ui/EventOverviewDisplayModel.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/ui/EventOverviewPhaseDisplayModel.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/domain/GetPhaseDetailUseCase.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/domain/GetPhaseDetailUseCaseImpl.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/state/PhaseDetailAction.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/state/PhaseDetailStateMutator.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/state/PhaseDetailViewState.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/ui/PhaseDetailDisplayModel.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/standings/StandingsDisplayModel.kt delete mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/standings/StandingsPlacementDisplayModel.kt delete mode 100644 team-api/build.gradle.kts delete mode 100644 team-api/src/androidMain/AndroidManifest.xml delete mode 100644 team-api/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/api/TeamRepository.kt delete mode 100644 team-implementation/build.gradle.kts delete mode 100644 team-implementation/src/androidMain/AndroidManifest.xml delete mode 100644 team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/OctaneGGAPIClient.kt delete mode 100644 team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/OctaneGGTeamService.kt delete mode 100644 team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/AccountDTO.kt delete mode 100644 team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/PlayerDTO.kt delete mode 100644 team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/TeamDTO.kt delete mode 100644 team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/TeamListResponseDTO.kt delete mode 100644 team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/TeamOverviewDTO.kt delete mode 100644 team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/mappers/PlayerMapper.kt delete mode 100644 team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/mappers/TeamMapper.kt diff --git a/.gitignore b/.gitignore index f9433175f..730942f7f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,16 +8,6 @@ .externalNativeBuild .cxx local.properties -/app/src/main/graphql/com/adammcneilly/pocketleague/.graphqlconfig -/shared/build/ -/core-models/build/ -/core-data/build/ -/core-datetime/build/ -/event-api/build/ -/event-implementation/build/ -/feature-eventsummarylist/build/ -/team-api/build/ -/team-implementation/build/ -/octanegg/build/ /buildSrc/build/ -PocketLeagueiOS/PocketLeagueiOS.xcodeproj/project.xcworkspace/xcuserdata/amcneilly.xcuserdatad/UserInterfaceState.xcuserstate +/octanegg/build/ +/app/src/main/graphql/com/adammcneilly/pocketleague/.graphqlconfig diff --git a/PocketLeagueiOS/PocketLeagueiOS.xcodeproj/project.pbxproj b/PocketLeagueiOS/PocketLeagueiOS.xcodeproj/project.pbxproj deleted file mode 100644 index b7595e59a..000000000 --- a/PocketLeagueiOS/PocketLeagueiOS.xcodeproj/project.pbxproj +++ /dev/null @@ -1,624 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 55; - objects = { - -/* Begin PBXBuildFile section */ - DD3C9B7527B8403F00AAEA7A /* PocketLeagueiOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3C9B7427B8403F00AAEA7A /* PocketLeagueiOSApp.swift */; }; - DD3C9B7727B8403F00AAEA7A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3C9B7627B8403F00AAEA7A /* ContentView.swift */; }; - DD3C9B7927B8404200AAEA7A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DD3C9B7827B8404200AAEA7A /* Assets.xcassets */; }; - DD3C9B7C27B8404200AAEA7A /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DD3C9B7B27B8404200AAEA7A /* Preview Assets.xcassets */; }; - DD3C9B8627B8404200AAEA7A /* PocketLeagueiOSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3C9B8527B8404200AAEA7A /* PocketLeagueiOSTests.swift */; }; - DD3C9B9027B8404200AAEA7A /* PocketLeagueiOSUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3C9B8F27B8404200AAEA7A /* PocketLeagueiOSUITests.swift */; }; - DD3C9B9227B8404200AAEA7A /* PocketLeagueiOSUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3C9B9127B8404200AAEA7A /* PocketLeagueiOSUITestsLaunchTests.swift */; }; - DD3C9BA027B84D1800AAEA7A /* EventSummaryListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3C9B9F27B84D1800AAEA7A /* EventSummaryListItem.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - DD3C9B8227B8404200AAEA7A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = DD3C9B6927B8403F00AAEA7A /* Project object */; - proxyType = 1; - remoteGlobalIDString = DD3C9B7027B8403F00AAEA7A; - remoteInfo = PocketLeagueiOS; - }; - DD3C9B8C27B8404200AAEA7A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = DD3C9B6927B8403F00AAEA7A /* Project object */; - proxyType = 1; - remoteGlobalIDString = DD3C9B7027B8403F00AAEA7A; - remoteInfo = PocketLeagueiOS; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - DD3C9B7127B8403F00AAEA7A /* PocketLeagueiOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PocketLeagueiOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; - DD3C9B7427B8403F00AAEA7A /* PocketLeagueiOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PocketLeagueiOSApp.swift; sourceTree = ""; }; - DD3C9B7627B8403F00AAEA7A /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; - DD3C9B7827B8404200AAEA7A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - DD3C9B7B27B8404200AAEA7A /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; - DD3C9B8127B8404200AAEA7A /* PocketLeagueiOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PocketLeagueiOSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - DD3C9B8527B8404200AAEA7A /* PocketLeagueiOSTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PocketLeagueiOSTests.swift; sourceTree = ""; }; - DD3C9B8B27B8404200AAEA7A /* PocketLeagueiOSUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PocketLeagueiOSUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - DD3C9B8F27B8404200AAEA7A /* PocketLeagueiOSUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PocketLeagueiOSUITests.swift; sourceTree = ""; }; - DD3C9B9127B8404200AAEA7A /* PocketLeagueiOSUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PocketLeagueiOSUITestsLaunchTests.swift; sourceTree = ""; }; - DD3C9B9F27B84D1800AAEA7A /* EventSummaryListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventSummaryListItem.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - DD3C9B6E27B8403F00AAEA7A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - DD3C9B7E27B8404200AAEA7A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - DD3C9B8827B8404200AAEA7A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - DD3C9B6827B8403F00AAEA7A = { - isa = PBXGroup; - children = ( - DD3C9B7327B8403F00AAEA7A /* PocketLeagueiOS */, - DD3C9B8427B8404200AAEA7A /* PocketLeagueiOSTests */, - DD3C9B8E27B8404200AAEA7A /* PocketLeagueiOSUITests */, - DD3C9B7227B8403F00AAEA7A /* Products */, - ); - sourceTree = ""; - }; - DD3C9B7227B8403F00AAEA7A /* Products */ = { - isa = PBXGroup; - children = ( - DD3C9B7127B8403F00AAEA7A /* PocketLeagueiOS.app */, - DD3C9B8127B8404200AAEA7A /* PocketLeagueiOSTests.xctest */, - DD3C9B8B27B8404200AAEA7A /* PocketLeagueiOSUITests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - DD3C9B7327B8403F00AAEA7A /* PocketLeagueiOS */ = { - isa = PBXGroup; - children = ( - DD3C9B7427B8403F00AAEA7A /* PocketLeagueiOSApp.swift */, - DD3C9B7627B8403F00AAEA7A /* ContentView.swift */, - DD3C9B7827B8404200AAEA7A /* Assets.xcassets */, - DD3C9B7A27B8404200AAEA7A /* Preview Content */, - DD3C9B9F27B84D1800AAEA7A /* EventSummaryListItem.swift */, - ); - path = PocketLeagueiOS; - sourceTree = ""; - }; - DD3C9B7A27B8404200AAEA7A /* Preview Content */ = { - isa = PBXGroup; - children = ( - DD3C9B7B27B8404200AAEA7A /* Preview Assets.xcassets */, - ); - path = "Preview Content"; - sourceTree = ""; - }; - DD3C9B8427B8404200AAEA7A /* PocketLeagueiOSTests */ = { - isa = PBXGroup; - children = ( - DD3C9B8527B8404200AAEA7A /* PocketLeagueiOSTests.swift */, - ); - path = PocketLeagueiOSTests; - sourceTree = ""; - }; - DD3C9B8E27B8404200AAEA7A /* PocketLeagueiOSUITests */ = { - isa = PBXGroup; - children = ( - DD3C9B8F27B8404200AAEA7A /* PocketLeagueiOSUITests.swift */, - DD3C9B9127B8404200AAEA7A /* PocketLeagueiOSUITestsLaunchTests.swift */, - ); - path = PocketLeagueiOSUITests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - DD3C9B7027B8403F00AAEA7A /* PocketLeagueiOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = DD3C9B9527B8404200AAEA7A /* Build configuration list for PBXNativeTarget "PocketLeagueiOS" */; - buildPhases = ( - DD3C9B9E27B8405800AAEA7A /* Run Script */, - DD3C9B6D27B8403F00AAEA7A /* Sources */, - DD3C9B6E27B8403F00AAEA7A /* Frameworks */, - DD3C9B6F27B8403F00AAEA7A /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = PocketLeagueiOS; - productName = PocketLeagueiOS; - productReference = DD3C9B7127B8403F00AAEA7A /* PocketLeagueiOS.app */; - productType = "com.apple.product-type.application"; - }; - DD3C9B8027B8404200AAEA7A /* PocketLeagueiOSTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = DD3C9B9827B8404200AAEA7A /* Build configuration list for PBXNativeTarget "PocketLeagueiOSTests" */; - buildPhases = ( - DD3C9B7D27B8404200AAEA7A /* Sources */, - DD3C9B7E27B8404200AAEA7A /* Frameworks */, - DD3C9B7F27B8404200AAEA7A /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - DD3C9B8327B8404200AAEA7A /* PBXTargetDependency */, - ); - name = PocketLeagueiOSTests; - productName = PocketLeagueiOSTests; - productReference = DD3C9B8127B8404200AAEA7A /* PocketLeagueiOSTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - DD3C9B8A27B8404200AAEA7A /* PocketLeagueiOSUITests */ = { - isa = PBXNativeTarget; - buildConfigurationList = DD3C9B9B27B8404200AAEA7A /* Build configuration list for PBXNativeTarget "PocketLeagueiOSUITests" */; - buildPhases = ( - DD3C9B8727B8404200AAEA7A /* Sources */, - DD3C9B8827B8404200AAEA7A /* Frameworks */, - DD3C9B8927B8404200AAEA7A /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - DD3C9B8D27B8404200AAEA7A /* PBXTargetDependency */, - ); - name = PocketLeagueiOSUITests; - productName = PocketLeagueiOSUITests; - productReference = DD3C9B8B27B8404200AAEA7A /* PocketLeagueiOSUITests.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - DD3C9B6927B8403F00AAEA7A /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1320; - LastUpgradeCheck = 1320; - TargetAttributes = { - DD3C9B7027B8403F00AAEA7A = { - CreatedOnToolsVersion = 13.2.1; - }; - DD3C9B8027B8404200AAEA7A = { - CreatedOnToolsVersion = 13.2.1; - TestTargetID = DD3C9B7027B8403F00AAEA7A; - }; - DD3C9B8A27B8404200AAEA7A = { - CreatedOnToolsVersion = 13.2.1; - TestTargetID = DD3C9B7027B8403F00AAEA7A; - }; - }; - }; - buildConfigurationList = DD3C9B6C27B8403F00AAEA7A /* Build configuration list for PBXProject "PocketLeagueiOS" */; - compatibilityVersion = "Xcode 13.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = DD3C9B6827B8403F00AAEA7A; - productRefGroup = DD3C9B7227B8403F00AAEA7A /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - DD3C9B7027B8403F00AAEA7A /* PocketLeagueiOS */, - DD3C9B8027B8404200AAEA7A /* PocketLeagueiOSTests */, - DD3C9B8A27B8404200AAEA7A /* PocketLeagueiOSUITests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - DD3C9B6F27B8403F00AAEA7A /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DD3C9B7C27B8404200AAEA7A /* Preview Assets.xcassets in Resources */, - DD3C9B7927B8404200AAEA7A /* Assets.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - DD3C9B7F27B8404200AAEA7A /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - DD3C9B8927B8404200AAEA7A /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - DD3C9B9E27B8405800AAEA7A /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "cd \"$SRCROOT/..\"\n./gradlew :eventsummary:embedAndSignAppleFrameworkForXcode :event-implementation:embedAndSignAppleFrameworkForXcode\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - DD3C9B6D27B8403F00AAEA7A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DD3C9B7727B8403F00AAEA7A /* ContentView.swift in Sources */, - DD3C9BA027B84D1800AAEA7A /* EventSummaryListItem.swift in Sources */, - DD3C9B7527B8403F00AAEA7A /* PocketLeagueiOSApp.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - DD3C9B7D27B8404200AAEA7A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DD3C9B8627B8404200AAEA7A /* PocketLeagueiOSTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - DD3C9B8727B8404200AAEA7A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DD3C9B9027B8404200AAEA7A /* PocketLeagueiOSUITests.swift in Sources */, - DD3C9B9227B8404200AAEA7A /* PocketLeagueiOSUITestsLaunchTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - DD3C9B8327B8404200AAEA7A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DD3C9B7027B8403F00AAEA7A /* PocketLeagueiOS */; - targetProxy = DD3C9B8227B8404200AAEA7A /* PBXContainerItemProxy */; - }; - DD3C9B8D27B8404200AAEA7A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DD3C9B7027B8403F00AAEA7A /* PocketLeagueiOS */; - targetProxy = DD3C9B8C27B8404200AAEA7A /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - DD3C9B9327B8404200AAEA7A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.2; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - DD3C9B9427B8404200AAEA7A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.2; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - DD3C9B9627B8404200AAEA7A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = "\"PocketLeagueiOS/Preview Content\""; - ENABLE_PREVIEWS = YES; - FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../eventsummary/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)"; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchScreen_Generation = YES; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - LIBRARY_SEARCH_PATHS = ""; - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "$(inherited)", - "-framework", - eventsummary, - ); - PRODUCT_BUNDLE_IDENTIFIER = com.adammcneilly.PocketLeagueiOS; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - DD3C9B9727B8404200AAEA7A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = "\"PocketLeagueiOS/Preview Content\""; - ENABLE_PREVIEWS = YES; - FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../eventsummary/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)"; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchScreen_Generation = YES; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - LIBRARY_SEARCH_PATHS = ""; - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "$(inherited)", - "-framework", - eventsummary, - ); - PRODUCT_BUNDLE_IDENTIFIER = com.adammcneilly.PocketLeagueiOS; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - DD3C9B9927B8404200AAEA7A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.2; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.adammcneilly.PocketLeagueiOSTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PocketLeagueiOS.app/PocketLeagueiOS"; - }; - name = Debug; - }; - DD3C9B9A27B8404200AAEA7A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.2; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.adammcneilly.PocketLeagueiOSTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PocketLeagueiOS.app/PocketLeagueiOS"; - }; - name = Release; - }; - DD3C9B9C27B8404200AAEA7A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.adammcneilly.PocketLeagueiOSUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = PocketLeagueiOS; - }; - name = Debug; - }; - DD3C9B9D27B8404200AAEA7A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.adammcneilly.PocketLeagueiOSUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = PocketLeagueiOS; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - DD3C9B6C27B8403F00AAEA7A /* Build configuration list for PBXProject "PocketLeagueiOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DD3C9B9327B8404200AAEA7A /* Debug */, - DD3C9B9427B8404200AAEA7A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - DD3C9B9527B8404200AAEA7A /* Build configuration list for PBXNativeTarget "PocketLeagueiOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DD3C9B9627B8404200AAEA7A /* Debug */, - DD3C9B9727B8404200AAEA7A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - DD3C9B9827B8404200AAEA7A /* Build configuration list for PBXNativeTarget "PocketLeagueiOSTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DD3C9B9927B8404200AAEA7A /* Debug */, - DD3C9B9A27B8404200AAEA7A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - DD3C9B9B27B8404200AAEA7A /* Build configuration list for PBXNativeTarget "PocketLeagueiOSUITests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DD3C9B9C27B8404200AAEA7A /* Debug */, - DD3C9B9D27B8404200AAEA7A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = DD3C9B6927B8403F00AAEA7A /* Project object */; -} diff --git a/PocketLeagueiOS/PocketLeagueiOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/PocketLeagueiOS/PocketLeagueiOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/PocketLeagueiOS/PocketLeagueiOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/PocketLeagueiOS/PocketLeagueiOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PocketLeagueiOS/PocketLeagueiOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003..000000000 --- a/PocketLeagueiOS/PocketLeagueiOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/PocketLeagueiOS/PocketLeagueiOS.xcodeproj/xcuserdata/amcneilly.xcuserdatad/xcschemes/xcschememanagement.plist b/PocketLeagueiOS/PocketLeagueiOS.xcodeproj/xcuserdata/amcneilly.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 2bea7fdf3..000000000 --- a/PocketLeagueiOS/PocketLeagueiOS.xcodeproj/xcuserdata/amcneilly.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SchemeUserState - - PocketLeagueiOS.xcscheme_^#shared#^_ - - orderHint - 0 - - - - diff --git a/PocketLeagueiOS/PocketLeagueiOS/Assets.xcassets/AccentColor.colorset/Contents.json b/PocketLeagueiOS/PocketLeagueiOS/Assets.xcassets/AccentColor.colorset/Contents.json deleted file mode 100644 index eb8789700..000000000 --- a/PocketLeagueiOS/PocketLeagueiOS/Assets.xcassets/AccentColor.colorset/Contents.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "colors" : [ - { - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/PocketLeagueiOS/PocketLeagueiOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/PocketLeagueiOS/PocketLeagueiOS/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 9221b9bb1..000000000 --- a/PocketLeagueiOS/PocketLeagueiOS/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/PocketLeagueiOS/PocketLeagueiOS/Assets.xcassets/Contents.json b/PocketLeagueiOS/PocketLeagueiOS/Assets.xcassets/Contents.json deleted file mode 100644 index 73c00596a..000000000 --- a/PocketLeagueiOS/PocketLeagueiOS/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/PocketLeagueiOS/PocketLeagueiOS/ContentView.swift b/PocketLeagueiOS/PocketLeagueiOS/ContentView.swift deleted file mode 100644 index 386636e5a..000000000 --- a/PocketLeagueiOS/PocketLeagueiOS/ContentView.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// ContentView.swift -// PocketLeagueiOS -// -// Created by Adam McNeilly on 2/12/22. -// - -import SwiftUI -import eventsummary - -struct ContentView: View { - - @StateObject var viewModel = EventSummaryListviewModel() - - var body: some View { - let displayModels = viewModel.viewState.events.map { - IdentifiableEventSummaryListItemDisplayModel(eventSummary: $0) - } - List(displayModels) { event in - EventSummaryListItem(eventSummary: event.eventSummary) - } - .onAppear { - viewModel.fetchUpcomingEvents() - } - } -} - -struct ContentView_Previews: PreviewProvider { - static var previews: some View { - ContentView() - } -} - -struct IdentifiableEventSummaryListItemDisplayModel : Identifiable { - var id = UUID() - - var eventSummary: eventsummary.EventSummaryListItemDisplayModel -} - -@MainActor -class EventSummaryListviewModel: ObservableObject { - @Published var viewState: EventSummaryListViewState = EventSummaryListViewState(showLoading: false, events: [], selectedEventId: nil, errorMessage: nil) - - func fetchUpcomingEvents() { - let mutator = IOSEventSummaryListStateMutatorKt.iOSEventSummaryListStateMutator(onChange: { newState in - self.viewState = newState - }) - - let action = EventSummaryListAction.FetchUpcomingEvents(leagueSlug: "rlcs-2021-22-1") - - mutator.accept(action) - } -} diff --git a/PocketLeagueiOS/PocketLeagueiOS/EventSummaryDisplayModel.swift b/PocketLeagueiOS/PocketLeagueiOS/EventSummaryDisplayModel.swift deleted file mode 100644 index 7f26a72dc..000000000 --- a/PocketLeagueiOS/PocketLeagueiOS/EventSummaryDisplayModel.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// EventSummaryListItemDisplayModel.swift -// PocketLeagueiOS -// -// Created by Adam McNeilly on 2/12/22. -// - -import Foundation - -struct EventSummaryListItemDisplayModel { - let startDate: String - let tournamentName: String - let eventName: String - let subtitle: String? - - static let example = EventSummaryListItemDisplayModel(startDate: "FEB 18, 2022", tournamentName: "RLCS 2021-22 Season - Winter Split Regional 3 - Oceania", eventName: "Main Event", subtitle: "8 Teams") -} diff --git a/PocketLeagueiOS/PocketLeagueiOS/EventSummaryListItem.swift b/PocketLeagueiOS/PocketLeagueiOS/EventSummaryListItem.swift deleted file mode 100644 index b5185a9c9..000000000 --- a/PocketLeagueiOS/PocketLeagueiOS/EventSummaryListItem.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// EventSummaryListItem.swift -// PocketLeagueiOS -// -// Created by Adam McNeilly on 2/12/22. -// - -import Foundation -import SwiftUI -import eventsummary - -struct EventSummaryListItem: View { - let eventSummary: EventSummaryListItemDisplayModel - - var body: some View { - VStack(alignment: HorizontalAlignment.leading, spacing: 4, content: { - Text(eventSummary.startDate) - .font(.caption) - - Text(eventSummary.tournamentName) - .font(.headline) - - Text(eventSummary.eventName) - .font(.subheadline) - - if let subtitle = eventSummary.subtitle { - Text(subtitle) - .font(.caption) - } - }) - } -} - -struct EventSummaryListItem_Previews: PreviewProvider { - static var previews: some View { - EventSummaryListItem(eventSummary: EventSummaryListItemDisplayModel(eventId: "EventID", startDate: "TODO: start date", tournamentName: "RLCS 2021-22 Season - Winter Split Regional 3 - Europe", eventName: "Main Event", subtitle: "16 Teams", image: nil)) - } -} diff --git a/PocketLeagueiOS/PocketLeagueiOS/PocketLeagueiOSApp.swift b/PocketLeagueiOS/PocketLeagueiOS/PocketLeagueiOSApp.swift deleted file mode 100644 index 8e411708a..000000000 --- a/PocketLeagueiOS/PocketLeagueiOS/PocketLeagueiOSApp.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// PocketLeagueiOSApp.swift -// PocketLeagueiOS -// -// Created by Adam McNeilly on 2/12/22. -// - -import SwiftUI - -@main -struct PocketLeagueiOSApp: App { - var body: some Scene { - WindowGroup { - ContentView() - } - } -} diff --git a/PocketLeagueiOS/PocketLeagueiOS/Preview Content/Preview Assets.xcassets/Contents.json b/PocketLeagueiOS/PocketLeagueiOS/Preview Content/Preview Assets.xcassets/Contents.json deleted file mode 100644 index 73c00596a..000000000 --- a/PocketLeagueiOS/PocketLeagueiOS/Preview Content/Preview Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/PocketLeagueiOS/PocketLeagueiOSTests/PocketLeagueiOSTests.swift b/PocketLeagueiOS/PocketLeagueiOSTests/PocketLeagueiOSTests.swift deleted file mode 100644 index 79add0471..000000000 --- a/PocketLeagueiOS/PocketLeagueiOSTests/PocketLeagueiOSTests.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// PocketLeagueiOSTests.swift -// PocketLeagueiOSTests -// -// Created by Adam McNeilly on 2/12/22. -// - -import XCTest -@testable import PocketLeagueiOS - -class PocketLeagueiOSTests: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - // Any test you write for XCTest can be annotated as throws and async. - // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. - // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. - } - - func testPerformanceExample() throws { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } - } - -} diff --git a/PocketLeagueiOS/PocketLeagueiOSUITests/PocketLeagueiOSUITests.swift b/PocketLeagueiOS/PocketLeagueiOSUITests/PocketLeagueiOSUITests.swift deleted file mode 100644 index 1bd07fc3a..000000000 --- a/PocketLeagueiOS/PocketLeagueiOSUITests/PocketLeagueiOSUITests.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// PocketLeagueiOSUITests.swift -// PocketLeagueiOSUITests -// -// Created by Adam McNeilly on 2/12/22. -// - -import XCTest - -class PocketLeagueiOSUITests: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - - // In UI tests it is usually best to stop immediately when a failure occurs. - continueAfterFailure = false - - // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() throws { - // UI tests must launch the application that they test. - let app = XCUIApplication() - app.launch() - - // Use recording to get started writing UI tests. - // Use XCTAssert and related functions to verify your tests produce the correct results. - } - - func testLaunchPerformance() throws { - if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { - // This measures how long it takes to launch your application. - measure(metrics: [XCTApplicationLaunchMetric()]) { - XCUIApplication().launch() - } - } - } -} diff --git a/PocketLeagueiOS/PocketLeagueiOSUITests/PocketLeagueiOSUITestsLaunchTests.swift b/PocketLeagueiOS/PocketLeagueiOSUITests/PocketLeagueiOSUITestsLaunchTests.swift deleted file mode 100644 index b81d2e823..000000000 --- a/PocketLeagueiOS/PocketLeagueiOSUITests/PocketLeagueiOSUITestsLaunchTests.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// PocketLeagueiOSUITestsLaunchTests.swift -// PocketLeagueiOSUITests -// -// Created by Adam McNeilly on 2/12/22. -// - -import XCTest - -class PocketLeagueiOSUITestsLaunchTests: XCTestCase { - - override class var runsForEachTargetApplicationUIConfiguration: Bool { - true - } - - override func setUpWithError() throws { - continueAfterFailure = false - } - - func testLaunch() throws { - let app = XCUIApplication() - app.launch() - - // Insert steps here to perform after app launch but before taking a screenshot, - // such as logging into a test account or navigating somewhere in the app - - let attachment = XCTAttachment(screenshot: app.screenshot()) - attachment.name = "Launch Screen" - attachment.lifetime = .keepAlways - add(attachment) - } -} diff --git a/android-design-system/build.gradle.kts b/android-design-system/build.gradle.kts index 37ad8ea7d..a90a57124 100644 --- a/android-design-system/build.gradle.kts +++ b/android-design-system/build.gradle.kts @@ -42,7 +42,6 @@ android { dependencies { - implementation(project(":shared")) implementation("androidx.compose.ui:ui:${Versions.compose}") implementation("androidx.compose.material:material:${Versions.compose}") implementation("androidx.compose.material3:material3:${Versions.composeMaterial3}") diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 615aca5bb..3cdee44b3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -6,7 +6,6 @@ plugins { id("kotlin-android") id("kotlin-kapt") id("dagger.hilt.android.plugin") - id("com.apollographql.apollo3").version("3.1.0") id("com.google.devtools.ksp").version("1.6.10-1.0.4") } @@ -85,12 +84,6 @@ android { dependencies { - implementation(project(":core-models")) - implementation(project(":shared")) - implementation(project(":android-design-system")) - implementation(project(":event-api")) - implementation(project(":event-implementation")) - implementation(project(":feature-eventsummarylist")) implementation("androidx.core:core-ktx:${Versions.ktxCore}") implementation("androidx.appcompat:appcompat:${Versions.appCompat}") implementation("com.google.android.material:material:${Versions.material}") @@ -100,29 +93,13 @@ dependencies { implementation("androidx.compose.ui:ui-tooling-preview:${Versions.compose}") implementation("androidx.lifecycle:lifecycle-runtime-ktx:${Versions.lifecycle}") implementation("androidx.activity:activity-compose:${Versions.activityCompose}") - implementation("com.github.murgupluoglu:flagkit-android:1.0.2") implementation("com.google.dagger:hilt-android:${Versions.hilt}") - implementation("androidx.hilt:hilt-navigation-compose:1.0.0") - implementation("io.coil-kt:coil-compose:1.4.0") - implementation("org.jsoup:jsoup:1.14.3") - implementation("com.squareup.retrofit2:retrofit:${Versions.retrofit}") - implementation("com.squareup.retrofit2:converter-moshi:${Versions.retrofit}") - implementation("com.squareup.okhttp3:logging-interceptor:${Versions.okhttp}") - implementation("com.squareup.moshi:moshi-kotlin:${Versions.moshi}") implementation("com.google.accompanist:accompanist-insets-ui:${Versions.accompanist}") implementation("com.google.accompanist:accompanist-systemuicontroller:${Versions.accompanist}") - implementation("com.apollographql.apollo3:apollo-runtime:${Versions.apollo}") - implementation("io.github.raamcosta.compose-destinations:core:${Versions.composeDestinations}") - implementation("androidx.navigation:navigation-compose:${Versions.composeNavigation}") - implementation("com.google.accompanist:accompanist-pager:${Versions.accompanist}") - implementation("com.tunjid.mutator:core:0.0.1") - implementation("com.tunjid.mutator:coroutines:0.0.1") implementation("androidx.window:window:${Versions.windowManager}") - ksp("io.github.raamcosta.compose-destinations:ksp:${Versions.composeDestinations}") kapt("com.google.dagger:hilt-compiler:${Versions.hilt}") testImplementation("junit:junit:${Versions.junit}") testImplementation("com.google.truth:truth:${Versions.truth}") - testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.coroutines}") testImplementation("app.cash.turbine:turbine:${Versions.turbine}") androidTestImplementation("androidx.test.ext:junit:${Versions.androidxTest}") androidTestImplementation("androidx.test.espresso:espresso-core:${Versions.espresso}") @@ -131,9 +108,3 @@ dependencies { debugImplementation("androidx.compose.ui:ui-test-manifest:${Versions.compose}") coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5") } - -apollo { - generateKotlinModels.set(true) - - packageName.set("com.adammcneilly.pocketleague.graphql") -} diff --git a/app/src/androidTest/java/com/adammcneilly/pocketleague/bracket/ui/BracketSeriesOverviewItemTest.kt b/app/src/androidTest/java/com/adammcneilly/pocketleague/bracket/ui/BracketSeriesOverviewItemTest.kt deleted file mode 100644 index 5eb99e3af..000000000 --- a/app/src/androidTest/java/com/adammcneilly/pocketleague/bracket/ui/BracketSeriesOverviewItemTest.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.adammcneilly.pocketleague.bracket.ui - -import androidx.compose.ui.test.assertIsDisplayed -import androidx.compose.ui.test.junit4.createComposeRule -import androidx.compose.ui.test.onNodeWithText -import com.adammcneilly.pocketleague.fakes.fakeSeriesOverviewDisplayModel -import org.junit.Rule -import org.junit.Test - -class BracketSeriesOverviewItemTest { - - @get:Rule - val composeTestRule = createComposeRule() - - @Test - fun renderWithTeamOneWinner() { - val displayModel = fakeSeriesOverviewDisplayModel.copy( - teamOneWins = 1, - teamTwoWins = 0, - ) - - composeTestRule.setContent { - BracketSeriesOverviewItem( - seriesOverview = displayModel, - ) - } - - composeTestRule.onNodeWithText(displayModel.teamOne.name).assertIsDisplayed() - composeTestRule.onNodeWithText(displayModel.teamOneWins.toString()).assertIsDisplayed() - - composeTestRule.onNodeWithText(displayModel.teamTwo.name).assertIsDisplayed() - composeTestRule.onNodeWithText(displayModel.teamTwoWins.toString()).assertIsDisplayed() - } - - @Test - fun renderWithTeamTwoWinner() { - val displayModel = fakeSeriesOverviewDisplayModel.copy( - teamOneWins = 0, - teamTwoWins = 1, - ) - - composeTestRule.setContent { - BracketSeriesOverviewItem( - seriesOverview = displayModel, - ) - } - - composeTestRule.onNodeWithText(displayModel.teamOne.name).assertIsDisplayed() - composeTestRule.onNodeWithText(displayModel.teamOneWins.toString()).assertIsDisplayed() - - composeTestRule.onNodeWithText(displayModel.teamTwo.name).assertIsDisplayed() - composeTestRule.onNodeWithText(displayModel.teamTwoWins.toString()).assertIsDisplayed() - } -} diff --git a/app/src/androidTest/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewContentTest.kt b/app/src/androidTest/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewContentTest.kt deleted file mode 100644 index 8e3e2105f..000000000 --- a/app/src/androidTest/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewContentTest.kt +++ /dev/null @@ -1,107 +0,0 @@ -package com.adammcneilly.pocketleague.eventoverview.ui - -import androidx.activity.ComponentActivity -import androidx.compose.ui.semantics.ProgressBarRangeInfo -import androidx.compose.ui.test.assertIsDisplayed -import androidx.compose.ui.test.hasProgressBarRangeInfo -import androidx.compose.ui.test.junit4.createAndroidComposeRule -import androidx.compose.ui.test.onNodeWithText -import com.adammcneilly.pocketleague.R -import com.adammcneilly.pocketleague.shared.core.ui.UIText -import com.adammcneilly.pocketleague.shared.eventoverview.state.EventOverviewViewState -import com.adammcneilly.pocketleague.shared.eventoverview.ui.EventOverviewDisplayModel -import com.adammcneilly.pocketleague.shared.standings.StandingsDisplayModel -import org.junit.Rule -import org.junit.Test - -class EventOverviewContentTest { - - @get:Rule - val composeTestRule = createAndroidComposeRule() - - @Test - fun renderLoadingState() { - val viewState = EventOverviewViewState( - showLoading = true, - ) - - composeTestRule.setContent { - EventOverviewContent( - viewState = viewState, - onPhaseClicked = {}, - ) - } - - composeTestRule - .onNode(hasProgressBarRangeInfo(ProgressBarRangeInfo.Indeterminate)) - .assertIsDisplayed() - } - - @Test - fun renderErrorMessage() { - val errorMessage = "Whoops" - - val viewState = EventOverviewViewState( - showLoading = false, - errorMessage = UIText.StringText(errorMessage), - ) - - composeTestRule.setContent { - EventOverviewContent( - viewState = viewState, - onPhaseClicked = {}, - ) - } - - composeTestRule - .onNodeWithText(errorMessage) - .assertIsDisplayed() - } - - @Test - fun renderEmptyStates() { - val eventName = "Open Qualifier" - val startDate = "Feb 11, 2022" - - val eventOverview = EventOverviewDisplayModel( - eventName = eventName, - startDate = startDate, - phases = emptyList(), - standings = StandingsDisplayModel( - placements = emptyList(), - ), - ) - - val viewState = EventOverviewViewState( - showLoading = false, - event = eventOverview, - ) - - composeTestRule.setContent { - EventOverviewContent( - viewState = viewState, - onPhaseClicked = {}, - ) - } - - composeTestRule - .onNodeWithText(eventName) - .assertIsDisplayed() - - composeTestRule - .onNodeWithText(startDate) - .assertIsDisplayed() - - composeTestRule - .onNodeWithText( - composeTestRule.activity.getString(R.string.bracket_information_unavailable) - ) - .assertIsDisplayed() - - composeTestRule - .onNodeWithText( - composeTestRule.activity.getString(R.string.standings_information_unavailable) - ) - .assertIsDisplayed() - } -} diff --git a/app/src/androidTest/java/com/adammcneilly/pocketleague/fakes/FakeSeriesOverviewDisplayModel.kt b/app/src/androidTest/java/com/adammcneilly/pocketleague/fakes/FakeSeriesOverviewDisplayModel.kt deleted file mode 100644 index e6ea85436..000000000 --- a/app/src/androidTest/java/com/adammcneilly/pocketleague/fakes/FakeSeriesOverviewDisplayModel.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.adammcneilly.pocketleague.fakes - -import com.adammcneilly.pocketleague.seriesoverview.ui.SeriesOverviewDisplayModel - -val fakeSeriesOverviewDisplayModel = SeriesOverviewDisplayModel( - teamOne = fakeTeamOverviewDisplayModel.copy( - name = "Team One", - ), - teamTwo = fakeTeamOverviewDisplayModel.copy( - name = "Team Two", - ), - teamOneWins = 0, - teamTwoWins = 0, -) diff --git a/app/src/androidTest/java/com/adammcneilly/pocketleague/fakes/FakeTeamOverviewDisplayModel.kt b/app/src/androidTest/java/com/adammcneilly/pocketleague/fakes/FakeTeamOverviewDisplayModel.kt deleted file mode 100644 index 6e1d15c50..000000000 --- a/app/src/androidTest/java/com/adammcneilly/pocketleague/fakes/FakeTeamOverviewDisplayModel.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.adammcneilly.pocketleague.fakes - -import com.adammcneilly.pocketleague.shared.core.ui.UIImage -import com.adammcneilly.pocketleague.teamoverview.ui.TeamOverviewDisplayModel - -val fakeTeamOverviewDisplayModel = TeamOverviewDisplayModel( - name = "", - lightLogoImage = UIImage.Remote(""), - darkLogoImage = UIImage.Remote(""), - roster = emptyList(), -) diff --git a/app/src/main/graphql/com/adammcneilly/pocketleague/EventOverviewQuery.graphql b/app/src/main/graphql/com/adammcneilly/pocketleague/EventOverviewQuery.graphql deleted file mode 100644 index 1705d6270..000000000 --- a/app/src/main/graphql/com/adammcneilly/pocketleague/EventOverviewQuery.graphql +++ /dev/null @@ -1,62 +0,0 @@ -fragment EventPlayerFragment on Player { - gamerTag -} - -fragment EventEntrantFragment on Entrant { - id - name - team { - members { - player { - ...EventPlayerFragment - } - } - images { - url - } - } -} - -fragment StandingsPlacementFragment on Standing { - entrant { - ...EventEntrantFragment - } - placement -} - -fragment PhaseOverviewFragment on Phase { - id - groupCount - numSeeds - name - phaseOrder - bracketType -} - -fragment PhaseGroupFragment on PhaseGroup { - id - bracketType - displayIdentifier - numRounds - phase { - ...PhaseOverviewFragment - } -} - -fragment EventOverviewFragment on Event { - ...EventSummaryFragment - phaseGroups { - ...PhaseGroupFragment - } - standings(query: $standingsQuery) { - nodes { - ...StandingsPlacementFragment - } - } -} - -query EventOverviewQuery($eventId: ID, $standingsQuery: StandingPaginationQuery!) { - event(id: $eventId) { - ...EventOverviewFragment - } -} \ No newline at end of file diff --git a/app/src/main/graphql/com/adammcneilly/pocketleague/EventSummaryListQuery.graphql b/app/src/main/graphql/com/adammcneilly/pocketleague/EventSummaryListQuery.graphql deleted file mode 100644 index 7451d424a..000000000 --- a/app/src/main/graphql/com/adammcneilly/pocketleague/EventSummaryListQuery.graphql +++ /dev/null @@ -1,27 +0,0 @@ -fragment EventSummaryFragment on Event { - id - name - slug - tournament { - name - images { - url - } - } - startAt - numEntrants - isOnline -} - -query EventSummaryListQuery($leagueSlug: String, $eventsQuery: LeagueEventsQuery) { - league(slug: $leagueSlug) { - events(query: $eventsQuery) { - pageInfo { - ...PageInfoFragment - } - nodes { - ...EventSummaryFragment - } - } - } -} \ No newline at end of file diff --git a/app/src/main/graphql/com/adammcneilly/pocketleague/PageInfo.graphql b/app/src/main/graphql/com/adammcneilly/pocketleague/PageInfo.graphql deleted file mode 100644 index ae1795d20..000000000 --- a/app/src/main/graphql/com/adammcneilly/pocketleague/PageInfo.graphql +++ /dev/null @@ -1,5 +0,0 @@ -fragment PageInfoFragment on PageInfo { - total - totalPages - page -} \ No newline at end of file diff --git a/app/src/main/graphql/com/adammcneilly/pocketleague/PhaseDetailQuery.graphql b/app/src/main/graphql/com/adammcneilly/pocketleague/PhaseDetailQuery.graphql deleted file mode 100644 index b91259a32..000000000 --- a/app/src/main/graphql/com/adammcneilly/pocketleague/PhaseDetailQuery.graphql +++ /dev/null @@ -1,41 +0,0 @@ -fragment SetSlotFragment on SetSlot { - entrant { - ...EventEntrantFragment - } - slotIndex -} - -fragment EventSetFragment on Set { - fullRoundText - displayScore - winnerId - round - slots { - ...SetSlotFragment - } -} - -fragment PhaseDetailFragment on Phase { - ...PhaseOverviewFragment - sets( - perPage: $perPage - ) { - pageInfo { - total - totalPages - page - } - nodes { - ...EventSetFragment - } - } -} - -query PhaseDetailQuery( - $id: ID, - $perPage: Int, -) { - phase(id: $id) { - ...PhaseDetailFragment - } -} \ No newline at end of file diff --git a/app/src/main/graphql/com/adammcneilly/pocketleague/TournamentDetailQuery.graphql b/app/src/main/graphql/com/adammcneilly/pocketleague/TournamentDetailQuery.graphql deleted file mode 100644 index 5d44f8bcf..000000000 --- a/app/src/main/graphql/com/adammcneilly/pocketleague/TournamentDetailQuery.graphql +++ /dev/null @@ -1,47 +0,0 @@ -query TournamentDetailQuery($slug: String) { - tournament(slug: $slug){ - id - name - events { - id - type - name - phases { - name - bracketType - waves { - id - identifier - } - groupCount - sets { - nodes { - fullRoundText - setGamesType - slots { - entrant { - id - name - } - prereqId - prereqType - slotIndex - standing { - stats { - score { - label - value - displayValue - } - } - } - } - totalGames - displayScore - winnerId - } - } - } - } - } -} diff --git a/app/src/main/graphql/com/adammcneilly/pocketleague/schema.json b/app/src/main/graphql/com/adammcneilly/pocketleague/schema.json deleted file mode 100644 index eaddc378d..000000000 --- a/app/src/main/graphql/com/adammcneilly/pocketleague/schema.json +++ /dev/null @@ -1 +0,0 @@ -{"data":{"__schema":{"queryType":{"name":"Query"},"mutationType":{"name":"Mutation"},"subscriptionType":null,"types":[{"kind":"OBJECT","name":"Query","description":null,"fields":[{"name":"currentUser","description":"Returns the authenticated user","args":[],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"event","description":"Returns an event given its id or slug","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"league","description":"Returns a league given its id or slug","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"League","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participant","description":"Returns a participant given its id","args":[{"name":"id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"isAdmin","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Participant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phase","description":"Returns a phase given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseGroup","description":"Returns a phase group given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"PhaseGroup","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":"Returns a player given an id","args":[{"name":"id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seed","description":"Returns a phase seed given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Seed","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"set","description":"Returns a set given its id","args":[{"name":"id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Set","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"shop","description":"A shop entity","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Shop","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":"Returns an stream given its id","args":[{"name":"id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Streams","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamQueue","description":"Returns all the stream queues for a given tournament","args":[{"name":"tournamentId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"includePlayerStreams","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"StreamQueue","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"team","description":"Returns a team given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"inviteCode","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"INTERFACE","name":"Team","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournament","description":"Returns a tournament given its id or slug","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Tournament","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournaments","description":"Paginated, filterable list of tournaments","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"TournamentQuery","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"TournamentConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"user","description":"Returns a user given a user slug of the form user\/abc123, or id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"videogame","description":"Returns a videogame given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Videogame","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"videogames","description":"Returns paginated list of videogames matching the search criteria.","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"VideogameQuery","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"VideogameConnection","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"User","description":"A user","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"authorizations","description":"Authorizations to external services (i.e. Twitch, Twitter)","args":[{"name":"types","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"SocialConnectionType","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"ProfileAuthorization","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"bio","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"birthday","description":"Public facing user birthday that respects user publishing settings","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discriminator","description":"Uniquely identifying token for user. Same as the hashed part of the slug","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"events","description":"Events this user has competed in","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserEventsPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"genderPronoun","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"leagues","description":"Leagues this user has competed in","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserLeaguesPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"LeagueConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"location","description":"Public location info for this user","args":[],"type":{"kind":"OBJECT","name":"Address","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Public facing user name that respects user publishing settings","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":"player for user","args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournaments","description":"Tournaments this user is organizing or competing in","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserTournamentsPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"TournamentConnection","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"ID","description":"The `ID` scalar type represents a unique identifier, often used to\nrefetch an object or as key for a cache. When expected as an input type, any string (such as `\"4\"`) or integer\n(such as `4`) input value will be accepted as an ID.","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"SocialConnectionType","description":"Represents the name of the third-party social service (e.g Twitter) for OAuth","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITTER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"TWITCH","description":"","isDeprecated":false,"deprecationReason":null},{"name":"DISCORD","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"XBOX","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"ProfileAuthorization","description":"An OAuth ProfileAuthorization object","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"externalId","description":"The id given by the external service","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"externalUsername","description":"The username given by the external service (including discriminator if discord)","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":null,"args":[],"type":{"kind":"OBJECT","name":"Stream","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":"The name of the external service providing this auth i.e. \"twitch\"","args":[],"type":{"kind":"ENUM","name":"AuthorizationType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"String","description":"The `String` scalar type represents textual data, represented as UTF-8\ncharacter sequences. The String type is most often used by GraphQL to\nrepresent free-form human-readable text.","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Stream","description":"A Stream object","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":"Whether the stream is currently live. May be slightly delayed.","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The name of the stream","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":"The name of the external service providing this auth i.e. \"twitch\"","args":[],"type":{"kind":"ENUM","name":"StreamType","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"Boolean","description":"The `Boolean` scalar type represents `true` or `false`.","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"StreamType","description":"Represents the type of stream service","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITCH","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"ENUM","name":"AuthorizationType","description":"Represents the name of the third-party service (e.g Twitter) for OAuth","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITTER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"TWITCH","description":"","isDeprecated":false,"deprecationReason":null},{"name":"STEAM","description":"","isDeprecated":false,"deprecationReason":null},{"name":"DISCORD","description":"","isDeprecated":false,"deprecationReason":null},{"name":"XBOX","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserEventsPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserEventsPaginationFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"Int","description":"The `Int` scalar type represents non-fractional signed whole numeric\nvalues. Int can represent values between -(2^31) and 2^31 - 1. ","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserEventsPaginationFilter","description":null,"fields":null,"inputFields":[{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventType","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"minEntrantCount","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"maxEntrantCount","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"location","description":null,"type":{"kind":"INPUT_OBJECT","name":"LocationFilterType","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"LocationFilterType","description":null,"fields":null,"inputFields":[{"name":"countryCode","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"state","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"city","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PaginationSearchType","description":null,"fields":null,"inputFields":[{"name":"fieldsToSearch","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"defaultValue":null},{"name":"searchString","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"PageInfo","description":null,"fields":[{"name":"total","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"totalPages","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"page","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"perPage","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"sortBy","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"filter","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"JSON","description":"The `JSON` scalar type represents JSON values as specified by\n\t\t[ECMA-404](http:\/\/www.ecma-international.org\/publications\/files\/ECMA-ST\/ECMA-404.pdf).","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Event","description":"An event in a tournament","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkInBuffer","description":"How long before the event start will the check-in end (in seconds)","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkInDuration","description":"How long the event check-in will last (in seconds)","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkInEnabled","description":"Whether check-in is enabled for this event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"createdAt","description":"When the event was created (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"deckSubmissionDeadline","description":"Last date attendees are able to create teams for team events","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrantSizeMax","description":"Maximum number of participants each Entrant can have","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"Migrate to teamRosterSize"},{"name":"entrantSizeMin","description":"Minimum number of participants each Entrant can have","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"Migrate to teamRosterSize"},{"name":"entrants","description":"The entrants that belong to an event, paginated by filter criteria","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"EventEntrantPageQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EntrantConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hasDecks","description":"Whether the event has decks","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hasTasks","description":"Are player tasks enabled for this event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":"Whether the event is an online event or not","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"league","description":null,"args":[],"type":{"kind":"OBJECT","name":"League","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"matchRulesMarkdown","description":"Markdown field for match rules\/instructions","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Title of event set by organizer","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numEntrants","description":"Gets the number of entrants in this event","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseGroups","description":"The phase groups that belong to an event.","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"PhaseGroup","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"phases","description":"The phases that belong to an event.","args":[{"name":"state","description":"Filter phases by state. If not specified will default to all phases","type":{"kind":"ENUM","name":"ActivityState","ofType":null},"defaultValue":null},{"name":"phaseId","description":"Optionally only return results for this phase","type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Phase","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"prizingInfo","description":"TO settings for prizing","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"publishing","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rulesMarkdown","description":"Markdown field for event rules\/instructions","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rulesetId","description":"Id of the event ruleset","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rulesetSettings","description":"Settings pulled from the event ruleset, if one exists","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":true,"deprecationReason":"Use ruleset"},{"name":"sets","description":"Paginated sets for this Event","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standings","description":"Paginated list of standings","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"StandingPaginationQuery","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StandingConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"When does this event start?","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"The state of the Event.","args":[],"type":{"kind":"ENUM","name":"ActivityState","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stations","description":"Paginated stations on this event","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"StationFilter","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StationsConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teamManagementDeadline","description":"Last date attendees are able to create teams for team events","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teamNameAllowed","description":"If this is a teams event, returns whether or not teams can set custom names","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teamRosterSize","description":"Team roster size requirements","args":[],"type":{"kind":"OBJECT","name":"TeamRosterSize","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournament","description":null,"args":[],"type":{"kind":"OBJECT","name":"Tournament","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":"The type of the event, whether an entrant will have one participant or multiple","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"updatedAt","description":"When the event was last modified (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"useEventSeeds","description":"Whether the event uses the new EventSeeds for seeding","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"videogame","description":null,"args":[],"type":{"kind":"OBJECT","name":"Videogame","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"waves","description":"The waves being used by the event","args":[{"name":"phaseId","description":"Waves filtered by phaseId, returns all if not set.","type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Wave","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"Timestamp","description":"Represents a Unix Timestamp. Supports up to 53 bit int values,\n\t\tas that is JavaScript's internal memory allocation for integer values.","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"EventEntrantPageQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"EventEntrantPageQueryFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"EventEntrantPageQueryFilter","description":null,"fields":null,"inputFields":[{"name":"name","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EntrantConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Entrant","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Entrant","description":"An entrant in an event","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"event","description":null,"args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"initialSeedNum","description":"Entrant's seed number in the first phase of the event.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isDisqualified","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The entrant name as it appears in bracket: gamerTag of the participant or team name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"paginatedSets","description":"Paginated sets for this entrant","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participants","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Participant","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"seeds","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Seed","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"skill","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standing","description":"Standing for this entrant given an event. All entrants queried must be in the same event (for now).","args":[],"type":{"kind":"OBJECT","name":"Standing","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":null,"args":[],"type":{"kind":"OBJECT","name":"Streams","ofType":null},"isDeprecated":true,"deprecationReason":"DEPRECATED. Use streams instead, which supports multiple stream types and teams."},{"name":"streams","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Streams","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"team","description":"Team linked to this entrant, if one exists","args":[],"type":{"kind":"INTERFACE","name":"Team","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"SetSortType","description":"Different sort type configurations used when displaying multiple sets","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"NONE","description":"Sets will not be sorted.","isDeprecated":false,"deprecationReason":null},{"name":"CALL_ORDER","description":"Sets are sorted in the suggested order that they be called to be played. The order of completed sets is reversed.","isDeprecated":false,"deprecationReason":null},{"name":"MAGIC","description":"Sets are sorted by relevancy dependent on the state and progress of the event.","isDeprecated":false,"deprecationReason":null},{"name":"RECENT","description":"Sets are sorted in the order that they were started.","isDeprecated":false,"deprecationReason":null},{"name":"STANDARD","description":"Deprecated. This is equivalent to CALL_ORDER","isDeprecated":false,"deprecationReason":null},{"name":"ROUND","description":"Sets sorted by round and identifier","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SetFilters","description":null,"fields":null,"inputFields":[{"name":"entrantIds","description":"Only return Sets for these Entrants","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"entrantSize","description":"Only return Sets for this Entrant size. For example, to fetch 1v1 Sets only, filter by an entrantSize of 1","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"hasVod","description":"Only return Sets that have an attached VOD","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"hideEmpty","description":"Do not return empty Sets. For example, set this to true to filter out sets that are waiting for progressions.","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"showByes","description":"Return sets that contain a bye","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"isEventOnline","description":"Only return Sets that are in an Online event. If omitted, Sets for both online and offline Events are returned","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"location","description":"Only return Sets in certain geographical areas.","type":{"kind":"INPUT_OBJECT","name":"SetFilterLocation","ofType":null},"defaultValue":null},{"name":"participantIds","description":"Only return Sets for these Participants","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"phaseGroupIds","description":"Only return Sets in these PhaseGroups","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"phaseIds","description":"Only return Sets in these Phases","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventIds","description":"Only return Sets in these Events","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"tournamentIds","description":"Only return Sets in these Tournaments","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"playerIds","description":"Only return Sets for these Players","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"roundNumber","description":"Only return Sets for these Rounds","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"state","description":"Only returns Sets that are in these states","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"stationIds","description":"Only return Sets that are assigned to these Station IDs","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"stationNumbers","description":"Only return Sets that are assigned to these Station numbers","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"updatedAfter","description":"Only return sets created or updated since this timestamp","type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SetFilterLocation","description":"Filter Sets by geographical constraints.","fields":null,"inputFields":[{"name":"state","description":"Only return Sets in this state. Only applicable to US states","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"country","description":"Only return Sets in this country. Expects a valid two-letter country code","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"distanceFrom","description":null,"type":{"kind":"INPUT_OBJECT","name":"SetFilterLocationDistanceFrom","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SetFilterLocationDistanceFrom","description":"Only return Sets that are a certain distance away from a specified point","fields":null,"inputFields":[{"name":"point","description":"Point at which to perform distance calculation","type":{"kind":"INPUT_OBJECT","name":"SetFilterLocationDistanceFromPoint","ofType":null},"defaultValue":null},{"name":"radius","description":"Distance from the point to include results in","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SetFilterLocationDistanceFromPoint","description":null,"fields":null,"inputFields":[{"name":"lat","description":null,"type":{"kind":"SCALAR","name":"Float","ofType":null},"defaultValue":null},{"name":"lon","description":null,"type":{"kind":"SCALAR","name":"Float","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"Float","description":"The `Float` scalar type represents signed double-precision fractional\nvalues as specified by\n[IEEE 754](http:\/\/en.wikipedia.org\/wiki\/IEEE_floating_point). ","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"SetConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Set","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Set","description":"A set","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"completedAt","description":"The time this set was marked as completed","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"createdAt","description":"The time this set was created","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"displayScore","description":null,"args":[{"name":"mainEntrantId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"event","description":"Event that this set belongs to.","args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"fullRoundText","description":"Full round text of this set.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"game","description":null,"args":[{"name":"orderNum","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Game","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"games","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Game","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"hasPlaceholder","description":"Whether this set contains a placeholder entrant","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"identifier","description":"The letters that describe a unique identifier within the pool. Eg. F, AT","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"lPlacement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseGroup","description":"Phase group that this Set belongs to.","args":[],"type":{"kind":"OBJECT","name":"PhaseGroup","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"round","description":"The round number of the set. Negative numbers are losers bracket","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"setGamesType","description":"Indicates whether the set is in best of or total games mode. This instructs\nwhich field is used to figure out how many games are in this set.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slots","description":"A possible spot in a set. Use this to get all entrants in a set. Use this for all bracket types (FFA, elimination, etc)","args":[{"name":"includeByes","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"false"}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"SetSlot","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"The start time of the Set. If there is no startAt time on the Set, will pull it from phaseGroup rounds configuration.","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startedAt","description":null,"args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"station","description":"Tournament event station for a set","args":[],"type":{"kind":"OBJECT","name":"Stations","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":"Tournament event stream for a set","args":[],"type":{"kind":"OBJECT","name":"Streams","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"totalGames","description":"If setGamesType is in total games mode, this defined the number of games in the set.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"vodUrl","description":"Url of a VOD for this set","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"wPlacement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"winnerId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Game","description":"A game represents a single game within a set.","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"orderNum","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"selections","description":"Selections for this game such as character, etc.","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"GameSelection","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"stage","description":"The stage that this game was played on (if applicable)","args":[],"type":{"kind":"OBJECT","name":"Stage","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"winnerId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Image","description":"An image","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"height","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"ratio","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"width","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"GameSelection","description":"A selection for this game. i.e. character\/stage selection, etc","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":"The entrant who this selection is for","args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"orderNum","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participant","description":"The participant who this selection is for. This is only populated if there are\nselections for multiple participants of a single entrant","args":[],"type":{"kind":"OBJECT","name":"Participant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"selectionType","description":null,"args":[],"type":{"kind":"ENUM","name":"GameSelectionType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"selectionValue","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Participant","description":"A participant of a tournament; either a spectator or competitor","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkedIn","description":"If this participant was checked-in by admin","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkedInAt","description":"The time this participant was checked-in by admin","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"connectedAccounts","description":"Info for connected accounts to external services.","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"contactInfo","description":"Contact Info selected during registration. Falls back to User.location and\/or\nUser.name if necessary. These fields are for admin use only and do not respect\nuser privacy settings. DO NOT display this information publicly.","args":[],"type":{"kind":"OBJECT","name":"ContactInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"email","description":"Email of the user, only available to admins within 18 months of tournament","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrants","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Entrant","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"events","description":"The events this participant registered for.","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"gamerTag","description":"The tag that was used in registration e.g. Mang0","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":null,"args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prefix","description":"The prefix that was used in registration e.g. C9","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"requiredConnections","description":"Admin only field for required social connections","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"ProfileAuthorization","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"user","description":"The user this participant is associated to.","args":[],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"verified","description":"If this participant is verified as actually being in the tournament","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ContactInfo","description":"Name, address, etc","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"city","description":"Participant City Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"country","description":"Participant Country Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"countryId","description":"Participant Country (region) id","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nameFirst","description":"First Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nameLast","description":"Last Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"Participant State Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stateId","description":"Participant State (region) id","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"zipcode","description":"Zip or Postal Code","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Player","description":"A player","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"gamerTag","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prefix","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rankings","description":"Most recent active & published rankings","args":[{"name":"limit","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"videogameId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"PlayerRank","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"recentSets","description":"Recent sets for this player.","args":[{"name":"opponentId","description":"Use this to get H2H history between two players","type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Set","ofType":null}},"isDeprecated":true,"deprecationReason":"Use the sets field instead."},{"name":"sets","description":"Set history for this player.","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"user","description":null,"args":[],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"PlayerRank","description":"A player's ranks","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rank","description":"The player's placement on the ranking","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"title","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"GameSelectionType","description":"The type of selection i.e. is it for a character or something else","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"CHARACTER","description":"Character selection","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"Stage","description":"Video Stage","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Stage name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"PhaseGroup","description":"A group within a phase","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":"The bracket type of this group's phase.","args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"displayIdentifier","description":"Unique identifier for this group within the context of its phase","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"firstRoundTime","description":"For the given phase group, this is the start time of the first round that occurs in the group.","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numRounds","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"paginatedSeeds","description":null,"args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SeedConnection","ofType":null},"isDeprecated":true,"deprecationReason":"Please use 'seeds', which is now paginated"},{"name":"paginatedSets","description":"Paginated sets on this phaseGroup","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":true,"deprecationReason":"Please use 'sets', which is now paginated"},{"name":"phase","description":"The phase associated with this phase group","args":[],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"progressionsOut","description":"The progressions out of this phase group","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Progression","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"rounds","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Round","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"seedMap","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seeds","description":"Paginated seeds for this phase group","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SeedConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"sets","description":"Paginated sets on this phaseGroup","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standings","description":"Paginated list of standings","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"StandingGroupStandingPageFilter","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StandingConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"Unix time the group is scheduled to start. This info could also be on the wave instead.","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tiebreakOrder","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"wave","description":null,"args":[],"type":{"kind":"OBJECT","name":"Wave","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"BracketType","description":"The type of Bracket format that a Phase is configured with.","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"SINGLE_ELIMINATION","description":"","isDeprecated":false,"deprecationReason":null},{"name":"DOUBLE_ELIMINATION","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ROUND_ROBIN","description":"","isDeprecated":false,"deprecationReason":null},{"name":"SWISS","description":"","isDeprecated":false,"deprecationReason":null},{"name":"EXHIBITION","description":"","isDeprecated":false,"deprecationReason":null},{"name":"CUSTOM_SCHEDULE","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MATCHMAKING","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ELIMINATION_ROUNDS","description":"","isDeprecated":false,"deprecationReason":null},{"name":"RACE","description":"","isDeprecated":false,"deprecationReason":null},{"name":"CIRCUIT","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"SeedPageFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SeedPageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"entrantName","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"checkInState","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"phaseGroupId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventCheckInGroupId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"phaseId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"SeedConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Seed","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Seed","description":"A seed for an entrant","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkedInParticipants","description":"Map of Participant ID to checked in boolean","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"groupSeedNum","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isBye","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phase","description":null,"args":[],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseGroup","description":null,"args":[],"type":{"kind":"OBJECT","name":"PhaseGroup","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"placeholderName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"placement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"players","description":"The player(s) associated with this seed's entrant","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Player","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"progressionSeedId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"progressionSource","description":"Source progression information","args":[],"type":{"kind":"OBJECT","name":"Progression","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seedNum","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"setRecordWithoutByes","description":"Entrant's win\/loss record for this standing. Scores do not include byes.","args":[{"name":"phaseGroupId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standings","description":null,"args":[{"name":"containerType","description":"The container of the standing groups to get standings for. If null, will return all standings.","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Standing","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Phase","description":"A phase in an event","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":"The bracket type of this phase.","args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"event","description":"The Event that this phase belongs to","args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"groupCount","description":"Number of phase groups in this phase","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isExhibition","description":"Is the phase an exhibition or not.","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Name of phase e.g. Round 1 Pools","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numSeeds","description":"The number of seeds this phase contains.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"paginatedSeeds","description":null,"args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SeedConnection","ofType":null},"isDeprecated":true,"deprecationReason":"Please use 'seeds' instead"},{"name":"phaseGroups","description":"Phase groups under this phase, paginated","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"PhaseGroupPageQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"PhaseGroupConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseOrder","description":"The relative order of this phase within an event","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seeds","description":"Paginated seeds for this phase","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SeedConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"sets","description":"Paginated sets for this Phase","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"State of the phase","args":[],"type":{"kind":"ENUM","name":"ActivityState","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"waves","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Wave","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PhaseGroupPageQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"entrantIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"PhaseGroupPageQueryFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PhaseGroupPageQueryFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"waveId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"PhaseGroupConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"PhaseGroup","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"ActivityState","description":"Represents the state of an activity","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"CREATED","description":"Activity is created","isDeprecated":false,"deprecationReason":null},{"name":"ACTIVE","description":"Activity is active or in progress","isDeprecated":false,"deprecationReason":null},{"name":"COMPLETED","description":"Activity is done","isDeprecated":false,"deprecationReason":null},{"name":"READY","description":"Activity is ready to be started","isDeprecated":false,"deprecationReason":null},{"name":"INVALID","description":"Activity is invalid","isDeprecated":false,"deprecationReason":null},{"name":"CALLED","description":"Activity, like a set, has been called to start","isDeprecated":false,"deprecationReason":null},{"name":"QUEUED","description":"Activity is queued to run","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"Wave","description":"A wave in a tournament","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"identifier","description":"The Wave Identifier","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"Unix time the wave is scheduled to start.","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Progression","description":"A connection between a placement in an origin phase group to a destination seed.","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"originOrder","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"originPhase","description":null,"args":[],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"originPhaseGroup","description":null,"args":[],"type":{"kind":"OBJECT","name":"PhaseGroup","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"originPlacement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Standing","description":"A standing indicates the placement of something within a container.","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"container","description":"The containing entity that contextualizes this standing. Event standings, for\nexample, represent an entrant's standing in the entire event vs. Set standings\nwhich is an entrant's standing in only a single set within an event.","args":[],"type":{"kind":"UNION","name":"StandingContainer","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":"If the entity this standing is assigned to can be resolved into an entrant, this will provide the entrant.","args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isFinal","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"metadata","description":"Metadata that goes along with this standing. Can take on different forms based on standing group type and settings.","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"placement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":"The player(s) tied to this standing's entity","args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standing","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"The \"placement\" field is identical and will eventually replace \"standing\""},{"name":"stats","description":null,"args":[],"type":{"kind":"OBJECT","name":"StandingStats","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"totalPoints","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"UNION","name":"StandingContainer","description":"The containing entity that this standing is for","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"Tournament","ofType":null},{"kind":"OBJECT","name":"Event","ofType":null},{"kind":"OBJECT","name":"PhaseGroup","ofType":null},{"kind":"OBJECT","name":"Set","ofType":null}]},{"kind":"OBJECT","name":"Tournament","description":"A tournament","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"addrState","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"admins","description":"Admin-only view of admins for this tournament","args":[{"name":"roles","description":"Which roles to show","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"User","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"city","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"countryCode","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"createdAt","description":"When the tournament was created (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"currency","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"endAt","description":"When the tournament ends","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"eventRegistrationClosesAt","description":"When does event registration close","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"events","description":null,"args":[{"name":"limit","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"EventFilter","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"hasOfflineEvents","description":"True if tournament has at least one offline event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hasOnlineEvents","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hashtag","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":"True if tournament has at least one online event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isRegistrationOpen","description":"Is tournament registration open","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"lat","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"links","description":null,"args":[],"type":{"kind":"OBJECT","name":"TournamentLinks","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"lng","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"mapsPlaceId","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The tournament name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numAttendees","description":"Number of attendees including spectators, if public","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"owner","description":"The user who created the tournament","args":[],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participants","description":"Paginated, queryable list of participants","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"ParticipantPaginationQuery","ofType":null}},"defaultValue":null},{"name":"isAdmin","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"ParticipantConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"postalCode","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"primaryContact","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"primaryContactType","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"publishing","description":"Publishing settings for this tournament","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"registrationClosesAt","description":"When does registration for the tournament end","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rules","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"shortSlug","description":"The short slug used to form the url","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":"The slug used to form the url","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"When the tournament Starts","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"State of the tournament, can be ActivityState::CREATED, ActivityState::ACTIVE, or ActivityState::COMPLETED","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stations","description":null,"args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StationsConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamQueue","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"StreamQueue","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"streams","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Streams","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"teamCreationClosesAt","description":"When is the team creation deadline","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teams","description":"Paginated, queryable list of teams","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"TeamPaginationQuery","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"TeamConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"timezone","description":"The timezone of the tournament","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournamentType","description":"The type of tournament from TournamentType","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"updatedAt","description":"When the tournament was last modified (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":"Build Tournament URL","args":[{"name":"tab","description":"Tournament tab to add to URL","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"relative","description":"Generate a relative URL. Defaults to true. Setting to false will generate an absolute URL","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"true"}],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"venueAddress","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"venueName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"waves","description":"List of all waves in this tournament","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Wave","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"EventFilter","description":null,"fields":null,"inputFields":[{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"type","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"published","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"TournamentLinks","description":null,"fields":[{"name":"facebook","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discord","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ParticipantPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"ParticipantPageFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ParticipantPageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"ids","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null},{"name":"gamerTag","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"unpaid","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"incompleteTeam","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"missingDeck","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"checkedIn","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"notCheckedIn","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ParticipantConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Participant","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"StationsConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Stations","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Stations","description":"Stations, such as a stream setup, at an event","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"canAutoAssign","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"clusterNumber","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"clusterPrefix","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"enabled","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"identifier","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numSetups","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"number","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prefix","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"queue","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"queueDepth","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"updatedAt","description":null,"args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"StreamQueue","description":"A Stream queue object","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"sets","description":"The sets on the stream","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Set","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":"The stream on the queue","args":[],"type":{"kind":"OBJECT","name":"Streams","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Streams","description":"Tournament Stream","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"enabled","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"followerCount","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numSetups","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"parentStreamId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamGame","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamId","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamLogo","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamSource","description":null,"args":[],"type":{"kind":"ENUM","name":"StreamSource","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamStatus","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamType","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamTypeId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"StreamSource","description":"Represents the source of a stream","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITCH","description":"Stream is on twitch.tv channel","isDeprecated":false,"deprecationReason":null},{"name":"HITBOX","description":"Stream is on smashcast.tv channel","isDeprecated":false,"deprecationReason":null},{"name":"STREAMME","description":"Stream is on a stream.me channel","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"Stream is on a mixer.com channel","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TeamPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"TeamPaginationFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TeamPaginationFilter","description":null,"fields":null,"inputFields":[{"name":"globalTeamId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"eventState","description":null,"type":{"kind":"ENUM","name":"ActivityState","ofType":null},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"eventIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"minEntrantCount","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"maxEntrantCount","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null},{"name":"type","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"tournamentId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"memberStatus","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null}},"defaultValue":null},{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"isLeague","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"past","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"rosterComplete","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"rosterIncomplete","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"TeamMemberStatus","description":"Membership status of a team member","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"UNKNOWN","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ACCEPTED","description":"","isDeprecated":false,"deprecationReason":null},{"name":"INVITED","description":"","isDeprecated":false,"deprecationReason":null},{"name":"REQUEST","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ALUM","description":"","isDeprecated":false,"deprecationReason":null},{"name":"HIATUS","description":"","isDeprecated":false,"deprecationReason":null},{"name":"OPEN_SPOT","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"TeamConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"INTERFACE","name":"Team","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INTERFACE","name":"Team","description":"A team, either at the global level or within the context of an event","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discriminator","description":"Uniquely identifying token for team. Same as the hashed part of the slug","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":true,"deprecationReason":"Use the entrant field off the EventTeam type"},{"name":"event","description":null,"args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":true,"deprecationReason":"Use the event field off the EventTeam type"},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"members","description":null,"args":[{"name":"status","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"TeamMember","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"EventTeam","ofType":null},{"kind":"OBJECT","name":"GlobalTeam","ofType":null}]},{"kind":"OBJECT","name":"TeamMember","description":"A member of a team","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isAlternate","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isCaptain","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"memberType","description":"The type of the team member","args":[],"type":{"kind":"ENUM","name":"TeamMemberType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Participant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":null,"args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"status","description":"The status of the team member","args":[],"type":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"TeamMemberType","description":"Membership type of a team member","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"PLAYER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"STAFF","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"StandingStats","description":"Any stats related to this standing. This type is experimental and very likely to change in the future.","fields":[{"name":"score","description":null,"args":[],"type":{"kind":"OBJECT","name":"Score","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Score","description":"The score that led to this standing being awarded. The meaning of this field can\nvary by standing type and is not used for some standing types.","fields":[{"name":"label","description":"The name of this score. e.g. \"Kills\" or \"Stocks\"","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"value","description":"The raw score value","args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"displayValue","description":"Like value, but formatted for race format events. Formatted according to the race config for the front end to use.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Round","description":"A round within a phase group","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bestOf","description":"If applicable, bestOf is the number of games\n\t\t\t\t\t\t\t\t\tone must win a majority out of to win a set in this round","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"number","description":"Indicates this round's order in the phase group","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"The time that this round is scheduled to start at","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StandingGroupStandingPageFilter","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"StandingConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Standing","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"SetSlot","description":"A slot in a set where a seed currently or will eventually exist in order to participate in the set.","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prereqId","description":"Pairs with prereqType, is the ID of the prereq.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prereqPlacement","description":"Given a set prereq type, defines the placement required in the origin set to end up in this slot.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prereqType","description":"Describes where the entity in this slot comes from.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seed","description":null,"args":[],"type":{"kind":"OBJECT","name":"Seed","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slotIndex","description":"The index of the slot. Unique per set.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standing","description":"The standing within this set for the seed currently assigned to this slot.","args":[],"type":{"kind":"OBJECT","name":"Standing","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"League","description":"A league","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"addrState","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"city","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"countryCode","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"createdAt","description":"When the tournament was created (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"currency","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"endAt","description":"When the tournament ends","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrantCount","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"eventOwners","description":null,"args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"EventOwnersQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventOwnerConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"eventRegistrationClosesAt","description":"When does event registration close","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"events","description":"Paginated list of events in a league","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"LeagueEventsQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"finalEventId","description":"Hacked \"progression\" into this final event","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"No longer used"},{"name":"hasOfflineEvents","description":"True if tournament has at least one offline event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hasOnlineEvents","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hashtag","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":"True if tournament has at least one online event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"lat","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"links","description":null,"args":[],"type":{"kind":"OBJECT","name":"TournamentLinks","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"lng","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"mapsPlaceId","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The tournament name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numProgressingToFinalEvent","description":"Top X number of people in the standings who progress to final event","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"No longer used"},{"name":"numUniquePlayers","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"postalCode","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"primaryContact","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"primaryContactType","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"publishing","description":"Publishing settings for this tournament","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"registrationClosesAt","description":"When does registration for the tournament end","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rules","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"shortSlug","description":"The short slug used to form the url","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"showStandings","description":"Whether standings for this league should be visible","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standings","description":"Paginated list of standings","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"StandingGroupStandingPageFilter","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StandingConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"When the tournament Starts","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"State of the tournament, can be ActivityState::CREATED, ActivityState::ACTIVE, or ActivityState::COMPLETED","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teamCreationClosesAt","description":"When is the team creation deadline","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tiers","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"EventTier","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"timezone","description":"The timezone of the tournament","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournamentType","description":"The type of tournament from TournamentType","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"updatedAt","description":"When the tournament was last modified (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":"Build Tournament URL","args":[{"name":"tab","description":"Tournament tab to add to URL","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"relative","description":"Generate a relative URL. Defaults to true. Setting to false will generate an absolute URL","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"true"}],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"venueAddress","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"venueName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"videogames","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Videogame","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"EventOwnersQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventOwnerConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"EventOwner","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventOwner","description":"Name and Gamertag of the owner of an event in a league","fields":[{"name":"eventId","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"email","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"gamerTag","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"fullName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"LeagueEventsQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"LeagueEventsFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"LeagueEventsFilter","description":null,"fields":null,"inputFields":[{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null},{"name":"pointMappingGroupIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"tierIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"userId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"leagueEntrantId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventTier","description":"Used for league application tiers","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Name of this tier","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Videogame","description":"A videogame","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"displayName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StandingPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"StandingPageFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StandingPageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"ids","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StationFilter","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"TeamRosterSize","description":"Team roster size requirements","fields":[{"name":"maxAlternates","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"maxPlayers","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"minAlternates","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"minPlayers","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserLeaguesPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserLeaguesPaginationFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserLeaguesPaginationFilter","description":null,"fields":null,"inputFields":[{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"past","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"LeagueConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"League","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Address","description":"A user's address","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"city","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"country","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"countryId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stateId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserTournamentsPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserTournamentsPaginationFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserTournamentsPaginationFilter","description":null,"fields":null,"inputFields":[{"name":"past","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null},{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"tournamentView","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"excludeId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"TournamentConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Tournament","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Shop","description":"A shop","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"levels","description":null,"args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"ShopLevelsQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"ShopLevelConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"messages","description":null,"args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"ShopOrderMessagesQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"ShopOrderMessageConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ShopLevelsQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ShopLevelConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"ShopLevel","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ShopLevel","description":"A shop level","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"currAmount","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"goalAmount","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ShopOrderMessagesQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ShopOrderMessageConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"ShopOrderMessage","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ShopOrderMessage","description":"The message and player info for a shop order","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"gamertag","description":"The player's gamertag. Returns null if anonymous message type","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"message","description":"The order message","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The player's name. Returns null unless name & tag display is selected","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":"The player who left the comment","args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"total","description":"The total order amount","args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TournamentQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"TournamentPageFilter","ofType":null},"defaultValue":null},{"name":"sort","description":null,"type":{"kind":"ENUM","name":"TournamentPaginationSort","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TournamentPageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"ids","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"ownerId","description":"ID of the user that owns this tournament.","type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"isCurrentUserAdmin","description":"If true, filter to only tournaments the currently authed user is an admin of","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"countryCode","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"addrState","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"location","description":null,"type":{"kind":"INPUT_OBJECT","name":"TournamentLocationFilter","ofType":null},"defaultValue":null},{"name":"afterDate","description":null,"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"defaultValue":null},{"name":"beforeDate","description":null,"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"defaultValue":null},{"name":"computedUpdatedAt","description":null,"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"defaultValue":null},{"name":"name","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"venueName","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"isFeatured","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"isLeague","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"hasBannerImages","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"activeShops","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"regOpen","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"past","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"published","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"publiclySearchable","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"staffPicks","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"hasOnlineEvents","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"topGames","description":null,"type":{"kind":"INPUT_OBJECT","name":"TopGameFilter","ofType":null},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"videogameIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"sortByScore","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TournamentLocationFilter","description":null,"fields":null,"inputFields":[{"name":"distanceFrom","description":"Latitude, Longitude","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"distance","description":"e.g. 50mi","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TopGameFilter","description":null,"fields":null,"inputFields":[{"name":"gameNums","description":"Array of which # top game you want to filter on.e.g. [2, 3] will filter on the 2nd and 3rd top games","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"TournamentPaginationSort","description":null,"fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"startAt","description":"","isDeprecated":false,"deprecationReason":null},{"name":"endAt","description":"","isDeprecated":false,"deprecationReason":null},{"name":"eventRegistrationClosesAt","description":"","isDeprecated":false,"deprecationReason":null},{"name":"computedUpdatedAt","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"VideogameQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"VideogamePageFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"VideogamePageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"name","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"forUser","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"VideogameConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Videogame","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Mutation","description":null,"fields":[{"name":"deletePhase","description":"Delete a phase by id","args":[{"name":"phaseId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"deleteStation","description":"Delete a station by id","args":[{"name":"stationId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"deleteWave","description":"Delete a wave by id","args":[{"name":"waveId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"resolveScheduleConflicts","description":"Automatically attempt to resolve all schedule conflicts. Returns a list of changed seeds","args":[{"name":"tournamentId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"options","description":null,"type":{"kind":"INPUT_OBJECT","name":"ResolveConflictsOptions","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Seed","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"swapSeeds","description":"Swap two seed ids in a phase","args":[{"name":"phaseId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"seed1Id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"seed2Id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Seed","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"updatePhaseGroups","description":"Update set of phase groups in a phase","args":[{"name":"groupConfigs","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"PhaseGroupUpdateInput","ofType":null}}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"PhaseGroup","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"updatePhaseSeeding","description":"Update the seeding for a phase","args":[{"name":"phaseId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"seedMapping","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"UpdatePhaseSeedInfo","ofType":null}}},"defaultValue":null},{"name":"options","description":null,"type":{"kind":"INPUT_OBJECT","name":"UpdatePhaseSeedingOptions","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"upsertPhase","description":"Create or update a Phase","args":[{"name":"phaseId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"payload","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"PhaseUpsertInput","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"upsertStation","description":"Add or update a station by id","args":[{"name":"stationId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"tournamentId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"fields","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"StationUpsertInput","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Stations","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"upsertWave","description":"Add or update a wave by id","args":[{"name":"waveId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"tournamentId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"fields","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"WaveUpsertInput","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Wave","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ResolveConflictsOptions","description":null,"fields":null,"inputFields":[{"name":"lockedSeeds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"ResolveConflictsLockedSeedConfig","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ResolveConflictsLockedSeedConfig","description":null,"fields":null,"inputFields":[{"name":"eventId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"numSeeds","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PhaseGroupUpdateInput","description":null,"fields":null,"inputFields":[{"name":"phaseGroupId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"stationId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"waveId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UpdatePhaseSeedInfo","description":null,"fields":null,"inputFields":[{"name":"seedId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"seedNum","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"phaseGroupId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UpdatePhaseSeedingOptions","description":null,"fields":null,"inputFields":[{"name":"strictMode","description":"Validate that seedMapping exactly accounts for all entrants in the phase","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PhaseUpsertInput","description":null,"fields":null,"inputFields":[{"name":"name","description":"The name of the Phase. For example, \"Top 8\" or \"Pools\"","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"groupCount","description":"The number of pools to configure for the Phase. Only applies to brackets that support pools","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"bracketType","description":null,"type":{"kind":"ENUM","name":"BracketType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StationUpsertInput","description":null,"fields":null,"inputFields":[{"name":"number","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"clusterId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"WaveUpsertInput","description":null,"fields":null,"inputFields":[{"name":"identifier","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"defaultValue":null},{"name":"startAt","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Timestamp","ofType":null}},"defaultValue":null},{"name":"endAt","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Timestamp","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__Schema","description":"A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.","fields":[{"name":"types","description":"A list of all types supported by this server.","args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"queryType","description":"The type that query operations will be rooted at.","args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"mutationType","description":"If this server supports mutation, the type that mutation operations will be rooted at.","args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"subscriptionType","description":"If this server support subscription, the type that subscription operations will be rooted at.","args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"directives","description":"A list of all directives supported by this server.","args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Directive","ofType":null}}}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__Type","description":"The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.","fields":[{"name":"kind","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"ENUM","name":"__TypeKind","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"fields","description":null,"args":[{"name":"includeDeprecated","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"false"}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Field","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"interfaces","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"possibleTypes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"enumValues","description":null,"args":[{"name":"includeDeprecated","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"false"}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__EnumValue","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"inputFields","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__InputValue","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"ofType","description":null,"args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"__TypeKind","description":"An enum describing what kind of type a given `__Type` is.","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"SCALAR","description":"Indicates this type is a scalar.","isDeprecated":false,"deprecationReason":null},{"name":"OBJECT","description":"Indicates this type is an object. `fields` and `interfaces` are valid fields.","isDeprecated":false,"deprecationReason":null},{"name":"INTERFACE","description":"Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.","isDeprecated":false,"deprecationReason":null},{"name":"UNION","description":"Indicates this type is a union. `possibleTypes` is a valid field.","isDeprecated":false,"deprecationReason":null},{"name":"ENUM","description":"Indicates this type is an enum. `enumValues` is a valid field.","isDeprecated":false,"deprecationReason":null},{"name":"INPUT_OBJECT","description":"Indicates this type is an input object. `inputFields` is a valid field.","isDeprecated":false,"deprecationReason":null},{"name":"LIST","description":"Indicates this type is a list. `ofType` is a valid field.","isDeprecated":false,"deprecationReason":null},{"name":"NON_NULL","description":"Indicates this type is a non-null. `ofType` is a valid field.","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"__Field","description":"Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"args","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__InputValue","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"isDeprecated","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"deprecationReason","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__InputValue","description":"Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"defaultValue","description":"A GraphQL-formatted string representing the default value for this input value.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__EnumValue","description":"One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isDeprecated","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"deprecationReason","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__Directive","description":"A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"locations","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"ENUM","name":"__DirectiveLocation","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"args","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__InputValue","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"onOperation","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":true,"deprecationReason":"Use `locations`."},{"name":"onFragment","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":true,"deprecationReason":"Use `locations`."},{"name":"onField","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":true,"deprecationReason":"Use `locations`."}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"__DirectiveLocation","description":"A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"QUERY","description":"Location adjacent to a query operation.","isDeprecated":false,"deprecationReason":null},{"name":"MUTATION","description":"Location adjacent to a mutation operation.","isDeprecated":false,"deprecationReason":null},{"name":"SUBSCRIPTION","description":"Location adjacent to a subscription operation.","isDeprecated":false,"deprecationReason":null},{"name":"FIELD","description":"Location adjacent to a field.","isDeprecated":false,"deprecationReason":null},{"name":"FRAGMENT_DEFINITION","description":"Location adjacent to a fragment definition.","isDeprecated":false,"deprecationReason":null},{"name":"FRAGMENT_SPREAD","description":"Location adjacent to a fragment spread.","isDeprecated":false,"deprecationReason":null},{"name":"INLINE_FRAGMENT","description":"Location adjacent to an inline fragment.","isDeprecated":false,"deprecationReason":null},{"name":"SCHEMA","description":"Location adjacent to a schema definition.","isDeprecated":false,"deprecationReason":null},{"name":"SCALAR","description":"Location adjacent to a scalar definition.","isDeprecated":false,"deprecationReason":null},{"name":"OBJECT","description":"Location adjacent to an object type definition.","isDeprecated":false,"deprecationReason":null},{"name":"FIELD_DEFINITION","description":"Location adjacent to a field definition.","isDeprecated":false,"deprecationReason":null},{"name":"ARGUMENT_DEFINITION","description":"Location adjacent to an argument definition.","isDeprecated":false,"deprecationReason":null},{"name":"INTERFACE","description":"Location adjacent to an interface definition.","isDeprecated":false,"deprecationReason":null},{"name":"UNION","description":"Location adjacent to a union definition.","isDeprecated":false,"deprecationReason":null},{"name":"ENUM","description":"Location adjacent to an enum definition.","isDeprecated":false,"deprecationReason":null},{"name":"ENUM_VALUE","description":"Location adjacent to an enum value definition.","isDeprecated":false,"deprecationReason":null},{"name":"INPUT_OBJECT","description":"Location adjacent to an input object type definition.","isDeprecated":false,"deprecationReason":null},{"name":"INPUT_FIELD_DEFINITION","description":"Location adjacent to an input object field definition.","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INTERFACE","name":"ActionSet","description":"A set of actions available for an entity to take","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"TeamActionSet","ofType":null}]},{"kind":"INTERFACE","name":"BracketConfig","description":"Bracket-specific configuration","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":null,"args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"RaceBracketConfig","ofType":null}]},{"kind":"ENUM","name":"Comparator","description":"Comparison operator","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"GREATER_THAN","description":"","isDeprecated":false,"deprecationReason":null},{"name":"GREATER_THAN_OR_EQUAL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"EQUAL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"LESS_THAN_OR_EQUAL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"LESS_THAN","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"EventTeam","description":"An event-level Team, in the context of some competition","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discriminator","description":"Uniquely identifying token for team. Same as the hashed part of the slug","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":true,"deprecationReason":"Use the entrant field off the EventTeam type"},{"name":"event","description":null,"args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":true,"deprecationReason":"Use the event field off the EventTeam type"},{"name":"globalTeam","description":null,"args":[],"type":{"kind":"OBJECT","name":"GlobalTeam","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"members","description":null,"args":[{"name":"status","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"TeamMember","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"Team","ofType":null}],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"GlobalTeam","description":"Global Team","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discriminator","description":"Uniquely identifying token for team. Same as the hashed part of the slug","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":true,"deprecationReason":"Use the entrant field off the EventTeam type"},{"name":"event","description":null,"args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":true,"deprecationReason":"Use the event field off the EventTeam type"},{"name":"eventTeams","description":null,"args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"TeamPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventTeamConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"leagueTeams","description":"Leagues-level teams for leagues this team is competing in","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"TeamPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventTeamConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"members","description":null,"args":[{"name":"status","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"TeamMember","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"Team","ofType":null}],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventTeamConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"EventTeam","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INTERFACE","name":"MatchConfig","description":"Match-level configuration","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":null,"args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"RaceMatchConfig","ofType":null}]},{"kind":"ENUM","name":"MatchConfigVerificationMethod","description":"Different options available for verifying player-reported match results","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITCH","description":"","isDeprecated":false,"deprecationReason":null},{"name":"STREAM_ME","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ANY","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"YOUTUBE","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"RaceBracketConfig","description":"Race specific bracket configuration","fields":[{"name":"automaticEndTime","description":null,"args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"automaticStartTime","description":null,"args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":null,"args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"goalTargetComparator","description":null,"args":[],"type":{"kind":"ENUM","name":"Comparator","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"goalTargetValue","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"limitMode","description":null,"args":[],"type":{"kind":"ENUM","name":"RaceLimitMode","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"limitValue","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"raceType","description":null,"args":[],"type":{"kind":"ENUM","name":"RaceType","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"BracketConfig","ofType":null}],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"RaceLimitMode","description":"Enforces limits on the amount of allowable Race submissions","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"BEST_ALL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"FIRST_ALL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"PLAYTIME","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"ENUM","name":"RaceType","description":"Race type","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"GOALS","description":"","isDeprecated":false,"deprecationReason":null},{"name":"TIMED","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"RaceMatchConfig","description":"Race specific match configuration","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":null,"args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"playerReportingEnabled","description":"Can players report results?","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"verificationMethods","description":"Accepted methods of verification that players can use","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"MatchConfigVerificationMethod","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"verificationRequired","description":"Are players required to submit verification of their reported results?","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"MatchConfig","ofType":null}],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"TeamActionSet","description":"A set of actions available for a team to take","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"ActionSet","ofType":null}],"enumValues":null,"possibleTypes":null}],"directives":[{"name":"publicCache","description":"Specify a query to be read from gql-public. Will use the configured cacheAge on\nthe query resolve configuration, or the override value passed through the\ndirective as publicCache(cacheAge: INT) argument.","locations":["FIELD"],"args":[{"name":"cacheAge","description":"Optional override for the query-level cacheAge value.","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null}]},{"name":"userData","description":"Specify a field to only be included in the response if the user is logged in.","locations":["FIELD"],"args":[]},{"name":"skip","description":"Directs the executor to skip this field or fragment when the `if` argument is true.","locations":["FIELD","FRAGMENT_SPREAD","INLINE_FRAGMENT"],"args":[{"name":"if","description":"Skipped when true.","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"defaultValue":null}]},{"name":"include","description":"Directs the executor to include this field or fragment only when the `if` argument is true.","locations":["FIELD","FRAGMENT_SPREAD","INLINE_FRAGMENT"],"args":[{"name":"if","description":"Included when true.","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"defaultValue":null}]},{"name":"deprecated","description":"Marks an element of a GraphQL schema as no longer supported.","locations":["FIELD_DEFINITION","ENUM_VALUE"],"args":[{"name":"reason","description":"Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted in [Markdown](https:\/\/daringfireball.net\/projects\/markdown\/).","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":"\"No longer supported\""}]}]}},"extensions":{"cacheControl":{"version":1,"hints":null},"queryComplexity":0},"actionRecords":[]} \ No newline at end of file diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ExcludeFromJacocoGeneratedReport.kt b/app/src/main/java/com/adammcneilly/pocketleague/ExcludeFromJacocoGeneratedReport.kt deleted file mode 100644 index 27ff82cdd..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/ExcludeFromJacocoGeneratedReport.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.adammcneilly.pocketleague - -/** - * Any time we have a function that we want excluded from our JaCoCo coverage report, we can add this - * annotation to it. - * - * NOTE: We should not use this lightly. Use it for things that are relevant to developers, like Jetpack Compose - * previews. Do not use this to hide your application code. - * - * https://stackoverflow.com/a/66918619/3131147 - */ -@Retention(AnnotationRetention.RUNTIME) -@Target(AnnotationTarget.FUNCTION) -annotation class ExcludeFromJacocoGeneratedReport diff --git a/app/src/main/java/com/adammcneilly/pocketleague/MainActivity.kt b/app/src/main/java/com/adammcneilly/pocketleague/MainActivity.kt index 21fef1f79..e58be714a 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/MainActivity.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/MainActivity.kt @@ -4,19 +4,14 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.runtime.SideEffect -import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.core.view.WindowCompat import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme import com.google.accompanist.insets.ProvideWindowInsets -import com.google.accompanist.insets.statusBarsPadding import com.google.accompanist.systemuicontroller.rememberSystemUiController -import com.ramcosta.composedestinations.DestinationsNavHost import dagger.hilt.android.AndroidEntryPoint /** @@ -36,13 +31,7 @@ class MainActivity : ComponentActivity() { SetSystemBarsTransparent() ProvideWindowInsets { - Scaffold { paddingValues -> - DestinationsNavHost( - modifier = Modifier - .padding(paddingValues) - .statusBarsPadding(), - ) - } + // Coming soon } } } diff --git a/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketPhaseContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketPhaseContent.kt deleted file mode 100644 index 3835c21c4..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketPhaseContent.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.adammcneilly.pocketleague.bracket.ui - -import android.content.res.Configuration -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import com.adammcneilly.pocketleague.R -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.seriesoverview.ui.SeriesOverviewDisplayModel -import com.adammcneilly.pocketleague.shared.core.ui.UIImage -import com.adammcneilly.pocketleague.teamoverview.ui.TeamOverviewDisplayModel -import com.google.accompanist.pager.ExperimentalPagerApi -import com.google.accompanist.pager.HorizontalPager - -/** - * Shows a collection of bracket rounds from the supplied [phase]. - */ -@OptIn(ExperimentalPagerApi::class) -@Composable -fun BracketPhaseContent( - phase: BracketPhaseDisplayModel, - modifier: Modifier = Modifier, -) { - HorizontalPager( - count = phase.rounds.size, - modifier = modifier, - ) { pageIndex -> - BracketRoundList( - bracket = phase.rounds[pageIndex], - modifier = Modifier - .fillMaxSize(), - ) - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun BracketPhaseContentPreview() { - val seriesOverview = SeriesOverviewDisplayModel( - teamOne = TeamOverviewDisplayModel( - name = "G2", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ), - teamTwo = TeamOverviewDisplayModel( - name = "GG", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ), - teamOneWins = 4, - teamTwoWins = 2, - ) - - val rounds = listOf( - BracketRoundDisplayModel( - roundName = "Quarter-Final", - series = listOf(seriesOverview, seriesOverview, seriesOverview, seriesOverview), - ), - BracketRoundDisplayModel( - roundName = "Semi-Final", - series = listOf(seriesOverview, seriesOverview), - ), - BracketRoundDisplayModel( - roundName = "Final", - series = listOf(seriesOverview), - ), - ) - - PocketLeagueTheme { - Surface { - BracketPhaseContent( - phase = BracketPhaseDisplayModel( - rounds = rounds, - ), - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketPhaseDisplayModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketPhaseDisplayModel.kt deleted file mode 100644 index 4ceef3c25..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketPhaseDisplayModel.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.adammcneilly.pocketleague.bracket.ui - -/** - * A collection of [rounds] for the bracket phase of an event. - */ -data class BracketPhaseDisplayModel( - val rounds: List, -) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketRoundDisplayModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketRoundDisplayModel.kt deleted file mode 100644 index 7df8bc256..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketRoundDisplayModel.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.adammcneilly.pocketleague.bracket.ui - -import com.adammcneilly.pocketleague.seriesoverview.ui.SeriesOverviewDisplayModel - -/** - * Information about a round in a bracket format, specified by the [roundName] like Quarter-Final or Semi-Final. - */ -data class BracketRoundDisplayModel( - val roundName: String, - val series: List, -) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketRoundList.kt b/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketRoundList.kt deleted file mode 100644 index 843c73e9f..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketRoundList.kt +++ /dev/null @@ -1,84 +0,0 @@ -package com.adammcneilly.pocketleague.bracket.ui - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.R -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.seriesoverview.ui.SeriesOverviewDisplayModel -import com.adammcneilly.pocketleague.shared.core.ui.UIImage -import com.adammcneilly.pocketleague.teamoverview.ui.TeamOverviewDisplayModel - -/** - * Displays a round of a bracket UI. - */ -@Composable -fun BracketRoundList( - bracket: BracketRoundDisplayModel, - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier - .padding(24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(24.dp) - ) { - - Text( - text = bracket.roundName, - style = MaterialTheme.typography.headlineSmall, - ) - - bracket.series.forEach { series -> - BracketSeriesOverviewItem(seriesOverview = series) - } - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun BracketRoundContentPreview() { - val seriesOverview = SeriesOverviewDisplayModel( - teamOne = TeamOverviewDisplayModel( - name = "G2", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ), - teamTwo = TeamOverviewDisplayModel( - name = "GG", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ), - teamOneWins = 4, - teamTwoWins = 2, - ) - - val bracket = BracketRoundDisplayModel( - roundName = "Quarter-Final", - series = listOf(seriesOverview, seriesOverview, seriesOverview, seriesOverview), - ) - - PocketLeagueTheme { - Surface { - BracketRoundList( - bracket = bracket, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketSeriesOverviewItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketSeriesOverviewItem.kt deleted file mode 100644 index a5d985730..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/bracket/ui/BracketSeriesOverviewItem.kt +++ /dev/null @@ -1,142 +0,0 @@ -package com.adammcneilly.pocketleague.bracket.ui - -import android.content.res.Configuration -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.IntrinsicSize -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.ExcludeFromJacocoGeneratedReport -import com.adammcneilly.pocketleague.R -import com.adammcneilly.pocketleague.android.design.components.Material3VerticalDivider -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.core.ui.Material3Divider -import com.adammcneilly.pocketleague.seriesoverview.ui.SeriesOverviewDisplayModel -import com.adammcneilly.pocketleague.shared.core.ui.UIImage -import com.adammcneilly.pocketleague.teamoverview.ui.TeamOverviewDisplayModel - -/** - * A [seriesOverview] between two teams that occurred inside a bracket format. - */ -@Composable -fun BracketSeriesOverviewItem( - seriesOverview: SeriesOverviewDisplayModel, - modifier: Modifier = Modifier, -) { - Surface( - color = MaterialTheme.colorScheme.background, - modifier = modifier - .border( - width = 1.dp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12F), - ) - ) { - Column { - TeamResult( - teamName = seriesOverview.teamOne.name, - teamWins = seriesOverview.teamOneWins, - isWinner = seriesOverview.teamOneWinner, - ) - - Material3Divider( - color = MaterialTheme.colorScheme.onBackground, - ) - - TeamResult( - teamName = seriesOverview.teamTwo.name, - teamWins = seriesOverview.teamTwoWins, - isWinner = seriesOverview.teamTwoWinner, - ) - } - } -} - -@Composable -private fun TeamResult( - teamName: String, - teamWins: Int, - isWinner: Boolean, -) { - val fontWeight = if (isWinner) { - FontWeight.Bold - } else { - FontWeight.Normal - } - - val backgroundColor = if (isWinner) { - MaterialTheme.colorScheme.primaryContainer - } else { - Color.Unspecified - } - - Row( - modifier = Modifier - .background(backgroundColor) - .height(IntrinsicSize.Max), - ) { - Text( - text = teamName, - fontWeight = fontWeight, - modifier = Modifier - .weight(1F) - .padding(8.dp), - textAlign = TextAlign.Center, - ) - - Material3VerticalDivider( - color = MaterialTheme.colorScheme.onBackground, - ) - - Text( - text = teamWins.toString(), - fontWeight = fontWeight, - modifier = Modifier - .padding(8.dp), - ) - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -@ExcludeFromJacocoGeneratedReport -private fun BracketSeriesOverviewItemPreview() { - val overview = SeriesOverviewDisplayModel( - teamOne = TeamOverviewDisplayModel( - name = "G2", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ), - teamTwo = TeamOverviewDisplayModel( - name = "GG", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ), - teamOneWins = 4, - teamTwoWins = 2, - ) - - PocketLeagueTheme { - BracketSeriesOverviewItem( - seriesOverview = overview, - ) - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/data/remote/smashgg/SmashGGAuthorizationInterceptor.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/data/remote/smashgg/SmashGGAuthorizationInterceptor.kt deleted file mode 100644 index fb5484ec6..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/data/remote/smashgg/SmashGGAuthorizationInterceptor.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.adammcneilly.pocketleague.core.data.remote.smashgg - -import com.adammcneilly.pocketleague.BuildConfig -import okhttp3.Interceptor -import okhttp3.Response -import javax.inject.Inject - -/** - * A custom [Interceptor] implementation that adds the Smash.gg API key as a header to all requests. - */ -class SmashGGAuthorizationInterceptor @Inject constructor() : Interceptor { - - override fun intercept(chain: Interceptor.Chain): Response { - val newRequest = chain - .request() - .newBuilder() - .addHeader("Authorization", "Bearer ${BuildConfig.SMASH_GG_API_KEY}") - .build() - - return chain.proceed(newRequest) - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/data/remote/smashgg/SmashGGModelMapper.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/data/remote/smashgg/SmashGGModelMapper.kt deleted file mode 100644 index 9c99df33d..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/data/remote/smashgg/SmashGGModelMapper.kt +++ /dev/null @@ -1,158 +0,0 @@ -package com.adammcneilly.pocketleague.core.data.remote.smashgg - -import com.adammcneilly.pocketleague.core.models.BracketType -import com.adammcneilly.pocketleague.core.models.EventOverview -import com.adammcneilly.pocketleague.core.models.EventSet -import com.adammcneilly.pocketleague.core.models.PhaseDetail -import com.adammcneilly.pocketleague.core.models.PhaseOverview -import com.adammcneilly.pocketleague.core.models.Player -import com.adammcneilly.pocketleague.core.models.SetSlot -import com.adammcneilly.pocketleague.core.models.Standings -import com.adammcneilly.pocketleague.core.models.StandingsPlacement -import com.adammcneilly.pocketleague.core.models.Team -import com.adammcneilly.pocketleague.graphql.fragment.EventEntrantFragment -import com.adammcneilly.pocketleague.graphql.fragment.EventOverviewFragment -import com.adammcneilly.pocketleague.graphql.fragment.EventPlayerFragment -import com.adammcneilly.pocketleague.graphql.fragment.EventSetFragment -import com.adammcneilly.pocketleague.graphql.fragment.PhaseDetailFragment -import com.adammcneilly.pocketleague.graphql.fragment.PhaseGroupFragment -import com.adammcneilly.pocketleague.graphql.fragment.SetSlotFragment -import com.adammcneilly.pocketleague.graphql.fragment.StandingsPlacementFragment -import kotlinx.datetime.Instant -import kotlinx.datetime.TimeZone -import kotlinx.datetime.toLocalDateTime -import javax.inject.Inject - -typealias ApolloBracketType = com.adammcneilly.pocketleague.graphql.type.BracketType - -/** - * A helper class that maps smash.gg DTO models to a corresponding Pocket League domain model. - */ -class SmashGGModelMapper @Inject constructor() { - /** - * Convert the supplied [eventOverview] to an [EventOverview] entity. - */ - fun eventOverviewFragmentToEventOverview(eventOverview: EventOverviewFragment?): EventOverview { - val eventTimeZone = TimeZone.UTC - val startSeconds = (eventOverview?.eventSummaryFragment?.startAt as Int).toLong() - val startDate = Instant.fromEpochSeconds(startSeconds).toLocalDateTime(eventTimeZone) - - return EventOverview( - name = eventOverview.eventSummaryFragment.name.orEmpty(), - phases = eventOverview.phaseGroups - ?.mapNotNull { - it?.phaseGroupFragment.let(PhaseGroupFragment?::toPhase) - } - ?.sortedBy { - it.phaseOrder - } - ?.distinctBy { phase -> - phase.phaseOrder - } - .orEmpty(), - startDate = startDate, - timeZone = eventTimeZone, - standings = Standings( - placements = eventOverview.standings - ?.nodes - ?.mapNotNull { node -> - node - ?.standingsPlacementFragment - .let(StandingsPlacementFragment?::toStandingsPlacement) - } - .orEmpty() - ), - ) - } - - /** - * Convert the supplied [phaseDetail] to a [PhaseDetail] entity. - */ - fun phaseDetailFragmentToPhaseDetail(phaseDetail: PhaseDetailFragment?): PhaseDetail { - val phaseOverview = phaseDetail?.phaseOverviewFragment - - return PhaseDetail( - id = phaseOverview?.id.orEmpty(), - groupId = "", - numPools = phaseOverview?.groupCount ?: 0, - numEntrants = phaseOverview?.numSeeds ?: 0, - name = phaseOverview?.name.orEmpty(), - phaseOrder = phaseOverview?.phaseOrder ?: 0, - bracketType = phaseOverview?.bracketType?.toBracketType() - ?: BracketType.UNKNOWN, - sets = phaseDetail?.sets?.nodes?.mapNotNull { set -> - set?.eventSetFragment.toEventSet() - }.orEmpty(), - ) - } -} - -private fun EventSetFragment?.toEventSet(): EventSet { - return EventSet( - fullRoundText = this?.fullRoundText.orEmpty(), - displayScore = this?.displayScore.orEmpty(), - round = this?.round.toString(), - winnerId = this?.winnerId.toString(), - slots = this?.slots?.mapNotNull { setSlot -> - setSlot?.setSlotFragment?.toSetSlot() - }.orEmpty(), - games = emptyList(), - ) -} - -private fun SetSlotFragment?.toSetSlot(): SetSlot { - return SetSlot( - team = this?.entrant?.eventEntrantFragment.toTeam(), - slotIndex = this?.slotIndex ?: 0, - ) -} - -private fun EventPlayerFragment?.toPlayer(): Player { - return Player( - countryCode = "", - gamerTag = this?.gamerTag.orEmpty(), - realName = "", - ) -} - -private fun EventEntrantFragment?.toTeam(): Team { - return Team( - name = this?.name.orEmpty(), - lightThemeLogoImageUrl = this?.team?.images?.firstOrNull()?.url, - darkThemeLogoImageUrl = this?.team?.images?.firstOrNull()?.url, - roster = this?.team?.members?.mapNotNull { member -> - member?.player?.eventPlayerFragment.let(EventPlayerFragment?::toPlayer) - }.orEmpty(), - ) -} - -private fun StandingsPlacementFragment?.toStandingsPlacement(): StandingsPlacement { - return StandingsPlacement( - placement = this?.placement ?: 0, - team = this?.entrant?.eventEntrantFragment.let(EventEntrantFragment?::toTeam), - ) -} - -private fun PhaseGroupFragment?.toPhase(): PhaseOverview { - val overview = this?.phase?.phaseOverviewFragment - - return PhaseOverview( - id = overview?.id.orEmpty(), - groupId = this?.id.orEmpty(), - numPools = overview?.groupCount ?: 0, - numEntrants = overview?.numSeeds ?: 0, - name = overview?.name.orEmpty(), - bracketType = this?.bracketType?.toBracketType() - ?: BracketType.UNKNOWN, - phaseOrder = overview?.phaseOrder ?: 0, - ) -} - -private fun ApolloBracketType.toBracketType(): BracketType { - return when (this) { - ApolloBracketType.CUSTOM_SCHEDULE -> BracketType.CUSTOM - ApolloBracketType.SINGLE_ELIMINATION -> BracketType.SINGLE_ELIMINATION - ApolloBracketType.DOUBLE_ELIMINATION -> BracketType.DOUBLE_ELIMINATION - else -> BracketType.UNKNOWN - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/di/DataModule.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/di/DataModule.kt deleted file mode 100644 index 6d34d372c..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/di/DataModule.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.adammcneilly.pocketleague.core.di - -import com.adammcneilly.pocketleague.shared.data.event.EventRepository -import com.adammcneilly.pocketleague.shared.data.event.remote.smashgg.SmashGGEventService -import com.adammcneilly.pocketleague.shared.data.phase.PhaseRepository -import com.adammcneilly.pocketleague.shared.data.phase.remote.smashgg.SmashGGPhaseService -import com.adammcneilly.pocketleague.teamlist.data.MockTeamListService -import com.adammcneilly.pocketleague.teamlist.data.TeamListService -import dagger.Binds -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent - -/** - * Defines all dependencies related to our data layer. - */ -@Module -@InstallIn(SingletonComponent::class) -@Suppress("UndocumentedPublicFunction") -abstract class DataModule { - @Binds - abstract fun bindTeamListService( - teamListService: MockTeamListService, - ): TeamListService - - companion object { - @Provides - fun provideFeatureEventRepository(): com.adammcneilly.pocketleague.event.api.EventRepository { - return com.adammcneilly.pocketleague.event.implementation.octanegg.OctaneGGEventService() - } - - @Provides - fun provideEventRepository(): EventRepository { - return SmashGGEventService() - } - - @Provides - fun providePhaseRepository(): PhaseRepository { - return SmashGGPhaseService() - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/di/RemoteModule.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/di/RemoteModule.kt deleted file mode 100644 index 84ab349c2..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/di/RemoteModule.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.adammcneilly.pocketleague.core.di - -import com.adammcneilly.pocketleague.BuildConfig -import com.adammcneilly.pocketleague.core.data.remote.smashgg.SmashGGAuthorizationInterceptor -import com.apollographql.apollo3.ApolloClient -import com.apollographql.apollo3.network.okHttpClient -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import okhttp3.OkHttpClient -import okhttp3.logging.HttpLoggingInterceptor -import javax.inject.Qualifier - -/** - * A [Qualifier] annotation for the Smash.gg OkHttp client dependency. - */ -@Qualifier -@Retention(AnnotationRetention.BINARY) -annotation class SmashGGOkHttpClient - -/** - * A module to provide all dependencies related to remote data requests. - */ -@Module -@InstallIn(SingletonComponent::class) -@Suppress("UndocumentedPublicFunction") -object RemoteModule { - - @Provides - fun provideLoggingInterceptor(): HttpLoggingInterceptor { - return HttpLoggingInterceptor().apply { - val level = if (BuildConfig.DEBUG) { - HttpLoggingInterceptor.Level.BODY - } else { - HttpLoggingInterceptor.Level.NONE - } - - setLevel(level) - } - } - - @SmashGGOkHttpClient - @Provides - fun provideSmashGGOkHttpClient( - authInterceptor: SmashGGAuthorizationInterceptor, - loggingInterceptor: HttpLoggingInterceptor, - ): OkHttpClient { - return OkHttpClient.Builder() - .addInterceptor(authInterceptor) - .addInterceptor(loggingInterceptor) - .build() - } - - @Provides - fun provideSmashGGApolloClient( - @SmashGGOkHttpClient - client: OkHttpClient, - ): ApolloClient { - return ApolloClient.Builder() - .serverUrl("https://api.smash.gg/gql/alpha") - .okHttpClient(client) - .build() - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/di/UseCaseModule.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/di/UseCaseModule.kt deleted file mode 100644 index 588681a23..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/di/UseCaseModule.kt +++ /dev/null @@ -1,59 +0,0 @@ -package com.adammcneilly.pocketleague.core.di - -import com.adammcneilly.pocketleague.event.api.EventRepository -import com.adammcneilly.pocketleague.feature.eventsummarylist.domain.GetEventSummariesUseCase -import com.adammcneilly.pocketleague.feature.eventsummarylist.domain.GetEventSummariesUseCaseImpl -import com.adammcneilly.pocketleague.shared.data.phase.PhaseRepository -import com.adammcneilly.pocketleague.shared.eventoverview.domain.GetEventOverviewUseCase -import com.adammcneilly.pocketleague.shared.eventoverview.domain.GetEventOverviewUseCaseImpl -import com.adammcneilly.pocketleague.shared.phasedetail.domain.GetPhaseDetailUseCase -import com.adammcneilly.pocketleague.shared.phasedetail.domain.GetPhaseDetailUseCaseImpl -import com.adammcneilly.pocketleague.teamlist.domain.usecases.FetchAllTeamsUseCase -import com.adammcneilly.pocketleague.teamlist.domain.usecases.FetchAllTeamsUseCaseImpl -import dagger.Binds -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent - -/** - * A collection of all use case dependencies in the application. - */ -@Module -@InstallIn(SingletonComponent::class) -@Suppress("UndocumentedPublicFunction") -abstract class UseCaseModule { - @Binds - abstract fun bindFetchAllTeamsUseCase( - fetchAllTeamsUseCase: FetchAllTeamsUseCaseImpl, - ): FetchAllTeamsUseCase - - companion object { - @Provides - fun provideGetUpcomingEventSummariesUseCase( - repository: EventRepository, - ): GetEventSummariesUseCase { - return GetEventSummariesUseCaseImpl( - repository = repository, - ) - } - - @Provides - fun provideGetEventOverviewUseCase( - repository: com.adammcneilly.pocketleague.shared.data.event.EventRepository, - ): GetEventOverviewUseCase { - return GetEventOverviewUseCaseImpl( - repository = repository, - ) - } - - @Provides - fun provideGetPhaseDetailUseCase( - repository: PhaseRepository, - ): GetPhaseDetailUseCase { - return GetPhaseDetailUseCaseImpl( - repository = repository, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/di/UtilModule.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/di/UtilModule.kt deleted file mode 100644 index 082e5a865..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/di/UtilModule.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.adammcneilly.pocketleague.core.di - -import android.content.Context -import com.adammcneilly.pocketleague.core.html.HTMLParser -import com.adammcneilly.pocketleague.core.html.JSoupHTMLParser -import com.adammcneilly.pocketleague.core.ui.FlagKitFlagResProvider -import com.adammcneilly.pocketleague.core.ui.FlagResProvider -import com.adammcneilly.pocketleague.core.utils.DateTimeHelper -import com.adammcneilly.pocketleague.core.utils.DateUtils -import dagger.Binds -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent - -/** - * Provides a number of dependencies that are related to utility classes. - */ -@Module -@InstallIn(SingletonComponent::class) -@Suppress("UndocumentedPublicFunction") -abstract class UtilModule { - - @Binds - abstract fun bindHTMLParser( - htmlParser: JSoupHTMLParser, - ): HTMLParser - - companion object { - @Provides - fun provideDateTimeHelper(): DateTimeHelper { - return DateUtils - } - - @Provides - fun provideFlagResProvider( - @ApplicationContext applicationContext: Context, - ): FlagResProvider { - return FlagKitFlagResProvider(applicationContext) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/html/HTMLDocument.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/html/HTMLDocument.kt deleted file mode 100644 index 6e4977f54..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/html/HTMLDocument.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.adammcneilly.pocketleague.core.html - -/** - * A wrapper interface that represents a document of HTML code for parsing. - */ -interface HTMLDocument { - /** - * Generates a collection of [HTMLElement] entities that match the given [elementType] and have - * a class value of [elementClass]. - */ - fun selectAll( - elementType: String, - elementClass: String, - ): List -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/html/HTMLElement.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/html/HTMLElement.kt deleted file mode 100644 index fe6f7f7a8..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/html/HTMLElement.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.adammcneilly.pocketleague.core.html - -/** - * An [HTMLElement] is a specific node within the tree of HTML content. - */ -interface HTMLElement { - /** - * Returns the text value of this element. - */ - fun getText(): String - - /** - * Generates a collection of [HTMLElement] entities that match the given [elementType] and have - * a class value of [elementClass]. - */ - fun selectAll( - elementType: String, - elementClass: String, - ): List - - /** - * Selects the first [HTMLElement] entity that matches the given [elementType] and have - * a class value of [elementClass]. - */ - fun selectFirst( - elementType: String, - elementClass: String, - ): HTMLElement? - - /** - * Finds an attribute with the given [attributeKey] and returns its value. - */ - fun getAttribute( - attributeKey: String, - ): String -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/html/HTMLParser.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/html/HTMLParser.kt deleted file mode 100644 index 9f37998f3..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/html/HTMLParser.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.adammcneilly.pocketleague.core.html - -/** - * A wrapper interface for any libraries used to parse HTML text. - */ -interface HTMLParser { - /** - * Sets the [html] we want to parse. - */ - fun setHTML(html: String) - - /** - * Generates a collection of [HTMLElement] entities that match the given [elementType] and have - * a class value of [elementClass]. - */ - fun selectAll( - elementType: String, - elementClass: String, - ): List -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/html/JSoupHTMLDocument.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/html/JSoupHTMLDocument.kt deleted file mode 100644 index ec7cf8108..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/html/JSoupHTMLDocument.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.adammcneilly.pocketleague.core.html - -import org.jsoup.nodes.Document - -/** - * A concrete implementation of an [HTMLDocument] that is backed by a jsoup [document]. - */ -class JSoupHTMLDocument( - private val document: Document, -) : HTMLDocument { - - override fun selectAll(elementType: String, elementClass: String): List { - val selector = StringBuilder(elementType).apply { - if (elementClass.isNotEmpty()) { - append(".$elementClass") - } - }.toString() - - val elements = document.select(selector) - - return elements.map { element -> - JSoupHTMLElement(element) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/html/JSoupHTMLElement.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/html/JSoupHTMLElement.kt deleted file mode 100644 index 750b2660d..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/html/JSoupHTMLElement.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.adammcneilly.pocketleague.core.html - -import org.jsoup.nodes.Element - -/** - * A concrete implementation of an [HTMLElement] that is backed by a jsoup [Element]. - */ -class JSoupHTMLElement( - private val element: Element, -) : HTMLElement { - override fun getText(): String { - return element.text() - } - - override fun selectAll(elementType: String, elementClass: String): List { - val selector = StringBuilder(elementType).apply { - if (elementClass.isNotEmpty()) { - append(".$elementClass") - } - }.toString() - - val elements = element.select(selector) - - return elements.map { element -> - JSoupHTMLElement(element) - } - } - - override fun selectFirst(elementType: String, elementClass: String): HTMLElement? { - return selectAll(elementType, elementClass).firstOrNull() - } - - override fun getAttribute(attributeKey: String): String { - return element - .attributes() - .get(attributeKey) - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/html/JSoupHTMLParser.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/html/JSoupHTMLParser.kt deleted file mode 100644 index 4602aab79..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/html/JSoupHTMLParser.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.adammcneilly.pocketleague.core.html - -import org.jsoup.Jsoup -import javax.inject.Inject - -/** - * A concrete implementation of an [HTMLParser] that is backed by the [Jsoup] library. - */ -class JSoupHTMLParser @Inject constructor() : HTMLParser { - private lateinit var document: HTMLDocument - - override fun setHTML(html: String) { - val doc = Jsoup.parse(html) - document = JSoupHTMLDocument(doc) - } - - override fun selectAll(elementType: String, elementClass: String): List { - return document.selectAll(elementType, elementClass) - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/FlagKitFlagResProvider.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/ui/FlagKitFlagResProvider.kt deleted file mode 100644 index 622861f54..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/FlagKitFlagResProvider.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.adammcneilly.pocketleague.core.ui - -import android.content.Context -import com.murgupluoglu.flagkit.FlagKit - -/** - * A concrete implementation of a [FlagResProvider] that uses the [FlagKit] API. - */ -class FlagKitFlagResProvider( - private val context: Context, -) : FlagResProvider { - - override fun getFlagRes(countryCode: String): Int { - return FlagKit.getResId(context, countryCode) - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/FlagResProvider.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/ui/FlagResProvider.kt deleted file mode 100644 index 1ab532b89..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/FlagResProvider.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.adammcneilly.pocketleague.core.ui - -/** - * This is a wrapper around any service that can provide image resources for a flag based on a - * country code. - */ -interface FlagResProvider { - /** - * Given a [countryCode], fetch the corresponding drawable resource for that country's flag. - */ - fun getFlagRes(countryCode: String): Int -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/Material3Card.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/ui/Material3Card.kt deleted file mode 100644 index d1b408d88..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/Material3Card.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.adammcneilly.pocketleague.core.ui - -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.material3.Card -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier - -/** - * A Material 3 version of a Card composable, until it's implemented by Google. - */ -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun Material3Card( - modifier: Modifier = Modifier, - content: @Composable ColumnScope.() -> Unit, -) { - Card( - modifier = modifier, - content = content, - ) -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/Material3CircularProgressIndicator.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/ui/Material3CircularProgressIndicator.kt deleted file mode 100644 index dbcfa4553..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/Material3CircularProgressIndicator.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.adammcneilly.pocketleague.core.ui - -import androidx.compose.foundation.layout.BoxScope -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.material.CircularProgressIndicator -import androidx.compose.material.ProgressIndicatorDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.Dp - -/** - * A custom implementation of a [CircularProgressIndicator] that abides by material 3 theming. - */ -@Composable -fun Material3CircularProgressIndicator( - modifier: Modifier = Modifier, - color: Color = MaterialTheme.colorScheme.primary, - strokeWidth: Dp = ProgressIndicatorDefaults.StrokeWidth, -) { - CircularProgressIndicator( - modifier = modifier, - color = color, - strokeWidth = strokeWidth, - ) -} - -/** - * A custom implementation of [Material3CircularProgressIndicator] that will center it within the - * [BoxScope]. - */ -@Composable -fun BoxScope.CenteredMaterial3CircularProgressIndicator() { - Material3CircularProgressIndicator( - modifier = Modifier - .wrapContentSize() - .align(Alignment.Center), - ) -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/Material3Divider.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/ui/Material3Divider.kt deleted file mode 100644 index da22c9700..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/Material3Divider.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.adammcneilly.pocketleague.core.ui - -import androidx.compose.material3.Divider -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color - -/** - * A wrapper around [Divider] that provides the color based on the material 3 theme. - */ -@Composable -fun Material3Divider( - modifier: Modifier = Modifier, - color: Color = MaterialTheme.colorScheme.onSurface -) { - Divider( - modifier = modifier, - color = color, - ) -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/PocketLeagueImage.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/ui/PocketLeagueImage.kt deleted file mode 100644 index 7c76eb6c4..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/PocketLeagueImage.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.adammcneilly.pocketleague.core.ui - -import androidx.compose.foundation.Image -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource -import coil.compose.rememberImagePainter -import com.adammcneilly.pocketleague.shared.core.ui.UIImage - -/** - * A custom composable for an [Image] that will set the painter based on the [image] supplied. - */ -@Composable -fun PocketLeagueImage( - image: UIImage, - contentDescription: String?, - modifier: Modifier = Modifier, - contentScale: ContentScale = ContentScale.Fit, -) { - when (image) { - is UIImage.AndroidResource -> { - Image( - painterResource(id = image.drawableRes), - contentDescription = contentDescription, - modifier = modifier, - contentScale = contentScale, - ) - } - is UIImage.Remote -> { - Image( - rememberImagePainter(data = image.imageUrl), - contentDescription = contentDescription, - modifier = modifier, - contentScale = contentScale, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/TextCard.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/ui/TextCard.kt deleted file mode 100644 index 70fa4cadd..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/TextCard.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.adammcneilly.pocketleague.core.ui - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.aspectRatio -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import com.adammcneilly.pocketleague.ExcludeFromJacocoGeneratedReport -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme - -private const val CARD_ASPECT_RATIO = 4.0F - -/** - * An instance of a [Material3Card] that presents some [text] to the user. - */ -@Composable -fun TextCard( - text: String, - modifier: Modifier = Modifier, -) { - Material3Card( - modifier = modifier - .fillMaxWidth() - .aspectRatio(CARD_ASPECT_RATIO), - ) { - Box( - modifier = Modifier - .fillMaxSize(), - ) { - Text( - text = text, - modifier = Modifier - .align(Alignment.Center), - ) - } - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -@ExcludeFromJacocoGeneratedReport -private fun TextCardPreview() { - PocketLeagueTheme { - TextCard( - text = "This information is currently unavailable." - ) - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/WindowSize.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/ui/WindowSize.kt deleted file mode 100644 index 7f366b6c2..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/ui/WindowSize.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.adammcneilly.pocketleague.core.ui - -import android.app.Activity -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.geometry.Size -import androidx.compose.ui.graphics.toComposeRect -import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.unit.DpSize -import androidx.compose.ui.unit.dp -import androidx.window.layout.WindowMetricsCalculator - -/** - * Opinionated set of viewport breakpoints - * - Compact: Most phones in portrait mode - * - Medium: Most foldables and tablets in portrait mode - * - Expanded: Most tablets in landscape mode - * - * More info: https://material.io/archive/guidelines/layout/responsive-ui.html - */ -enum class WindowSize { Compact, Medium, Expanded } - -/** - * Remembers the [WindowSize] class for the window corresponding to the current window metrics. - */ -@Composable -fun Activity.rememberWindowSizeClass(): WindowSize { - // Get the size (in pixels) of the window - val windowSize = rememberWindowSize() - - // Convert the window size to [Dp] - val windowDpSize = with(LocalDensity.current) { - windowSize.toDpSize() - } - - // Calculate the window size class - return getWindowSizeClass(windowDpSize) -} - -/** - * Remembers the [Size] in pixels of the window corresponding to the current window metrics. - */ -@Composable -private fun Activity.rememberWindowSize(): Size { - val configuration = LocalConfiguration.current - // WindowMetricsCalculator implicitly depends on the configuration through the activity, - // so re-calculate it upon changes. - val windowMetrics = remember(configuration) { - WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(this) - } - return windowMetrics.bounds.toComposeRect().size -} - -/** - * Partitions a [DpSize] into a enumerated [WindowSize] class. - */ -fun getWindowSizeClass(windowDpSize: DpSize): WindowSize = when { - windowDpSize.width < 0.dp -> throw IllegalArgumentException("Dp value cannot be negative") - windowDpSize.width < 600.dp -> WindowSize.Compact - windowDpSize.width < 840.dp -> WindowSize.Medium - else -> WindowSize.Expanded -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/utils/DateTimeHelper.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/utils/DateTimeHelper.kt deleted file mode 100644 index 9f919d223..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/utils/DateTimeHelper.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.adammcneilly.pocketleague.core.utils - -import java.time.LocalDateTime - -/** - * A collection of helper functions for dealing with date and time objects. - */ -interface DateTimeHelper { - /** - * Given a [date], format into a user friendly time string for a series between two teams. - */ - fun getSeriesDayTimeString(date: LocalDateTime): String - - /** - * Given some [epochSeconds], convert it to a user friendly string to show the day of this event. - */ - fun getEventDayString(epochSeconds: Long): String -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/core/utils/DateUtils.kt b/app/src/main/java/com/adammcneilly/pocketleague/core/utils/DateUtils.kt deleted file mode 100644 index 0c0c3bcef..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/core/utils/DateUtils.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.adammcneilly.pocketleague.core.utils - -import java.time.Instant -import java.time.LocalDateTime -import java.time.ZoneOffset -import java.time.format.DateTimeFormatter - -/** - * A concrete implementation of a [DateTimeHelper] that will do date formatting. - */ -object DateUtils : DateTimeHelper { - private const val SERIES_DAY_TIME_FORMAT = "MMMM dd, yyyy - HH:mm" - - private const val EVENT_DAY_FORMAT = "MMM dd, yyyy" - - override fun getSeriesDayTimeString(date: LocalDateTime): String { - return DateTimeFormatter.ofPattern(SERIES_DAY_TIME_FORMAT).format(date) - } - - override fun getEventDayString(epochSeconds: Long): String { - val zonedDateTime = Instant - .ofEpochSecond(epochSeconds) - .atOffset(ZoneOffset.UTC) - .toZonedDateTime() - - return DateTimeFormatter.ofPattern(EVENT_DAY_FORMAT).format(zonedDateTime) - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventContent.kt deleted file mode 100644 index bf1e9af6b..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventContent.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.adammcneilly.pocketleague.event.ui - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.swiss.ui.SwissRoundList - -/** - * The concrete UI content for the event screen based on the supplied [viewState]. - */ -@Composable -fun EventContent( - viewState: EventViewState, - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier - .verticalScroll(rememberScrollState()) - .padding(16.dp), - ) { - viewState.swissStage?.rounds.orEmpty().forEach { swissRound -> - SwissRoundList(swissRound = swissRound) - - Spacer(modifier = Modifier.height(16.dp)) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventScreen.kt b/app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventScreen.kt deleted file mode 100644 index 7bf1db3e1..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventScreen.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.adammcneilly.pocketleague.event.ui - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.ui.Modifier -import androidx.hilt.navigation.compose.hiltViewModel - -/** - * The composable representing the event screen that consumes a UI state - * from the [viewModel]. - */ -@Composable -fun EventScreen( - modifier: Modifier = Modifier, - viewModel: EventViewModel = hiltViewModel(), -) { - val viewState = viewModel.viewState.collectAsState() - - EventContent( - viewState = viewState.value, - modifier = modifier, - ) -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventViewModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventViewModel.kt deleted file mode 100644 index da4e9a810..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventViewModel.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.adammcneilly.pocketleague.event.ui - -import androidx.lifecycle.ViewModel -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import javax.inject.Inject - -/** - * A UI State management class for the event detail screen. - */ -@HiltViewModel -class EventViewModel @Inject constructor() : ViewModel() { - private val _viewState = MutableStateFlow(EventViewState()) - val viewState: StateFlow = _viewState -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventViewState.kt b/app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventViewState.kt deleted file mode 100644 index 23691aa67..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/event/ui/EventViewState.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.adammcneilly.pocketleague.event.ui - -import com.adammcneilly.pocketleague.swiss.ui.SwissStageDisplayModel - -/** - * All information necessary to render the UI for an RLCS event. This includes the - * loading/content/error states. - */ -data class EventViewState( - val showLoading: Boolean = true, - val showContent: Boolean = false, - val showError: Boolean = false, - val swissStage: SwissStageDisplayModel? = null, -) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewContent.kt deleted file mode 100644 index 4e416ab84..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewContent.kt +++ /dev/null @@ -1,232 +0,0 @@ -package com.adammcneilly.pocketleague.eventoverview.ui - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.ExcludeFromJacocoGeneratedReport -import com.adammcneilly.pocketleague.R -import com.adammcneilly.pocketleague.android.design.getValue -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.core.ui.CenteredMaterial3CircularProgressIndicator -import com.adammcneilly.pocketleague.core.ui.Material3Card -import com.adammcneilly.pocketleague.core.ui.TextCard -import com.adammcneilly.pocketleague.phase.ui.PhaseList -import com.adammcneilly.pocketleague.shared.eventoverview.state.EventOverviewViewState -import com.adammcneilly.pocketleague.shared.eventoverview.ui.EventOverviewDisplayModel -import com.adammcneilly.pocketleague.shared.eventoverview.ui.EventOverviewPhaseDisplayModel -import com.adammcneilly.pocketleague.shared.standings.StandingsDisplayModel -import com.adammcneilly.pocketleague.shared.standings.StandingsPlacementDisplayModel -import com.adammcneilly.pocketleague.standings.ui.StandingsList - -/** - * Displays the event overview information given the [viewState]. - */ -@Composable -fun EventOverviewContent( - viewState: EventOverviewViewState, - onPhaseClicked: (String) -> Unit, - modifier: Modifier = Modifier, -) { - Box( - modifier = modifier - .fillMaxSize(), - ) { - if (viewState.showLoading) { - CenteredMaterial3CircularProgressIndicator() - } - - val displayModel = viewState.event - - if (displayModel != null) { - SuccessContent( - event = displayModel, - onPhaseClicked = onPhaseClicked, - ) - } - - val errorMessage = viewState.errorMessage - - if (errorMessage != null) { - Text( - text = errorMessage.getValue(), - ) - } - } -} - -@Composable -private fun SuccessContent( - event: EventOverviewDisplayModel, - onPhaseClicked: (String) -> Unit, -) { - Column( - modifier = Modifier - .padding(16.dp) - .verticalScroll(rememberScrollState()), - verticalArrangement = Arrangement.spacedBy(16.dp), - ) { - HeaderLabel( - text = stringResource(R.string.summary), - ) - - Material3Card { - EventOverviewHeader( - event = event, - ) - } - - HeaderLabel( - text = stringResource(R.string.brackets), - ) - - if (event.phases.isNotEmpty()) { - PhaseList( - phases = event.phases, - onPhaseClicked = onPhaseClicked, - ) - } else { - TextCard( - text = stringResource(R.string.bracket_information_unavailable), - ) - } - - HeaderLabel( - text = stringResource(R.string.standings), - ) - - if (event.standings.placements.isNotEmpty()) { - Material3Card { - StandingsList( - standings = event.standings, - ) - } - } else { - TextCard( - text = stringResource(R.string.standings_information_unavailable), - ) - } - } -} - -@Composable -private fun HeaderLabel( - text: String, -) { - Text( - text = text, - style = MaterialTheme.typography.headlineMedium, - ) -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -@Suppress("LongMethod") -@ExcludeFromJacocoGeneratedReport -private fun EventOverviewContentPreview() { - val placements = (1..10).map { - StandingsPlacementDisplayModel( - placement = it.toString(), - teamName = "Pittsburgh Knights", - roster = "sosa / AlphaKep / ElOmarMaton", - teamLogo = null, - ) - } - - val standings = StandingsDisplayModel( - placements = placements, - ) - - val event = EventOverviewDisplayModel( - eventName = "Main Event", - phases = listOf( - EventOverviewPhaseDisplayModel( - phaseId = "123", - phaseName = "Day 1: Swiss Matches", - numPools = "1", - bracketType = "Custom", - numEntrants = "16", - ), - EventOverviewPhaseDisplayModel( - phaseId = "123", - phaseName = "Day 2-3: Single Elimination", - numPools = "1", - bracketType = "SE", - numEntrants = "8", - ), - ), - startDate = "November 12, 2021", - standings = standings, - ) - - val viewState = EventOverviewViewState( - showLoading = false, - event = event, - ) - - PocketLeagueTheme { - Surface { - EventOverviewContent( - viewState = viewState, - onPhaseClicked = {}, - ) - } - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -@Suppress("LongMethod") -@ExcludeFromJacocoGeneratedReport -private fun EventOverviewUpcomingContentPreview() { - val standings = StandingsDisplayModel( - placements = emptyList(), - ) - - val event = EventOverviewDisplayModel( - eventName = "Main Event", - phases = emptyList(), - startDate = "November 12, 2021", - standings = standings, - ) - - val viewState = EventOverviewViewState( - showLoading = false, - event = event, - ) - - PocketLeagueTheme { - Surface { - EventOverviewContent( - viewState = viewState, - onPhaseClicked = {}, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewHeader.kt b/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewHeader.kt deleted file mode 100644 index d2d33b9e3..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewHeader.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.adammcneilly.pocketleague.eventoverview.ui - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.shared.eventoverview.ui.EventOverviewDisplayModel - -/** - * Displays a summary of an [event] overview, if that makes sense lol. Shows the event name, date, - * intended to appear at the top of [EventOverviewcontent]. - */ -@Composable -fun EventOverviewHeader( - event: EventOverviewDisplayModel, - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier - .fillMaxWidth() - .padding(16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp), - ) { - Text( - text = event.startDate, - ) - - Text( - text = event.eventName, - style = MaterialTheme.typography.headlineSmall, - ) - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewNavArgs.kt b/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewNavArgs.kt deleted file mode 100644 index a0a1ae638..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewNavArgs.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.adammcneilly.pocketleague.eventoverview.ui - -/** - * Navigation arguments that will be passed into an [EventOverviewScreen]. - */ -data class EventOverviewNavArgs( - val eventId: String, -) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewScreen.kt b/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewScreen.kt deleted file mode 100644 index a653b0f01..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewScreen.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.adammcneilly.pocketleague.eventoverview.ui - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.ui.Modifier -import androidx.hilt.navigation.compose.hiltViewModel -import com.ramcosta.composedestinations.PhaseDetailScreenDestination -import com.ramcosta.composedestinations.annotation.Destination -import com.ramcosta.composedestinations.navigation.DestinationsNavigator - -/** - * Displays the [EventOverviewContent] with the view state pulled from the supplied [viewModel]. - */ -@Destination( - navArgsDelegate = EventOverviewNavArgs::class, -) -@Composable -fun EventOverviewScreen( - navigator: DestinationsNavigator, - modifier: Modifier = Modifier, - viewModel: EventOverviewViewModel = hiltViewModel(), -) { - val viewState = viewModel.viewState.collectAsState() - - LaunchedEffect(viewState.value) { - val selectedPhaseId = viewState.value.selectedPhaseId - - if (selectedPhaseId != null) { - navigator.navigate( - PhaseDetailScreenDestination( - phaseId = selectedPhaseId - ) - ) - - viewModel.navigatedToPhase() - } - } - - EventOverviewContent( - viewState = viewState.value, - onPhaseClicked = viewModel::phaseClicked, - modifier = modifier, - ) -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewViewModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewViewModel.kt deleted file mode 100644 index fd5747336..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/eventoverview/ui/EventOverviewViewModel.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.adammcneilly.pocketleague.eventoverview.ui - -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.adammcneilly.pocketleague.shared.eventoverview.domain.GetEventOverviewUseCase -import com.adammcneilly.pocketleague.shared.eventoverview.state.EventOverviewAction -import com.adammcneilly.pocketleague.shared.eventoverview.state.eventOverviewStateMutator -import com.ramcosta.composedestinations.EventOverviewScreenDestination -import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject - -/** - * A state management container for the [EventOverviewScreen]. - */ -@HiltViewModel -class EventOverviewViewModel @Inject constructor( - getEventOverviewUseCase: GetEventOverviewUseCase, - savedStateHandle: SavedStateHandle, -) : ViewModel() { - private val mutator = eventOverviewStateMutator( - scope = viewModelScope, - getEventOverviewUseCase = getEventOverviewUseCase, - ) - - val viewState = mutator.state - - private val navArgs = EventOverviewScreenDestination.argsFrom(savedStateHandle) - - init { - val fetchAction = EventOverviewAction.FetchEventOverview( - eventId = navArgs.eventId, - ) - - mutator.accept(fetchAction) - } - - /** - * Triggered whenever the user clicks on a phase section with the given [phaseId]. - */ - fun phaseClicked(phaseId: String) { - val selectAction = EventOverviewAction.SelectPhase(phaseId = phaseId) - - mutator.accept(selectAction) - } - - /** - * When we navigate to a phase, we should clear our selected phase so that we don't - * continue to show it. - */ - fun navigatedToPhase() { - val navigatedAction = EventOverviewAction.NavigatedToPhaseDetail - - mutator.accept(navigatedAction) - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryList.kt b/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryList.kt deleted file mode 100644 index a89380ea9..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryList.kt +++ /dev/null @@ -1,89 +0,0 @@ -package com.adammcneilly.pocketleague.eventsummary.ui - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.ExcludeFromJacocoGeneratedReport -import com.adammcneilly.pocketleague.android.design.adaptiveWidth -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.feature.eventsummarylist.ui.EventSummaryListItemDisplayModel - -/** - * Renders a scrollable list of [displayModels] for event summaries. - */ -@Composable -fun EventSummaryList( - displayModels: List, - eventClicked: (String) -> Unit, - modifier: Modifier = Modifier, -) { - LazyColumn( - modifier = modifier - .adaptiveWidth(), - contentPadding = PaddingValues(16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - items(displayModels) { displayModel -> - EventSummaryListItem( - displayModel = displayModel, - eventClicked = eventClicked, - modifier = Modifier - .fillMaxWidth(), - ) - } - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Preview( - name = "Medium", - uiMode = Configuration.UI_MODE_NIGHT_NO, - widthDp = 800, -) -@Preview( - name = "Expanded", - uiMode = Configuration.UI_MODE_NIGHT_NO, - widthDp = 900, -) -@Composable -@ExcludeFromJacocoGeneratedReport -private fun EventSummaryListPreview() { - val displayModel = EventSummaryListItemDisplayModel( - eventId = "1234", - startDate = "Nov 12, 2021", - eventName = "Main Event", - tournamentName = "RLCS 2021-22 Season - Fall Split Regional 3 - North America", - subtitle = "16 Teams", - imageUrl = null, - ) - - val displayModels = (1..2).map { - displayModel - } - - PocketLeagueTheme { - Surface { - EventSummaryList( - displayModels = displayModels, - eventClicked = {}, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListContent.kt deleted file mode 100644 index 250aaa13c..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListContent.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.adammcneilly.pocketleague.eventsummary.ui - -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.adammcneilly.pocketleague.core.ui.CenteredMaterial3CircularProgressIndicator -import com.adammcneilly.pocketleague.feature.eventsummarylist.state.EventSummaryListViewState -import com.google.accompanist.insets.navigationBarsPadding - -/** - * Displays the content of an event summary list based on the supplied [viewState]. - */ -@Composable -fun EventSummaryListContent( - viewState: EventSummaryListViewState, - eventClicked: (String) -> Unit, - modifier: Modifier = Modifier, -) { - Box( - modifier = modifier, - ) { - if (viewState.showLoading) { - CenteredMaterial3CircularProgressIndicator() - } - - Column { - if (viewState.events.isNotEmpty()) { - EventSummaryList( - displayModels = viewState.events, - eventClicked = eventClicked, - modifier = Modifier.navigationBarsPadding(), - ) - } - } - - val errorMessage = viewState.errorMessage - - if (errorMessage != null) { - Text( - text = errorMessage, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListItem.kt deleted file mode 100644 index fd04b99fa..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListItem.kt +++ /dev/null @@ -1,147 +0,0 @@ -package com.adammcneilly.pocketleague.eventsummary.ui - -import android.content.res.Configuration -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.intl.Locale -import androidx.compose.ui.text.toUpperCase -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.core.ui.Material3Card -import com.adammcneilly.pocketleague.feature.eventsummarylist.ui.EventSummaryListItemDisplayModel - -/** - * Renders a [displayModel] to show a summary of an RLCS event. - */ -@Composable -fun EventSummaryListItem( - displayModel: EventSummaryListItemDisplayModel, - eventClicked: (String) -> Unit, - modifier: Modifier = Modifier, -) { - Material3Card( - modifier = modifier - .clickable( - onClick = { - eventClicked.invoke(displayModel.eventId) - }, - ), - ) { - Column { - // Removing this for the time being, I don't think it was as good as I expected. - // But I think I could benefit from this code in the future. -// PocketLeagueImage( -// image = displayModel.image, -// contentDescription = stringResource(R.string.event_image_content_description), -// modifier = Modifier -// .fillMaxWidth() -// .aspectRatio(1F), -// contentScale = ContentScale.Crop, -// ) - - SummaryInfo(displayModel) - } - } -} - -@Composable -private fun SummaryInfo( - displayModel: EventSummaryListItemDisplayModel -) { - Column( - modifier = Modifier - .padding(16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp), - ) { - EventDateLabel(eventDate = displayModel.startDate) - - TournamentNameLabel(tournamentName = displayModel.tournamentName) - - EventNameLabel(eventName = displayModel.eventName) - - val subtitle = displayModel.subtitle - - if (subtitle != null) { - EventSubtitleLabel(eventSubtitle = subtitle) - } - } -} - -@Composable -private fun EventSubtitleLabel( - eventSubtitle: String, -) { - Text( - text = eventSubtitle, - style = MaterialTheme.typography.bodySmall, - ) -} - -@Composable -private fun EventDateLabel( - eventDate: String, -) { - Text( - text = eventDate.toUpperCase(Locale.current), - style = MaterialTheme.typography.labelSmall, - ) -} - -@Composable -private fun TournamentNameLabel( - tournamentName: String, -) { - Text( - text = tournamentName, - style = MaterialTheme.typography.headlineSmall, - ) -} - -@Composable -private fun EventNameLabel( - eventName: String -) { - Text( - text = eventName, - style = MaterialTheme.typography.bodyMedium, - ) -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun EventSummaryListItemPreview() { - val displayModel = EventSummaryListItemDisplayModel( - eventId = "1234", - startDate = "Nov 12, 2021", - eventName = "Main Event", - tournamentName = "RLCS 2021-22 Season - Fall Split Regional 3 - North America", - subtitle = "16 Teams", - imageUrl = null, - ) - - PocketLeagueTheme { - Surface { - EventSummaryListItem( - displayModel = displayModel, - eventClicked = {}, - modifier = Modifier - .padding(16.dp), - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListScreen.kt b/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListScreen.kt deleted file mode 100644 index a2d759325..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListScreen.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.adammcneilly.pocketleague.eventsummary.ui - -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.ui.Modifier -import androidx.hilt.navigation.compose.hiltViewModel -import com.ramcosta.composedestinations.EventOverviewScreenDestination -import com.ramcosta.composedestinations.annotation.Destination -import com.ramcosta.composedestinations.navigation.DestinationsNavigator - -/** - * The screen composable for [EventSummaryListContent] that manages state from the given [viewModel]. - */ -@Destination(start = true) -@Composable -fun EventSummaryListScreen( - navigator: DestinationsNavigator, - modifier: Modifier = Modifier, - viewModel: EventSummaryListViewModel = hiltViewModel(), -) { - val viewState = viewModel.viewState.collectAsState() - - LaunchedEffect(viewState.value) { - val selectedEventId = viewState.value.selectedEventId - - if (selectedEventId != null) { - navigator.navigate( - EventOverviewScreenDestination( - eventId = selectedEventId, - ) - ) - - viewModel.navigatedToEventOverview() - } - } - - EventSummaryListContent( - viewState = viewState.value, - eventClicked = viewModel::eventClicked, - modifier = modifier - .fillMaxSize(), - ) -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListViewModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListViewModel.kt deleted file mode 100644 index 13f003fe0..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/eventsummary/ui/EventSummaryListViewModel.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.adammcneilly.pocketleague.eventsummary.ui - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.adammcneilly.pocketleague.feature.eventsummarylist.EventSummaryListSort -import com.adammcneilly.pocketleague.feature.eventsummarylist.domain.GetEventSummariesUseCase -import com.adammcneilly.pocketleague.feature.eventsummarylist.state.EventSummaryListAction -import com.adammcneilly.pocketleague.feature.eventsummarylist.state.eventSummaryListStateMutator -import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject - -/** - * A state management container for the [EventSummaryListScreen]. - */ -@HiltViewModel -class EventSummaryListViewModel @Inject constructor( - getEventsUseCase: GetEventSummariesUseCase, -) : ViewModel() { - - private val mutator = eventSummaryListStateMutator( - scope = viewModelScope, - getEventsUseCase = getEventsUseCase, - ) - - val viewState = mutator.state - - init { - val fetchAction = EventSummaryListAction.FetchEventSummaries( - request = GetEventSummariesUseCase.Request(), - ) - - mutator.accept(fetchAction) - } - - /** - * When we navigate to an event overview, we should clear our selected event so that we don't - * continue to show it. - */ - fun navigatedToEventOverview() { - val action = EventSummaryListAction.NavigatedToEventOverview - - mutator.accept(action) - } - - /** - * Whenever a user clicks an event we consume that [eventId] and update state accordingly. - */ - fun eventClicked(eventId: String) { - val action = EventSummaryListAction.SelectedEvent(eventId) - - mutator.accept(action) - } - - /** - * Whenever the user toggles the sort option for the summary list. - */ - fun sortChanged(sort: EventSummaryListSort) { - val action = EventSummaryListAction.SelectedSort(sort) - - mutator.accept(action) - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/gameresult/ui/GameResultDisplayModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/gameresult/ui/GameResultDisplayModel.kt deleted file mode 100644 index 7afa2480d..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/gameresult/ui/GameResultDisplayModel.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.adammcneilly.pocketleague.gameresult.ui - -/** - * Defines the UI configuration for the result of an individual game. - * - * NOTE: Should we define orange/blue team? Can we? Should winner be an enum? - * - * @property[stadium] The RL map that the game took place on. - * @property[teamOneScore] The score of the first team. - * @property[teamTwoScore] The score of the second team. - */ -data class GameResultDisplayModel( - val stadium: String, - val teamOneScore: Int, - val teamTwoScore: Int, -) { - - val teamOneWinner: Boolean - get() = teamOneScore > teamTwoScore - - val teamTwoWinner: Boolean - get() = teamTwoScore > teamOneScore -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/gameresult/ui/GameResultList.kt b/app/src/main/java/com/adammcneilly/pocketleague/gameresult/ui/GameResultList.kt deleted file mode 100644 index 3e4cdcfb7..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/gameresult/ui/GameResultList.kt +++ /dev/null @@ -1,88 +0,0 @@ -package com.adammcneilly.pocketleague.gameresult.ui - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Column -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.core.ui.Material3Divider - -/** - * Shows a list of [games] between two teams. Could be used for a bracket series, swiss series, etc. - */ -@Composable -fun GameResultList( - games: List, - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier, - ) { - games.forEach { gameResult -> - GameResultListItem( - result = gameResult, - ) - - Material3Divider() - } - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun GameResultListPreview() { - val gameOne = GameResultDisplayModel( - stadium = "Mannfield (Night)", - teamOneScore = 1, - teamTwoScore = 2, - ) - - val gameTwo = GameResultDisplayModel( - stadium = "Forbidden Temple", - teamOneScore = 2, - teamTwoScore = 1, - ) - - val gameThree = GameResultDisplayModel( - stadium = "DFH Stadium", - teamOneScore = 1, - teamTwoScore = 0, - ) - - val gameFour = GameResultDisplayModel( - stadium = "Utopia Coliseum (Dusk)", - teamOneScore = 2, - teamTwoScore = 3, - ) - - val gameFive = GameResultDisplayModel( - stadium = "Champions Field", - teamOneScore = 2, - teamTwoScore = 3, - ) - - val games = listOf( - gameOne, - gameTwo, - gameThree, - gameFour, - gameFive, - ) - - PocketLeagueTheme { - Surface { - GameResultList( - games = games, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/gameresult/ui/GameResultListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/gameresult/ui/GameResultListItem.kt deleted file mode 100644 index c5da2be16..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/gameresult/ui/GameResultListItem.kt +++ /dev/null @@ -1,105 +0,0 @@ -package com.adammcneilly.pocketleague.gameresult.ui - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Check -import androidx.compose.material3.Icon -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme - -/** - * Given a [result], render information on the UI. This is intended to be used in a list - * of games. - */ -@Composable -fun GameResultListItem( - result: GameResultDisplayModel, - modifier: Modifier = Modifier, -) { - Row( - modifier = modifier - .padding(8.dp), - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Box( - modifier = Modifier - .size(24.dp), - ) { - if (result.teamOneWinner) { - WinnerCheckmark() - } - } - - Text( - text = result.teamOneScore.toString(), - ) - - Text( - text = result.stadium, - modifier = Modifier - .weight(1F), - textAlign = TextAlign.Center, - ) - - Text( - text = result.teamTwoScore.toString(), - ) - - Box( - modifier = Modifier - .size(24.dp), - ) { - if (result.teamTwoWinner) { - WinnerCheckmark() - } - } - } -} - -@Composable -private fun WinnerCheckmark() { - Icon( - Icons.Default.Check, - contentDescription = null, - tint = Color.Green, - ) -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun GameResultListItemPreview() { - val displayModel = GameResultDisplayModel( - stadium = "Mannfield (Night)", - teamOneScore = 1, - teamTwoScore = 2, - ) - - PocketLeagueTheme { - Surface { - GameResultListItem( - result = displayModel, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailContent.kt deleted file mode 100644 index 82613cf96..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailContent.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.adammcneilly.pocketleague.phase.ui - -import androidx.compose.foundation.layout.Box -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.adammcneilly.pocketleague.shared.phasedetail.state.PhaseDetailViewState - -/** - * Given a [viewState], render the UI for phase detail information. - */ -@Composable -fun PhaseDetailContent( - viewState: PhaseDetailViewState, - modifier: Modifier = Modifier, -) { - Box( - modifier = modifier, - ) { - Text( - text = "Phase detail: ${viewState.phase?.phaseName}" - ) - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailNavArgs.kt b/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailNavArgs.kt deleted file mode 100644 index 98cb790e8..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailNavArgs.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.adammcneilly.pocketleague.phase.ui - -/** - * Navigation arguments that will be passed into an [PhaseDetailScreen]. - */ -data class PhaseDetailNavArgs( - val phaseId: String, -) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailScreen.kt b/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailScreen.kt deleted file mode 100644 index 6cdb69af5..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailScreen.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.adammcneilly.pocketleague.phase.ui - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.ui.Modifier -import androidx.hilt.navigation.compose.hiltViewModel -import com.ramcosta.composedestinations.annotation.Destination - -/** - * A screen for phase detail information managed by the supplied [viewModel]. - */ -@Destination( - navArgsDelegate = PhaseDetailNavArgs::class, -) -@Composable -fun PhaseDetailScreen( - modifier: Modifier = Modifier, - viewModel: PhaseDetailViewModel = hiltViewModel(), -) { - val viewState = viewModel.viewState.collectAsState() - - PhaseDetailContent( - viewState = viewState.value, - modifier = modifier, - ) -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailViewModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailViewModel.kt deleted file mode 100644 index 994b01755..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseDetailViewModel.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.adammcneilly.pocketleague.phase.ui - -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.adammcneilly.pocketleague.shared.phasedetail.domain.GetPhaseDetailUseCase -import com.adammcneilly.pocketleague.shared.phasedetail.state.PhaseDetailAction -import com.adammcneilly.pocketleague.shared.phasedetail.state.phaseDetailStateMutator -import com.ramcosta.composedestinations.PhaseDetailScreenDestination -import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject - -/** - * A state management container for the [PhaseDetailScreen]. - */ -@HiltViewModel -class PhaseDetailViewModel @Inject constructor( - savedStateHandle: SavedStateHandle, - getPhaseDetailUseCase: GetPhaseDetailUseCase, -) : ViewModel() { - private val mutator = phaseDetailStateMutator( - scope = viewModelScope, - getPhaseDetailUseCase = getPhaseDetailUseCase, - ) - - val viewState = mutator.state - - private val navArgs = PhaseDetailScreenDestination.argsFrom(savedStateHandle) - - init { - val fetchAction = PhaseDetailAction.FetchPhaseDetail(navArgs.phaseId) - - mutator.accept(fetchAction) - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseList.kt b/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseList.kt deleted file mode 100644 index 4c81d5293..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseList.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.adammcneilly.pocketleague.phase.ui - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.core.ui.Material3Card -import com.adammcneilly.pocketleague.shared.eventoverview.ui.EventOverviewPhaseDisplayModel - -/** - * Displays a collection of [phases]. - */ -@Composable -fun PhaseList( - phases: List, - onPhaseClicked: (String) -> Unit, - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier, - verticalArrangement = Arrangement.spacedBy(16.dp), - ) { - phases.forEach { phase -> - Material3Card { - PhaseListItem( - phase = phase, - onPhaseClicked = onPhaseClicked, - ) - } - } - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun PhaseListPreview() { - val phases = listOf( - EventOverviewPhaseDisplayModel( - phaseId = "123", - phaseName = "Day 1: Swiss Matches", - numPools = "1", - bracketType = "Custom", - numEntrants = "16", - ), - EventOverviewPhaseDisplayModel( - phaseId = "123", - phaseName = "Day 2-3: Single Elimination", - numPools = "1", - bracketType = "SE", - numEntrants = "8", - ), - ) - - PocketLeagueTheme { - Surface { - PhaseList( - phases = phases, - onPhaseClicked = {}, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseListItem.kt deleted file mode 100644 index 4fe296735..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/phase/ui/PhaseListItem.kt +++ /dev/null @@ -1,111 +0,0 @@ -package com.adammcneilly.pocketleague.phase.ui - -import android.content.res.Configuration -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.intl.Locale -import androidx.compose.ui.text.toUpperCase -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.shared.eventoverview.ui.EventOverviewPhaseDisplayModel - -private const val PHASE_INFO_WIDTH_PERCENTAGE = 0.75F - -/** - * Displays information about the supplied [phase]. - */ -@Composable -fun PhaseListItem( - phase: EventOverviewPhaseDisplayModel, - onPhaseClicked: (String) -> Unit, - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier - .clickable( - onClick = { - onPhaseClicked.invoke(phase.phaseId) - }, - ) - .fillMaxWidth() - .padding(16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp), - ) { - PhaseNameLabel(phase) - - Row( - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier - .fillMaxWidth(PHASE_INFO_WIDTH_PERCENTAGE), - ) { - InfoItemLabel(infoKey = "pools", infoValue = phase.numPools) - - InfoItemLabel(infoKey = "type", infoValue = phase.bracketType) - - InfoItemLabel(infoKey = "entrants", infoValue = phase.numEntrants) - } - } -} - -@Composable -private fun PhaseNameLabel(phase: EventOverviewPhaseDisplayModel) { - Text( - text = phase.phaseName, - style = MaterialTheme.typography.headlineSmall, - ) -} - -@Composable -private fun InfoItemLabel( - infoKey: String, - infoValue: String, -) { - Column { - Text( - text = infoValue, - ) - - Text( - text = infoKey.toUpperCase(Locale.current), - style = MaterialTheme.typography.labelSmall, - ) - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun PhaseListItemPreview() { - val phase = EventOverviewPhaseDisplayModel( - phaseId = "123", - phaseName = "Day 1: Swiss Matches", - numPools = "1", - bracketType = "Custom", - numEntrants = "16", - ) - - PocketLeagueTheme { - Surface { - PhaseListItem( - phase = phase, - onPhaseClicked = {}, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerDisplayModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerDisplayModel.kt deleted file mode 100644 index 4236b632c..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerDisplayModel.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.adammcneilly.pocketleague.player.ui - -import com.adammcneilly.pocketleague.core.models.Player -import com.adammcneilly.pocketleague.core.ui.FlagResProvider -import com.adammcneilly.pocketleague.shared.core.ui.UIImage - -/** - * A display model to present a player in a user friendly manner on the UI. - */ -data class PlayerDisplayModel( - val flagImage: UIImage, - val gamerTag: String, - val realName: String, - val notes: String?, -) - -/** - * Converts a [Player] to a [PlayerDisplayModel] so that we can present the player in a user friendly - * manner. - * - * @param[flagResProvider] A utility for mapping the player's country code to the relevant flag - * resource. - */ -fun Player.toDisplayModel( - flagResProvider: FlagResProvider, -): PlayerDisplayModel { - val flagResId = flagResProvider.getFlagRes(this.countryCode) - return PlayerDisplayModel( - flagImage = UIImage.AndroidResource(flagResId), - gamerTag = this.gamerTag, - realName = "(${this.realName})", - notes = this.notes?.let { notes -> - "($notes)" - }, - ) -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerList.kt b/app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerList.kt deleted file mode 100644 index 7339698cd..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerList.kt +++ /dev/null @@ -1,100 +0,0 @@ -package com.adammcneilly.pocketleague.player.ui - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Column -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.tooling.preview.Preview -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.core.ui.Material3Divider -import com.adammcneilly.pocketleague.shared.core.ui.UIImage -import com.murgupluoglu.flagkit.FlagKit - -/** - * Given a list of [players], render that collection on the UI. - */ -@Composable -fun PlayerList( - players: List, - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier, - ) { - players.map { player -> - PlayerListItem(player = player) - - Material3Divider() - } - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun PlayerListPreview() { - val caFlag = FlagKit.getResId(LocalContext.current, "ca") - val usFlag = FlagKit.getResId(LocalContext.current, "us") - - val caFlagImage = UIImage.AndroidResource(caFlag) - val usFlagImage = UIImage.AndroidResource(usFlag) - - val sosa = PlayerDisplayModel( - flagImage = caFlagImage, - gamerTag = "Sosa", - realName = "(Testing McTestFace)", - notes = null, - ) - - val kep = PlayerDisplayModel( - flagImage = usFlagImage, - gamerTag = "AlphaKep", - realName = "(Testing McTestFace)", - notes = null, - ) - - val omar = PlayerDisplayModel( - flagImage = usFlagImage, - gamerTag = "ElOmarMaton", - realName = "(Testing McTestFace)", - notes = null, - ) - - val dino = PlayerDisplayModel( - flagImage = usFlagImage, - gamerTag = "Dino", - realName = "(Testing McTestFace)", - notes = "(Substitute)", - ) - - val lando = PlayerDisplayModel( - flagImage = usFlagImage, - gamerTag = "McLando", - realName = "(Testing McTestFace)", - notes = "(Coach)", - ) - - val players = listOf( - sosa, - kep, - omar, - dino, - lando, - ) - - PocketLeagueTheme { - Surface { - PlayerList( - players = players, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerListItem.kt deleted file mode 100644 index b568bb9b1..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerListItem.kt +++ /dev/null @@ -1,133 +0,0 @@ -package com.adammcneilly.pocketleague.player.ui - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.text.font.FontStyle -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.core.ui.PocketLeagueImage -import com.adammcneilly.pocketleague.shared.core.ui.UIImage -import com.murgupluoglu.flagkit.FlagKit - -/** - * Given a [player], render the UI to show information about that player - * within a list. - */ -@Composable -fun PlayerListItem( - player: PlayerDisplayModel, - modifier: Modifier = Modifier, -) { - Row( - modifier = modifier - .padding(16.dp), - horizontalArrangement = Arrangement.spacedBy(12.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - PocketLeagueImage( - image = player.flagImage, - contentDescription = "Country Flag", - ) - - PlayerInfoColumn(player) - } -} - -@Composable -private fun PlayerInfoColumn( - player: PlayerDisplayModel -) { - Column( - verticalArrangement = Arrangement.spacedBy(12.dp), - ) { - PlayerNameRow(player) - - if (player.notes != null) { - Text( - text = player.notes, - fontStyle = FontStyle.Italic, - ) - } - } -} - -@Composable -private fun PlayerNameRow(player: PlayerDisplayModel) { - Row( - horizontalArrangement = Arrangement.spacedBy(12.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - text = player.gamerTag, - ) - - Text( - text = player.realName, - fontStyle = FontStyle.Italic, - ) - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun PlayerListItemPreviewWithNotes() { - val usFlag = FlagKit.getResId(LocalContext.current, "us") - val player = PlayerDisplayModel( - flagImage = UIImage.AndroidResource(usFlag), - gamerTag = "Tstn", - realName = "(Testing McTestFace)", - notes = "(Coach)", - ) - - PocketLeagueTheme { - Surface { - PlayerListItem( - player = player, - ) - } - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun PlayerListItemPreviewWithoutNotes() { - val usFlag = FlagKit.getResId(LocalContext.current, "us") - val player = PlayerDisplayModel( - flagImage = UIImage.AndroidResource(usFlag), - gamerTag = "Tstn", - realName = "(Testing McTestFace)", - notes = null, - ) - - PocketLeagueTheme { - Surface { - PlayerListItem( - player = player, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerOverviewDisplayModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerOverviewDisplayModel.kt deleted file mode 100644 index 924fb2618..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/player/ui/PlayerOverviewDisplayModel.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.adammcneilly.pocketleague.player.ui - -/** - * Displays high level information about an RLCS player. - */ -data class PlayerOverviewDisplayModel( - val gamerTag: String, -) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/seriesdetail/ui/SeriesDetailContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/seriesdetail/ui/SeriesDetailContent.kt deleted file mode 100644 index 26375c9c0..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/seriesdetail/ui/SeriesDetailContent.kt +++ /dev/null @@ -1,140 +0,0 @@ -package com.adammcneilly.pocketleague.seriesdetail.ui - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.R -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.core.ui.Material3Divider -import com.adammcneilly.pocketleague.gameresult.ui.GameResultDisplayModel -import com.adammcneilly.pocketleague.gameresult.ui.GameResultList -import com.adammcneilly.pocketleague.shared.core.ui.UIImage -import com.adammcneilly.pocketleague.teamdetail.ui.TeamDetailDisplayModel - -/** - * Shows the UI content for a [result] of a series between two teams. - */ -@Composable -fun SeriesResultContent( - result: SeriesDetailDisplayModel, - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(8.dp), - horizontalArrangement = Arrangement.SpaceAround, - ) { - Text( - text = result.teamOne.name, - style = MaterialTheme.typography.headlineSmall, - ) - - Text( - text = result.teamTwo.name, - style = MaterialTheme.typography.headlineSmall, - ) - } - - Material3Divider() - - Text( - text = result.gameTime, - modifier = Modifier - .padding(8.dp), - ) - - Material3Divider() - - GameResultList(games = result.games) - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun SeriesResultContentPreview() { - val gameOne = GameResultDisplayModel( - stadium = "Mannfield (Night)", - teamOneScore = 1, - teamTwoScore = 2, - ) - - val gameTwo = GameResultDisplayModel( - stadium = "Forbidden Temple", - teamOneScore = 2, - teamTwoScore = 1, - ) - - val gameThree = GameResultDisplayModel( - stadium = "DFH Stadium", - teamOneScore = 1, - teamTwoScore = 0, - ) - - val gameFour = GameResultDisplayModel( - stadium = "Utopia Coliseum (Dusk)", - teamOneScore = 2, - teamTwoScore = 3, - ) - - val gameFive = GameResultDisplayModel( - stadium = "Champions Field", - teamOneScore = 2, - teamTwoScore = 3, - ) - - val games = listOf( - gameOne, - gameTwo, - gameThree, - gameFour, - gameFive, - ) - - val teamOne = TeamDetailDisplayModel( - name = "NRG", - logo = UIImage.AndroidResource(R.drawable.us), - players = emptyList(), - ) - - val teamTwo = TeamDetailDisplayModel( - name = "NV", - logo = UIImage.AndroidResource(R.drawable.ca), - players = emptyList(), - ) - - val result = SeriesDetailDisplayModel( - gameTime = "October 29, 2021 - 18:30", - games = games, - teamOne = teamOne, - teamTwo = teamTwo, - ) - - PocketLeagueTheme { - Surface { - SeriesResultContent(result = result) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/seriesdetail/ui/SeriesDetailDisplayModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/seriesdetail/ui/SeriesDetailDisplayModel.kt deleted file mode 100644 index 774fead8e..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/seriesdetail/ui/SeriesDetailDisplayModel.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.adammcneilly.pocketleague.seriesdetail.ui - -import com.adammcneilly.pocketleague.gameresult.ui.GameResultDisplayModel -import com.adammcneilly.pocketleague.teamdetail.ui.TeamDetailDisplayModel - -/** - * A class to present series details in a user friendly fashion. - */ -data class SeriesDetailDisplayModel( - val gameTime: String, - val games: List, - val teamOne: TeamDetailDisplayModel, - val teamTwo: TeamDetailDisplayModel, -) { - - private val teamOneWins = games.count { game -> - game.teamOneWinner - } - - private val teamTwoWins = games.count { game -> - game.teamTwoWinner - } - - val teamOneWinner: Boolean - get() = teamOneWins > teamTwoWins - - val teamTwoWinner: Boolean - get() = teamTwoWins > teamOneWins -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/seriesoverview/domain/models/SeriesOverview.kt b/app/src/main/java/com/adammcneilly/pocketleague/seriesoverview/domain/models/SeriesOverview.kt deleted file mode 100644 index 7294a91d4..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/seriesoverview/domain/models/SeriesOverview.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.adammcneilly.pocketleague.seriesoverview.domain.models - -import com.adammcneilly.pocketleague.core.models.Team - -/** - * An overview of a series between two teams and how many wins each team had. - */ -data class SeriesOverview( - val teamOne: Team, - val teamTwo: Team, - val teamOneWins: Int, - val teamTwoWins: Int, -) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/seriesoverview/ui/SeriesOverviewDisplayModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/seriesoverview/ui/SeriesOverviewDisplayModel.kt deleted file mode 100644 index a4bc007c6..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/seriesoverview/ui/SeriesOverviewDisplayModel.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.adammcneilly.pocketleague.seriesoverview.ui - -import com.adammcneilly.pocketleague.seriesoverview.domain.models.SeriesOverview -import com.adammcneilly.pocketleague.teamoverview.ui.TeamOverviewDisplayModel -import com.adammcneilly.pocketleague.teamoverview.ui.toOverviewDisplayModelWithoutRoster - -/** - * Presents a [SeriesOverview] entity on the UI with user friendly values. - */ -data class SeriesOverviewDisplayModel( - val teamOne: TeamOverviewDisplayModel, - val teamTwo: TeamOverviewDisplayModel, - val teamOneWins: Int, - val teamTwoWins: Int, -) { - - val teamOneWinner: Boolean - get() = teamOneWins > teamTwoWins - - val teamTwoWinner: Boolean - get() = teamTwoWins > teamOneWins -} - -/** - * Converts a [SeriesOverview] to a [SeriesOverviewDisplayModel] so it can be rendered appropriately - * on the UI. - */ -fun SeriesOverview.toDisplayModel(): SeriesOverviewDisplayModel { - return SeriesOverviewDisplayModel( - teamOne = this.teamOne.toOverviewDisplayModelWithoutRoster(), - teamTwo = this.teamTwo.toOverviewDisplayModelWithoutRoster(), - teamOneWins = this.teamOneWins, - teamTwoWins = this.teamTwoWins, - ) -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/standings/ui/StandingsList.kt b/app/src/main/java/com/adammcneilly/pocketleague/standings/ui/StandingsList.kt deleted file mode 100644 index 8e9361a14..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/standings/ui/StandingsList.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.adammcneilly.pocketleague.standings.ui - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Column -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.core.ui.Material3Divider -import com.adammcneilly.pocketleague.shared.standings.StandingsDisplayModel -import com.adammcneilly.pocketleague.shared.standings.StandingsPlacementDisplayModel - -/** - * Shows a collection of [standings] for some event. - */ -@Composable -fun StandingsList( - standings: StandingsDisplayModel, - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier, - ) { - standings.placements.forEach { placement -> - StandingsPlacementListItem(placement = placement) - - Material3Divider() - } - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun StandingsListPreview() { - val placements = (1..10).map { - StandingsPlacementDisplayModel( - placement = it.toString(), - teamName = "Pittsburgh Knights", - roster = "sosa / AlphaKep / ElOmarMaton", - teamLogo = null, - ) - } - - val standings = StandingsDisplayModel( - placements = placements, - ) - - PocketLeagueTheme { - Surface { - StandingsList( - standings = standings, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/standings/ui/StandingsPlacementListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/standings/ui/StandingsPlacementListItem.kt deleted file mode 100644 index eab22b0db..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/standings/ui/StandingsPlacementListItem.kt +++ /dev/null @@ -1,138 +0,0 @@ -package com.adammcneilly.pocketleague.standings.ui - -import android.content.res.Configuration -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.core.ui.PocketLeagueImage -import com.adammcneilly.pocketleague.shared.standings.StandingsPlacementDisplayModel - -private const val PLACEMENT_WEIGHT = 1F -private const val TEAM_WEIGHT = 7F - -/** - * Given a [placement], render information about a team's standing within some event. - */ -@Composable -fun StandingsPlacementListItem( - placement: StandingsPlacementDisplayModel, - modifier: Modifier = Modifier, -) { - Row( - modifier = modifier - .fillMaxWidth() - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp), - ) { - Box( - modifier = Modifier - .weight(PLACEMENT_WEIGHT), - ) { - Text( - text = placement.placement, - fontWeight = FontWeight.Bold, - style = MaterialTheme.typography.headlineSmall, - modifier = Modifier.align(Alignment.Center), - ) - } - - LetterCircle(placement) - - Column( - modifier = Modifier - .weight(TEAM_WEIGHT), - verticalArrangement = Arrangement.spacedBy(8.dp), - ) { - Text( - text = placement.teamName, - fontWeight = FontWeight.Bold, - ) - - Text( - text = placement.roster, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - } - } -} - -@Composable -private fun LetterCircle(placement: StandingsPlacementDisplayModel) { - Box( - modifier = Modifier - .size(48.dp) - .clip(CircleShape) - .background( - color = MaterialTheme.colorScheme.secondaryContainer, - ), - ) { - Text( - text = placement.teamName.first().toString(), - fontWeight = FontWeight.Bold, - style = MaterialTheme.typography.headlineSmall, - color = MaterialTheme.colorScheme.onSecondaryContainer, - modifier = Modifier - .align(Alignment.Center), - ) - - val teamLogo = placement.teamLogo - - if (teamLogo != null) { - PocketLeagueImage( - image = teamLogo, - modifier = Modifier - .size(48.dp) - .clip(CircleShape), - contentDescription = "Team Logo", - contentScale = ContentScale.Crop, - ) - } - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun StandingsListItemPreview() { - val displayModel = StandingsPlacementDisplayModel( - placement = "1", - teamName = "Pittsburgh Knights", - roster = "sosa / AlphaKep / ElOmarMaton", - teamLogo = null, - ) - - PocketLeagueTheme { - Surface { - StandingsPlacementListItem( - placement = displayModel, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/swiss/domain/models/SwissRound.kt b/app/src/main/java/com/adammcneilly/pocketleague/swiss/domain/models/SwissRound.kt deleted file mode 100644 index 649086a60..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/swiss/domain/models/SwissRound.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.adammcneilly.pocketleague.swiss.domain.models - -import com.adammcneilly.pocketleague.seriesoverview.domain.models.SeriesOverview - -/** - * This represents one individual round of a [SwissStage]. - * - * @property[roundDescription] The description of this round, such as "Round 1 Matches", "Round 2 Low Matches", etc. - * @property[series] All of the [SeriesOverview] entities for this particular swiss round. - */ -data class SwissRound( - val roundDescription: String, - val series: List, -) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/swiss/domain/models/SwissStage.kt b/app/src/main/java/com/adammcneilly/pocketleague/swiss/domain/models/SwissStage.kt deleted file mode 100644 index ca31d665a..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/swiss/domain/models/SwissStage.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.adammcneilly.pocketleague.swiss.domain.models - -/** - * This data class represents one specific stage of the swiss portion of an event. The [rounds] - * can either be a single round (in case of round 1), or potentially have high/mid/low rounds, like - * round 3. This will vary based on the number of teams participating. - */ -data class SwissStage( - val rounds: List, -) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissRoundDisplayModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissRoundDisplayModel.kt deleted file mode 100644 index 33eff66dd..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissRoundDisplayModel.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.adammcneilly.pocketleague.swiss.ui - -import com.adammcneilly.pocketleague.seriesoverview.domain.models.SeriesOverview -import com.adammcneilly.pocketleague.seriesoverview.ui.SeriesOverviewDisplayModel -import com.adammcneilly.pocketleague.seriesoverview.ui.toDisplayModel -import com.adammcneilly.pocketleague.swiss.domain.models.SwissRound - -/** - * Defines UI friendly information of a [SwissRound] entity. - */ -data class SwissRoundDisplayModel( - val roundDescription: String, - val series: List, -) - -/** - * Given a [SwissRound] domain item, convert it to a corresponding [SwissRoundDisplayModel] for usage - * in UI code. - */ -fun SwissRound.toDisplayModel(): SwissRoundDisplayModel { - return SwissRoundDisplayModel( - roundDescription = this.roundDescription, - series = this.series.map(SeriesOverview::toDisplayModel), - ) -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissRoundList.kt b/app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissRoundList.kt deleted file mode 100644 index 204e93dd2..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissRoundList.kt +++ /dev/null @@ -1,122 +0,0 @@ -package com.adammcneilly.pocketleague.swiss.ui - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.R -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.core.ui.Material3Divider -import com.adammcneilly.pocketleague.seriesoverview.ui.SeriesOverviewDisplayModel -import com.adammcneilly.pocketleague.shared.core.ui.UIImage -import com.adammcneilly.pocketleague.teamoverview.ui.TeamOverviewDisplayModel - -/** - * Given a [SwissRoundDisplayModel], create a list of all series that - * occurred during that swiss round. - */ -@Composable -fun SwissRoundList( - swissRound: SwissRoundDisplayModel, - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Text( - text = swissRound.roundDescription, - modifier = Modifier - .padding(8.dp), - ) - - Material3Divider() - - swissRound.series.forEach { series -> - SwissSeriesOverviewItem( - seriesOverview = series, - ) - - Material3Divider() - } - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun SwissRoundListPreview() { - val torV1Overview = SeriesOverviewDisplayModel( - teamOne = TeamOverviewDisplayModel( - name = "TOR", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ), - teamTwo = TeamOverviewDisplayModel( - name = "V1", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ), - teamOneWins = 1, - teamTwoWins = 3, - ) - - val fazeSSGOverview = SeriesOverviewDisplayModel( - teamOne = TeamOverviewDisplayModel( - name = "FAZE", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ), - teamTwo = TeamOverviewDisplayModel( - name = "SSG", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ), - teamOneWins = 1, - teamTwoWins = 3, - ) - - val ghostVIBOverview = SeriesOverviewDisplayModel( - teamOne = TeamOverviewDisplayModel( - name = "GG", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ), - teamTwo = TeamOverviewDisplayModel( - name = "VIB", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ), - teamOneWins = 3, - teamTwoWins = 1, - ) - - val swissRound = SwissRoundDisplayModel( - roundDescription = "Round 5 Matches", - series = listOf( - torV1Overview, - fazeSSGOverview, - ghostVIBOverview, - ), - ) - - PocketLeagueTheme { - Surface { - SwissRoundList( - swissRound = swissRound, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissSeriesOverviewItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissSeriesOverviewItem.kt deleted file mode 100644 index 72d5cb27b..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissSeriesOverviewItem.kt +++ /dev/null @@ -1,196 +0,0 @@ -package com.adammcneilly.pocketleague.swiss.ui - -import android.content.res.Configuration -import androidx.compose.foundation.border -import androidx.compose.foundation.layout.IntrinsicSize -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.material3.contentColorFor -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.R -import com.adammcneilly.pocketleague.android.design.components.Material3VerticalDivider -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.seriesoverview.ui.SeriesOverviewDisplayModel -import com.adammcneilly.pocketleague.shared.core.ui.UIImage -import com.adammcneilly.pocketleague.teamoverview.ui.TeamOverviewDisplayModel - -/** - * Given a [seriesOverview], render that on the UI. This is intended to be used inside a list of - * series. - */ -@Composable -fun SwissSeriesOverviewItem( - seriesOverview: SeriesOverviewDisplayModel, - modifier: Modifier = Modifier, -) { - Surface( - color = MaterialTheme.colorScheme.background, - modifier = modifier - .border( - width = 1.dp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12F), - ) - ) { - Row( - modifier = Modifier - .height(IntrinsicSize.Min) - ) { - FirstTeamResult( - teamName = seriesOverview.teamOne.name, - teamWins = seriesOverview.teamOneWins, - isWinner = seriesOverview.teamOneWinner, - modifier = Modifier.weight(1F), - ) - - Material3VerticalDivider( - color = MaterialTheme.colorScheme.onBackground, - ) - - SecondTeamResult( - teamName = seriesOverview.teamTwo.name, - teamWins = seriesOverview.teamTwoWins, - isWinner = seriesOverview.teamTwoWinner, - modifier = Modifier.weight(1F), - ) - } - } -} - -@Composable -private fun FirstTeamResult( - teamName: String, - teamWins: Int, - isWinner: Boolean, - modifier: Modifier = Modifier, -) { - val fontWeight = if (isWinner) { - FontWeight.Bold - } else { - FontWeight.Normal - } - - val backgroundColor = isWinner.toBackgroundColor() - - Surface( - color = backgroundColor, - modifier = modifier - .height(IntrinsicSize.Max) - ) { - Row { - Text( - text = teamName, - fontWeight = fontWeight, - modifier = Modifier - .weight(1F) - .padding(8.dp), - textAlign = TextAlign.Center, - ) - - Material3VerticalDivider( - color = MaterialTheme.colorScheme.contentColorFor(backgroundColor), - ) - - Text( - text = teamWins.toString(), - fontWeight = fontWeight, - modifier = Modifier - .padding(8.dp), - ) - } - } -} - -@Composable -private fun SecondTeamResult( - teamName: String, - teamWins: Int, - isWinner: Boolean, - modifier: Modifier = Modifier, -) { - val fontWeight = if (isWinner) { - FontWeight.Bold - } else { - FontWeight.Normal - } - - val backgroundColor = isWinner.toBackgroundColor() - - Surface( - color = backgroundColor, - modifier = modifier - .height(IntrinsicSize.Max), - ) { - Row { - Text( - text = teamWins.toString(), - fontWeight = fontWeight, - modifier = Modifier - .padding(8.dp), - ) - - Material3VerticalDivider( - color = MaterialTheme.colorScheme.contentColorFor(backgroundColor), - ) - - Text( - text = teamName, - fontWeight = fontWeight, - modifier = Modifier - .weight(1F) - .padding(8.dp), - textAlign = TextAlign.Center, - ) - } - } -} - -@Composable -private fun Boolean.toBackgroundColor(): Color { - return if (this) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.surface - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun SwissSeriesOverviewItemPreview() { - val overview = SeriesOverviewDisplayModel( - teamOne = TeamOverviewDisplayModel( - name = "G2", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ), - teamTwo = TeamOverviewDisplayModel( - name = "GG", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ), - teamOneWins = 4, - teamTwoWins = 2, - ) - - PocketLeagueTheme { - SwissSeriesOverviewItem( - seriesOverview = overview, - ) - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissStageDisplayModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissStageDisplayModel.kt deleted file mode 100644 index eccf58d09..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/swiss/ui/SwissStageDisplayModel.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.adammcneilly.pocketleague.swiss.ui - -import com.adammcneilly.pocketleague.swiss.domain.models.SwissRound -import com.adammcneilly.pocketleague.swiss.domain.models.SwissStage - -/** - * Takes a list of [rounds] and presents them in a user friendly manner. - */ -data class SwissStageDisplayModel( - val rounds: List, -) - -/** - * Converts a [SwissStage] to a [SwissStageDisplayModel] which will be used to render information - * on the UI. - */ -fun SwissStage.toDisplayModel(): SwissStageDisplayModel { - return SwissStageDisplayModel( - rounds = this.rounds.map(SwissRound::toDisplayModel), - ) -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/teamdetail/ui/TeamDetailContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/teamdetail/ui/TeamDetailContent.kt deleted file mode 100644 index 9fb8ce169..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/teamdetail/ui/TeamDetailContent.kt +++ /dev/null @@ -1,130 +0,0 @@ -package com.adammcneilly.pocketleague.teamdetail.ui - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.R -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.core.ui.PocketLeagueImage -import com.adammcneilly.pocketleague.player.ui.PlayerDisplayModel -import com.adammcneilly.pocketleague.player.ui.PlayerList -import com.adammcneilly.pocketleague.shared.core.ui.UIImage -import com.murgupluoglu.flagkit.FlagKit - -/** - * The UI content of the team detail screen based on the supplied [team]. - */ -@Composable -fun TeamDetailContent( - team: TeamDetailDisplayModel, - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier - .padding(16.dp) - .fillMaxSize() - .verticalScroll(rememberScrollState()), - verticalArrangement = Arrangement.spacedBy(24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - PocketLeagueImage( - image = team.logo, - contentDescription = "Team Logo", - modifier = Modifier - .size(120.dp), - ) - - Text( - text = team.name, - style = MaterialTheme.typography.headlineLarge, - ) - - PlayerList(team.players) - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun TeamDetailContentPreview() { - val caFlag = FlagKit.getResId(LocalContext.current, "ca") - val usFlag = FlagKit.getResId(LocalContext.current, "us") - - val caFlagImage = UIImage.AndroidResource(caFlag) - val usFlagImage = UIImage.AndroidResource(usFlag) - - val sosa = PlayerDisplayModel( - flagImage = caFlagImage, - gamerTag = "Sosa", - realName = "(Testing McTestFace)", - notes = null, - ) - - val kep = PlayerDisplayModel( - flagImage = usFlagImage, - gamerTag = "AlphaKep", - realName = "(Testing McTestFace)", - notes = null, - ) - - val omar = PlayerDisplayModel( - flagImage = usFlagImage, - gamerTag = "ElOmarMaton", - realName = "(Testing McTestFace)", - notes = null, - ) - - val dino = PlayerDisplayModel( - flagImage = usFlagImage, - gamerTag = "Dino", - realName = "(Testing McTestFace)", - notes = "(Substitute)", - ) - - val lando = PlayerDisplayModel( - flagImage = usFlagImage, - gamerTag = "McLando", - realName = "(Testing McTestFace)", - notes = "(Coach)", - ) - - val players = listOf( - sosa, - kep, - omar, - dino, - lando, - ) - - val teamDetail = TeamDetailDisplayModel( - name = "Pittsburgh Knights", - logo = UIImage.AndroidResource(R.drawable.us), - players = players, - ) - - PocketLeagueTheme { - Surface { - TeamDetailContent(team = teamDetail) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/teamdetail/ui/TeamDetailDisplayModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/teamdetail/ui/TeamDetailDisplayModel.kt deleted file mode 100644 index d47045684..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/teamdetail/ui/TeamDetailDisplayModel.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.adammcneilly.pocketleague.teamdetail.ui - -import com.adammcneilly.pocketleague.core.models.Team -import com.adammcneilly.pocketleague.core.ui.FlagResProvider -import com.adammcneilly.pocketleague.player.ui.PlayerDisplayModel -import com.adammcneilly.pocketleague.player.ui.toDisplayModel -import com.adammcneilly.pocketleague.shared.core.ui.UIImage - -/** - * A class that presents a team in a user friendly fashion. - */ -data class TeamDetailDisplayModel( - val name: String, - val logo: UIImage, - val players: List, -) - -/** - * Converts a [Team] to a [TeamDetailDisplayModel]. - * - * @param[flagResProvider] Used to determine the flag images for the players. - */ -fun Team.toDetailDisplayModel( - flagResProvider: FlagResProvider, -): TeamDetailDisplayModel { - return TeamDetailDisplayModel( - name = this.name, - logo = UIImage.Remote(this.lightThemeLogoImageUrl.orEmpty()), - players = this.roster.map { player -> - player.toDisplayModel(flagResProvider) - }, - ) -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/data/TeamListService.kt b/app/src/main/java/com/adammcneilly/pocketleague/teamlist/data/TeamListService.kt deleted file mode 100644 index c5fa372ad..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/data/TeamListService.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.adammcneilly.pocketleague.teamlist.data - -import com.adammcneilly.pocketleague.core.models.Team -import com.adammcneilly.pocketleague.shared.data.Result -import javax.inject.Inject - -/** - * Defines the data contract for fetching collections of teams. - */ -interface TeamListService { - /** - * Fetch all available RLCS teams. - */ - suspend fun fetchAllTeams(): Result> -} - -/** - * This exists temporarily to keep things compiling, but screens for this aren't actually in use - * right now. - */ -class MockTeamListService @Inject constructor() : TeamListService { - override suspend fun fetchAllTeams(): Result> { - TODO("Not yet implemented") - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/domain/models/FetchTeamListResult.kt b/app/src/main/java/com/adammcneilly/pocketleague/teamlist/domain/models/FetchTeamListResult.kt deleted file mode 100644 index d7c2bab55..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/domain/models/FetchTeamListResult.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.adammcneilly.pocketleague.teamlist.domain.models - -import com.adammcneilly.pocketleague.core.models.Team - -/** - * A collection of possible result types for fetching a list of teams. - */ -sealed class FetchTeamListResult { - /** - * This indicates we had a successful request to fetch the [teams]. - */ - data class Success(val teams: List) : FetchTeamListResult() - - /** - * This indicates some error occurred when trying to request teams. - */ - object Failure : FetchTeamListResult() -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/domain/usecases/FetchAllTeamsUseCase.kt b/app/src/main/java/com/adammcneilly/pocketleague/teamlist/domain/usecases/FetchAllTeamsUseCase.kt deleted file mode 100644 index 0765f62a6..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/domain/usecases/FetchAllTeamsUseCase.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.adammcneilly.pocketleague.teamlist.domain.usecases - -import com.adammcneilly.pocketleague.teamlist.domain.models.FetchTeamListResult - -/** - * A use case to fetch all RLCS teams. - */ -interface FetchAllTeamsUseCase { - /** - * @see [FetchAllTeamsUseCase] - */ - suspend operator fun invoke(): FetchTeamListResult -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/domain/usecases/FetchAllTeamsUseCaseImpl.kt b/app/src/main/java/com/adammcneilly/pocketleague/teamlist/domain/usecases/FetchAllTeamsUseCaseImpl.kt deleted file mode 100644 index d7d98183a..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/domain/usecases/FetchAllTeamsUseCaseImpl.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.adammcneilly.pocketleague.teamlist.domain.usecases - -import com.adammcneilly.pocketleague.shared.data.Result -import com.adammcneilly.pocketleague.teamlist.data.TeamListService -import com.adammcneilly.pocketleague.teamlist.domain.models.FetchTeamListResult -import javax.inject.Inject - -/** - * A concrete implementation of [FetchAllTeamsUseCase] that will fetch teams from a given [service]. - */ -class FetchAllTeamsUseCaseImpl @Inject constructor( - private val service: TeamListService, -) : FetchAllTeamsUseCase { - - override suspend fun invoke(): FetchTeamListResult { - val result = service.fetchAllTeams() - - return when (result) { - is Result.Success -> { - FetchTeamListResult.Success(result.data) - } - is Result.Error -> { - FetchTeamListResult.Failure - } - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListContent.kt deleted file mode 100644 index ac76ac68c..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListContent.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.adammcneilly.pocketleague.teamlist.ui - -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.adammcneilly.pocketleague.core.ui.CenteredMaterial3CircularProgressIndicator -import com.adammcneilly.pocketleague.teamoverview.ui.TeamOverviewList - -/** - * Renders the actual content of the team list screen given the [viewState]. - */ -@Composable -fun TeamListContent( - viewState: TeamListViewState, - modifier: Modifier = Modifier, -) { - Box( - modifier = modifier - .fillMaxSize(), - ) { - if (viewState.showContent) { - TeamOverviewList(teams = viewState.teams) - } - - if (viewState.showLoading) { - CenteredMaterial3CircularProgressIndicator() - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListScreen.kt b/app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListScreen.kt deleted file mode 100644 index 064b95279..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListScreen.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.adammcneilly.pocketleague.teamlist.ui - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.ui.Modifier -import androidx.hilt.navigation.compose.hiltViewModel - -/** - * The containing screen to show a list of teams. All UI information - * is powered by the supplied [viewModel]. - */ -@Composable -fun TeamListScreen( - modifier: Modifier = Modifier, - viewModel: TeamListViewModel = hiltViewModel(), -) { - val viewState = viewModel.viewState.collectAsState() - - TeamListContent( - viewState = viewState.value, - modifier = modifier, - ) -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListViewModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListViewModel.kt deleted file mode 100644 index cbddefe7a..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListViewModel.kt +++ /dev/null @@ -1,59 +0,0 @@ -package com.adammcneilly.pocketleague.teamlist.ui - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.adammcneilly.pocketleague.core.ui.FlagResProvider -import com.adammcneilly.pocketleague.teamlist.domain.models.FetchTeamListResult -import com.adammcneilly.pocketleague.teamlist.domain.usecases.FetchAllTeamsUseCase -import com.adammcneilly.pocketleague.teamoverview.ui.toOverviewDisplayModel -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import javax.inject.Inject - -/** - * The UI state management container for the team list screen. - */ -@HiltViewModel -class TeamListViewModel @Inject constructor( - private val fetchAllTeamsUseCase: FetchAllTeamsUseCase, - private val flagResProvider: FlagResProvider, -) : ViewModel() { - - private val _viewState = MutableStateFlow(TeamListViewState()) - val viewState: StateFlow = _viewState - - init { - viewModelScope.launch { - val allTeamsResult = fetchAllTeamsUseCase() - - when (allTeamsResult) { - is FetchTeamListResult.Success -> { - processSuccessfulTeamListRequest(allTeamsResult) - } - is FetchTeamListResult.Failure -> { - processFailedTeamListRequest() - } - } - } - } - - private fun processFailedTeamListRequest() { - _viewState.value = _viewState.value.copy( - showLoading = false, - showContent = false, - showError = true, - ) - } - - private fun processSuccessfulTeamListRequest(allTeamsResult: FetchTeamListResult.Success) { - _viewState.value = _viewState.value.copy( - showLoading = false, - showContent = true, - teams = allTeamsResult.teams.map { team -> - team.toOverviewDisplayModel(flagResProvider) - }, - ) - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListViewState.kt b/app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListViewState.kt deleted file mode 100644 index 0c47e56e9..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/teamlist/ui/TeamListViewState.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.adammcneilly.pocketleague.teamlist.ui - -import com.adammcneilly.pocketleague.teamoverview.ui.TeamOverviewDisplayModel - -/** - * All information required to present a list of teams, including the loading content and error states. - */ -data class TeamListViewState( - val showLoading: Boolean = true, - val showContent: Boolean = false, - val showError: Boolean = false, - val teams: List = emptyList(), -) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/TeamOverviewDisplayModel.kt b/app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/TeamOverviewDisplayModel.kt deleted file mode 100644 index 92fdbf4a9..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/TeamOverviewDisplayModel.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.adammcneilly.pocketleague.teamoverview.ui - -import com.adammcneilly.pocketleague.core.models.Team -import com.adammcneilly.pocketleague.core.ui.FlagResProvider -import com.adammcneilly.pocketleague.player.ui.PlayerDisplayModel -import com.adammcneilly.pocketleague.player.ui.toDisplayModel -import com.adammcneilly.pocketleague.shared.core.ui.UIImage - -/** - * Defines UI information for a team item to be shown at a high level. - */ -data class TeamOverviewDisplayModel( - val name: String, - val lightLogoImage: UIImage, - val darkLogoImage: UIImage = lightLogoImage, - val roster: List, -) - -/** - * Converts a [Team] entity to a [TeamOverviewDisplayModel] without roster information. - */ -fun Team.toOverviewDisplayModelWithoutRoster(): TeamOverviewDisplayModel { - return TeamOverviewDisplayModel( - name = this.name, - lightLogoImage = UIImage.Remote(this.lightThemeLogoImageUrl.orEmpty()), - darkLogoImage = UIImage.Remote(this.darkThemeLogoImageUrl.orEmpty()), - roster = emptyList(), - ) -} - -/** - * Converts a [Team] entity to a [TeamOverviewDisplayModel] including roster information. - */ -fun Team.toOverviewDisplayModel( - flagResProvider: FlagResProvider, -): TeamOverviewDisplayModel { - return TeamOverviewDisplayModel( - name = this.name, - lightLogoImage = UIImage.Remote(this.lightThemeLogoImageUrl.orEmpty()), - darkLogoImage = UIImage.Remote(this.darkThemeLogoImageUrl.orEmpty()), - roster = this.roster.map { player -> - player.toDisplayModel(flagResProvider) - }, - ) -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/TeamOverviewList.kt b/app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/TeamOverviewList.kt deleted file mode 100644 index baf78d523..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/TeamOverviewList.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.adammcneilly.pocketleague.teamoverview.ui - -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.adammcneilly.pocketleague.core.ui.Material3Divider - -/** - * Consumes a list of [teams] and displays their overview information. - */ -@Composable -fun TeamOverviewList( - teams: List, - modifier: Modifier = Modifier, -) { - LazyColumn( - modifier = modifier, - ) { - items(teams) { team -> - ToggleableTeamOverviewListItem( - team = team, - ) - - Material3Divider() - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/TeamOverviewListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/TeamOverviewListItem.kt deleted file mode 100644 index fed95944f..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/TeamOverviewListItem.kt +++ /dev/null @@ -1,98 +0,0 @@ -package com.adammcneilly.pocketleague.teamoverview.ui - -import android.content.res.Configuration -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.adammcneilly.pocketleague.R -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme -import com.adammcneilly.pocketleague.core.ui.PocketLeagueImage -import com.adammcneilly.pocketleague.player.ui.PlayerList -import com.adammcneilly.pocketleague.shared.core.ui.UIImage - -/** - * Shows a specific [team] item within a list of teams. - * - * @param[team] The [TeamOverviewDisplayModel] of the team we want to display. - * @param[showRosterList] If true, shows the roster information as well as the team. - * @param[modifier] An optional [Modifier] to customize this list item if necessary. - */ -@Composable -fun TeamOverviewListItem( - team: TeamOverviewDisplayModel, - showRosterList: Boolean, - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier, - ) { - Row( - modifier = Modifier - .padding(16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - PocketLeagueImage( - team.logoImage(), - contentDescription = "Team Logo", - modifier = Modifier - .size(24.dp), - ) - - Text( - text = team.name, - ) - } - - if (showRosterList) { - PlayerList( - players = team.roster, - ) - } - } -} - -@Composable -private fun TeamOverviewDisplayModel.logoImage(): UIImage { - return if (isSystemInDarkTheme()) { - this.darkLogoImage - } else { - this.lightLogoImage - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Composable -private fun TeamOverviewListItemPreview() { - val team = TeamOverviewDisplayModel( - name = "Pittsburgh Knights", - lightLogoImage = UIImage.AndroidResource(R.drawable.us), - roster = emptyList(), - ) - - PocketLeagueTheme { - Surface { - TeamOverviewListItem( - team = team, - showRosterList = false, - ) - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/ToggleableTeamOverviewListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/ToggleableTeamOverviewListItem.kt deleted file mode 100644 index 6bc559dd6..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/teamoverview/ui/ToggleableTeamOverviewListItem.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.adammcneilly.pocketleague.teamoverview.ui - -import androidx.compose.foundation.clickable -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier - -/** - * A wrapper around a [TeamOverviewListItem] which maintains state - * about whether or not to show the roster list. - */ -@Composable -fun ToggleableTeamOverviewListItem( - team: TeamOverviewDisplayModel, - modifier: Modifier = Modifier, -) { - val showRosterList = remember { - mutableStateOf(false) - } - - TeamOverviewListItem( - team = team, - showRosterList = showRosterList.value, - modifier = modifier - .clickable { - showRosterList.value = !showRosterList.value - }, - ) -} diff --git a/app/src/test/java/com/adammcneilly/pocketleague/core/ui/FakeFlagResProvider.kt b/app/src/test/java/com/adammcneilly/pocketleague/core/ui/FakeFlagResProvider.kt deleted file mode 100644 index 87362fd2a..000000000 --- a/app/src/test/java/com/adammcneilly/pocketleague/core/ui/FakeFlagResProvider.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.adammcneilly.pocketleague.core.ui - -class FakeFlagResProvider : FlagResProvider { - private val flagResResponses: MutableMap = mutableMapOf() - - fun mockFlagResForCountry( - countryCode: String, - flagRes: Int, - ) { - flagResResponses[countryCode] = flagRes - } - - override fun getFlagRes(countryCode: String): Int { - return flagResResponses[countryCode]!! - } -} diff --git a/app/src/test/java/com/adammcneilly/pocketleague/core/utils/DateUtilsTest.kt b/app/src/test/java/com/adammcneilly/pocketleague/core/utils/DateUtilsTest.kt deleted file mode 100644 index c2e438ee7..000000000 --- a/app/src/test/java/com/adammcneilly/pocketleague/core/utils/DateUtilsTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.adammcneilly.pocketleague.core.utils - -import com.google.common.truth.Truth.assertThat -import org.junit.Test -import java.time.LocalDateTime - -class DateUtilsTest { - - @Test - fun getSeriesDayTimeString() { - val date = LocalDateTime.of( - 2021, - 10, - 29, - 18, - 30, - ) - - val result = DateUtils.getSeriesDayTimeString(date) - assertThat(result).isEqualTo("October 29, 2021 - 18:30") - } -} diff --git a/app/src/test/java/com/adammcneilly/pocketleague/core/utils/FakeDateTimeHelper.kt b/app/src/test/java/com/adammcneilly/pocketleague/core/utils/FakeDateTimeHelper.kt deleted file mode 100644 index c4753bae7..000000000 --- a/app/src/test/java/com/adammcneilly/pocketleague/core/utils/FakeDateTimeHelper.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.adammcneilly.pocketleague.core.utils - -import java.time.LocalDateTime - -class FakeDateTimeHelper : DateTimeHelper { - private val seriesDayTimeStringResults: MutableMap = mutableMapOf() - private val eventDayStringResults: MutableMap = mutableMapOf() - - fun mockSeriesDayTimeStringForDate(date: LocalDateTime, result: String) { - seriesDayTimeStringResults[date] = result - } - - fun mockEventDayStringForDate(epochSeconds: Long, result: String) { - eventDayStringResults[epochSeconds] = result - } - - override fun getSeriesDayTimeString(date: LocalDateTime): String { - return seriesDayTimeStringResults[date].toString() - } - - override fun getEventDayString(epochSeconds: Long): String { - return eventDayStringResults[epochSeconds].toString() - } -} diff --git a/app/src/test/java/com/adammcneilly/pocketleague/player/ui/PlayerDisplayModelTest.kt b/app/src/test/java/com/adammcneilly/pocketleague/player/ui/PlayerDisplayModelTest.kt deleted file mode 100644 index 490106747..000000000 --- a/app/src/test/java/com/adammcneilly/pocketleague/player/ui/PlayerDisplayModelTest.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.adammcneilly.pocketleague.player.ui - -import com.adammcneilly.pocketleague.core.models.Player -import com.adammcneilly.pocketleague.core.ui.FakeFlagResProvider -import com.adammcneilly.pocketleague.shared.core.ui.UIImage -import com.google.common.truth.Truth.assertThat -import org.junit.Test - -class PlayerDisplayModelTest { - - @Test - fun createFromPlayerWithoutNotes() { - val countryCode = "US" - val flagResProvider = FakeFlagResProvider() - val mockFlagRes = 123 - flagResProvider.mockFlagResForCountry(countryCode, mockFlagRes) - - val player = Player( - countryCode = countryCode, - gamerTag = "Testy", - realName = "McTestFace", - notes = null, - ) - - val displayModel = player.toDisplayModel(flagResProvider) - - with(displayModel) { - assertThat(flagImage).isEqualTo(UIImage.AndroidResource(mockFlagRes)) - assertThat(gamerTag).isEqualTo("Testy") - assertThat(realName).isEqualTo("(McTestFace)") - assertThat(notes).isNull() - } - } - - @Test - fun createFromPlayerWithNotes() { - val countryCode = "US" - val flagResProvider = FakeFlagResProvider() - val mockFlagRes = 123 - flagResProvider.mockFlagResForCountry(countryCode, mockFlagRes) - - val player = Player( - countryCode = countryCode, - gamerTag = "Testy", - realName = "McTestFace", - notes = "Coach", - ) - - val displayModel = player.toDisplayModel(flagResProvider) - - with(displayModel) { - assertThat(flagImage).isEqualTo(UIImage.AndroidResource(mockFlagRes)) - assertThat(gamerTag).isEqualTo("Testy") - assertThat(realName).isEqualTo("(McTestFace)") - assertThat(notes).isEqualTo("(Coach)") - } - } -} diff --git a/app/src/test/java/com/adammcneilly/pocketleague/teamdetail/ui/TeamDetailDisplayModelTest.kt b/app/src/test/java/com/adammcneilly/pocketleague/teamdetail/ui/TeamDetailDisplayModelTest.kt deleted file mode 100644 index 4f22356ff..000000000 --- a/app/src/test/java/com/adammcneilly/pocketleague/teamdetail/ui/TeamDetailDisplayModelTest.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.adammcneilly.pocketleague.teamdetail.ui - -import com.adammcneilly.pocketleague.core.models.Player -import com.adammcneilly.pocketleague.core.models.Team -import com.adammcneilly.pocketleague.core.ui.FakeFlagResProvider -import com.adammcneilly.pocketleague.player.ui.toDisplayModel -import com.adammcneilly.pocketleague.shared.core.ui.UIImage -import com.google.common.truth.Truth.assertThat -import org.junit.Test - -class TeamDetailDisplayModelTest { - - @Test - fun createFromTeam() { - val countryCode = "US" - val flagResProvider = FakeFlagResProvider() - val mockFlagRes = 123 - flagResProvider.mockFlagResForCountry(countryCode, mockFlagRes) - - val player = Player( - countryCode = countryCode, - gamerTag = "Testy", - realName = "McTestFace", - notes = null, - ) - - val team = Team( - name = "PK", - lightThemeLogoImageUrl = "LogoURL", - darkThemeLogoImageUrl = "LogoURL", - roster = listOf(player), - ) - - val displayModel = team.toDetailDisplayModel(flagResProvider) - - with(displayModel) { - assertThat(name).isEqualTo(team.name) - assertThat(logo).isEqualTo(UIImage.Remote(team.lightThemeLogoImageUrl.orEmpty())) - assertThat(players).isEqualTo(listOf(player.toDisplayModel(flagResProvider))) - } - } -} diff --git a/app/src/test/java/com/adammcneilly/pocketleague/teamlist/data/FakeTeamListService.kt b/app/src/test/java/com/adammcneilly/pocketleague/teamlist/data/FakeTeamListService.kt deleted file mode 100644 index 3e9a8c8a0..000000000 --- a/app/src/test/java/com/adammcneilly/pocketleague/teamlist/data/FakeTeamListService.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.adammcneilly.pocketleague.teamlist.data - -import com.adammcneilly.pocketleague.core.models.Team -import com.adammcneilly.pocketleague.shared.data.Result - -class FakeTeamListService : TeamListService { - private lateinit var mockAllTeamsResult: Result> - - fun mockAllTeamsResult( - result: Result>, - ) { - mockAllTeamsResult = result - } - - override suspend fun fetchAllTeams(): Result> { - return mockAllTeamsResult - } -} diff --git a/app/src/test/java/com/adammcneilly/pocketleague/teamlist/domain/usecases/FetchAllTeamsUseCaseImplTest.kt b/app/src/test/java/com/adammcneilly/pocketleague/teamlist/domain/usecases/FetchAllTeamsUseCaseImplTest.kt deleted file mode 100644 index 4ad60766c..000000000 --- a/app/src/test/java/com/adammcneilly/pocketleague/teamlist/domain/usecases/FetchAllTeamsUseCaseImplTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.adammcneilly.pocketleague.teamlist.domain.usecases - -import com.adammcneilly.pocketleague.core.models.Team -import com.adammcneilly.pocketleague.shared.data.Result -import com.adammcneilly.pocketleague.teamlist.data.FakeTeamListService -import com.adammcneilly.pocketleague.teamlist.domain.models.FetchTeamListResult -import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.test.runTest -import org.junit.Test - -class FetchAllTeamsUseCaseImplTest { - private val fakeTeamListService = FakeTeamListService() - private val useCase = FetchAllTeamsUseCaseImpl( - service = fakeTeamListService, - ) - - @Test - fun invokeSuccess() = runTest { - val fakeTeam = Team( - name = "Team Name", - lightThemeLogoImageUrl = null, - darkThemeLogoImageUrl = null, - roster = emptyList(), - ) - - val mockServiceResult = Result.Success(listOf(fakeTeam)) - - fakeTeamListService.mockAllTeamsResult(mockServiceResult) - - val actualResult = useCase.invoke() - val expectedResult = FetchTeamListResult.Success(listOf(fakeTeam)) - assertThat(actualResult).isEqualTo(expectedResult) - } - - @Test - fun invokeFailure() = runTest { - val mockServiceResult = Result.Error(Throwable()) - - fakeTeamListService.mockAllTeamsResult(mockServiceResult) - - val actualResult = useCase.invoke() - val expectedResult = FetchTeamListResult.Failure - assertThat(actualResult).isEqualTo(expectedResult) - } -} diff --git a/core-data/README.md b/core-data/README.md deleted file mode 100644 index ceaf99bb5..000000000 --- a/core-data/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Core-Data Module - -The core-data module manages any classes that are shared among different data layer implementations throughout the Pocket League application. This is classes such as [DataResult](src/commonMain/kotlin/com/adammcneilly/pocketleague/core/data/DataResult.kt), which helps determine if a data request was successful or not by wrapping both cases into a single type. \ No newline at end of file diff --git a/core-data/build.gradle.kts b/core-data/build.gradle.kts deleted file mode 100644 index aba2a7a3a..000000000 --- a/core-data/build.gradle.kts +++ /dev/null @@ -1,56 +0,0 @@ -plugins { - kotlin("multiplatform") - id("com.android.library") -} - -kotlin { - android() - - listOf( - iosX64(), - iosArm64(), - iosSimulatorArm64() - ).forEach { - it.binaries.framework { - baseName = "core-data" - } - } - - sourceSets { - val commonMain by getting - val commonTest by getting { - dependencies { - implementation(kotlin("test")) - } - } - val androidMain by getting - val androidTest by getting - val iosX64Main by getting - val iosArm64Main by getting - val iosSimulatorArm64Main by getting - val iosMain by creating { - dependsOn(commonMain) - iosX64Main.dependsOn(this) - iosArm64Main.dependsOn(this) - iosSimulatorArm64Main.dependsOn(this) - } - val iosX64Test by getting - val iosArm64Test by getting - val iosSimulatorArm64Test by getting - val iosTest by creating { - dependsOn(commonTest) - iosX64Test.dependsOn(this) - iosArm64Test.dependsOn(this) - iosSimulatorArm64Test.dependsOn(this) - } - } -} - -android { - compileSdk = AndroidConfig.compileSDK - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") - defaultConfig { - minSdk = AndroidConfig.minSDK - targetSdk = AndroidConfig.targetSDK - } -} diff --git a/core-data/src/androidMain/AndroidManifest.xml b/core-data/src/androidMain/AndroidManifest.xml deleted file mode 100644 index 9ec04a27c..000000000 --- a/core-data/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/core-data/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/data/DataResult.kt b/core-data/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/data/DataResult.kt deleted file mode 100644 index 4301d3ec7..000000000 --- a/core-data/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/data/DataResult.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.adammcneilly.pocketleague.core.data - -/** - * This is a sealed class that represents two options for a data response, where the response is - * either successful or a failure. - * - * By wrapping a response into this single type, we can provide a way for asynchronous streams to - * handle both success and failure scenarios, without having to catch exceptions. This is because any - * exceptions will be wrapped inside an [Error] class. - */ -sealed class DataResult { - /** - * A successful result which implies we will have some [data] returned. - */ - data class Success(val data: T) : DataResult() - - /** - * An unsuccessful result because some [error] occurred. - */ - data class Error(val error: Throwable) : DataResult() -} diff --git a/core-datetime/build.gradle.kts b/core-datetime/build.gradle.kts deleted file mode 100644 index cbf0c5ca8..000000000 --- a/core-datetime/build.gradle.kts +++ /dev/null @@ -1,66 +0,0 @@ -plugins { - kotlin("multiplatform") - id("com.android.library") -} - -kotlin { - android() - - listOf( - iosX64(), - iosArm64(), - iosSimulatorArm64() - ).forEach { - it.binaries.framework { - baseName = "core-datetime" - } - } - - sourceSets { - val commonMain by getting { - dependencies { - api("org.jetbrains.kotlinx:kotlinx-datetime:${Versions.kotlinxDatetime}") - } - } - val commonTest by getting { - dependencies { - implementation(kotlin("test")) - } - } - val androidMain by getting - val androidTest by getting - val iosX64Main by getting - val iosArm64Main by getting - val iosSimulatorArm64Main by getting - val iosMain by creating { - dependsOn(commonMain) - iosX64Main.dependsOn(this) - iosArm64Main.dependsOn(this) - iosSimulatorArm64Main.dependsOn(this) - } - val iosX64Test by getting - val iosArm64Test by getting - val iosSimulatorArm64Test by getting - val iosTest by creating { - dependsOn(commonTest) - iosX64Test.dependsOn(this) - iosArm64Test.dependsOn(this) - iosSimulatorArm64Test.dependsOn(this) - } - } -} - -android { - compileSdk = AndroidConfig.compileSDK - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") - defaultConfig { - minSdk = AndroidConfig.minSDK - targetSdk = AndroidConfig.targetSDK - } - - compileOptions { - sourceCompatibility(JavaVersion.VERSION_1_8) - targetCompatibility(JavaVersion.VERSION_1_8) - isCoreLibraryDesugaringEnabled = true - } -} diff --git a/core-datetime/src/androidMain/AndroidManifest.xml b/core-datetime/src/androidMain/AndroidManifest.xml deleted file mode 100644 index 5bd3639dc..000000000 --- a/core-datetime/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/core-datetime/src/androidMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeFormatter.kt b/core-datetime/src/androidMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeFormatter.kt deleted file mode 100644 index bf49b182e..000000000 --- a/core-datetime/src/androidMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeFormatter.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.adammcneilly.pocketleague.core.datetime - -import kotlinx.datetime.LocalDateTime -import kotlinx.datetime.toJavaLocalDateTime -import java.time.format.DateTimeFormatter - -/** - * See commonMain documentation. - */ -actual class DateTimeFormatter actual constructor() { - - /** - * See commonMain documentation. - */ - actual fun formatLocalDateTime( - localDateTime: LocalDateTime, - formatPattern: String, - ): String? { - val dateTimeFormatter = DateTimeFormatter.ofPattern(formatPattern) - - return localDateTime.toJavaLocalDateTime().format(dateTimeFormatter) - } -} diff --git a/core-datetime/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeFormatter.kt b/core-datetime/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeFormatter.kt deleted file mode 100644 index 1179966da..000000000 --- a/core-datetime/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeFormatter.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.adammcneilly.pocketleague.core.datetime - -import kotlinx.datetime.LocalDateTime - -/** - * A shared class between platforms that is used to format a date into a user friendly string. - */ -expect class DateTimeFormatter constructor() { - - /** - * Given a [localDateTime], apply the [formatPattern] to it to convert it into a user readable string. - * - * @return The user friendly string for the [localDateTime], or null if unable to parse correctly. - */ - fun formatLocalDateTime( - localDateTime: LocalDateTime, - formatPattern: String, - ): String? -} diff --git a/core-datetime/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeParser.kt b/core-datetime/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeParser.kt deleted file mode 100644 index 5e43f0cea..000000000 --- a/core-datetime/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeParser.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.adammcneilly.pocketleague.core.datetime - -import kotlinx.datetime.Clock -import kotlinx.datetime.Instant -import kotlinx.datetime.LocalDateTime -import kotlinx.datetime.TimeZone -import kotlinx.datetime.toLocalDateTime - -/** - * A helper class for parsing an ISO friendly string into a date. - */ -class DateTimeParser { - /** - * Converts the supplied [isoString] into a LocalDateTime or returning today as a default. - */ - fun parseOrToday( - isoString: String?, - timeZone: TimeZone = TimeZone.UTC, - ): LocalDateTime { - val today = Clock.System.now() - - val parsedDate = isoString?.let(Instant.Companion::parse) - - return (parsedDate ?: today).toLocalDateTime(timeZone) - } -} diff --git a/core-datetime/src/iosMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeFormatter.kt b/core-datetime/src/iosMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeFormatter.kt deleted file mode 100644 index 5de13c097..000000000 --- a/core-datetime/src/iosMain/kotlin/com/adammcneilly/pocketleague/core/datetime/DateTimeFormatter.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.adammcneilly.pocketleague.core.datetime - -import kotlinx.datetime.LocalDateTime -import kotlinx.datetime.toNSDateComponents -import platform.Foundation.NSCalendar -import platform.Foundation.NSDateFormatter - -/** - * See commonMain documentation. - */ -actual class DateTimeFormatter actual constructor() { - - /** - * See commonMain documentation. - */ - actual fun formatLocalDateTime( - localDateTime: LocalDateTime, - formatPattern: String, - ): String? { - val nsComponents = localDateTime.toNSDateComponents() - val nsDate = NSCalendar.currentCalendar.dateFromComponents(nsComponents) - - val formatter = NSDateFormatter().apply { - dateFormat = formatPattern - } - - return nsDate?.let { date -> - formatter.stringFromDate(date) - } - } -} diff --git a/core-models/README.md b/core-models/README.md deleted file mode 100644 index 5d7e1abf1..000000000 --- a/core-models/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Core-Models Module - -In the core-models module, we maintain all of the data classes for the model objects used in the Pocket League application. These files should be strictly data classes, with no (or very minimal) calculated properties or mapping to any other types. \ No newline at end of file diff --git a/core-models/build.gradle.kts b/core-models/build.gradle.kts deleted file mode 100644 index bc89cbda8..000000000 --- a/core-models/build.gradle.kts +++ /dev/null @@ -1,60 +0,0 @@ -plugins { - kotlin("multiplatform") - id("com.android.library") -} - -kotlin { - android() - - listOf( - iosX64(), - iosArm64(), - iosSimulatorArm64() - ).forEach { - it.binaries.framework { - baseName = "core-models" - } - } - - sourceSets { - val commonMain by getting { - dependencies { - api("org.jetbrains.kotlinx:kotlinx-datetime:${Versions.kotlinxDatetime}") - } - } - val commonTest by getting { - dependencies { - implementation(kotlin("test")) - } - } - val androidMain by getting - val androidTest by getting - val iosX64Main by getting - val iosArm64Main by getting - val iosSimulatorArm64Main by getting - val iosMain by creating { - dependsOn(commonMain) - iosX64Main.dependsOn(this) - iosArm64Main.dependsOn(this) - iosSimulatorArm64Main.dependsOn(this) - } - val iosX64Test by getting - val iosArm64Test by getting - val iosSimulatorArm64Test by getting - val iosTest by creating { - dependsOn(commonTest) - iosX64Test.dependsOn(this) - iosArm64Test.dependsOn(this) - iosSimulatorArm64Test.dependsOn(this) - } - } -} - -android { - compileSdk = AndroidConfig.compileSDK - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") - defaultConfig { - minSdk = AndroidConfig.minSDK - targetSdk = AndroidConfig.targetSDK - } -} diff --git a/core-models/src/androidMain/AndroidManifest.xml b/core-models/src/androidMain/AndroidManifest.xml deleted file mode 100644 index 0035e9d0e..000000000 --- a/core-models/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/BracketType.kt b/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/BracketType.kt deleted file mode 100644 index 2674320ea..000000000 --- a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/BracketType.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.adammcneilly.pocketleague.core.models - -/** - * An enumeration of possible bracket formats that can occur. - */ -enum class BracketType { - CUSTOM, - SINGLE_ELIMINATION, - DOUBLE_ELIMINATION, - UNKNOWN, -} diff --git a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/EventOverview.kt b/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/EventOverview.kt deleted file mode 100644 index e47bb049f..000000000 --- a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/EventOverview.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.adammcneilly.pocketleague.core.models - -import kotlinx.datetime.LocalDateTime -import kotlinx.datetime.TimeZone - -/** - * A high level overview of an event including its [phases]. - */ -data class EventOverview( - val name: String, - val startDate: LocalDateTime, - val timeZone: TimeZone, - val phases: List, - val standings: Standings, -) diff --git a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/EventSet.kt b/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/EventSet.kt deleted file mode 100644 index 8fe66dcee..000000000 --- a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/EventSet.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.adammcneilly.pocketleague.core.models - -/** - * A [EventSet] represents a series or collection of series between two teams in an event. - */ -data class EventSet( - val fullRoundText: String, - val displayScore: String, - val round: String, - val winnerId: String, - val slots: List, - val games: List, -) diff --git a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/EventSummary.kt b/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/EventSummary.kt deleted file mode 100644 index 4e811aa63..000000000 --- a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/EventSummary.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.adammcneilly.pocketleague.core.models - -import kotlinx.datetime.LocalDateTime -import kotlinx.datetime.TimeZone - -/** - * Represents an individual RLCS Event. Example params below. - * - * @property[id] The unique identifier of the event, like 1234. - * @property[eventName] The name for the event, which can be "Open Qualifier" or "Main Event". - * @property[tournamentName] The broader name for the tournament being captured, such as - * "RLCS 2021-22 Season - Winter Split Regional 1 - North America". - * @property[tournamentImageUrl] An image URL to some image that will be used to identify this tournament. - * @property[startDate] The local date time, in the [timeZone], that this event will begin. - * @property[timeZone] The [TimeZone] that this event is scheduled in, so we can map [startDate] to the proper instant. - * @property[numEntrants] The number of teams registered or participating in this event. Optional if - * no one has registered yet. - * @property[isOnline] True if this is an event taking place digitally, false if in person LAN. - */ -data class EventSummary( - val id: String, - val eventName: String, - val tournamentName: String, - val tournamentImageUrl: String?, - val startDate: LocalDateTime, - val timeZone: TimeZone, - val numEntrants: Int?, - val isOnline: Boolean, -) diff --git a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Game.kt b/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Game.kt deleted file mode 100644 index 664032686..000000000 --- a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Game.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.adammcneilly.pocketleague.core.models - -/** - * Defines a 5 minute game between two RLCS teams. - * - * @property[id] The unique identifier of this game. - * @property[winnerId] The ID of the [Team] that won this game. - */ -data class Game( - val id: String, - val winnerId: String, -) diff --git a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/PhaseDetail.kt b/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/PhaseDetail.kt deleted file mode 100644 index bb1b2fd29..000000000 --- a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/PhaseDetail.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.adammcneilly.pocketleague.core.models - -/** - * A [PhaseDetail] is a portion of an event. An example could be a Swiss stage and a Bracket stage. They'll - * be sorted by the [phaseOrder] property. - */ -data class PhaseDetail( - val id: String, - val groupId: String, - val numPools: Int, - val numEntrants: Int, - val name: String, - val phaseOrder: Int, - val bracketType: BracketType, - val sets: List, -) diff --git a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/PhaseOverview.kt b/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/PhaseOverview.kt deleted file mode 100644 index 31b716e46..000000000 --- a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/PhaseOverview.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.adammcneilly.pocketleague.core.models - -/** - * A [PhaseOverview] is a portion of an event. An example could be a Swiss stage and a Bracket stage. They'll - * be sorted by the [phaseOrder] property. - */ -data class PhaseOverview( - val id: String, - val groupId: String, - val numPools: Int, - val numEntrants: Int, - val name: String, - val phaseOrder: Int, - val bracketType: BracketType, -) diff --git a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Player.kt b/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Player.kt deleted file mode 100644 index b9d03444b..000000000 --- a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Player.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.adammcneilly.pocketleague.core.models - -/** - * The domain information regarding any RLCS player. - */ -data class Player( - val countryCode: String, - val gamerTag: String, - val realName: String, - val notes: String? = null, -) diff --git a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/SetSlot.kt b/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/SetSlot.kt deleted file mode 100644 index 4c61f0814..000000000 --- a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/SetSlot.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.adammcneilly.pocketleague.core.models - -/** - * An entry within a [EventSet] that contains the [team] and their respective [slotIndex]. - */ -data class SetSlot( - val team: Team, - val slotIndex: Int, -) diff --git a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Standings.kt b/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Standings.kt deleted file mode 100644 index e1fde1568..000000000 --- a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Standings.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.adammcneilly.pocketleague.core.models - -/** - * Represents the standings [placements] for some event. - */ -data class Standings( - val placements: List, -) diff --git a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/StandingsPlacement.kt b/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/StandingsPlacement.kt deleted file mode 100644 index 15ffa59bb..000000000 --- a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/StandingsPlacement.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.adammcneilly.pocketleague.core.models - -/** - * Represents the [placement] within standings for a given [team]. - */ -data class StandingsPlacement( - val placement: Int, - val team: Team, -) diff --git a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Team.kt b/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Team.kt deleted file mode 100644 index efc84e793..000000000 --- a/core-models/src/commonMain/kotlin/com/adammcneilly/pocketleague/core/models/Team.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.adammcneilly.pocketleague.core.models - -/** - * A [Team] is any collection of players that competes in RLCS. - */ -data class Team( - val name: String, - val lightThemeLogoImageUrl: String?, - val darkThemeLogoImageUrl: String?, - val roster: List, -) diff --git a/event-api/README.md b/event-api/README.md deleted file mode 100644 index 1fe07184c..000000000 --- a/event-api/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Event-Api Module - -This module is responsible for defining the data layer for any requests related to the events domain. This should strictly be interface contracts, and not any implementation. \ No newline at end of file diff --git a/event-api/build.gradle.kts b/event-api/build.gradle.kts deleted file mode 100644 index f4483df1e..000000000 --- a/event-api/build.gradle.kts +++ /dev/null @@ -1,62 +0,0 @@ -plugins { - kotlin("multiplatform") - id("com.android.library") -} - -kotlin { - android() - - listOf( - iosX64(), - iosArm64(), - iosSimulatorArm64() - ).forEach { - it.binaries.framework { - baseName = "event-api" - } - } - - sourceSets { - val commonMain by getting { - dependencies { - api(project(":core-models")) - api(project(":core-data")) - api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.coroutines}") - } - } - val commonTest by getting { - dependencies { - implementation(kotlin("test")) - } - } - val androidMain by getting - val androidTest by getting - val iosX64Main by getting - val iosArm64Main by getting - val iosSimulatorArm64Main by getting - val iosMain by creating { - dependsOn(commonMain) - iosX64Main.dependsOn(this) - iosArm64Main.dependsOn(this) - iosSimulatorArm64Main.dependsOn(this) - } - val iosX64Test by getting - val iosArm64Test by getting - val iosSimulatorArm64Test by getting - val iosTest by creating { - dependsOn(commonTest) - iosX64Test.dependsOn(this) - iosArm64Test.dependsOn(this) - iosSimulatorArm64Test.dependsOn(this) - } - } -} - -android { - compileSdk = AndroidConfig.compileSDK - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") - defaultConfig { - minSdk = AndroidConfig.minSDK - targetSdk = AndroidConfig.targetSDK - } -} diff --git a/event-api/src/androidMain/AndroidManifest.xml b/event-api/src/androidMain/AndroidManifest.xml deleted file mode 100644 index 1442dfbf5..000000000 --- a/event-api/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/event-api/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/api/EventRepository.kt b/event-api/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/api/EventRepository.kt deleted file mode 100644 index 65571e066..000000000 --- a/event-api/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/api/EventRepository.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.adammcneilly.pocketleague.event.api - -import com.adammcneilly.pocketleague.core.data.DataResult -import com.adammcneilly.pocketleague.core.models.EventOverview -import com.adammcneilly.pocketleague.core.models.EventSummary -import kotlinx.coroutines.flow.Flow - -/** - * Data layer definition for requesting event information. - */ -interface EventRepository { - /** - * Fetch a list of [EventSummary] entities. Actual querying support will come later. - */ - fun fetchEventSummaries(): Flow>> - - /** - * Given an [eventId], fetch the [EventOverview] entity for this event. - */ - fun fetchEventOverview( - eventId: String, - ): Flow> -} diff --git a/event-implementation/README.md b/event-implementation/README.md deleted file mode 100644 index 6d3439732..000000000 --- a/event-implementation/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Event-Implementation Module - -This module is responsible for the concrete implementations of the data layer for the event domain. These interfaces should map to those in the [event-api](../event-api) module. \ No newline at end of file diff --git a/event-implementation/build.gradle.kts b/event-implementation/build.gradle.kts deleted file mode 100644 index 7d5b2a4e3..000000000 --- a/event-implementation/build.gradle.kts +++ /dev/null @@ -1,96 +0,0 @@ -import java.io.FileInputStream -import java.util.Properties - -plugins { - kotlin("multiplatform") - id("com.android.library") - id("com.apollographql.apollo3").version(Versions.apollo) - id("com.codingfeline.buildkonfig").version(Versions.buildKonfig) -} - -kotlin { - android() - - listOf( - iosX64(), - iosArm64(), - iosSimulatorArm64() - ).forEach { - it.binaries.framework { - baseName = "event-implementation" - } - } - - sourceSets { - val commonMain by getting { - dependencies { - implementation(project(":event-api")) - implementation(project(":core-datetime")) - implementation(project(":octanegg")) - implementation("com.apollographql.apollo3:apollo-runtime:${Versions.apollo}") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2") - implementation("io.ktor:ktor-client-core:${Versions.ktor}") - implementation("io.ktor:ktor-client-json:${Versions.ktor}") - implementation("io.ktor:ktor-client-logging:${Versions.ktor}") - implementation("io.ktor:ktor-client-serialization:${Versions.ktor}") - } - } - val commonTest by getting { - dependencies { - implementation(kotlin("test")) - } - } - val androidMain by getting - val androidTest by getting - val iosX64Main by getting - val iosArm64Main by getting - val iosSimulatorArm64Main by getting - val iosMain by creating { - dependsOn(commonMain) - iosX64Main.dependsOn(this) - iosArm64Main.dependsOn(this) - iosSimulatorArm64Main.dependsOn(this) - } - val iosX64Test by getting - val iosArm64Test by getting - val iosSimulatorArm64Test by getting - val iosTest by creating { - dependsOn(commonTest) - iosX64Test.dependsOn(this) - iosArm64Test.dependsOn(this) - iosSimulatorArm64Test.dependsOn(this) - } - } -} - -android { - compileSdk = AndroidConfig.compileSDK - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") - defaultConfig { - minSdk = AndroidConfig.minSDK - targetSdk = AndroidConfig.targetSDK - } -} - -apollo { - packageName.set("com.adammcneilly.pocketleague.event.implementation.graphql") -} - -buildkonfig { - val secretsFile = File("event-implementation/local.properties") - val properties = Properties() - - if (secretsFile.exists()) { - properties.load(FileInputStream(secretsFile)) - } - - defaultConfigs { - packageName = "com.adammcneilly.pocketleague.event.implementation" - - buildConfigField( - type = com.codingfeline.buildkonfig.compiler.FieldSpec.Type.STRING, - name = "SMASH_GG_API_KEY", - value = properties["SmashGGAPIKey"].toString(), - ) - } -} diff --git a/event-implementation/src/androidMain/AndroidManifest.xml b/event-implementation/src/androidMain/AndroidManifest.xml deleted file mode 100644 index 507fbcf8a..000000000 --- a/event-implementation/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/event-implementation/src/commonMain/graphql/EventOverviewQuery.graphql b/event-implementation/src/commonMain/graphql/EventOverviewQuery.graphql deleted file mode 100644 index 1705d6270..000000000 --- a/event-implementation/src/commonMain/graphql/EventOverviewQuery.graphql +++ /dev/null @@ -1,62 +0,0 @@ -fragment EventPlayerFragment on Player { - gamerTag -} - -fragment EventEntrantFragment on Entrant { - id - name - team { - members { - player { - ...EventPlayerFragment - } - } - images { - url - } - } -} - -fragment StandingsPlacementFragment on Standing { - entrant { - ...EventEntrantFragment - } - placement -} - -fragment PhaseOverviewFragment on Phase { - id - groupCount - numSeeds - name - phaseOrder - bracketType -} - -fragment PhaseGroupFragment on PhaseGroup { - id - bracketType - displayIdentifier - numRounds - phase { - ...PhaseOverviewFragment - } -} - -fragment EventOverviewFragment on Event { - ...EventSummaryFragment - phaseGroups { - ...PhaseGroupFragment - } - standings(query: $standingsQuery) { - nodes { - ...StandingsPlacementFragment - } - } -} - -query EventOverviewQuery($eventId: ID, $standingsQuery: StandingPaginationQuery!) { - event(id: $eventId) { - ...EventOverviewFragment - } -} \ No newline at end of file diff --git a/event-implementation/src/commonMain/graphql/EventSummaryListQuery.graphql b/event-implementation/src/commonMain/graphql/EventSummaryListQuery.graphql deleted file mode 100644 index aaa7b7771..000000000 --- a/event-implementation/src/commonMain/graphql/EventSummaryListQuery.graphql +++ /dev/null @@ -1,33 +0,0 @@ -fragment PageInfoFragment on PageInfo { - total - totalPages - page -} - -fragment EventSummaryFragment on Event { - id - name - slug - tournament { - name - images { - url - } - } - startAt - numEntrants - isOnline -} - -query EventSummaryListQuery($leagueSlug: String, $eventsQuery: LeagueEventsQuery) { - league(slug: $leagueSlug) { - events(query: $eventsQuery) { - pageInfo { - ...PageInfoFragment - } - nodes { - ...EventSummaryFragment - } - } - } -} \ No newline at end of file diff --git a/event-implementation/src/commonMain/graphql/PhaseDetailQuery.graphql b/event-implementation/src/commonMain/graphql/PhaseDetailQuery.graphql deleted file mode 100644 index cf85c5ab5..000000000 --- a/event-implementation/src/commonMain/graphql/PhaseDetailQuery.graphql +++ /dev/null @@ -1,45 +0,0 @@ -fragment SetSlotFragment on SetSlot { - entrant { - ...EventEntrantFragment - } - slotIndex -} - -fragment EventSetFragment on Set { - fullRoundText - displayScore - winnerId - round - slots { - ...SetSlotFragment - } - games { - id - winnerId - } -} - -fragment PhaseDetailFragment on Phase { - ...PhaseOverviewFragment - sets( - perPage: $perPage - ) { - pageInfo { - total - totalPages - page - } - nodes { - ...EventSetFragment - } - } -} - -query PhaseDetailQuery( - $id: ID, - $perPage: Int, -) { - phase(id: $id) { - ...PhaseDetailFragment - } -} \ No newline at end of file diff --git a/event-implementation/src/commonMain/graphql/schema.json b/event-implementation/src/commonMain/graphql/schema.json deleted file mode 100644 index eaddc378d..000000000 --- a/event-implementation/src/commonMain/graphql/schema.json +++ /dev/null @@ -1 +0,0 @@ -{"data":{"__schema":{"queryType":{"name":"Query"},"mutationType":{"name":"Mutation"},"subscriptionType":null,"types":[{"kind":"OBJECT","name":"Query","description":null,"fields":[{"name":"currentUser","description":"Returns the authenticated user","args":[],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"event","description":"Returns an event given its id or slug","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"league","description":"Returns a league given its id or slug","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"League","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participant","description":"Returns a participant given its id","args":[{"name":"id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"isAdmin","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Participant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phase","description":"Returns a phase given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseGroup","description":"Returns a phase group given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"PhaseGroup","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":"Returns a player given an id","args":[{"name":"id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seed","description":"Returns a phase seed given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Seed","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"set","description":"Returns a set given its id","args":[{"name":"id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Set","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"shop","description":"A shop entity","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Shop","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":"Returns an stream given its id","args":[{"name":"id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Streams","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamQueue","description":"Returns all the stream queues for a given tournament","args":[{"name":"tournamentId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"includePlayerStreams","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"StreamQueue","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"team","description":"Returns a team given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"inviteCode","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"INTERFACE","name":"Team","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournament","description":"Returns a tournament given its id or slug","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Tournament","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournaments","description":"Paginated, filterable list of tournaments","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"TournamentQuery","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"TournamentConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"user","description":"Returns a user given a user slug of the form user\/abc123, or id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"videogame","description":"Returns a videogame given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Videogame","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"videogames","description":"Returns paginated list of videogames matching the search criteria.","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"VideogameQuery","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"VideogameConnection","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"User","description":"A user","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"authorizations","description":"Authorizations to external services (i.e. Twitch, Twitter)","args":[{"name":"types","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"SocialConnectionType","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"ProfileAuthorization","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"bio","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"birthday","description":"Public facing user birthday that respects user publishing settings","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discriminator","description":"Uniquely identifying token for user. Same as the hashed part of the slug","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"events","description":"Events this user has competed in","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserEventsPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"genderPronoun","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"leagues","description":"Leagues this user has competed in","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserLeaguesPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"LeagueConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"location","description":"Public location info for this user","args":[],"type":{"kind":"OBJECT","name":"Address","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Public facing user name that respects user publishing settings","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":"player for user","args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournaments","description":"Tournaments this user is organizing or competing in","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserTournamentsPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"TournamentConnection","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"ID","description":"The `ID` scalar type represents a unique identifier, often used to\nrefetch an object or as key for a cache. When expected as an input type, any string (such as `\"4\"`) or integer\n(such as `4`) input value will be accepted as an ID.","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"SocialConnectionType","description":"Represents the name of the third-party social service (e.g Twitter) for OAuth","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITTER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"TWITCH","description":"","isDeprecated":false,"deprecationReason":null},{"name":"DISCORD","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"XBOX","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"ProfileAuthorization","description":"An OAuth ProfileAuthorization object","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"externalId","description":"The id given by the external service","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"externalUsername","description":"The username given by the external service (including discriminator if discord)","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":null,"args":[],"type":{"kind":"OBJECT","name":"Stream","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":"The name of the external service providing this auth i.e. \"twitch\"","args":[],"type":{"kind":"ENUM","name":"AuthorizationType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"String","description":"The `String` scalar type represents textual data, represented as UTF-8\ncharacter sequences. The String type is most often used by GraphQL to\nrepresent free-form human-readable text.","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Stream","description":"A Stream object","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":"Whether the stream is currently live. May be slightly delayed.","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The name of the stream","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":"The name of the external service providing this auth i.e. \"twitch\"","args":[],"type":{"kind":"ENUM","name":"StreamType","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"Boolean","description":"The `Boolean` scalar type represents `true` or `false`.","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"StreamType","description":"Represents the type of stream service","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITCH","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"ENUM","name":"AuthorizationType","description":"Represents the name of the third-party service (e.g Twitter) for OAuth","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITTER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"TWITCH","description":"","isDeprecated":false,"deprecationReason":null},{"name":"STEAM","description":"","isDeprecated":false,"deprecationReason":null},{"name":"DISCORD","description":"","isDeprecated":false,"deprecationReason":null},{"name":"XBOX","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserEventsPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserEventsPaginationFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"Int","description":"The `Int` scalar type represents non-fractional signed whole numeric\nvalues. Int can represent values between -(2^31) and 2^31 - 1. ","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserEventsPaginationFilter","description":null,"fields":null,"inputFields":[{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventType","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"minEntrantCount","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"maxEntrantCount","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"location","description":null,"type":{"kind":"INPUT_OBJECT","name":"LocationFilterType","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"LocationFilterType","description":null,"fields":null,"inputFields":[{"name":"countryCode","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"state","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"city","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PaginationSearchType","description":null,"fields":null,"inputFields":[{"name":"fieldsToSearch","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"defaultValue":null},{"name":"searchString","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"PageInfo","description":null,"fields":[{"name":"total","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"totalPages","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"page","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"perPage","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"sortBy","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"filter","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"JSON","description":"The `JSON` scalar type represents JSON values as specified by\n\t\t[ECMA-404](http:\/\/www.ecma-international.org\/publications\/files\/ECMA-ST\/ECMA-404.pdf).","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Event","description":"An event in a tournament","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkInBuffer","description":"How long before the event start will the check-in end (in seconds)","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkInDuration","description":"How long the event check-in will last (in seconds)","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkInEnabled","description":"Whether check-in is enabled for this event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"createdAt","description":"When the event was created (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"deckSubmissionDeadline","description":"Last date attendees are able to create teams for team events","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrantSizeMax","description":"Maximum number of participants each Entrant can have","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"Migrate to teamRosterSize"},{"name":"entrantSizeMin","description":"Minimum number of participants each Entrant can have","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"Migrate to teamRosterSize"},{"name":"entrants","description":"The entrants that belong to an event, paginated by filter criteria","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"EventEntrantPageQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EntrantConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hasDecks","description":"Whether the event has decks","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hasTasks","description":"Are player tasks enabled for this event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":"Whether the event is an online event or not","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"league","description":null,"args":[],"type":{"kind":"OBJECT","name":"League","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"matchRulesMarkdown","description":"Markdown field for match rules\/instructions","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Title of event set by organizer","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numEntrants","description":"Gets the number of entrants in this event","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseGroups","description":"The phase groups that belong to an event.","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"PhaseGroup","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"phases","description":"The phases that belong to an event.","args":[{"name":"state","description":"Filter phases by state. If not specified will default to all phases","type":{"kind":"ENUM","name":"ActivityState","ofType":null},"defaultValue":null},{"name":"phaseId","description":"Optionally only return results for this phase","type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Phase","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"prizingInfo","description":"TO settings for prizing","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"publishing","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rulesMarkdown","description":"Markdown field for event rules\/instructions","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rulesetId","description":"Id of the event ruleset","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rulesetSettings","description":"Settings pulled from the event ruleset, if one exists","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":true,"deprecationReason":"Use ruleset"},{"name":"sets","description":"Paginated sets for this Event","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standings","description":"Paginated list of standings","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"StandingPaginationQuery","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StandingConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"When does this event start?","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"The state of the Event.","args":[],"type":{"kind":"ENUM","name":"ActivityState","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stations","description":"Paginated stations on this event","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"StationFilter","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StationsConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teamManagementDeadline","description":"Last date attendees are able to create teams for team events","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teamNameAllowed","description":"If this is a teams event, returns whether or not teams can set custom names","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teamRosterSize","description":"Team roster size requirements","args":[],"type":{"kind":"OBJECT","name":"TeamRosterSize","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournament","description":null,"args":[],"type":{"kind":"OBJECT","name":"Tournament","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":"The type of the event, whether an entrant will have one participant or multiple","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"updatedAt","description":"When the event was last modified (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"useEventSeeds","description":"Whether the event uses the new EventSeeds for seeding","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"videogame","description":null,"args":[],"type":{"kind":"OBJECT","name":"Videogame","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"waves","description":"The waves being used by the event","args":[{"name":"phaseId","description":"Waves filtered by phaseId, returns all if not set.","type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Wave","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"Timestamp","description":"Represents a Unix Timestamp. Supports up to 53 bit int values,\n\t\tas that is JavaScript's internal memory allocation for integer values.","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"EventEntrantPageQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"EventEntrantPageQueryFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"EventEntrantPageQueryFilter","description":null,"fields":null,"inputFields":[{"name":"name","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EntrantConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Entrant","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Entrant","description":"An entrant in an event","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"event","description":null,"args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"initialSeedNum","description":"Entrant's seed number in the first phase of the event.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isDisqualified","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The entrant name as it appears in bracket: gamerTag of the participant or team name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"paginatedSets","description":"Paginated sets for this entrant","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participants","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Participant","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"seeds","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Seed","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"skill","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standing","description":"Standing for this entrant given an event. All entrants queried must be in the same event (for now).","args":[],"type":{"kind":"OBJECT","name":"Standing","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":null,"args":[],"type":{"kind":"OBJECT","name":"Streams","ofType":null},"isDeprecated":true,"deprecationReason":"DEPRECATED. Use streams instead, which supports multiple stream types and teams."},{"name":"streams","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Streams","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"team","description":"Team linked to this entrant, if one exists","args":[],"type":{"kind":"INTERFACE","name":"Team","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"SetSortType","description":"Different sort type configurations used when displaying multiple sets","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"NONE","description":"Sets will not be sorted.","isDeprecated":false,"deprecationReason":null},{"name":"CALL_ORDER","description":"Sets are sorted in the suggested order that they be called to be played. The order of completed sets is reversed.","isDeprecated":false,"deprecationReason":null},{"name":"MAGIC","description":"Sets are sorted by relevancy dependent on the state and progress of the event.","isDeprecated":false,"deprecationReason":null},{"name":"RECENT","description":"Sets are sorted in the order that they were started.","isDeprecated":false,"deprecationReason":null},{"name":"STANDARD","description":"Deprecated. This is equivalent to CALL_ORDER","isDeprecated":false,"deprecationReason":null},{"name":"ROUND","description":"Sets sorted by round and identifier","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SetFilters","description":null,"fields":null,"inputFields":[{"name":"entrantIds","description":"Only return Sets for these Entrants","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"entrantSize","description":"Only return Sets for this Entrant size. For example, to fetch 1v1 Sets only, filter by an entrantSize of 1","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"hasVod","description":"Only return Sets that have an attached VOD","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"hideEmpty","description":"Do not return empty Sets. For example, set this to true to filter out sets that are waiting for progressions.","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"showByes","description":"Return sets that contain a bye","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"isEventOnline","description":"Only return Sets that are in an Online event. If omitted, Sets for both online and offline Events are returned","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"location","description":"Only return Sets in certain geographical areas.","type":{"kind":"INPUT_OBJECT","name":"SetFilterLocation","ofType":null},"defaultValue":null},{"name":"participantIds","description":"Only return Sets for these Participants","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"phaseGroupIds","description":"Only return Sets in these PhaseGroups","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"phaseIds","description":"Only return Sets in these Phases","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventIds","description":"Only return Sets in these Events","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"tournamentIds","description":"Only return Sets in these Tournaments","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"playerIds","description":"Only return Sets for these Players","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"roundNumber","description":"Only return Sets for these Rounds","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"state","description":"Only returns Sets that are in these states","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"stationIds","description":"Only return Sets that are assigned to these Station IDs","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"stationNumbers","description":"Only return Sets that are assigned to these Station numbers","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"updatedAfter","description":"Only return sets created or updated since this timestamp","type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SetFilterLocation","description":"Filter Sets by geographical constraints.","fields":null,"inputFields":[{"name":"state","description":"Only return Sets in this state. Only applicable to US states","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"country","description":"Only return Sets in this country. Expects a valid two-letter country code","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"distanceFrom","description":null,"type":{"kind":"INPUT_OBJECT","name":"SetFilterLocationDistanceFrom","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SetFilterLocationDistanceFrom","description":"Only return Sets that are a certain distance away from a specified point","fields":null,"inputFields":[{"name":"point","description":"Point at which to perform distance calculation","type":{"kind":"INPUT_OBJECT","name":"SetFilterLocationDistanceFromPoint","ofType":null},"defaultValue":null},{"name":"radius","description":"Distance from the point to include results in","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SetFilterLocationDistanceFromPoint","description":null,"fields":null,"inputFields":[{"name":"lat","description":null,"type":{"kind":"SCALAR","name":"Float","ofType":null},"defaultValue":null},{"name":"lon","description":null,"type":{"kind":"SCALAR","name":"Float","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"Float","description":"The `Float` scalar type represents signed double-precision fractional\nvalues as specified by\n[IEEE 754](http:\/\/en.wikipedia.org\/wiki\/IEEE_floating_point). ","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"SetConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Set","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Set","description":"A set","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"completedAt","description":"The time this set was marked as completed","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"createdAt","description":"The time this set was created","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"displayScore","description":null,"args":[{"name":"mainEntrantId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"event","description":"Event that this set belongs to.","args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"fullRoundText","description":"Full round text of this set.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"game","description":null,"args":[{"name":"orderNum","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Game","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"games","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Game","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"hasPlaceholder","description":"Whether this set contains a placeholder entrant","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"identifier","description":"The letters that describe a unique identifier within the pool. Eg. F, AT","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"lPlacement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseGroup","description":"Phase group that this Set belongs to.","args":[],"type":{"kind":"OBJECT","name":"PhaseGroup","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"round","description":"The round number of the set. Negative numbers are losers bracket","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"setGamesType","description":"Indicates whether the set is in best of or total games mode. This instructs\nwhich field is used to figure out how many games are in this set.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slots","description":"A possible spot in a set. Use this to get all entrants in a set. Use this for all bracket types (FFA, elimination, etc)","args":[{"name":"includeByes","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"false"}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"SetSlot","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"The start time of the Set. If there is no startAt time on the Set, will pull it from phaseGroup rounds configuration.","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startedAt","description":null,"args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"station","description":"Tournament event station for a set","args":[],"type":{"kind":"OBJECT","name":"Stations","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":"Tournament event stream for a set","args":[],"type":{"kind":"OBJECT","name":"Streams","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"totalGames","description":"If setGamesType is in total games mode, this defined the number of games in the set.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"vodUrl","description":"Url of a VOD for this set","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"wPlacement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"winnerId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Game","description":"A game represents a single game within a set.","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"orderNum","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"selections","description":"Selections for this game such as character, etc.","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"GameSelection","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"stage","description":"The stage that this game was played on (if applicable)","args":[],"type":{"kind":"OBJECT","name":"Stage","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"winnerId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Image","description":"An image","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"height","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"ratio","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"width","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"GameSelection","description":"A selection for this game. i.e. character\/stage selection, etc","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":"The entrant who this selection is for","args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"orderNum","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participant","description":"The participant who this selection is for. This is only populated if there are\nselections for multiple participants of a single entrant","args":[],"type":{"kind":"OBJECT","name":"Participant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"selectionType","description":null,"args":[],"type":{"kind":"ENUM","name":"GameSelectionType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"selectionValue","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Participant","description":"A participant of a tournament; either a spectator or competitor","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkedIn","description":"If this participant was checked-in by admin","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkedInAt","description":"The time this participant was checked-in by admin","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"connectedAccounts","description":"Info for connected accounts to external services.","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"contactInfo","description":"Contact Info selected during registration. Falls back to User.location and\/or\nUser.name if necessary. These fields are for admin use only and do not respect\nuser privacy settings. DO NOT display this information publicly.","args":[],"type":{"kind":"OBJECT","name":"ContactInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"email","description":"Email of the user, only available to admins within 18 months of tournament","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrants","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Entrant","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"events","description":"The events this participant registered for.","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"gamerTag","description":"The tag that was used in registration e.g. Mang0","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":null,"args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prefix","description":"The prefix that was used in registration e.g. C9","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"requiredConnections","description":"Admin only field for required social connections","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"ProfileAuthorization","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"user","description":"The user this participant is associated to.","args":[],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"verified","description":"If this participant is verified as actually being in the tournament","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ContactInfo","description":"Name, address, etc","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"city","description":"Participant City Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"country","description":"Participant Country Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"countryId","description":"Participant Country (region) id","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nameFirst","description":"First Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nameLast","description":"Last Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"Participant State Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stateId","description":"Participant State (region) id","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"zipcode","description":"Zip or Postal Code","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Player","description":"A player","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"gamerTag","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prefix","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rankings","description":"Most recent active & published rankings","args":[{"name":"limit","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"videogameId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"PlayerRank","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"recentSets","description":"Recent sets for this player.","args":[{"name":"opponentId","description":"Use this to get H2H history between two players","type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Set","ofType":null}},"isDeprecated":true,"deprecationReason":"Use the sets field instead."},{"name":"sets","description":"Set history for this player.","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"user","description":null,"args":[],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"PlayerRank","description":"A player's ranks","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rank","description":"The player's placement on the ranking","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"title","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"GameSelectionType","description":"The type of selection i.e. is it for a character or something else","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"CHARACTER","description":"Character selection","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"Stage","description":"Video Stage","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Stage name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"PhaseGroup","description":"A group within a phase","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":"The bracket type of this group's phase.","args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"displayIdentifier","description":"Unique identifier for this group within the context of its phase","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"firstRoundTime","description":"For the given phase group, this is the start time of the first round that occurs in the group.","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numRounds","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"paginatedSeeds","description":null,"args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SeedConnection","ofType":null},"isDeprecated":true,"deprecationReason":"Please use 'seeds', which is now paginated"},{"name":"paginatedSets","description":"Paginated sets on this phaseGroup","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":true,"deprecationReason":"Please use 'sets', which is now paginated"},{"name":"phase","description":"The phase associated with this phase group","args":[],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"progressionsOut","description":"The progressions out of this phase group","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Progression","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"rounds","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Round","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"seedMap","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seeds","description":"Paginated seeds for this phase group","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SeedConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"sets","description":"Paginated sets on this phaseGroup","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standings","description":"Paginated list of standings","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"StandingGroupStandingPageFilter","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StandingConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"Unix time the group is scheduled to start. This info could also be on the wave instead.","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tiebreakOrder","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"wave","description":null,"args":[],"type":{"kind":"OBJECT","name":"Wave","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"BracketType","description":"The type of Bracket format that a Phase is configured with.","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"SINGLE_ELIMINATION","description":"","isDeprecated":false,"deprecationReason":null},{"name":"DOUBLE_ELIMINATION","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ROUND_ROBIN","description":"","isDeprecated":false,"deprecationReason":null},{"name":"SWISS","description":"","isDeprecated":false,"deprecationReason":null},{"name":"EXHIBITION","description":"","isDeprecated":false,"deprecationReason":null},{"name":"CUSTOM_SCHEDULE","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MATCHMAKING","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ELIMINATION_ROUNDS","description":"","isDeprecated":false,"deprecationReason":null},{"name":"RACE","description":"","isDeprecated":false,"deprecationReason":null},{"name":"CIRCUIT","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"SeedPageFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SeedPageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"entrantName","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"checkInState","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"phaseGroupId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventCheckInGroupId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"phaseId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"SeedConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Seed","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Seed","description":"A seed for an entrant","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkedInParticipants","description":"Map of Participant ID to checked in boolean","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"groupSeedNum","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isBye","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phase","description":null,"args":[],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseGroup","description":null,"args":[],"type":{"kind":"OBJECT","name":"PhaseGroup","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"placeholderName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"placement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"players","description":"The player(s) associated with this seed's entrant","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Player","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"progressionSeedId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"progressionSource","description":"Source progression information","args":[],"type":{"kind":"OBJECT","name":"Progression","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seedNum","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"setRecordWithoutByes","description":"Entrant's win\/loss record for this standing. Scores do not include byes.","args":[{"name":"phaseGroupId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standings","description":null,"args":[{"name":"containerType","description":"The container of the standing groups to get standings for. If null, will return all standings.","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Standing","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Phase","description":"A phase in an event","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":"The bracket type of this phase.","args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"event","description":"The Event that this phase belongs to","args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"groupCount","description":"Number of phase groups in this phase","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isExhibition","description":"Is the phase an exhibition or not.","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Name of phase e.g. Round 1 Pools","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numSeeds","description":"The number of seeds this phase contains.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"paginatedSeeds","description":null,"args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SeedConnection","ofType":null},"isDeprecated":true,"deprecationReason":"Please use 'seeds' instead"},{"name":"phaseGroups","description":"Phase groups under this phase, paginated","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"PhaseGroupPageQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"PhaseGroupConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseOrder","description":"The relative order of this phase within an event","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seeds","description":"Paginated seeds for this phase","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SeedConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"sets","description":"Paginated sets for this Phase","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"State of the phase","args":[],"type":{"kind":"ENUM","name":"ActivityState","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"waves","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Wave","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PhaseGroupPageQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"entrantIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"PhaseGroupPageQueryFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PhaseGroupPageQueryFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"waveId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"PhaseGroupConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"PhaseGroup","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"ActivityState","description":"Represents the state of an activity","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"CREATED","description":"Activity is created","isDeprecated":false,"deprecationReason":null},{"name":"ACTIVE","description":"Activity is active or in progress","isDeprecated":false,"deprecationReason":null},{"name":"COMPLETED","description":"Activity is done","isDeprecated":false,"deprecationReason":null},{"name":"READY","description":"Activity is ready to be started","isDeprecated":false,"deprecationReason":null},{"name":"INVALID","description":"Activity is invalid","isDeprecated":false,"deprecationReason":null},{"name":"CALLED","description":"Activity, like a set, has been called to start","isDeprecated":false,"deprecationReason":null},{"name":"QUEUED","description":"Activity is queued to run","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"Wave","description":"A wave in a tournament","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"identifier","description":"The Wave Identifier","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"Unix time the wave is scheduled to start.","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Progression","description":"A connection between a placement in an origin phase group to a destination seed.","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"originOrder","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"originPhase","description":null,"args":[],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"originPhaseGroup","description":null,"args":[],"type":{"kind":"OBJECT","name":"PhaseGroup","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"originPlacement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Standing","description":"A standing indicates the placement of something within a container.","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"container","description":"The containing entity that contextualizes this standing. Event standings, for\nexample, represent an entrant's standing in the entire event vs. Set standings\nwhich is an entrant's standing in only a single set within an event.","args":[],"type":{"kind":"UNION","name":"StandingContainer","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":"If the entity this standing is assigned to can be resolved into an entrant, this will provide the entrant.","args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isFinal","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"metadata","description":"Metadata that goes along with this standing. Can take on different forms based on standing group type and settings.","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"placement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":"The player(s) tied to this standing's entity","args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standing","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"The \"placement\" field is identical and will eventually replace \"standing\""},{"name":"stats","description":null,"args":[],"type":{"kind":"OBJECT","name":"StandingStats","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"totalPoints","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"UNION","name":"StandingContainer","description":"The containing entity that this standing is for","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"Tournament","ofType":null},{"kind":"OBJECT","name":"Event","ofType":null},{"kind":"OBJECT","name":"PhaseGroup","ofType":null},{"kind":"OBJECT","name":"Set","ofType":null}]},{"kind":"OBJECT","name":"Tournament","description":"A tournament","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"addrState","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"admins","description":"Admin-only view of admins for this tournament","args":[{"name":"roles","description":"Which roles to show","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"User","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"city","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"countryCode","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"createdAt","description":"When the tournament was created (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"currency","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"endAt","description":"When the tournament ends","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"eventRegistrationClosesAt","description":"When does event registration close","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"events","description":null,"args":[{"name":"limit","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"EventFilter","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"hasOfflineEvents","description":"True if tournament has at least one offline event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hasOnlineEvents","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hashtag","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":"True if tournament has at least one online event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isRegistrationOpen","description":"Is tournament registration open","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"lat","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"links","description":null,"args":[],"type":{"kind":"OBJECT","name":"TournamentLinks","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"lng","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"mapsPlaceId","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The tournament name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numAttendees","description":"Number of attendees including spectators, if public","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"owner","description":"The user who created the tournament","args":[],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participants","description":"Paginated, queryable list of participants","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"ParticipantPaginationQuery","ofType":null}},"defaultValue":null},{"name":"isAdmin","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"ParticipantConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"postalCode","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"primaryContact","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"primaryContactType","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"publishing","description":"Publishing settings for this tournament","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"registrationClosesAt","description":"When does registration for the tournament end","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rules","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"shortSlug","description":"The short slug used to form the url","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":"The slug used to form the url","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"When the tournament Starts","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"State of the tournament, can be ActivityState::CREATED, ActivityState::ACTIVE, or ActivityState::COMPLETED","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stations","description":null,"args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StationsConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamQueue","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"StreamQueue","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"streams","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Streams","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"teamCreationClosesAt","description":"When is the team creation deadline","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teams","description":"Paginated, queryable list of teams","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"TeamPaginationQuery","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"TeamConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"timezone","description":"The timezone of the tournament","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournamentType","description":"The type of tournament from TournamentType","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"updatedAt","description":"When the tournament was last modified (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":"Build Tournament URL","args":[{"name":"tab","description":"Tournament tab to add to URL","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"relative","description":"Generate a relative URL. Defaults to true. Setting to false will generate an absolute URL","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"true"}],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"venueAddress","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"venueName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"waves","description":"List of all waves in this tournament","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Wave","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"EventFilter","description":null,"fields":null,"inputFields":[{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"type","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"published","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"TournamentLinks","description":null,"fields":[{"name":"facebook","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discord","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ParticipantPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"ParticipantPageFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ParticipantPageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"ids","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null},{"name":"gamerTag","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"unpaid","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"incompleteTeam","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"missingDeck","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"checkedIn","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"notCheckedIn","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ParticipantConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Participant","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"StationsConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Stations","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Stations","description":"Stations, such as a stream setup, at an event","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"canAutoAssign","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"clusterNumber","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"clusterPrefix","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"enabled","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"identifier","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numSetups","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"number","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prefix","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"queue","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"queueDepth","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"updatedAt","description":null,"args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"StreamQueue","description":"A Stream queue object","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"sets","description":"The sets on the stream","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Set","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":"The stream on the queue","args":[],"type":{"kind":"OBJECT","name":"Streams","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Streams","description":"Tournament Stream","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"enabled","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"followerCount","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numSetups","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"parentStreamId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamGame","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamId","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamLogo","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamSource","description":null,"args":[],"type":{"kind":"ENUM","name":"StreamSource","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamStatus","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamType","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamTypeId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"StreamSource","description":"Represents the source of a stream","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITCH","description":"Stream is on twitch.tv channel","isDeprecated":false,"deprecationReason":null},{"name":"HITBOX","description":"Stream is on smashcast.tv channel","isDeprecated":false,"deprecationReason":null},{"name":"STREAMME","description":"Stream is on a stream.me channel","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"Stream is on a mixer.com channel","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TeamPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"TeamPaginationFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TeamPaginationFilter","description":null,"fields":null,"inputFields":[{"name":"globalTeamId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"eventState","description":null,"type":{"kind":"ENUM","name":"ActivityState","ofType":null},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"eventIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"minEntrantCount","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"maxEntrantCount","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null},{"name":"type","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"tournamentId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"memberStatus","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null}},"defaultValue":null},{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"isLeague","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"past","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"rosterComplete","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"rosterIncomplete","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"TeamMemberStatus","description":"Membership status of a team member","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"UNKNOWN","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ACCEPTED","description":"","isDeprecated":false,"deprecationReason":null},{"name":"INVITED","description":"","isDeprecated":false,"deprecationReason":null},{"name":"REQUEST","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ALUM","description":"","isDeprecated":false,"deprecationReason":null},{"name":"HIATUS","description":"","isDeprecated":false,"deprecationReason":null},{"name":"OPEN_SPOT","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"TeamConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"INTERFACE","name":"Team","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INTERFACE","name":"Team","description":"A team, either at the global level or within the context of an event","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discriminator","description":"Uniquely identifying token for team. Same as the hashed part of the slug","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":true,"deprecationReason":"Use the entrant field off the EventTeam type"},{"name":"event","description":null,"args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":true,"deprecationReason":"Use the event field off the EventTeam type"},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"members","description":null,"args":[{"name":"status","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"TeamMember","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"EventTeam","ofType":null},{"kind":"OBJECT","name":"GlobalTeam","ofType":null}]},{"kind":"OBJECT","name":"TeamMember","description":"A member of a team","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isAlternate","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isCaptain","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"memberType","description":"The type of the team member","args":[],"type":{"kind":"ENUM","name":"TeamMemberType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Participant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":null,"args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"status","description":"The status of the team member","args":[],"type":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"TeamMemberType","description":"Membership type of a team member","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"PLAYER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"STAFF","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"StandingStats","description":"Any stats related to this standing. This type is experimental and very likely to change in the future.","fields":[{"name":"score","description":null,"args":[],"type":{"kind":"OBJECT","name":"Score","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Score","description":"The score that led to this standing being awarded. The meaning of this field can\nvary by standing type and is not used for some standing types.","fields":[{"name":"label","description":"The name of this score. e.g. \"Kills\" or \"Stocks\"","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"value","description":"The raw score value","args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"displayValue","description":"Like value, but formatted for race format events. Formatted according to the race config for the front end to use.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Round","description":"A round within a phase group","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bestOf","description":"If applicable, bestOf is the number of games\n\t\t\t\t\t\t\t\t\tone must win a majority out of to win a set in this round","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"number","description":"Indicates this round's order in the phase group","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"The time that this round is scheduled to start at","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StandingGroupStandingPageFilter","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"StandingConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Standing","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"SetSlot","description":"A slot in a set where a seed currently or will eventually exist in order to participate in the set.","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prereqId","description":"Pairs with prereqType, is the ID of the prereq.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prereqPlacement","description":"Given a set prereq type, defines the placement required in the origin set to end up in this slot.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prereqType","description":"Describes where the entity in this slot comes from.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seed","description":null,"args":[],"type":{"kind":"OBJECT","name":"Seed","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slotIndex","description":"The index of the slot. Unique per set.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standing","description":"The standing within this set for the seed currently assigned to this slot.","args":[],"type":{"kind":"OBJECT","name":"Standing","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"League","description":"A league","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"addrState","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"city","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"countryCode","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"createdAt","description":"When the tournament was created (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"currency","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"endAt","description":"When the tournament ends","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrantCount","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"eventOwners","description":null,"args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"EventOwnersQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventOwnerConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"eventRegistrationClosesAt","description":"When does event registration close","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"events","description":"Paginated list of events in a league","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"LeagueEventsQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"finalEventId","description":"Hacked \"progression\" into this final event","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"No longer used"},{"name":"hasOfflineEvents","description":"True if tournament has at least one offline event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hasOnlineEvents","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hashtag","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":"True if tournament has at least one online event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"lat","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"links","description":null,"args":[],"type":{"kind":"OBJECT","name":"TournamentLinks","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"lng","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"mapsPlaceId","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The tournament name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numProgressingToFinalEvent","description":"Top X number of people in the standings who progress to final event","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"No longer used"},{"name":"numUniquePlayers","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"postalCode","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"primaryContact","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"primaryContactType","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"publishing","description":"Publishing settings for this tournament","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"registrationClosesAt","description":"When does registration for the tournament end","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rules","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"shortSlug","description":"The short slug used to form the url","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"showStandings","description":"Whether standings for this league should be visible","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standings","description":"Paginated list of standings","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"StandingGroupStandingPageFilter","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StandingConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"When the tournament Starts","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"State of the tournament, can be ActivityState::CREATED, ActivityState::ACTIVE, or ActivityState::COMPLETED","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teamCreationClosesAt","description":"When is the team creation deadline","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tiers","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"EventTier","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"timezone","description":"The timezone of the tournament","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournamentType","description":"The type of tournament from TournamentType","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"updatedAt","description":"When the tournament was last modified (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":"Build Tournament URL","args":[{"name":"tab","description":"Tournament tab to add to URL","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"relative","description":"Generate a relative URL. Defaults to true. Setting to false will generate an absolute URL","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"true"}],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"venueAddress","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"venueName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"videogames","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Videogame","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"EventOwnersQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventOwnerConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"EventOwner","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventOwner","description":"Name and Gamertag of the owner of an event in a league","fields":[{"name":"eventId","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"email","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"gamerTag","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"fullName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"LeagueEventsQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"LeagueEventsFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"LeagueEventsFilter","description":null,"fields":null,"inputFields":[{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null},{"name":"pointMappingGroupIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"tierIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"userId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"leagueEntrantId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventTier","description":"Used for league application tiers","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Name of this tier","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Videogame","description":"A videogame","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"displayName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StandingPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"StandingPageFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StandingPageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"ids","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StationFilter","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"TeamRosterSize","description":"Team roster size requirements","fields":[{"name":"maxAlternates","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"maxPlayers","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"minAlternates","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"minPlayers","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserLeaguesPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserLeaguesPaginationFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserLeaguesPaginationFilter","description":null,"fields":null,"inputFields":[{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"past","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"LeagueConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"League","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Address","description":"A user's address","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"city","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"country","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"countryId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stateId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserTournamentsPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserTournamentsPaginationFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserTournamentsPaginationFilter","description":null,"fields":null,"inputFields":[{"name":"past","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null},{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"tournamentView","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"excludeId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"TournamentConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Tournament","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Shop","description":"A shop","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"levels","description":null,"args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"ShopLevelsQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"ShopLevelConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"messages","description":null,"args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"ShopOrderMessagesQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"ShopOrderMessageConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ShopLevelsQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ShopLevelConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"ShopLevel","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ShopLevel","description":"A shop level","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"currAmount","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"goalAmount","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ShopOrderMessagesQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ShopOrderMessageConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"ShopOrderMessage","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ShopOrderMessage","description":"The message and player info for a shop order","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"gamertag","description":"The player's gamertag. Returns null if anonymous message type","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"message","description":"The order message","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The player's name. Returns null unless name & tag display is selected","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":"The player who left the comment","args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"total","description":"The total order amount","args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TournamentQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"TournamentPageFilter","ofType":null},"defaultValue":null},{"name":"sort","description":null,"type":{"kind":"ENUM","name":"TournamentPaginationSort","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TournamentPageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"ids","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"ownerId","description":"ID of the user that owns this tournament.","type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"isCurrentUserAdmin","description":"If true, filter to only tournaments the currently authed user is an admin of","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"countryCode","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"addrState","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"location","description":null,"type":{"kind":"INPUT_OBJECT","name":"TournamentLocationFilter","ofType":null},"defaultValue":null},{"name":"afterDate","description":null,"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"defaultValue":null},{"name":"beforeDate","description":null,"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"defaultValue":null},{"name":"computedUpdatedAt","description":null,"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"defaultValue":null},{"name":"name","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"venueName","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"isFeatured","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"isLeague","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"hasBannerImages","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"activeShops","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"regOpen","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"past","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"published","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"publiclySearchable","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"staffPicks","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"hasOnlineEvents","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"topGames","description":null,"type":{"kind":"INPUT_OBJECT","name":"TopGameFilter","ofType":null},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"videogameIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"sortByScore","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TournamentLocationFilter","description":null,"fields":null,"inputFields":[{"name":"distanceFrom","description":"Latitude, Longitude","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"distance","description":"e.g. 50mi","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TopGameFilter","description":null,"fields":null,"inputFields":[{"name":"gameNums","description":"Array of which # top game you want to filter on.e.g. [2, 3] will filter on the 2nd and 3rd top games","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"TournamentPaginationSort","description":null,"fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"startAt","description":"","isDeprecated":false,"deprecationReason":null},{"name":"endAt","description":"","isDeprecated":false,"deprecationReason":null},{"name":"eventRegistrationClosesAt","description":"","isDeprecated":false,"deprecationReason":null},{"name":"computedUpdatedAt","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"VideogameQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"VideogamePageFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"VideogamePageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"name","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"forUser","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"VideogameConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Videogame","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Mutation","description":null,"fields":[{"name":"deletePhase","description":"Delete a phase by id","args":[{"name":"phaseId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"deleteStation","description":"Delete a station by id","args":[{"name":"stationId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"deleteWave","description":"Delete a wave by id","args":[{"name":"waveId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"resolveScheduleConflicts","description":"Automatically attempt to resolve all schedule conflicts. Returns a list of changed seeds","args":[{"name":"tournamentId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"options","description":null,"type":{"kind":"INPUT_OBJECT","name":"ResolveConflictsOptions","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Seed","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"swapSeeds","description":"Swap two seed ids in a phase","args":[{"name":"phaseId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"seed1Id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"seed2Id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Seed","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"updatePhaseGroups","description":"Update set of phase groups in a phase","args":[{"name":"groupConfigs","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"PhaseGroupUpdateInput","ofType":null}}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"PhaseGroup","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"updatePhaseSeeding","description":"Update the seeding for a phase","args":[{"name":"phaseId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"seedMapping","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"UpdatePhaseSeedInfo","ofType":null}}},"defaultValue":null},{"name":"options","description":null,"type":{"kind":"INPUT_OBJECT","name":"UpdatePhaseSeedingOptions","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"upsertPhase","description":"Create or update a Phase","args":[{"name":"phaseId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"payload","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"PhaseUpsertInput","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"upsertStation","description":"Add or update a station by id","args":[{"name":"stationId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"tournamentId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"fields","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"StationUpsertInput","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Stations","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"upsertWave","description":"Add or update a wave by id","args":[{"name":"waveId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"tournamentId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"fields","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"WaveUpsertInput","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Wave","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ResolveConflictsOptions","description":null,"fields":null,"inputFields":[{"name":"lockedSeeds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"ResolveConflictsLockedSeedConfig","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ResolveConflictsLockedSeedConfig","description":null,"fields":null,"inputFields":[{"name":"eventId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"numSeeds","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PhaseGroupUpdateInput","description":null,"fields":null,"inputFields":[{"name":"phaseGroupId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"stationId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"waveId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UpdatePhaseSeedInfo","description":null,"fields":null,"inputFields":[{"name":"seedId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"seedNum","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"phaseGroupId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UpdatePhaseSeedingOptions","description":null,"fields":null,"inputFields":[{"name":"strictMode","description":"Validate that seedMapping exactly accounts for all entrants in the phase","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PhaseUpsertInput","description":null,"fields":null,"inputFields":[{"name":"name","description":"The name of the Phase. For example, \"Top 8\" or \"Pools\"","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"groupCount","description":"The number of pools to configure for the Phase. Only applies to brackets that support pools","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"bracketType","description":null,"type":{"kind":"ENUM","name":"BracketType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StationUpsertInput","description":null,"fields":null,"inputFields":[{"name":"number","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"clusterId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"WaveUpsertInput","description":null,"fields":null,"inputFields":[{"name":"identifier","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"defaultValue":null},{"name":"startAt","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Timestamp","ofType":null}},"defaultValue":null},{"name":"endAt","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Timestamp","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__Schema","description":"A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.","fields":[{"name":"types","description":"A list of all types supported by this server.","args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"queryType","description":"The type that query operations will be rooted at.","args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"mutationType","description":"If this server supports mutation, the type that mutation operations will be rooted at.","args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"subscriptionType","description":"If this server support subscription, the type that subscription operations will be rooted at.","args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"directives","description":"A list of all directives supported by this server.","args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Directive","ofType":null}}}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__Type","description":"The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.","fields":[{"name":"kind","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"ENUM","name":"__TypeKind","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"fields","description":null,"args":[{"name":"includeDeprecated","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"false"}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Field","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"interfaces","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"possibleTypes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"enumValues","description":null,"args":[{"name":"includeDeprecated","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"false"}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__EnumValue","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"inputFields","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__InputValue","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"ofType","description":null,"args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"__TypeKind","description":"An enum describing what kind of type a given `__Type` is.","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"SCALAR","description":"Indicates this type is a scalar.","isDeprecated":false,"deprecationReason":null},{"name":"OBJECT","description":"Indicates this type is an object. `fields` and `interfaces` are valid fields.","isDeprecated":false,"deprecationReason":null},{"name":"INTERFACE","description":"Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.","isDeprecated":false,"deprecationReason":null},{"name":"UNION","description":"Indicates this type is a union. `possibleTypes` is a valid field.","isDeprecated":false,"deprecationReason":null},{"name":"ENUM","description":"Indicates this type is an enum. `enumValues` is a valid field.","isDeprecated":false,"deprecationReason":null},{"name":"INPUT_OBJECT","description":"Indicates this type is an input object. `inputFields` is a valid field.","isDeprecated":false,"deprecationReason":null},{"name":"LIST","description":"Indicates this type is a list. `ofType` is a valid field.","isDeprecated":false,"deprecationReason":null},{"name":"NON_NULL","description":"Indicates this type is a non-null. `ofType` is a valid field.","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"__Field","description":"Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"args","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__InputValue","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"isDeprecated","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"deprecationReason","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__InputValue","description":"Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"defaultValue","description":"A GraphQL-formatted string representing the default value for this input value.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__EnumValue","description":"One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isDeprecated","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"deprecationReason","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__Directive","description":"A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"locations","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"ENUM","name":"__DirectiveLocation","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"args","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__InputValue","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"onOperation","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":true,"deprecationReason":"Use `locations`."},{"name":"onFragment","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":true,"deprecationReason":"Use `locations`."},{"name":"onField","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":true,"deprecationReason":"Use `locations`."}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"__DirectiveLocation","description":"A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"QUERY","description":"Location adjacent to a query operation.","isDeprecated":false,"deprecationReason":null},{"name":"MUTATION","description":"Location adjacent to a mutation operation.","isDeprecated":false,"deprecationReason":null},{"name":"SUBSCRIPTION","description":"Location adjacent to a subscription operation.","isDeprecated":false,"deprecationReason":null},{"name":"FIELD","description":"Location adjacent to a field.","isDeprecated":false,"deprecationReason":null},{"name":"FRAGMENT_DEFINITION","description":"Location adjacent to a fragment definition.","isDeprecated":false,"deprecationReason":null},{"name":"FRAGMENT_SPREAD","description":"Location adjacent to a fragment spread.","isDeprecated":false,"deprecationReason":null},{"name":"INLINE_FRAGMENT","description":"Location adjacent to an inline fragment.","isDeprecated":false,"deprecationReason":null},{"name":"SCHEMA","description":"Location adjacent to a schema definition.","isDeprecated":false,"deprecationReason":null},{"name":"SCALAR","description":"Location adjacent to a scalar definition.","isDeprecated":false,"deprecationReason":null},{"name":"OBJECT","description":"Location adjacent to an object type definition.","isDeprecated":false,"deprecationReason":null},{"name":"FIELD_DEFINITION","description":"Location adjacent to a field definition.","isDeprecated":false,"deprecationReason":null},{"name":"ARGUMENT_DEFINITION","description":"Location adjacent to an argument definition.","isDeprecated":false,"deprecationReason":null},{"name":"INTERFACE","description":"Location adjacent to an interface definition.","isDeprecated":false,"deprecationReason":null},{"name":"UNION","description":"Location adjacent to a union definition.","isDeprecated":false,"deprecationReason":null},{"name":"ENUM","description":"Location adjacent to an enum definition.","isDeprecated":false,"deprecationReason":null},{"name":"ENUM_VALUE","description":"Location adjacent to an enum value definition.","isDeprecated":false,"deprecationReason":null},{"name":"INPUT_OBJECT","description":"Location adjacent to an input object type definition.","isDeprecated":false,"deprecationReason":null},{"name":"INPUT_FIELD_DEFINITION","description":"Location adjacent to an input object field definition.","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INTERFACE","name":"ActionSet","description":"A set of actions available for an entity to take","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"TeamActionSet","ofType":null}]},{"kind":"INTERFACE","name":"BracketConfig","description":"Bracket-specific configuration","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":null,"args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"RaceBracketConfig","ofType":null}]},{"kind":"ENUM","name":"Comparator","description":"Comparison operator","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"GREATER_THAN","description":"","isDeprecated":false,"deprecationReason":null},{"name":"GREATER_THAN_OR_EQUAL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"EQUAL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"LESS_THAN_OR_EQUAL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"LESS_THAN","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"EventTeam","description":"An event-level Team, in the context of some competition","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discriminator","description":"Uniquely identifying token for team. Same as the hashed part of the slug","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":true,"deprecationReason":"Use the entrant field off the EventTeam type"},{"name":"event","description":null,"args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":true,"deprecationReason":"Use the event field off the EventTeam type"},{"name":"globalTeam","description":null,"args":[],"type":{"kind":"OBJECT","name":"GlobalTeam","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"members","description":null,"args":[{"name":"status","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"TeamMember","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"Team","ofType":null}],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"GlobalTeam","description":"Global Team","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discriminator","description":"Uniquely identifying token for team. Same as the hashed part of the slug","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":true,"deprecationReason":"Use the entrant field off the EventTeam type"},{"name":"event","description":null,"args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":true,"deprecationReason":"Use the event field off the EventTeam type"},{"name":"eventTeams","description":null,"args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"TeamPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventTeamConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"leagueTeams","description":"Leagues-level teams for leagues this team is competing in","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"TeamPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventTeamConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"members","description":null,"args":[{"name":"status","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"TeamMember","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"Team","ofType":null}],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventTeamConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"EventTeam","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INTERFACE","name":"MatchConfig","description":"Match-level configuration","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":null,"args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"RaceMatchConfig","ofType":null}]},{"kind":"ENUM","name":"MatchConfigVerificationMethod","description":"Different options available for verifying player-reported match results","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITCH","description":"","isDeprecated":false,"deprecationReason":null},{"name":"STREAM_ME","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ANY","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"YOUTUBE","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"RaceBracketConfig","description":"Race specific bracket configuration","fields":[{"name":"automaticEndTime","description":null,"args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"automaticStartTime","description":null,"args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":null,"args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"goalTargetComparator","description":null,"args":[],"type":{"kind":"ENUM","name":"Comparator","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"goalTargetValue","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"limitMode","description":null,"args":[],"type":{"kind":"ENUM","name":"RaceLimitMode","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"limitValue","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"raceType","description":null,"args":[],"type":{"kind":"ENUM","name":"RaceType","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"BracketConfig","ofType":null}],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"RaceLimitMode","description":"Enforces limits on the amount of allowable Race submissions","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"BEST_ALL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"FIRST_ALL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"PLAYTIME","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"ENUM","name":"RaceType","description":"Race type","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"GOALS","description":"","isDeprecated":false,"deprecationReason":null},{"name":"TIMED","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"RaceMatchConfig","description":"Race specific match configuration","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":null,"args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"playerReportingEnabled","description":"Can players report results?","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"verificationMethods","description":"Accepted methods of verification that players can use","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"MatchConfigVerificationMethod","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"verificationRequired","description":"Are players required to submit verification of their reported results?","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"MatchConfig","ofType":null}],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"TeamActionSet","description":"A set of actions available for a team to take","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"ActionSet","ofType":null}],"enumValues":null,"possibleTypes":null}],"directives":[{"name":"publicCache","description":"Specify a query to be read from gql-public. Will use the configured cacheAge on\nthe query resolve configuration, or the override value passed through the\ndirective as publicCache(cacheAge: INT) argument.","locations":["FIELD"],"args":[{"name":"cacheAge","description":"Optional override for the query-level cacheAge value.","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null}]},{"name":"userData","description":"Specify a field to only be included in the response if the user is logged in.","locations":["FIELD"],"args":[]},{"name":"skip","description":"Directs the executor to skip this field or fragment when the `if` argument is true.","locations":["FIELD","FRAGMENT_SPREAD","INLINE_FRAGMENT"],"args":[{"name":"if","description":"Skipped when true.","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"defaultValue":null}]},{"name":"include","description":"Directs the executor to include this field or fragment only when the `if` argument is true.","locations":["FIELD","FRAGMENT_SPREAD","INLINE_FRAGMENT"],"args":[{"name":"if","description":"Included when true.","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"defaultValue":null}]},{"name":"deprecated","description":"Marks an element of a GraphQL schema as no longer supported.","locations":["FIELD_DEFINITION","ENUM_VALUE"],"args":[{"name":"reason","description":"Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted in [Markdown](https:\/\/daringfireball.net\/projects\/markdown\/).","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":"\"No longer supported\""}]}]}},"extensions":{"cacheControl":{"version":1,"hints":null},"queryComplexity":0},"actionRecords":[]} \ No newline at end of file diff --git a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/octanegg/OctaneGGEventService.kt b/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/octanegg/OctaneGGEventService.kt deleted file mode 100644 index 918187c27..000000000 --- a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/octanegg/OctaneGGEventService.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.adammcneilly.pocketleague.event.implementation.octanegg - -import com.adammcneilly.pocketleague.core.data.DataResult -import com.adammcneilly.pocketleague.core.models.EventOverview -import com.adammcneilly.pocketleague.core.models.EventSummary -import com.adammcneilly.pocketleague.data.remote.octanegg.OctaneGGAPIClient -import com.adammcneilly.pocketleague.data.remote.octanegg.dtos.EventDTO -import com.adammcneilly.pocketleague.data.remote.octanegg.dtos.EventListResponseDTO -import com.adammcneilly.pocketleague.data.remote.octanegg.mappers.toEventSummary -import com.adammcneilly.pocketleague.event.api.EventRepository -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow - -/** - * A concrete implementation of an [EventRepository] that requests data from the - * Octane.gg API. - */ -class OctaneGGEventService : EventRepository { - - private val apiClient = OctaneGGAPIClient() - - override fun fetchEventOverview(eventId: String): Flow> { - TODO("Not yet implemented") - } - - override fun fetchEventSummaries(): Flow>> { - return flow { - val apiResult = apiClient.getResponse("events") - - val mappedResult: DataResult> = when (apiResult) { - is DataResult.Success -> { - val mappedEvents = apiResult.data.events.map(EventDTO::toEventSummary) - - val sortedEvents = mappedEvents.sortedBy(EventSummary::startDate) - - DataResult.Success(sortedEvents) - } - is DataResult.Error -> { - DataResult.Error(apiResult.error) - } - } - - emit(mappedResult) - } - } -} diff --git a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/SmashGGApolloClient.kt b/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/SmashGGApolloClient.kt deleted file mode 100644 index e5fabc616..000000000 --- a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/SmashGGApolloClient.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.adammcneilly.pocketleague.event.implementation.smashgg - -import com.apollographql.apollo3.ApolloClient - -/** - * A shared instance of an [ApolloClient] to be used for smash.gg API requests. - */ -val smashGGApolloClient = ApolloClient.Builder() - .serverUrl("https://api.smash.gg/gql/alpha") - .addHttpInterceptor(SmashGGAuthorizationInterceptor()) - .build() diff --git a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/SmashGGAuthorizationInterceptor.kt b/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/SmashGGAuthorizationInterceptor.kt deleted file mode 100644 index 8a9718e7a..000000000 --- a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/SmashGGAuthorizationInterceptor.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.adammcneilly.pocketleague.event.implementation.smashgg - -import com.adammcneilly.pocketleague.event.implementation.BuildKonfig -import com.apollographql.apollo3.api.http.HttpRequest -import com.apollographql.apollo3.api.http.HttpResponse -import com.apollographql.apollo3.network.http.HttpInterceptor -import com.apollographql.apollo3.network.http.HttpInterceptorChain - -/** - * An [HttpInterceptor] that applies our smash.gg authorization token to the header of each request. - */ -internal class SmashGGAuthorizationInterceptor : HttpInterceptor { - - override suspend fun intercept( - request: HttpRequest, - chain: HttpInterceptorChain - ): HttpResponse { - val authToken = BuildKonfig.SMASH_GG_API_KEY - - val newRequest = request - .newBuilder() - .addHeader("Authorization", "Bearer $authToken") - .build() - - return chain.proceed(newRequest) - } -} diff --git a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/SmashGGEventService.kt b/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/SmashGGEventService.kt deleted file mode 100644 index f63e28c66..000000000 --- a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/SmashGGEventService.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.adammcneilly.pocketleague.event.implementation.smashgg - -import com.adammcneilly.pocketleague.core.data.DataResult -import com.adammcneilly.pocketleague.core.models.EventOverview -import com.adammcneilly.pocketleague.core.models.EventSummary -import com.adammcneilly.pocketleague.event.api.EventRepository -import com.adammcneilly.pocketleague.event.implementation.graphql.EventOverviewQuery -import com.adammcneilly.pocketleague.event.implementation.graphql.EventSummaryListQuery -import com.adammcneilly.pocketleague.event.implementation.graphql.type.StandingPaginationQuery -import com.adammcneilly.pocketleague.event.implementation.smashgg.mappers.toEventOverview -import com.adammcneilly.pocketleague.event.implementation.smashgg.mappers.toEventSummary -import com.apollographql.apollo3.api.Optional -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.mapNotNull - -/** - * A concrete implementation of [EventRepository] that will request information - * from the smash.gg API. - */ -class SmashGGEventService : EventRepository { - - override fun fetchEventSummaries(): Flow>> { - val query = EventSummaryListQuery( - leagueSlug = Optional.Present("rlcs-2021-22-1"), - ) - - val response = smashGGApolloClient.query(query).toFlow() - - return response.map { dataResponse -> - val events = dataResponse - .data - ?.league - ?.events - ?.nodes - ?.mapNotNull { - it?.eventSummaryFragment?.toEventSummary() - } - .orEmpty() - - DataResult.Success(events) - } - } - - override fun fetchEventOverview(eventId: String): Flow> { - val query = EventOverviewQuery( - eventId = Optional.Present(eventId), - standingsQuery = StandingPaginationQuery(), - ) - - val response = smashGGApolloClient.query(query).toFlow() - - return response.mapNotNull { dataResponse -> - val overview = dataResponse - .data - ?.event - ?.eventOverviewFragment - ?.toEventOverview() - - if (overview != null) { - DataResult.Success(overview) - } else { - DataResult.Error(Throwable("Unable to request EventOverview for id: $eventId")) - } - } - } -} diff --git a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/BracketTypeMapper.kt b/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/BracketTypeMapper.kt deleted file mode 100644 index c4fa7d1e9..000000000 --- a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/BracketTypeMapper.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.adammcneilly.pocketleague.event.implementation.smashgg.mappers - -import com.adammcneilly.pocketleague.core.models.BracketType - -typealias ApolloBracketType = com.adammcneilly.pocketleague.event.implementation.graphql.type.BracketType - -/** - * Converts an [ApolloBracketType] from the smash.gg API to the [BracketType] within our domain. - */ -fun ApolloBracketType.toBracketType(): BracketType { - return when (this) { - ApolloBracketType.CUSTOM_SCHEDULE -> BracketType.CUSTOM - ApolloBracketType.SINGLE_ELIMINATION -> BracketType.SINGLE_ELIMINATION - ApolloBracketType.DOUBLE_ELIMINATION -> BracketType.DOUBLE_ELIMINATION - else -> BracketType.UNKNOWN - } -} diff --git a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventEntrantMapper.kt b/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventEntrantMapper.kt deleted file mode 100644 index 0a660a39b..000000000 --- a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventEntrantMapper.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.adammcneilly.pocketleague.event.implementation.smashgg.mappers - -import com.adammcneilly.pocketleague.core.models.Team -import com.adammcneilly.pocketleague.event.implementation.graphql.fragment.EventEntrantFragment -import com.adammcneilly.pocketleague.event.implementation.graphql.fragment.EventPlayerFragment - -/** - * Converting an [EventEntrantFragment] from the smash.gg API into a [Team] from our domain. - */ -fun EventEntrantFragment?.toTeam(): Team { - return Team( - name = this?.name.orEmpty(), - lightThemeLogoImageUrl = this?.team?.images?.firstOrNull()?.url, - darkThemeLogoImageUrl = this?.team?.images?.firstOrNull()?.url, - roster = this?.team?.members?.mapNotNull { member -> - member?.player?.eventPlayerFragment.let(EventPlayerFragment?::toPlayer) - }.orEmpty(), - ) -} diff --git a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventOverviewMapper.kt b/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventOverviewMapper.kt deleted file mode 100644 index 2710b479c..000000000 --- a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventOverviewMapper.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.adammcneilly.pocketleague.event.implementation.smashgg.mappers - -import com.adammcneilly.pocketleague.core.models.EventOverview -import com.adammcneilly.pocketleague.core.models.Standings -import com.adammcneilly.pocketleague.event.implementation.graphql.fragment.EventOverviewFragment -import com.adammcneilly.pocketleague.event.implementation.graphql.fragment.StandingsPlacementFragment -import kotlinx.datetime.Clock -import kotlinx.datetime.TimeZone -import kotlinx.datetime.toLocalDateTime - -/** - * Converts an [EventOverviewFragment] from the Apollo domain into an [EventOverview] in ours. - */ -fun EventOverviewFragment.toEventOverview(): EventOverview { - val summaryFragment = this.eventSummaryFragment - - return EventOverview( - name = summaryFragment.name.orEmpty(), - startDate = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()), - phases = this.phaseGroups - ?.mapNotNull { phaseGroup -> - phaseGroup?.phaseGroupFragment?.toPhaseOverview() - } - .orEmpty(), - standings = Standings( - placements = this.standings - ?.nodes - ?.mapNotNull { node -> - node - ?.standingsPlacementFragment - .let(StandingsPlacementFragment?::toStandingsPlacement) - } - .orEmpty() - ), - timeZone = TimeZone.UTC, - ) -} diff --git a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventPlayerMapper.kt b/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventPlayerMapper.kt deleted file mode 100644 index a88abfd02..000000000 --- a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventPlayerMapper.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.adammcneilly.pocketleague.event.implementation.smashgg.mappers - -import com.adammcneilly.pocketleague.core.models.Player -import com.adammcneilly.pocketleague.event.implementation.graphql.fragment.EventPlayerFragment - -/** - * Converting an [EventPlayerFragment] from the smash.gg API into a [Player] from our domain. - */ -fun EventPlayerFragment?.toPlayer(): Player { - return Player( - countryCode = "", - gamerTag = this?.gamerTag.orEmpty(), - realName = "", - ) -} diff --git a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventSummaryMapper.kt b/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventSummaryMapper.kt deleted file mode 100644 index 5bc6b7ec8..000000000 --- a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/EventSummaryMapper.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.adammcneilly.pocketleague.event.implementation.smashgg.mappers - -import com.adammcneilly.pocketleague.core.models.EventSummary -import com.adammcneilly.pocketleague.event.implementation.graphql.fragment.EventSummaryFragment -import kotlinx.datetime.Instant -import kotlinx.datetime.TimeZone -import kotlinx.datetime.toLocalDateTime - -/** - * Converts an [EventSummaryFragment] generated class from Apollo to an [EventSummary] from our - * domain. - */ -fun EventSummaryFragment.toEventSummary(): EventSummary { - val startSeconds = (this.startAt as Int).toLong() - val eventTimeZone = TimeZone.UTC - val startDate = Instant.fromEpochSeconds(startSeconds).toLocalDateTime(eventTimeZone) - - return EventSummary( - id = this.id.orEmpty(), - eventName = this.name.orEmpty(), - tournamentName = this.tournament?.name.orEmpty(), - startDate = startDate, - timeZone = eventTimeZone, - numEntrants = this.numEntrants, - isOnline = this.isOnline == true, - tournamentImageUrl = this.tournament?.images?.firstOrNull()?.url.orEmpty(), - ) -} diff --git a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/PhaseGroupMapper.kt b/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/PhaseGroupMapper.kt deleted file mode 100644 index 085871233..000000000 --- a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/PhaseGroupMapper.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.adammcneilly.pocketleague.event.implementation.smashgg.mappers - -import com.adammcneilly.pocketleague.core.models.BracketType -import com.adammcneilly.pocketleague.core.models.PhaseOverview -import com.adammcneilly.pocketleague.event.implementation.graphql.fragment.PhaseGroupFragment - -/** - * Converts the Apollo generated [PhaseGroupFragment] into a [PhaseOverview]. - */ -fun PhaseGroupFragment?.toPhaseOverview(): PhaseOverview { - val overview = this?.phase?.phaseOverviewFragment - - return PhaseOverview( - id = overview?.id.orEmpty(), - groupId = this?.id.orEmpty(), - numPools = overview?.groupCount ?: 0, - numEntrants = overview?.numSeeds ?: 0, - name = overview?.name.orEmpty(), - bracketType = this?.bracketType?.toBracketType() - ?: BracketType.UNKNOWN, - phaseOrder = overview?.phaseOrder ?: 0, - ) -} diff --git a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/StandingsPlacementMapper.kt b/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/StandingsPlacementMapper.kt deleted file mode 100644 index d49b467a3..000000000 --- a/event-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/event/implementation/smashgg/mappers/StandingsPlacementMapper.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.adammcneilly.pocketleague.event.implementation.smashgg.mappers - -import com.adammcneilly.pocketleague.core.models.StandingsPlacement -import com.adammcneilly.pocketleague.event.implementation.graphql.fragment.EventEntrantFragment -import com.adammcneilly.pocketleague.event.implementation.graphql.fragment.StandingsPlacementFragment - -/** - * Converts a [StandingsPlacementFragment] Apollo generated object to a [StandingsPlacement] from - * our domain. - */ -fun StandingsPlacementFragment?.toStandingsPlacement(): StandingsPlacement { - return StandingsPlacement( - placement = this?.placement ?: 0, - team = this?.entrant?.eventEntrantFragment.let(EventEntrantFragment?::toTeam), - ) -} diff --git a/feature-eventsummarylist/build.gradle.kts b/feature-eventsummarylist/build.gradle.kts deleted file mode 100644 index 06cdccf88..000000000 --- a/feature-eventsummarylist/build.gradle.kts +++ /dev/null @@ -1,64 +0,0 @@ -plugins { - kotlin("multiplatform") - id("com.android.library") -} - -kotlin { - android() - - listOf( - iosX64(), - iosArm64(), - iosSimulatorArm64() - ).forEach { - it.binaries.framework { - baseName = "feature-eventsummarylist" - } - } - - sourceSets { - val commonMain by getting { - dependencies { - implementation(project(":event-api")) - implementation(project(":event-implementation")) - implementation(project(":core-datetime")) - implementation("com.tunjid.mutator:core:${Versions.mutator}") - implementation("com.tunjid.mutator:coroutines:${Versions.mutator}") - } - } - val commonTest by getting { - dependencies { - implementation(kotlin("test")) - } - } - val androidMain by getting - val androidTest by getting - val iosX64Main by getting - val iosArm64Main by getting - val iosSimulatorArm64Main by getting - val iosMain by creating { - dependsOn(commonMain) - iosX64Main.dependsOn(this) - iosArm64Main.dependsOn(this) - iosSimulatorArm64Main.dependsOn(this) - } - val iosX64Test by getting - val iosArm64Test by getting - val iosSimulatorArm64Test by getting - val iosTest by creating { - dependsOn(commonTest) - iosX64Test.dependsOn(this) - iosArm64Test.dependsOn(this) - iosSimulatorArm64Test.dependsOn(this) - } - } -} - -android { - compileSdk = AndroidConfig.compileSDK - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") - defaultConfig { - minSdk = AndroidConfig.minSDK - targetSdk = AndroidConfig.targetSDK - } -} diff --git a/feature-eventsummarylist/src/androidMain/AndroidManifest.xml b/feature-eventsummarylist/src/androidMain/AndroidManifest.xml deleted file mode 100644 index 43e5b42f8..000000000 --- a/feature-eventsummarylist/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/EventSummaryListSort.kt b/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/EventSummaryListSort.kt deleted file mode 100644 index b29c1e9cd..000000000 --- a/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/EventSummaryListSort.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.adammcneilly.pocketleague.feature.eventsummarylist - -/** - * Possible sort variations for a list of event summaries. - * - * @property[displayText] The user friendly explanation of this text to show to the user. - */ -enum class EventSummaryListSort( - val displayText: String, -) { - UPCOMING( - displayText = "Upcoming", - ), - PAST( - displayText = "Past", - ), -} diff --git a/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/domain/GetEventSummariesUseCase.kt b/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/domain/GetEventSummariesUseCase.kt deleted file mode 100644 index e5128953f..000000000 --- a/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/domain/GetEventSummariesUseCase.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.adammcneilly.pocketleague.feature.eventsummarylist.domain - -import com.adammcneilly.pocketleague.core.models.EventSummary -import kotlinx.coroutines.flow.Flow - -/** - * Use case to request a list of event summaries. - */ -interface GetEventSummariesUseCase { - - /** - * @see [GetEventSummariesUseCase] - */ - fun invoke( - request: Request, - ): Flow - - /** - * Data class to define all of the request parameters for fetching a list of event summaries. - * - * @property[upcoming] True if we want to request the upcoming events, false otherwise. - */ - data class Request( - val upcoming: Boolean = true, - ) - - /** - * All possible response variations for the [GetEventSummariesUseCase]. - */ - sealed class Result { - /** - * This is returned when our use case is successful and we have a list of [events] to - * provide. - */ - data class Success(val events: List) : Result() - - /** - * This is returned when our use case is unsuccessful and some [errorMessage] occurred. - */ - data class Error(val errorMessage: String?) : Result() - } -} diff --git a/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/domain/GetEventSummariesUseCaseImpl.kt b/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/domain/GetEventSummariesUseCaseImpl.kt deleted file mode 100644 index d97a5e9f6..000000000 --- a/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/domain/GetEventSummariesUseCaseImpl.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.adammcneilly.pocketleague.feature.eventsummarylist.domain - -import com.adammcneilly.pocketleague.core.data.DataResult -import com.adammcneilly.pocketleague.event.api.EventRepository -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map - -/** - * Concrete implementation of [GetEventSummariesUseCase] that will fetch - * events from the supplied [repository]. - */ -class GetEventSummariesUseCaseImpl( - private val repository: EventRepository, -) : GetEventSummariesUseCase { - - override fun invoke( - request: GetEventSummariesUseCase.Request, - ): Flow { - - return repository.fetchEventSummaries().map { repositoryResult -> - when (repositoryResult) { - is DataResult.Success -> { - GetEventSummariesUseCase.Result.Success(repositoryResult.data) - } - is DataResult.Error -> { - GetEventSummariesUseCase.Result.Error(repositoryResult.error.message) - } - } - } - } -} diff --git a/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/state/EventSummaryListAction.kt b/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/state/EventSummaryListAction.kt deleted file mode 100644 index 0e2efb770..000000000 --- a/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/state/EventSummaryListAction.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.adammcneilly.pocketleague.feature.eventsummarylist.state - -import com.adammcneilly.pocketleague.feature.eventsummarylist.EventSummaryListSort -import com.adammcneilly.pocketleague.feature.eventsummarylist.domain.GetEventSummariesUseCase - -/** - * A collection of possible domain actions that can occur within the event summary list feature. - */ -sealed class EventSummaryListAction { - /** - * This action will trigger the loading of event summaries. - */ - data class FetchEventSummaries( - val request: GetEventSummariesUseCase.Request, - ) : EventSummaryListAction() - - /** - * Action fired when the user clicks on a specific [eventId]. - */ - data class SelectedEvent( - val eventId: String, - ) : EventSummaryListAction() - - /** - * Action fired when the user changes their sort selection for an event summary list. - */ - data class SelectedSort( - val sort: EventSummaryListSort, - ) : EventSummaryListAction() - - /** - * Once we know the user has navigated to an event overview, we can clear the selected event - * to avoid navigating again. - */ - object NavigatedToEventOverview : EventSummaryListAction() -} diff --git a/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/state/EventSummaryListStateMutator.kt b/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/state/EventSummaryListStateMutator.kt deleted file mode 100644 index d6cd0cb0c..000000000 --- a/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/state/EventSummaryListStateMutator.kt +++ /dev/null @@ -1,148 +0,0 @@ -@file:Suppress("TooManyFunctions") - -package com.adammcneilly.pocketleague.feature.eventsummarylist.state - -import com.adammcneilly.pocketleague.core.datetime.DateTimeFormatter -import com.adammcneilly.pocketleague.core.models.EventSummary -import com.adammcneilly.pocketleague.feature.eventsummarylist.domain.GetEventSummariesUseCase -import com.adammcneilly.pocketleague.feature.eventsummarylist.ui.EventSummaryListItemDisplayModel -import com.tunjid.mutator.Mutation -import com.tunjid.mutator.coroutines.stateFlowMutator -import com.tunjid.mutator.coroutines.toMutationStream -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.onStart - -/** - * Creates a [stateFlowMutator] which will consume [EventSummaryListAction] entities and map them - * to the correct [EventSummaryListViewState]. - */ -fun eventSummaryListStateMutator( - getEventsUseCase: GetEventSummariesUseCase, - scope: CoroutineScope, -) = stateFlowMutator( - scope = scope, - initialState = EventSummaryListViewState(), - actionTransform = { actions -> - actions.toMutationStream { - when (val action = type()) { - is EventSummaryListAction.FetchEventSummaries -> action.flow.fetchEventMutations( - getEventsUseCase = getEventsUseCase, - ) - is EventSummaryListAction.NavigatedToEventOverview -> action.flow.clearEventMutations() - is EventSummaryListAction.SelectedEvent -> action.flow.selectEventMutations() - is EventSummaryListAction.SelectedSort -> action.flow.selectSortMutations() - } - } - } -) - -private fun Flow.selectSortMutations() = this.map { action -> - Mutation { - copy( - currentSort = action.sort, - ) - } -} - -private fun Flow.fetchEventMutations( - getEventsUseCase: GetEventSummariesUseCase, -): Flow> { - return this.flatMapLatest { action -> - getEventsUseCase - .invoke( - action.request, - ) - .map { result -> - when (result) { - is GetEventSummariesUseCase.Result.Success -> { - successMutation( - events = result.events, - ) - } - is GetEventSummariesUseCase.Result.Error -> { - errorMutation() - } - } - } - .onStart { - emit(loadingMutation()) - } - } -} - -private fun errorMutation() = Mutation { - copy( - showLoading = false, - errorMessage = "Fetching upcoming events failed.", - ) -} - -private fun successMutation( - events: List, -) = Mutation { - copy( - showLoading = false, - events = events.map { event -> - event.toSummaryDisplayModel() - } - ) -} - -private fun loadingMutation() = Mutation { - copy( - showLoading = true, - ) -} - -private fun Flow.clearEventMutations(): - Flow> { - - return this.map { - Mutation { - copy( - selectedEventId = null, - ) - } - } -} - -private fun Flow.selectEventMutations(): - Flow> { - - return this.map { action -> - Mutation { - copy( - selectedEventId = action.eventId, - ) - } - } -} - -/** - * Converts an [EventSummary] domain object to a user friendly [EventSummaryListItemDisplayModel]. - */ -private fun EventSummary.toSummaryDisplayModel(): EventSummaryListItemDisplayModel { - return EventSummaryListItemDisplayModel( - eventId = this.id, - startDate = DateTimeFormatter().formatLocalDateTime( - this.startDate, - EventSummaryListItemDisplayModel.START_DATE_FORMAT, - ).orEmpty(), - tournamentName = this.tournamentName, - eventName = this.eventName, - subtitle = this.buildSubtitle(), - imageUrl = this.tournamentImageUrl, - ) -} - -/** - * Generates a user friendly subtitle for an [EventSummary] intended to be passed to an [EventSummaryListItemDisplayModel]. - */ -private fun EventSummary.buildSubtitle(): String? { - return this.numEntrants?.let { numEntrants -> - "$numEntrants Teams" - } -} diff --git a/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/state/EventSummaryListViewState.kt b/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/state/EventSummaryListViewState.kt deleted file mode 100644 index fa5866b5f..000000000 --- a/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/state/EventSummaryListViewState.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.adammcneilly.pocketleague.feature.eventsummarylist.state - -import com.adammcneilly.pocketleague.feature.eventsummarylist.EventSummaryListSort -import com.adammcneilly.pocketleague.feature.eventsummarylist.ui.EventSummaryListItemDisplayModel - -/** - * A collection of possible view states for [EventSummaryListScreen]. - */ -data class EventSummaryListViewState( - val showLoading: Boolean = true, - val events: List = emptyList(), - val selectedEventId: String? = null, - val errorMessage: String? = null, - val currentSort: EventSummaryListSort = EventSummaryListSort.UPCOMING, -) diff --git a/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/ui/EventSummaryListItemDisplayModel.kt b/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/ui/EventSummaryListItemDisplayModel.kt deleted file mode 100644 index 084573cc1..000000000 --- a/feature-eventsummarylist/src/commonMain/kotlin/com/adammcneilly/pocketleague/feature/eventsummarylist/ui/EventSummaryListItemDisplayModel.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.adammcneilly.pocketleague.feature.eventsummarylist.ui - -/** - * A user friendly summary of an [EventSummary] to be displayed on the UI. - */ -data class EventSummaryListItemDisplayModel( - val eventId: String, - val startDate: String, - val tournamentName: String, - val eventName: String, - val subtitle: String?, - val imageUrl: String?, -) { - - companion object { - const val START_DATE_FORMAT = "MMM dd, yyyy" - } -} diff --git a/settings.gradle b/settings.gradle index 071ec9649..8e0c7ed01 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,13 +1,4 @@ rootProject.name = "PocketLeague" + include ':app' include ':android-design-system' -include ':shared' -include ':core-models' -include ':core-data' -include ':event-api' -include ':event-implementation' -include ':feature-eventsummarylist' -include ':core-datetime' -include ':team-api' -include ':team-implementation' -include ':octanegg' diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts deleted file mode 100644 index 2472cd19f..000000000 --- a/shared/build.gradle.kts +++ /dev/null @@ -1,93 +0,0 @@ -import java.io.FileInputStream -import java.util.Properties - -plugins { - kotlin("multiplatform") - id("com.android.library") - id("com.apollographql.apollo3").version(Versions.apollo) - id("com.codingfeline.buildkonfig").version(Versions.buildKonfig) -} - -kotlin { - android() - - listOf( - iosX64(), - iosArm64(), - iosSimulatorArm64() - ).forEach { - it.binaries.framework { - baseName = "shared" - } - } - - sourceSets { - val commonMain by getting { - dependencies { - implementation(project(":core-models")) - api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.coroutines}") - implementation(project(":core-datetime")) - implementation("com.apollographql.apollo3:apollo-runtime:${Versions.apollo}") - implementation("com.tunjid.mutator:core:${Versions.mutator}") - implementation("com.tunjid.mutator:coroutines:${Versions.mutator}") - } - } - val commonTest by getting { - dependencies { - implementation(kotlin("test")) - } - } - val androidMain by getting - val androidTest by getting - val iosX64Main by getting - val iosArm64Main by getting - val iosSimulatorArm64Main by getting - val iosMain by creating { - dependsOn(commonMain) - iosX64Main.dependsOn(this) - iosArm64Main.dependsOn(this) - iosSimulatorArm64Main.dependsOn(this) - } - val iosX64Test by getting - val iosArm64Test by getting - val iosSimulatorArm64Test by getting - val iosTest by creating { - dependsOn(commonTest) - iosX64Test.dependsOn(this) - iosArm64Test.dependsOn(this) - iosSimulatorArm64Test.dependsOn(this) - } - } -} - -android { - compileSdk = AndroidConfig.compileSDK - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") - defaultConfig { - minSdk = AndroidConfig.minSDK - targetSdk = AndroidConfig.targetSDK - } -} - -apollo { - packageName.set("com.adammcneilly.pocketleague.shared.graphql") -} - -buildkonfig { - val secretsFile = File("shared/local.properties") - val properties = Properties() - - if (secretsFile.exists()) { - properties.load(FileInputStream(secretsFile)) - } - - defaultConfigs { - packageName = "com.adammcneilly.pocketleague.shared" - - buildConfigField( - type = com.codingfeline.buildkonfig.compiler.FieldSpec.Type.STRING, - name = "SMASH_GG_API_KEY", - value = properties["SmashGGAPIKey"].toString(), - ) - } -} diff --git a/shared/src/androidMain/AndroidManifest.xml b/shared/src/androidMain/AndroidManifest.xml deleted file mode 100644 index df7238178..000000000 --- a/shared/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/shared/src/commonMain/graphql/EventOverviewQuery.graphql b/shared/src/commonMain/graphql/EventOverviewQuery.graphql deleted file mode 100644 index 1705d6270..000000000 --- a/shared/src/commonMain/graphql/EventOverviewQuery.graphql +++ /dev/null @@ -1,62 +0,0 @@ -fragment EventPlayerFragment on Player { - gamerTag -} - -fragment EventEntrantFragment on Entrant { - id - name - team { - members { - player { - ...EventPlayerFragment - } - } - images { - url - } - } -} - -fragment StandingsPlacementFragment on Standing { - entrant { - ...EventEntrantFragment - } - placement -} - -fragment PhaseOverviewFragment on Phase { - id - groupCount - numSeeds - name - phaseOrder - bracketType -} - -fragment PhaseGroupFragment on PhaseGroup { - id - bracketType - displayIdentifier - numRounds - phase { - ...PhaseOverviewFragment - } -} - -fragment EventOverviewFragment on Event { - ...EventSummaryFragment - phaseGroups { - ...PhaseGroupFragment - } - standings(query: $standingsQuery) { - nodes { - ...StandingsPlacementFragment - } - } -} - -query EventOverviewQuery($eventId: ID, $standingsQuery: StandingPaginationQuery!) { - event(id: $eventId) { - ...EventOverviewFragment - } -} \ No newline at end of file diff --git a/shared/src/commonMain/graphql/EventSummaryListQuery.graphql b/shared/src/commonMain/graphql/EventSummaryListQuery.graphql deleted file mode 100644 index aaa7b7771..000000000 --- a/shared/src/commonMain/graphql/EventSummaryListQuery.graphql +++ /dev/null @@ -1,33 +0,0 @@ -fragment PageInfoFragment on PageInfo { - total - totalPages - page -} - -fragment EventSummaryFragment on Event { - id - name - slug - tournament { - name - images { - url - } - } - startAt - numEntrants - isOnline -} - -query EventSummaryListQuery($leagueSlug: String, $eventsQuery: LeagueEventsQuery) { - league(slug: $leagueSlug) { - events(query: $eventsQuery) { - pageInfo { - ...PageInfoFragment - } - nodes { - ...EventSummaryFragment - } - } - } -} \ No newline at end of file diff --git a/shared/src/commonMain/graphql/PhaseDetailQuery.graphql b/shared/src/commonMain/graphql/PhaseDetailQuery.graphql deleted file mode 100644 index cf85c5ab5..000000000 --- a/shared/src/commonMain/graphql/PhaseDetailQuery.graphql +++ /dev/null @@ -1,45 +0,0 @@ -fragment SetSlotFragment on SetSlot { - entrant { - ...EventEntrantFragment - } - slotIndex -} - -fragment EventSetFragment on Set { - fullRoundText - displayScore - winnerId - round - slots { - ...SetSlotFragment - } - games { - id - winnerId - } -} - -fragment PhaseDetailFragment on Phase { - ...PhaseOverviewFragment - sets( - perPage: $perPage - ) { - pageInfo { - total - totalPages - page - } - nodes { - ...EventSetFragment - } - } -} - -query PhaseDetailQuery( - $id: ID, - $perPage: Int, -) { - phase(id: $id) { - ...PhaseDetailFragment - } -} \ No newline at end of file diff --git a/shared/src/commonMain/graphql/schema.json b/shared/src/commonMain/graphql/schema.json deleted file mode 100644 index eaddc378d..000000000 --- a/shared/src/commonMain/graphql/schema.json +++ /dev/null @@ -1 +0,0 @@ -{"data":{"__schema":{"queryType":{"name":"Query"},"mutationType":{"name":"Mutation"},"subscriptionType":null,"types":[{"kind":"OBJECT","name":"Query","description":null,"fields":[{"name":"currentUser","description":"Returns the authenticated user","args":[],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"event","description":"Returns an event given its id or slug","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"league","description":"Returns a league given its id or slug","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"League","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participant","description":"Returns a participant given its id","args":[{"name":"id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"isAdmin","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Participant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phase","description":"Returns a phase given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseGroup","description":"Returns a phase group given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"PhaseGroup","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":"Returns a player given an id","args":[{"name":"id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seed","description":"Returns a phase seed given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Seed","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"set","description":"Returns a set given its id","args":[{"name":"id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Set","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"shop","description":"A shop entity","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Shop","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":"Returns an stream given its id","args":[{"name":"id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Streams","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamQueue","description":"Returns all the stream queues for a given tournament","args":[{"name":"tournamentId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"includePlayerStreams","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"StreamQueue","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"team","description":"Returns a team given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"inviteCode","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"INTERFACE","name":"Team","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournament","description":"Returns a tournament given its id or slug","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Tournament","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournaments","description":"Paginated, filterable list of tournaments","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"TournamentQuery","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"TournamentConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"user","description":"Returns a user given a user slug of the form user\/abc123, or id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"slug","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"videogame","description":"Returns a videogame given its id","args":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Videogame","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"videogames","description":"Returns paginated list of videogames matching the search criteria.","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"VideogameQuery","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"VideogameConnection","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"User","description":"A user","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"authorizations","description":"Authorizations to external services (i.e. Twitch, Twitter)","args":[{"name":"types","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"SocialConnectionType","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"ProfileAuthorization","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"bio","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"birthday","description":"Public facing user birthday that respects user publishing settings","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discriminator","description":"Uniquely identifying token for user. Same as the hashed part of the slug","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"events","description":"Events this user has competed in","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserEventsPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"genderPronoun","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"leagues","description":"Leagues this user has competed in","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserLeaguesPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"LeagueConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"location","description":"Public location info for this user","args":[],"type":{"kind":"OBJECT","name":"Address","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Public facing user name that respects user publishing settings","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":"player for user","args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournaments","description":"Tournaments this user is organizing or competing in","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserTournamentsPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"TournamentConnection","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"ID","description":"The `ID` scalar type represents a unique identifier, often used to\nrefetch an object or as key for a cache. When expected as an input type, any string (such as `\"4\"`) or integer\n(such as `4`) input value will be accepted as an ID.","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"SocialConnectionType","description":"Represents the name of the third-party social service (e.g Twitter) for OAuth","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITTER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"TWITCH","description":"","isDeprecated":false,"deprecationReason":null},{"name":"DISCORD","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"XBOX","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"ProfileAuthorization","description":"An OAuth ProfileAuthorization object","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"externalId","description":"The id given by the external service","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"externalUsername","description":"The username given by the external service (including discriminator if discord)","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":null,"args":[],"type":{"kind":"OBJECT","name":"Stream","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":"The name of the external service providing this auth i.e. \"twitch\"","args":[],"type":{"kind":"ENUM","name":"AuthorizationType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"String","description":"The `String` scalar type represents textual data, represented as UTF-8\ncharacter sequences. The String type is most often used by GraphQL to\nrepresent free-form human-readable text.","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Stream","description":"A Stream object","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":"Whether the stream is currently live. May be slightly delayed.","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The name of the stream","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":"The name of the external service providing this auth i.e. \"twitch\"","args":[],"type":{"kind":"ENUM","name":"StreamType","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"Boolean","description":"The `Boolean` scalar type represents `true` or `false`.","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"StreamType","description":"Represents the type of stream service","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITCH","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"ENUM","name":"AuthorizationType","description":"Represents the name of the third-party service (e.g Twitter) for OAuth","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITTER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"TWITCH","description":"","isDeprecated":false,"deprecationReason":null},{"name":"STEAM","description":"","isDeprecated":false,"deprecationReason":null},{"name":"DISCORD","description":"","isDeprecated":false,"deprecationReason":null},{"name":"XBOX","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserEventsPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserEventsPaginationFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"Int","description":"The `Int` scalar type represents non-fractional signed whole numeric\nvalues. Int can represent values between -(2^31) and 2^31 - 1. ","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserEventsPaginationFilter","description":null,"fields":null,"inputFields":[{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventType","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"minEntrantCount","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"maxEntrantCount","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"location","description":null,"type":{"kind":"INPUT_OBJECT","name":"LocationFilterType","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"LocationFilterType","description":null,"fields":null,"inputFields":[{"name":"countryCode","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"state","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"city","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PaginationSearchType","description":null,"fields":null,"inputFields":[{"name":"fieldsToSearch","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"defaultValue":null},{"name":"searchString","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"PageInfo","description":null,"fields":[{"name":"total","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"totalPages","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"page","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"perPage","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"sortBy","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"filter","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"JSON","description":"The `JSON` scalar type represents JSON values as specified by\n\t\t[ECMA-404](http:\/\/www.ecma-international.org\/publications\/files\/ECMA-ST\/ECMA-404.pdf).","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Event","description":"An event in a tournament","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkInBuffer","description":"How long before the event start will the check-in end (in seconds)","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkInDuration","description":"How long the event check-in will last (in seconds)","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkInEnabled","description":"Whether check-in is enabled for this event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"createdAt","description":"When the event was created (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"deckSubmissionDeadline","description":"Last date attendees are able to create teams for team events","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrantSizeMax","description":"Maximum number of participants each Entrant can have","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"Migrate to teamRosterSize"},{"name":"entrantSizeMin","description":"Minimum number of participants each Entrant can have","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"Migrate to teamRosterSize"},{"name":"entrants","description":"The entrants that belong to an event, paginated by filter criteria","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"EventEntrantPageQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EntrantConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hasDecks","description":"Whether the event has decks","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hasTasks","description":"Are player tasks enabled for this event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":"Whether the event is an online event or not","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"league","description":null,"args":[],"type":{"kind":"OBJECT","name":"League","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"matchRulesMarkdown","description":"Markdown field for match rules\/instructions","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Title of event set by organizer","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numEntrants","description":"Gets the number of entrants in this event","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseGroups","description":"The phase groups that belong to an event.","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"PhaseGroup","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"phases","description":"The phases that belong to an event.","args":[{"name":"state","description":"Filter phases by state. If not specified will default to all phases","type":{"kind":"ENUM","name":"ActivityState","ofType":null},"defaultValue":null},{"name":"phaseId","description":"Optionally only return results for this phase","type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Phase","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"prizingInfo","description":"TO settings for prizing","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"publishing","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rulesMarkdown","description":"Markdown field for event rules\/instructions","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rulesetId","description":"Id of the event ruleset","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rulesetSettings","description":"Settings pulled from the event ruleset, if one exists","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":true,"deprecationReason":"Use ruleset"},{"name":"sets","description":"Paginated sets for this Event","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standings","description":"Paginated list of standings","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"StandingPaginationQuery","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StandingConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"When does this event start?","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"The state of the Event.","args":[],"type":{"kind":"ENUM","name":"ActivityState","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stations","description":"Paginated stations on this event","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"StationFilter","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StationsConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teamManagementDeadline","description":"Last date attendees are able to create teams for team events","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teamNameAllowed","description":"If this is a teams event, returns whether or not teams can set custom names","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teamRosterSize","description":"Team roster size requirements","args":[],"type":{"kind":"OBJECT","name":"TeamRosterSize","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournament","description":null,"args":[],"type":{"kind":"OBJECT","name":"Tournament","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":"The type of the event, whether an entrant will have one participant or multiple","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"updatedAt","description":"When the event was last modified (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"useEventSeeds","description":"Whether the event uses the new EventSeeds for seeding","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"videogame","description":null,"args":[],"type":{"kind":"OBJECT","name":"Videogame","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"waves","description":"The waves being used by the event","args":[{"name":"phaseId","description":"Waves filtered by phaseId, returns all if not set.","type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Wave","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"Timestamp","description":"Represents a Unix Timestamp. Supports up to 53 bit int values,\n\t\tas that is JavaScript's internal memory allocation for integer values.","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"EventEntrantPageQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"EventEntrantPageQueryFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"EventEntrantPageQueryFilter","description":null,"fields":null,"inputFields":[{"name":"name","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EntrantConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Entrant","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Entrant","description":"An entrant in an event","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"event","description":null,"args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"initialSeedNum","description":"Entrant's seed number in the first phase of the event.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isDisqualified","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The entrant name as it appears in bracket: gamerTag of the participant or team name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"paginatedSets","description":"Paginated sets for this entrant","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participants","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Participant","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"seeds","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Seed","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"skill","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standing","description":"Standing for this entrant given an event. All entrants queried must be in the same event (for now).","args":[],"type":{"kind":"OBJECT","name":"Standing","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":null,"args":[],"type":{"kind":"OBJECT","name":"Streams","ofType":null},"isDeprecated":true,"deprecationReason":"DEPRECATED. Use streams instead, which supports multiple stream types and teams."},{"name":"streams","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Streams","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"team","description":"Team linked to this entrant, if one exists","args":[],"type":{"kind":"INTERFACE","name":"Team","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"SetSortType","description":"Different sort type configurations used when displaying multiple sets","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"NONE","description":"Sets will not be sorted.","isDeprecated":false,"deprecationReason":null},{"name":"CALL_ORDER","description":"Sets are sorted in the suggested order that they be called to be played. The order of completed sets is reversed.","isDeprecated":false,"deprecationReason":null},{"name":"MAGIC","description":"Sets are sorted by relevancy dependent on the state and progress of the event.","isDeprecated":false,"deprecationReason":null},{"name":"RECENT","description":"Sets are sorted in the order that they were started.","isDeprecated":false,"deprecationReason":null},{"name":"STANDARD","description":"Deprecated. This is equivalent to CALL_ORDER","isDeprecated":false,"deprecationReason":null},{"name":"ROUND","description":"Sets sorted by round and identifier","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SetFilters","description":null,"fields":null,"inputFields":[{"name":"entrantIds","description":"Only return Sets for these Entrants","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"entrantSize","description":"Only return Sets for this Entrant size. For example, to fetch 1v1 Sets only, filter by an entrantSize of 1","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"hasVod","description":"Only return Sets that have an attached VOD","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"hideEmpty","description":"Do not return empty Sets. For example, set this to true to filter out sets that are waiting for progressions.","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"showByes","description":"Return sets that contain a bye","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"isEventOnline","description":"Only return Sets that are in an Online event. If omitted, Sets for both online and offline Events are returned","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"location","description":"Only return Sets in certain geographical areas.","type":{"kind":"INPUT_OBJECT","name":"SetFilterLocation","ofType":null},"defaultValue":null},{"name":"participantIds","description":"Only return Sets for these Participants","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"phaseGroupIds","description":"Only return Sets in these PhaseGroups","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"phaseIds","description":"Only return Sets in these Phases","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventIds","description":"Only return Sets in these Events","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"tournamentIds","description":"Only return Sets in these Tournaments","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"playerIds","description":"Only return Sets for these Players","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"roundNumber","description":"Only return Sets for these Rounds","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"state","description":"Only returns Sets that are in these states","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"stationIds","description":"Only return Sets that are assigned to these Station IDs","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"stationNumbers","description":"Only return Sets that are assigned to these Station numbers","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"updatedAfter","description":"Only return sets created or updated since this timestamp","type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SetFilterLocation","description":"Filter Sets by geographical constraints.","fields":null,"inputFields":[{"name":"state","description":"Only return Sets in this state. Only applicable to US states","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"country","description":"Only return Sets in this country. Expects a valid two-letter country code","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"distanceFrom","description":null,"type":{"kind":"INPUT_OBJECT","name":"SetFilterLocationDistanceFrom","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SetFilterLocationDistanceFrom","description":"Only return Sets that are a certain distance away from a specified point","fields":null,"inputFields":[{"name":"point","description":"Point at which to perform distance calculation","type":{"kind":"INPUT_OBJECT","name":"SetFilterLocationDistanceFromPoint","ofType":null},"defaultValue":null},{"name":"radius","description":"Distance from the point to include results in","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SetFilterLocationDistanceFromPoint","description":null,"fields":null,"inputFields":[{"name":"lat","description":null,"type":{"kind":"SCALAR","name":"Float","ofType":null},"defaultValue":null},{"name":"lon","description":null,"type":{"kind":"SCALAR","name":"Float","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"Float","description":"The `Float` scalar type represents signed double-precision fractional\nvalues as specified by\n[IEEE 754](http:\/\/en.wikipedia.org\/wiki\/IEEE_floating_point). ","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"SetConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Set","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Set","description":"A set","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"completedAt","description":"The time this set was marked as completed","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"createdAt","description":"The time this set was created","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"displayScore","description":null,"args":[{"name":"mainEntrantId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"event","description":"Event that this set belongs to.","args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"fullRoundText","description":"Full round text of this set.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"game","description":null,"args":[{"name":"orderNum","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Game","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"games","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Game","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"hasPlaceholder","description":"Whether this set contains a placeholder entrant","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"identifier","description":"The letters that describe a unique identifier within the pool. Eg. F, AT","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"lPlacement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseGroup","description":"Phase group that this Set belongs to.","args":[],"type":{"kind":"OBJECT","name":"PhaseGroup","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"round","description":"The round number of the set. Negative numbers are losers bracket","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"setGamesType","description":"Indicates whether the set is in best of or total games mode. This instructs\nwhich field is used to figure out how many games are in this set.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slots","description":"A possible spot in a set. Use this to get all entrants in a set. Use this for all bracket types (FFA, elimination, etc)","args":[{"name":"includeByes","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"false"}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"SetSlot","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"The start time of the Set. If there is no startAt time on the Set, will pull it from phaseGroup rounds configuration.","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startedAt","description":null,"args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"station","description":"Tournament event station for a set","args":[],"type":{"kind":"OBJECT","name":"Stations","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":"Tournament event stream for a set","args":[],"type":{"kind":"OBJECT","name":"Streams","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"totalGames","description":"If setGamesType is in total games mode, this defined the number of games in the set.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"vodUrl","description":"Url of a VOD for this set","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"wPlacement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"winnerId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Game","description":"A game represents a single game within a set.","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"orderNum","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"selections","description":"Selections for this game such as character, etc.","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"GameSelection","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"stage","description":"The stage that this game was played on (if applicable)","args":[],"type":{"kind":"OBJECT","name":"Stage","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"winnerId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Image","description":"An image","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"height","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"ratio","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"width","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"GameSelection","description":"A selection for this game. i.e. character\/stage selection, etc","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":"The entrant who this selection is for","args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"orderNum","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participant","description":"The participant who this selection is for. This is only populated if there are\nselections for multiple participants of a single entrant","args":[],"type":{"kind":"OBJECT","name":"Participant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"selectionType","description":null,"args":[],"type":{"kind":"ENUM","name":"GameSelectionType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"selectionValue","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Participant","description":"A participant of a tournament; either a spectator or competitor","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkedIn","description":"If this participant was checked-in by admin","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkedInAt","description":"The time this participant was checked-in by admin","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"connectedAccounts","description":"Info for connected accounts to external services.","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"contactInfo","description":"Contact Info selected during registration. Falls back to User.location and\/or\nUser.name if necessary. These fields are for admin use only and do not respect\nuser privacy settings. DO NOT display this information publicly.","args":[],"type":{"kind":"OBJECT","name":"ContactInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"email","description":"Email of the user, only available to admins within 18 months of tournament","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrants","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Entrant","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"events","description":"The events this participant registered for.","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"gamerTag","description":"The tag that was used in registration e.g. Mang0","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":null,"args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prefix","description":"The prefix that was used in registration e.g. C9","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"requiredConnections","description":"Admin only field for required social connections","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"ProfileAuthorization","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"user","description":"The user this participant is associated to.","args":[],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"verified","description":"If this participant is verified as actually being in the tournament","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ContactInfo","description":"Name, address, etc","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"city","description":"Participant City Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"country","description":"Participant Country Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"countryId","description":"Participant Country (region) id","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nameFirst","description":"First Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nameLast","description":"Last Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"Participant State Name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stateId","description":"Participant State (region) id","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"zipcode","description":"Zip or Postal Code","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Player","description":"A player","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"gamerTag","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prefix","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rankings","description":"Most recent active & published rankings","args":[{"name":"limit","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"videogameId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"PlayerRank","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"recentSets","description":"Recent sets for this player.","args":[{"name":"opponentId","description":"Use this to get H2H history between two players","type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Set","ofType":null}},"isDeprecated":true,"deprecationReason":"Use the sets field instead."},{"name":"sets","description":"Set history for this player.","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"user","description":null,"args":[],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"PlayerRank","description":"A player's ranks","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rank","description":"The player's placement on the ranking","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"title","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"GameSelectionType","description":"The type of selection i.e. is it for a character or something else","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"CHARACTER","description":"Character selection","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"Stage","description":"Video Stage","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Stage name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"PhaseGroup","description":"A group within a phase","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":"The bracket type of this group's phase.","args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"displayIdentifier","description":"Unique identifier for this group within the context of its phase","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"firstRoundTime","description":"For the given phase group, this is the start time of the first round that occurs in the group.","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numRounds","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"paginatedSeeds","description":null,"args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SeedConnection","ofType":null},"isDeprecated":true,"deprecationReason":"Please use 'seeds', which is now paginated"},{"name":"paginatedSets","description":"Paginated sets on this phaseGroup","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":true,"deprecationReason":"Please use 'sets', which is now paginated"},{"name":"phase","description":"The phase associated with this phase group","args":[],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"progressionsOut","description":"The progressions out of this phase group","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Progression","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"rounds","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Round","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"seedMap","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seeds","description":"Paginated seeds for this phase group","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SeedConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"sets","description":"Paginated sets on this phaseGroup","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standings","description":"Paginated list of standings","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"StandingGroupStandingPageFilter","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StandingConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"Unix time the group is scheduled to start. This info could also be on the wave instead.","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tiebreakOrder","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"wave","description":null,"args":[],"type":{"kind":"OBJECT","name":"Wave","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"BracketType","description":"The type of Bracket format that a Phase is configured with.","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"SINGLE_ELIMINATION","description":"","isDeprecated":false,"deprecationReason":null},{"name":"DOUBLE_ELIMINATION","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ROUND_ROBIN","description":"","isDeprecated":false,"deprecationReason":null},{"name":"SWISS","description":"","isDeprecated":false,"deprecationReason":null},{"name":"EXHIBITION","description":"","isDeprecated":false,"deprecationReason":null},{"name":"CUSTOM_SCHEDULE","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MATCHMAKING","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ELIMINATION_ROUNDS","description":"","isDeprecated":false,"deprecationReason":null},{"name":"RACE","description":"","isDeprecated":false,"deprecationReason":null},{"name":"CIRCUIT","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"SeedPageFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"SeedPageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"entrantName","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"checkInState","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"phaseGroupId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventCheckInGroupId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"phaseId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"SeedConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Seed","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Seed","description":"A seed for an entrant","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"checkedInParticipants","description":"Map of Participant ID to checked in boolean","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"groupSeedNum","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isBye","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phase","description":null,"args":[],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseGroup","description":null,"args":[],"type":{"kind":"OBJECT","name":"PhaseGroup","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"placeholderName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"placement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"players","description":"The player(s) associated with this seed's entrant","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Player","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"progressionSeedId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"progressionSource","description":"Source progression information","args":[],"type":{"kind":"OBJECT","name":"Progression","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seedNum","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"setRecordWithoutByes","description":"Entrant's win\/loss record for this standing. Scores do not include byes.","args":[{"name":"phaseGroupId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standings","description":null,"args":[{"name":"containerType","description":"The container of the standing groups to get standings for. If null, will return all standings.","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Standing","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Phase","description":"A phase in an event","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":"The bracket type of this phase.","args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"event","description":"The Event that this phase belongs to","args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"groupCount","description":"Number of phase groups in this phase","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isExhibition","description":"Is the phase an exhibition or not.","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Name of phase e.g. Round 1 Pools","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numSeeds","description":"The number of seeds this phase contains.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"paginatedSeeds","description":null,"args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SeedConnection","ofType":null},"isDeprecated":true,"deprecationReason":"Please use 'seeds' instead"},{"name":"phaseGroups","description":"Phase groups under this phase, paginated","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"PhaseGroupPageQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"PhaseGroupConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"phaseOrder","description":"The relative order of this phase within an event","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seeds","description":"Paginated seeds for this phase","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"SeedPaginationQuery","ofType":null}},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SeedConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"sets","description":"Paginated sets for this Phase","args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortType","description":"How to sort these sets","type":{"kind":"ENUM","name":"SetSortType","ofType":null},"defaultValue":null},{"name":"filters","description":"Supported filter options to filter down set results.","type":{"kind":"INPUT_OBJECT","name":"SetFilters","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"SetConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"State of the phase","args":[],"type":{"kind":"ENUM","name":"ActivityState","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"waves","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Wave","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PhaseGroupPageQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"entrantIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"PhaseGroupPageQueryFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PhaseGroupPageQueryFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"waveId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"PhaseGroupConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"PhaseGroup","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"ActivityState","description":"Represents the state of an activity","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"CREATED","description":"Activity is created","isDeprecated":false,"deprecationReason":null},{"name":"ACTIVE","description":"Activity is active or in progress","isDeprecated":false,"deprecationReason":null},{"name":"COMPLETED","description":"Activity is done","isDeprecated":false,"deprecationReason":null},{"name":"READY","description":"Activity is ready to be started","isDeprecated":false,"deprecationReason":null},{"name":"INVALID","description":"Activity is invalid","isDeprecated":false,"deprecationReason":null},{"name":"CALLED","description":"Activity, like a set, has been called to start","isDeprecated":false,"deprecationReason":null},{"name":"QUEUED","description":"Activity is queued to run","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"Wave","description":"A wave in a tournament","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"identifier","description":"The Wave Identifier","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"Unix time the wave is scheduled to start.","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Progression","description":"A connection between a placement in an origin phase group to a destination seed.","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"originOrder","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"originPhase","description":null,"args":[],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"originPhaseGroup","description":null,"args":[],"type":{"kind":"OBJECT","name":"PhaseGroup","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"originPlacement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Standing","description":"A standing indicates the placement of something within a container.","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"container","description":"The containing entity that contextualizes this standing. Event standings, for\nexample, represent an entrant's standing in the entire event vs. Set standings\nwhich is an entrant's standing in only a single set within an event.","args":[],"type":{"kind":"UNION","name":"StandingContainer","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":"If the entity this standing is assigned to can be resolved into an entrant, this will provide the entrant.","args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isFinal","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"metadata","description":"Metadata that goes along with this standing. Can take on different forms based on standing group type and settings.","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"placement","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":"The player(s) tied to this standing's entity","args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standing","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"The \"placement\" field is identical and will eventually replace \"standing\""},{"name":"stats","description":null,"args":[],"type":{"kind":"OBJECT","name":"StandingStats","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"totalPoints","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"UNION","name":"StandingContainer","description":"The containing entity that this standing is for","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"Tournament","ofType":null},{"kind":"OBJECT","name":"Event","ofType":null},{"kind":"OBJECT","name":"PhaseGroup","ofType":null},{"kind":"OBJECT","name":"Set","ofType":null}]},{"kind":"OBJECT","name":"Tournament","description":"A tournament","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"addrState","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"admins","description":"Admin-only view of admins for this tournament","args":[{"name":"roles","description":"Which roles to show","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"User","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"city","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"countryCode","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"createdAt","description":"When the tournament was created (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"currency","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"endAt","description":"When the tournament ends","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"eventRegistrationClosesAt","description":"When does event registration close","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"events","description":null,"args":[{"name":"limit","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"EventFilter","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"hasOfflineEvents","description":"True if tournament has at least one offline event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hasOnlineEvents","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hashtag","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":"True if tournament has at least one online event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isRegistrationOpen","description":"Is tournament registration open","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"lat","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"links","description":null,"args":[],"type":{"kind":"OBJECT","name":"TournamentLinks","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"lng","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"mapsPlaceId","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The tournament name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numAttendees","description":"Number of attendees including spectators, if public","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"owner","description":"The user who created the tournament","args":[],"type":{"kind":"OBJECT","name":"User","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participants","description":"Paginated, queryable list of participants","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"ParticipantPaginationQuery","ofType":null}},"defaultValue":null},{"name":"isAdmin","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"ParticipantConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"postalCode","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"primaryContact","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"primaryContactType","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"publishing","description":"Publishing settings for this tournament","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"registrationClosesAt","description":"When does registration for the tournament end","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rules","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"shortSlug","description":"The short slug used to form the url","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":"The slug used to form the url","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"When the tournament Starts","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"State of the tournament, can be ActivityState::CREATED, ActivityState::ACTIVE, or ActivityState::COMPLETED","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stations","description":null,"args":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StationsConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamQueue","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"StreamQueue","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"streams","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Streams","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"teamCreationClosesAt","description":"When is the team creation deadline","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teams","description":"Paginated, queryable list of teams","args":[{"name":"query","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"TeamPaginationQuery","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"TeamConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"timezone","description":"The timezone of the tournament","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournamentType","description":"The type of tournament from TournamentType","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"updatedAt","description":"When the tournament was last modified (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":"Build Tournament URL","args":[{"name":"tab","description":"Tournament tab to add to URL","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"relative","description":"Generate a relative URL. Defaults to true. Setting to false will generate an absolute URL","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"true"}],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"venueAddress","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"venueName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"waves","description":"List of all waves in this tournament","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Wave","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"EventFilter","description":null,"fields":null,"inputFields":[{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"type","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"published","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"TournamentLinks","description":null,"fields":[{"name":"facebook","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discord","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ParticipantPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"ParticipantPageFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ParticipantPageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"ids","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"eventIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null},{"name":"gamerTag","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"unpaid","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"incompleteTeam","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"missingDeck","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"checkedIn","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"notCheckedIn","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ParticipantConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Participant","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"StationsConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Stations","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Stations","description":"Stations, such as a stream setup, at an event","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"canAutoAssign","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"clusterNumber","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"clusterPrefix","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"enabled","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"identifier","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numSetups","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"number","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prefix","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"queue","description":null,"args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"queueDepth","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"updatedAt","description":null,"args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"StreamQueue","description":"A Stream queue object","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"sets","description":"The sets on the stream","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Set","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"stream","description":"The stream on the queue","args":[],"type":{"kind":"OBJECT","name":"Streams","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Streams","description":"Tournament Stream","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"enabled","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"followerCount","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numSetups","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"parentStreamId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamGame","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamId","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamLogo","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamSource","description":null,"args":[],"type":{"kind":"ENUM","name":"StreamSource","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamStatus","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamType","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"streamTypeId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"StreamSource","description":"Represents the source of a stream","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITCH","description":"Stream is on twitch.tv channel","isDeprecated":false,"deprecationReason":null},{"name":"HITBOX","description":"Stream is on smashcast.tv channel","isDeprecated":false,"deprecationReason":null},{"name":"STREAMME","description":"Stream is on a stream.me channel","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"Stream is on a mixer.com channel","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TeamPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"TeamPaginationFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TeamPaginationFilter","description":null,"fields":null,"inputFields":[{"name":"globalTeamId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"eventState","description":null,"type":{"kind":"ENUM","name":"ActivityState","ofType":null},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"eventIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"minEntrantCount","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"maxEntrantCount","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null},{"name":"type","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"tournamentId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"memberStatus","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null}},"defaultValue":null},{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"isLeague","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"past","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"rosterComplete","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"rosterIncomplete","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"TeamMemberStatus","description":"Membership status of a team member","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"UNKNOWN","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ACCEPTED","description":"","isDeprecated":false,"deprecationReason":null},{"name":"INVITED","description":"","isDeprecated":false,"deprecationReason":null},{"name":"REQUEST","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ALUM","description":"","isDeprecated":false,"deprecationReason":null},{"name":"HIATUS","description":"","isDeprecated":false,"deprecationReason":null},{"name":"OPEN_SPOT","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"TeamConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"INTERFACE","name":"Team","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INTERFACE","name":"Team","description":"A team, either at the global level or within the context of an event","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discriminator","description":"Uniquely identifying token for team. Same as the hashed part of the slug","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":true,"deprecationReason":"Use the entrant field off the EventTeam type"},{"name":"event","description":null,"args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":true,"deprecationReason":"Use the event field off the EventTeam type"},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"members","description":null,"args":[{"name":"status","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"TeamMember","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"EventTeam","ofType":null},{"kind":"OBJECT","name":"GlobalTeam","ofType":null}]},{"kind":"OBJECT","name":"TeamMember","description":"A member of a team","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isAlternate","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isCaptain","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"memberType","description":"The type of the team member","args":[],"type":{"kind":"ENUM","name":"TeamMemberType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"participant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Participant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":null,"args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"status","description":"The status of the team member","args":[],"type":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"TeamMemberType","description":"Membership type of a team member","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"PLAYER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"STAFF","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"StandingStats","description":"Any stats related to this standing. This type is experimental and very likely to change in the future.","fields":[{"name":"score","description":null,"args":[],"type":{"kind":"OBJECT","name":"Score","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Score","description":"The score that led to this standing being awarded. The meaning of this field can\nvary by standing type and is not used for some standing types.","fields":[{"name":"label","description":"The name of this score. e.g. \"Kills\" or \"Stocks\"","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"value","description":"The raw score value","args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"displayValue","description":"Like value, but formatted for race format events. Formatted according to the race config for the front end to use.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Round","description":"A round within a phase group","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bestOf","description":"If applicable, bestOf is the number of games\n\t\t\t\t\t\t\t\t\tone must win a majority out of to win a set in this round","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"number","description":"Indicates this round's order in the phase group","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"The time that this round is scheduled to start at","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StandingGroupStandingPageFilter","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"StandingConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Standing","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"SetSlot","description":"A slot in a set where a seed currently or will eventually exist in order to participate in the set.","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prereqId","description":"Pairs with prereqType, is the ID of the prereq.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prereqPlacement","description":"Given a set prereq type, defines the placement required in the origin set to end up in this slot.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"prereqType","description":"Describes where the entity in this slot comes from.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"seed","description":null,"args":[],"type":{"kind":"OBJECT","name":"Seed","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slotIndex","description":"The index of the slot. Unique per set.","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standing","description":"The standing within this set for the seed currently assigned to this slot.","args":[],"type":{"kind":"OBJECT","name":"Standing","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"League","description":"A league","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"addrState","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"city","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"countryCode","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"createdAt","description":"When the tournament was created (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"currency","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"endAt","description":"When the tournament ends","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrantCount","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"eventOwners","description":null,"args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"EventOwnersQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventOwnerConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"eventRegistrationClosesAt","description":"When does event registration close","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"events","description":"Paginated list of events in a league","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"LeagueEventsQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"finalEventId","description":"Hacked \"progression\" into this final event","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"No longer used"},{"name":"hasOfflineEvents","description":"True if tournament has at least one offline event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hasOnlineEvents","description":null,"args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"hashtag","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"isOnline","description":"True if tournament has at least one online event","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"lat","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"links","description":null,"args":[],"type":{"kind":"OBJECT","name":"TournamentLinks","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"lng","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"mapsPlaceId","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The tournament name","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"numProgressingToFinalEvent","description":"Top X number of people in the standings who progress to final event","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":true,"deprecationReason":"No longer used"},{"name":"numUniquePlayers","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"postalCode","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"primaryContact","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"primaryContactType","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"publishing","description":"Publishing settings for this tournament","args":[],"type":{"kind":"SCALAR","name":"JSON","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"registrationClosesAt","description":"When does registration for the tournament end","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"rules","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"shortSlug","description":"The short slug used to form the url","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"showStandings","description":"Whether standings for this league should be visible","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"standings","description":"Paginated list of standings","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"StandingGroupStandingPageFilter","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"StandingConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"startAt","description":"When the tournament Starts","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":"State of the tournament, can be ActivityState::CREATED, ActivityState::ACTIVE, or ActivityState::COMPLETED","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"teamCreationClosesAt","description":"When is the team creation deadline","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tiers","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"EventTier","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"timezone","description":"The timezone of the tournament","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"tournamentType","description":"The type of tournament from TournamentType","args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"updatedAt","description":"When the tournament was last modified (unix timestamp)","args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":"Build Tournament URL","args":[{"name":"tab","description":"Tournament tab to add to URL","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"relative","description":"Generate a relative URL. Defaults to true. Setting to false will generate an absolute URL","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"true"}],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"venueAddress","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"venueName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"videogames","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Videogame","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"EventOwnersQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventOwnerConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"EventOwner","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventOwner","description":"Name and Gamertag of the owner of an event in a league","fields":[{"name":"eventId","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"email","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"gamerTag","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"fullName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"LeagueEventsQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"LeagueEventsFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"LeagueEventsFilter","description":null,"fields":null,"inputFields":[{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null},{"name":"pointMappingGroupIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"tierIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"userId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"leagueEntrantId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventTier","description":"Used for league application tiers","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"Name of this tier","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Videogame","description":"A videogame","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"displayName","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StandingPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"StandingPageFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StandingPageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"ids","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StationFilter","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"perPage","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"TeamRosterSize","description":"Team roster size requirements","fields":[{"name":"maxAlternates","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"maxPlayers","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"minAlternates","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"minPlayers","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserLeaguesPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserLeaguesPaginationFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserLeaguesPaginationFilter","description":null,"fields":null,"inputFields":[{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"past","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"LeagueConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"League","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Address","description":"A user's address","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"city","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"country","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"countryId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"state","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"stateId","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserTournamentsPaginationQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"UserTournamentsPaginationFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UserTournamentsPaginationFilter","description":null,"fields":null,"inputFields":[{"name":"past","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"search","description":null,"type":{"kind":"INPUT_OBJECT","name":"PaginationSearchType","ofType":null},"defaultValue":null},{"name":"videogameId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"tournamentView","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"excludeId","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"TournamentConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Tournament","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Shop","description":"A shop","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"levels","description":null,"args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"ShopLevelsQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"ShopLevelConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"messages","description":null,"args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"ShopOrderMessagesQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"ShopOrderMessageConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"slug","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"url","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ShopLevelsQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ShopLevelConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"ShopLevel","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ShopLevel","description":"A shop level","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"currAmount","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"goalAmount","description":null,"args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ShopOrderMessagesQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ShopOrderMessageConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"ShopOrderMessage","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"ShopOrderMessage","description":"The message and player info for a shop order","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"gamertag","description":"The player's gamertag. Returns null if anonymous message type","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"message","description":"The order message","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":"The player's name. Returns null unless name & tag display is selected","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"player","description":"The player who left the comment","args":[],"type":{"kind":"OBJECT","name":"Player","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"total","description":"The total order amount","args":[],"type":{"kind":"SCALAR","name":"Float","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TournamentQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"TournamentPageFilter","ofType":null},"defaultValue":null},{"name":"sort","description":null,"type":{"kind":"ENUM","name":"TournamentPaginationSort","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TournamentPageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"ids","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"ownerId","description":"ID of the user that owns this tournament.","type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"isCurrentUserAdmin","description":"If true, filter to only tournaments the currently authed user is an admin of","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"countryCode","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"addrState","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"location","description":null,"type":{"kind":"INPUT_OBJECT","name":"TournamentLocationFilter","ofType":null},"defaultValue":null},{"name":"afterDate","description":null,"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"defaultValue":null},{"name":"beforeDate","description":null,"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"defaultValue":null},{"name":"computedUpdatedAt","description":null,"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"defaultValue":null},{"name":"name","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"venueName","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"isFeatured","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"isLeague","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"hasBannerImages","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"activeShops","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"regOpen","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"past","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"published","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"publiclySearchable","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"staffPicks","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"hasOnlineEvents","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"topGames","description":null,"type":{"kind":"INPUT_OBJECT","name":"TopGameFilter","ofType":null},"defaultValue":null},{"name":"upcoming","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"videogameIds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"sortByScore","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TournamentLocationFilter","description":null,"fields":null,"inputFields":[{"name":"distanceFrom","description":"Latitude, Longitude","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"distance","description":"e.g. 50mi","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"TopGameFilter","description":null,"fields":null,"inputFields":[{"name":"gameNums","description":"Array of which # top game you want to filter on.e.g. [2, 3] will filter on the 2nd and 3rd top games","type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"TournamentPaginationSort","description":null,"fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"startAt","description":"","isDeprecated":false,"deprecationReason":null},{"name":"endAt","description":"","isDeprecated":false,"deprecationReason":null},{"name":"eventRegistrationClosesAt","description":"","isDeprecated":false,"deprecationReason":null},{"name":"computedUpdatedAt","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"VideogameQuery","description":null,"fields":null,"inputFields":[{"name":"page","description":null,"type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"1"},{"name":"perPage","description":"How many nodes to return for the page. Maximum value of 500","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":"25"},{"name":"sortBy","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"filter","description":null,"type":{"kind":"INPUT_OBJECT","name":"VideogamePageFilter","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"VideogamePageFilter","description":null,"fields":null,"inputFields":[{"name":"id","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"name","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"forUser","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"VideogameConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Videogame","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Mutation","description":null,"fields":[{"name":"deletePhase","description":"Delete a phase by id","args":[{"name":"phaseId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"deleteStation","description":"Delete a station by id","args":[{"name":"stationId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"deleteWave","description":"Delete a wave by id","args":[{"name":"waveId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"resolveScheduleConflicts","description":"Automatically attempt to resolve all schedule conflicts. Returns a list of changed seeds","args":[{"name":"tournamentId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"options","description":null,"type":{"kind":"INPUT_OBJECT","name":"ResolveConflictsOptions","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Seed","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"swapSeeds","description":"Swap two seed ids in a phase","args":[{"name":"phaseId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"seed1Id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"seed2Id","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Seed","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"updatePhaseGroups","description":"Update set of phase groups in a phase","args":[{"name":"groupConfigs","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"PhaseGroupUpdateInput","ofType":null}}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"PhaseGroup","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"updatePhaseSeeding","description":"Update the seeding for a phase","args":[{"name":"phaseId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"seedMapping","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"UpdatePhaseSeedInfo","ofType":null}}},"defaultValue":null},{"name":"options","description":null,"type":{"kind":"INPUT_OBJECT","name":"UpdatePhaseSeedingOptions","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"upsertPhase","description":"Create or update a Phase","args":[{"name":"phaseId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"eventId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"payload","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"PhaseUpsertInput","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Phase","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"upsertStation","description":"Add or update a station by id","args":[{"name":"stationId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"tournamentId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"fields","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"StationUpsertInput","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Stations","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"upsertWave","description":"Add or update a wave by id","args":[{"name":"waveId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"tournamentId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"fields","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"WaveUpsertInput","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"Wave","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ResolveConflictsOptions","description":null,"fields":null,"inputFields":[{"name":"lockedSeeds","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"INPUT_OBJECT","name":"ResolveConflictsLockedSeedConfig","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"ResolveConflictsLockedSeedConfig","description":null,"fields":null,"inputFields":[{"name":"eventId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"numSeeds","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PhaseGroupUpdateInput","description":null,"fields":null,"inputFields":[{"name":"phaseGroupId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"stationId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null},{"name":"waveId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UpdatePhaseSeedInfo","description":null,"fields":null,"inputFields":[{"name":"seedId","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"seedNum","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"defaultValue":null},{"name":"phaseGroupId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"UpdatePhaseSeedingOptions","description":null,"fields":null,"inputFields":[{"name":"strictMode","description":"Validate that seedMapping exactly accounts for all entrants in the phase","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"PhaseUpsertInput","description":null,"fields":null,"inputFields":[{"name":"name","description":"The name of the Phase. For example, \"Top 8\" or \"Pools\"","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null},{"name":"groupCount","description":"The number of pools to configure for the Phase. Only applies to brackets that support pools","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null},{"name":"bracketType","description":null,"type":{"kind":"ENUM","name":"BracketType","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"StationUpsertInput","description":null,"fields":null,"inputFields":[{"name":"number","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"defaultValue":null},{"name":"clusterId","description":null,"type":{"kind":"SCALAR","name":"ID","ofType":null},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"INPUT_OBJECT","name":"WaveUpsertInput","description":null,"fields":null,"inputFields":[{"name":"identifier","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"defaultValue":null},{"name":"startAt","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Timestamp","ofType":null}},"defaultValue":null},{"name":"endAt","description":null,"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Timestamp","ofType":null}},"defaultValue":null}],"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__Schema","description":"A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.","fields":[{"name":"types","description":"A list of all types supported by this server.","args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"queryType","description":"The type that query operations will be rooted at.","args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"mutationType","description":"If this server supports mutation, the type that mutation operations will be rooted at.","args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"subscriptionType","description":"If this server support subscription, the type that subscription operations will be rooted at.","args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"directives","description":"A list of all directives supported by this server.","args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Directive","ofType":null}}}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__Type","description":"The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.","fields":[{"name":"kind","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"ENUM","name":"__TypeKind","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"fields","description":null,"args":[{"name":"includeDeprecated","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"false"}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Field","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"interfaces","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"possibleTypes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"enumValues","description":null,"args":[{"name":"includeDeprecated","description":null,"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":"false"}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__EnumValue","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"inputFields","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__InputValue","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"ofType","description":null,"args":[],"type":{"kind":"OBJECT","name":"__Type","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"__TypeKind","description":"An enum describing what kind of type a given `__Type` is.","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"SCALAR","description":"Indicates this type is a scalar.","isDeprecated":false,"deprecationReason":null},{"name":"OBJECT","description":"Indicates this type is an object. `fields` and `interfaces` are valid fields.","isDeprecated":false,"deprecationReason":null},{"name":"INTERFACE","description":"Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.","isDeprecated":false,"deprecationReason":null},{"name":"UNION","description":"Indicates this type is a union. `possibleTypes` is a valid field.","isDeprecated":false,"deprecationReason":null},{"name":"ENUM","description":"Indicates this type is an enum. `enumValues` is a valid field.","isDeprecated":false,"deprecationReason":null},{"name":"INPUT_OBJECT","description":"Indicates this type is an input object. `inputFields` is a valid field.","isDeprecated":false,"deprecationReason":null},{"name":"LIST","description":"Indicates this type is a list. `ofType` is a valid field.","isDeprecated":false,"deprecationReason":null},{"name":"NON_NULL","description":"Indicates this type is a non-null. `ofType` is a valid field.","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"__Field","description":"Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"args","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__InputValue","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"isDeprecated","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"deprecationReason","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__InputValue","description":"Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"type","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__Type","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"defaultValue","description":"A GraphQL-formatted string representing the default value for this input value.","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__EnumValue","description":"One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"isDeprecated","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"deprecationReason","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"__Directive","description":"A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.","fields":[{"name":"name","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"description","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"locations","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"ENUM","name":"__DirectiveLocation","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"args","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"__InputValue","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"onOperation","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":true,"deprecationReason":"Use `locations`."},{"name":"onFragment","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":true,"deprecationReason":"Use `locations`."},{"name":"onField","description":null,"args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"isDeprecated":true,"deprecationReason":"Use `locations`."}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"__DirectiveLocation","description":"A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"QUERY","description":"Location adjacent to a query operation.","isDeprecated":false,"deprecationReason":null},{"name":"MUTATION","description":"Location adjacent to a mutation operation.","isDeprecated":false,"deprecationReason":null},{"name":"SUBSCRIPTION","description":"Location adjacent to a subscription operation.","isDeprecated":false,"deprecationReason":null},{"name":"FIELD","description":"Location adjacent to a field.","isDeprecated":false,"deprecationReason":null},{"name":"FRAGMENT_DEFINITION","description":"Location adjacent to a fragment definition.","isDeprecated":false,"deprecationReason":null},{"name":"FRAGMENT_SPREAD","description":"Location adjacent to a fragment spread.","isDeprecated":false,"deprecationReason":null},{"name":"INLINE_FRAGMENT","description":"Location adjacent to an inline fragment.","isDeprecated":false,"deprecationReason":null},{"name":"SCHEMA","description":"Location adjacent to a schema definition.","isDeprecated":false,"deprecationReason":null},{"name":"SCALAR","description":"Location adjacent to a scalar definition.","isDeprecated":false,"deprecationReason":null},{"name":"OBJECT","description":"Location adjacent to an object type definition.","isDeprecated":false,"deprecationReason":null},{"name":"FIELD_DEFINITION","description":"Location adjacent to a field definition.","isDeprecated":false,"deprecationReason":null},{"name":"ARGUMENT_DEFINITION","description":"Location adjacent to an argument definition.","isDeprecated":false,"deprecationReason":null},{"name":"INTERFACE","description":"Location adjacent to an interface definition.","isDeprecated":false,"deprecationReason":null},{"name":"UNION","description":"Location adjacent to a union definition.","isDeprecated":false,"deprecationReason":null},{"name":"ENUM","description":"Location adjacent to an enum definition.","isDeprecated":false,"deprecationReason":null},{"name":"ENUM_VALUE","description":"Location adjacent to an enum value definition.","isDeprecated":false,"deprecationReason":null},{"name":"INPUT_OBJECT","description":"Location adjacent to an input object type definition.","isDeprecated":false,"deprecationReason":null},{"name":"INPUT_FIELD_DEFINITION","description":"Location adjacent to an input object field definition.","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"INTERFACE","name":"ActionSet","description":"A set of actions available for an entity to take","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"TeamActionSet","ofType":null}]},{"kind":"INTERFACE","name":"BracketConfig","description":"Bracket-specific configuration","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":null,"args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"RaceBracketConfig","ofType":null}]},{"kind":"ENUM","name":"Comparator","description":"Comparison operator","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"GREATER_THAN","description":"","isDeprecated":false,"deprecationReason":null},{"name":"GREATER_THAN_OR_EQUAL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"EQUAL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"LESS_THAN_OR_EQUAL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"LESS_THAN","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"EventTeam","description":"An event-level Team, in the context of some competition","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discriminator","description":"Uniquely identifying token for team. Same as the hashed part of the slug","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":true,"deprecationReason":"Use the entrant field off the EventTeam type"},{"name":"event","description":null,"args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":true,"deprecationReason":"Use the event field off the EventTeam type"},{"name":"globalTeam","description":null,"args":[],"type":{"kind":"OBJECT","name":"GlobalTeam","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"members","description":null,"args":[{"name":"status","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"TeamMember","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"Team","ofType":null}],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"GlobalTeam","description":"Global Team","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"discriminator","description":"Uniquely identifying token for team. Same as the hashed part of the slug","args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"entrant","description":null,"args":[],"type":{"kind":"OBJECT","name":"Entrant","ofType":null},"isDeprecated":true,"deprecationReason":"Use the entrant field off the EventTeam type"},{"name":"event","description":null,"args":[],"type":{"kind":"OBJECT","name":"Event","ofType":null},"isDeprecated":true,"deprecationReason":"Use the event field off the EventTeam type"},{"name":"eventTeams","description":null,"args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"TeamPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventTeamConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"images","description":null,"args":[{"name":"type","description":null,"type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"Image","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"leagueTeams","description":"Leagues-level teams for leagues this team is competing in","args":[{"name":"query","description":null,"type":{"kind":"INPUT_OBJECT","name":"TeamPaginationQuery","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"EventTeamConnection","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"members","description":null,"args":[{"name":"status","description":null,"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"TeamMemberStatus","ofType":null}},"defaultValue":null}],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"TeamMember","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"name","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"Team","ofType":null}],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"EventTeamConnection","description":null,"fields":[{"name":"pageInfo","description":null,"args":[],"type":{"kind":"OBJECT","name":"PageInfo","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"nodes","description":null,"args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"EventTeam","ofType":null}},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[],"enumValues":null,"possibleTypes":null},{"kind":"INTERFACE","name":"MatchConfig","description":"Match-level configuration","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":null,"args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":[{"kind":"OBJECT","name":"RaceMatchConfig","ofType":null}]},{"kind":"ENUM","name":"MatchConfigVerificationMethod","description":"Different options available for verifying player-reported match results","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"TWITCH","description":"","isDeprecated":false,"deprecationReason":null},{"name":"STREAM_ME","description":"","isDeprecated":false,"deprecationReason":null},{"name":"ANY","description":"","isDeprecated":false,"deprecationReason":null},{"name":"MIXER","description":"","isDeprecated":false,"deprecationReason":null},{"name":"YOUTUBE","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"RaceBracketConfig","description":"Race specific bracket configuration","fields":[{"name":"automaticEndTime","description":null,"args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"automaticStartTime","description":null,"args":[],"type":{"kind":"SCALAR","name":"Timestamp","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":null,"args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"goalTargetComparator","description":null,"args":[],"type":{"kind":"ENUM","name":"Comparator","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"goalTargetValue","description":null,"args":[],"type":{"kind":"SCALAR","name":"String","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"limitMode","description":null,"args":[],"type":{"kind":"ENUM","name":"RaceLimitMode","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"limitValue","description":null,"args":[],"type":{"kind":"SCALAR","name":"Int","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"raceType","description":null,"args":[],"type":{"kind":"ENUM","name":"RaceType","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"BracketConfig","ofType":null}],"enumValues":null,"possibleTypes":null},{"kind":"ENUM","name":"RaceLimitMode","description":"Enforces limits on the amount of allowable Race submissions","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"BEST_ALL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"FIRST_ALL","description":"","isDeprecated":false,"deprecationReason":null},{"name":"PLAYTIME","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"ENUM","name":"RaceType","description":"Race type","fields":null,"inputFields":null,"interfaces":null,"enumValues":[{"name":"GOALS","description":"","isDeprecated":false,"deprecationReason":null},{"name":"TIMED","description":"","isDeprecated":false,"deprecationReason":null}],"possibleTypes":null},{"kind":"OBJECT","name":"RaceMatchConfig","description":"Race specific match configuration","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"bracketType","description":null,"args":[],"type":{"kind":"ENUM","name":"BracketType","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"playerReportingEnabled","description":"Can players report results?","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"verificationMethods","description":"Accepted methods of verification that players can use","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"ENUM","name":"MatchConfigVerificationMethod","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"verificationRequired","description":"Are players required to submit verification of their reported results?","args":[],"type":{"kind":"SCALAR","name":"Boolean","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"MatchConfig","ofType":null}],"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"TeamActionSet","description":"A set of actions available for a team to take","fields":[{"name":"id","description":null,"args":[],"type":{"kind":"SCALAR","name":"ID","ofType":null},"isDeprecated":false,"deprecationReason":null}],"inputFields":null,"interfaces":[{"kind":"INTERFACE","name":"ActionSet","ofType":null}],"enumValues":null,"possibleTypes":null}],"directives":[{"name":"publicCache","description":"Specify a query to be read from gql-public. Will use the configured cacheAge on\nthe query resolve configuration, or the override value passed through the\ndirective as publicCache(cacheAge: INT) argument.","locations":["FIELD"],"args":[{"name":"cacheAge","description":"Optional override for the query-level cacheAge value.","type":{"kind":"SCALAR","name":"Int","ofType":null},"defaultValue":null}]},{"name":"userData","description":"Specify a field to only be included in the response if the user is logged in.","locations":["FIELD"],"args":[]},{"name":"skip","description":"Directs the executor to skip this field or fragment when the `if` argument is true.","locations":["FIELD","FRAGMENT_SPREAD","INLINE_FRAGMENT"],"args":[{"name":"if","description":"Skipped when true.","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"defaultValue":null}]},{"name":"include","description":"Directs the executor to include this field or fragment only when the `if` argument is true.","locations":["FIELD","FRAGMENT_SPREAD","INLINE_FRAGMENT"],"args":[{"name":"if","description":"Included when true.","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"defaultValue":null}]},{"name":"deprecated","description":"Marks an element of a GraphQL schema as no longer supported.","locations":["FIELD_DEFINITION","ENUM_VALUE"],"args":[{"name":"reason","description":"Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted in [Markdown](https:\/\/daringfireball.net\/projects\/markdown\/).","type":{"kind":"SCALAR","name":"String","ofType":null},"defaultValue":"\"No longer supported\""}]}]}},"extensions":{"cacheControl":{"version":1,"hints":null},"queryComplexity":0},"actionRecords":[]} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/core/ui/UIImage.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/core/ui/UIImage.kt deleted file mode 100644 index 5350a7739..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/core/ui/UIImage.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.adammcneilly.pocketleague.shared.core.ui - -/** - * This sealed class defines all of the different formats an image can be represented in UI code. - */ -sealed class UIImage { - - /** - * This class is used when we want to show an image stored in a specific [drawableRes]. - */ - data class AndroidResource(val drawableRes: Int) : UIImage() - - /** - * This class is used when we have an image at a remote [imageUrl] that must be rendered. - */ - data class Remote(val imageUrl: String) : UIImage() -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/core/ui/UIText.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/core/ui/UIText.kt deleted file mode 100644 index f6ff9e277..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/core/ui/UIText.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.adammcneilly.pocketleague.shared.core.ui - -/** - * A collection of possible representations of text in our UI layer. - */ -sealed class UIText { - /** - * Text that should be fetched from resources using the supplied [stringRes]. - */ - data class AndroidResourceText(val stringRes: Int) : UIText() - - /** - * Text that is presented as a [string]. - */ - data class StringText(val string: String) : UIText() -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Result.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Result.kt deleted file mode 100644 index 8dd7fb289..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Result.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.adammcneilly.pocketleague.shared.data - -/** - * This is a sealed class that represents two options for a data response, where the response is - * either successful or a failure. - * - * By wrapping a response into this single type, we can provide a way for asynchronous streams to - * handle both success and failure scenarios, without having to catch exceptions. This is because any - * exceptions will be wrapped inside an [Error] class. - */ -sealed class Result { - /** - * A successful result which implies we will have some [data] returned. - */ - data class Success(val data: T) : Result() - - /** - * An unsuccessful result because some [error] occurred. - */ - data class Error(val error: Throwable) : Result() -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/event/EventListRequestBody.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/event/EventListRequestBody.kt deleted file mode 100644 index 531079f7d..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/event/EventListRequestBody.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.adammcneilly.pocketleague.shared.data.event - -/** - * Request body for pulling a list of events. - * - * @property[upcoming] If true, request events that have not begun yet. False will request past and current events. - * If not supplied, API will use a default. - * @property[numEvents] The number of events that should be returned by the API. Will return up to this number based on what's available. - * If not supplied, API will use a default. - */ -data class EventListRequestBody( - val upcoming: Boolean? = null, - val numEvents: Int? = null, -) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/event/EventRepository.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/event/EventRepository.kt deleted file mode 100644 index 6c43795d6..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/event/EventRepository.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.adammcneilly.pocketleague.shared.data.event - -import com.adammcneilly.pocketleague.core.models.EventOverview -import com.adammcneilly.pocketleague.core.models.EventSummary -import com.adammcneilly.pocketleague.shared.data.Result -import kotlinx.coroutines.flow.Flow - -/** - * Data layer definition for requesting event information. - */ -interface EventRepository { - /** - * Given a [leagueSlug], fetch the [EventSummary] entities that match the supplied [requestBody]. - */ - fun fetchEventSummaries( - leagueSlug: String, - requestBody: EventListRequestBody, - ): Flow>> - - /** - * Given an [eventId], fetch the [EventOverview] entity for this event. - */ - fun fetchEventOverview( - eventId: String, - ): Flow> -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/event/remote/smashgg/SmashGGEventService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/event/remote/smashgg/SmashGGEventService.kt deleted file mode 100644 index df5706250..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/event/remote/smashgg/SmashGGEventService.kt +++ /dev/null @@ -1,165 +0,0 @@ -package com.adammcneilly.pocketleague.shared.data.event.remote.smashgg - -import com.adammcneilly.pocketleague.core.models.BracketType -import com.adammcneilly.pocketleague.core.models.EventOverview -import com.adammcneilly.pocketleague.core.models.EventSummary -import com.adammcneilly.pocketleague.core.models.PhaseOverview -import com.adammcneilly.pocketleague.core.models.Standings -import com.adammcneilly.pocketleague.core.models.StandingsPlacement -import com.adammcneilly.pocketleague.shared.data.Result -import com.adammcneilly.pocketleague.shared.data.event.EventListRequestBody -import com.adammcneilly.pocketleague.shared.data.event.EventRepository -import com.adammcneilly.pocketleague.shared.data.smashgg.mappers.toBracketType -import com.adammcneilly.pocketleague.shared.data.smashgg.mappers.toTeam -import com.adammcneilly.pocketleague.shared.data.smashgg.smashGGApolloClient -import com.adammcneilly.pocketleague.shared.graphql.EventOverviewQuery -import com.adammcneilly.pocketleague.shared.graphql.EventSummaryListQuery -import com.adammcneilly.pocketleague.shared.graphql.fragment.EventEntrantFragment -import com.adammcneilly.pocketleague.shared.graphql.fragment.EventOverviewFragment -import com.adammcneilly.pocketleague.shared.graphql.fragment.EventSummaryFragment -import com.adammcneilly.pocketleague.shared.graphql.fragment.PhaseGroupFragment -import com.adammcneilly.pocketleague.shared.graphql.fragment.StandingsPlacementFragment -import com.adammcneilly.pocketleague.shared.graphql.type.LeagueEventsFilter -import com.adammcneilly.pocketleague.shared.graphql.type.LeagueEventsQuery -import com.adammcneilly.pocketleague.shared.graphql.type.StandingPaginationQuery -import com.apollographql.apollo3.api.Optional -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.mapNotNull -import kotlinx.datetime.Clock -import kotlinx.datetime.Instant -import kotlinx.datetime.TimeZone -import kotlinx.datetime.toLocalDateTime - -/** - * A concrete implementation of [EventRepository] that will request information - * from the smash.gg API. - */ -class SmashGGEventService : EventRepository { - - override fun fetchEventSummaries( - leagueSlug: String, - requestBody: EventListRequestBody, - ): Flow>> { - val upcomingFilter = Optional.Present( - LeagueEventsFilter( - upcoming = Optional.presentIfNotNull(requestBody.upcoming), - ) - ) - - val eventsQuery = Optional.Present( - LeagueEventsQuery( - filter = upcomingFilter, - perPage = Optional.presentIfNotNull(requestBody.numEvents), - ) - ) - - val query = EventSummaryListQuery( - leagueSlug = Optional.Present(leagueSlug), - eventsQuery = eventsQuery, - ) - - val response = smashGGApolloClient.query(query).toFlow() - - return response.map { dataResponse -> - val events = dataResponse - .data - ?.league - ?.events - ?.nodes - ?.mapNotNull { - it?.eventSummaryFragment?.toEvent() - } - .orEmpty() - - Result.Success(events) - } - } - - override fun fetchEventOverview(eventId: String): Flow> { - val query = EventOverviewQuery( - eventId = Optional.Present(eventId), - standingsQuery = StandingPaginationQuery(), - ) - - val response = smashGGApolloClient.query(query).toFlow() - - return response.mapNotNull { dataResponse -> - val overview = dataResponse - .data - ?.event - ?.eventOverviewFragment - ?.toEventOverview() - - if (overview != null) { - Result.Success(overview) - } else { - Result.Error(Throwable("Unable to request EventOverview for id: $eventId")) - } - } - } -} - -private fun EventOverviewFragment.toEventOverview(): EventOverview { - val summaryFragment = this.eventSummaryFragment - - return EventOverview( - name = summaryFragment.name.orEmpty(), - startDate = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()), - phases = this.phaseGroups - ?.mapNotNull { phaseGroup -> - phaseGroup?.phaseGroupFragment?.toPhase() - } - .orEmpty(), - standings = Standings( - placements = this.standings - ?.nodes - ?.mapNotNull { node -> - node - ?.standingsPlacementFragment - .let(StandingsPlacementFragment?::toStandingsPlacement) - } - .orEmpty() - ), - timeZone = TimeZone.UTC, - ) -} - -private fun PhaseGroupFragment?.toPhase(): PhaseOverview { - val overview = this?.phase?.phaseOverviewFragment - - return PhaseOverview( - id = overview?.id.orEmpty(), - groupId = this?.id.orEmpty(), - numPools = overview?.groupCount ?: 0, - numEntrants = overview?.numSeeds ?: 0, - name = overview?.name.orEmpty(), - bracketType = this?.bracketType?.toBracketType() - ?: BracketType.UNKNOWN, - phaseOrder = overview?.phaseOrder ?: 0, - ) -} - -private fun EventSummaryFragment.toEvent(): EventSummary { - val startSeconds = (this.startAt as Int).toLong() - val eventTimeZone = TimeZone.UTC - val startDate = Instant.fromEpochSeconds(startSeconds).toLocalDateTime(eventTimeZone) - - return EventSummary( - id = this.id.orEmpty(), - eventName = this.name.orEmpty(), - tournamentName = this.tournament?.name.orEmpty(), - startDate = startDate, - timeZone = eventTimeZone, - numEntrants = this.numEntrants, - isOnline = this.isOnline == true, - tournamentImageUrl = this.tournament?.images?.firstOrNull()?.url.orEmpty(), - ) -} - -private fun StandingsPlacementFragment?.toStandingsPlacement(): StandingsPlacement { - return StandingsPlacement( - placement = this?.placement ?: 0, - team = this?.entrant?.eventEntrantFragment.let(EventEntrantFragment?::toTeam), - ) -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/phase/PhaseRepository.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/phase/PhaseRepository.kt deleted file mode 100644 index 7de344aaf..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/phase/PhaseRepository.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.adammcneilly.pocketleague.shared.data.phase - -import com.adammcneilly.pocketleague.core.models.PhaseDetail -import com.adammcneilly.pocketleague.shared.data.Result -import kotlinx.coroutines.flow.Flow - -/** - * The data contract to fetch information about a phase. - */ -interface PhaseRepository { - /** - * Fetch the [PhaseDetail] information for the supplied [phaseId]. - */ - suspend fun fetchPhaseDetail(phaseId: String): Flow> -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/phase/remote/smashgg/SmashGGPhaseService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/phase/remote/smashgg/SmashGGPhaseService.kt deleted file mode 100644 index 704eee29e..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/phase/remote/smashgg/SmashGGPhaseService.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.adammcneilly.pocketleague.shared.data.phase.remote.smashgg - -import com.adammcneilly.pocketleague.core.models.BracketType -import com.adammcneilly.pocketleague.core.models.EventSet -import com.adammcneilly.pocketleague.core.models.PhaseDetail -import com.adammcneilly.pocketleague.core.models.SetSlot -import com.adammcneilly.pocketleague.shared.data.Result -import com.adammcneilly.pocketleague.shared.data.phase.PhaseRepository -import com.adammcneilly.pocketleague.shared.data.smashgg.mappers.toBracketType -import com.adammcneilly.pocketleague.shared.data.smashgg.mappers.toTeam -import com.adammcneilly.pocketleague.shared.data.smashgg.smashGGApolloClient -import com.adammcneilly.pocketleague.shared.graphql.PhaseDetailQuery -import com.adammcneilly.pocketleague.shared.graphql.fragment.EventSetFragment -import com.adammcneilly.pocketleague.shared.graphql.fragment.PhaseDetailFragment -import com.adammcneilly.pocketleague.shared.graphql.fragment.SetSlotFragment -import com.apollographql.apollo3.api.Optional -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map - -/** - * A concrete implementation of a [PhaseRepository] that requests information from the Smash.gg - * API. - */ -class SmashGGPhaseService : PhaseRepository { - - override suspend fun fetchPhaseDetail(phaseId: String): Flow> { - val query = PhaseDetailQuery( - id = Optional.presentIfNotNull(phaseId), - ) - - val response = smashGGApolloClient.query(query).toFlow() - - return response.map { dataResponse -> - val phaseDetail = dataResponse - .data - ?.phase - ?.phaseDetailFragment - ?.toPhaseDetail() - - if (phaseDetail != null) { - Result.Success(phaseDetail) - } else { - Result.Error(Throwable("Unable to fetch phase detail: $phaseId")) - } - } - } -} - -private fun PhaseDetailFragment.toPhaseDetail(): PhaseDetail { - val overviewFragment = this.phaseOverviewFragment - - return PhaseDetail( - id = overviewFragment.id.orEmpty(), - groupId = "TODO: NOT IMPLEMENTED", - numPools = overviewFragment.groupCount ?: 0, - numEntrants = overviewFragment.numSeeds ?: 0, - name = overviewFragment.name.orEmpty(), - phaseOrder = overviewFragment.phaseOrder ?: 0, - bracketType = overviewFragment.bracketType?.toBracketType() ?: BracketType.UNKNOWN, - sets = this.sets?.nodes?.mapNotNull { setNode -> - setNode?.eventSetFragment?.toEventSet() - }.orEmpty(), - ) -} - -private fun EventSetFragment.toEventSet(): EventSet { - return EventSet( - fullRoundText = this.fullRoundText.orEmpty(), - displayScore = this.displayScore.orEmpty(), - round = this.round?.toString().orEmpty(), - winnerId = this.winnerId?.toString().orEmpty(), - slots = this.slots?.mapNotNull { setSlotNode -> - setSlotNode?.setSlotFragment?.toSetSlot() - }.orEmpty(), - // Games coming soon - games = emptyList(), - ) -} - -private fun SetSlotFragment.toSetSlot(): SetSlot { - return SetSlot( - team = this.entrant?.eventEntrantFragment?.toTeam()!!, - slotIndex = this.slotIndex ?: 0, - ) -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/SmashGGAPI.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/SmashGGAPI.kt deleted file mode 100644 index 9245f78d8..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/SmashGGAPI.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.adammcneilly.pocketleague.shared.data.smashgg - -import com.apollographql.apollo3.ApolloClient - -/** - * A shared instance of an [ApolloClient] to be used for smash.gg API requests. - */ -val smashGGApolloClient = ApolloClient.Builder() - .serverUrl("https://api.smash.gg/gql/alpha") - .addHttpInterceptor(SmashGGAuthorizationInterceptor()) - .build() diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/SmashGGAuthorizationInterceptor.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/SmashGGAuthorizationInterceptor.kt deleted file mode 100644 index e1d9b8745..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/SmashGGAuthorizationInterceptor.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.adammcneilly.pocketleague.shared.data.smashgg - -import com.adammcneilly.pocketleague.shared.BuildKonfig -import com.apollographql.apollo3.api.http.HttpRequest -import com.apollographql.apollo3.api.http.HttpResponse -import com.apollographql.apollo3.network.http.HttpInterceptor -import com.apollographql.apollo3.network.http.HttpInterceptorChain - -/** - * An [HttpInterceptor] that applies our smash.gg authorization token to the header of each request. - */ -internal class SmashGGAuthorizationInterceptor : HttpInterceptor { - - override suspend fun intercept( - request: HttpRequest, - chain: HttpInterceptorChain - ): HttpResponse { - val authToken = BuildKonfig.SMASH_GG_API_KEY - - val newRequest = request - .newBuilder() - .addHeader("Authorization", "Bearer $authToken") - .build() - - return chain.proceed(newRequest) - } -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/mappers/BracketTypeMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/mappers/BracketTypeMapper.kt deleted file mode 100644 index d5923fa35..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/mappers/BracketTypeMapper.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.adammcneilly.pocketleague.shared.data.smashgg.mappers - -import com.adammcneilly.pocketleague.core.models.BracketType - -typealias ApolloBracketType = com.adammcneilly.pocketleague.shared.graphql.type.BracketType - -/** - * Converts an [ApolloBracketType] from the smash.gg API to the [BracketType] within our domain. - */ -fun ApolloBracketType.toBracketType(): BracketType { - return when (this) { - ApolloBracketType.CUSTOM_SCHEDULE -> BracketType.CUSTOM - ApolloBracketType.SINGLE_ELIMINATION -> BracketType.SINGLE_ELIMINATION - ApolloBracketType.DOUBLE_ELIMINATION -> BracketType.DOUBLE_ELIMINATION - else -> BracketType.UNKNOWN - } -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/mappers/EventEntrantMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/mappers/EventEntrantMapper.kt deleted file mode 100644 index 156867b38..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/mappers/EventEntrantMapper.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.adammcneilly.pocketleague.shared.data.smashgg.mappers - -import com.adammcneilly.pocketleague.core.models.Team -import com.adammcneilly.pocketleague.shared.graphql.fragment.EventEntrantFragment -import com.adammcneilly.pocketleague.shared.graphql.fragment.EventPlayerFragment - -/** - * Converting an [EventEntrantFragment] from the smash.gg API into a [Team] from our domain. - */ -fun EventEntrantFragment?.toTeam(): Team { - return Team( - name = this?.name.orEmpty(), - lightThemeLogoImageUrl = this?.team?.images?.firstOrNull()?.url, - darkThemeLogoImageUrl = this?.team?.images?.firstOrNull()?.url, - roster = this?.team?.members?.mapNotNull { member -> - member?.player?.eventPlayerFragment.let(EventPlayerFragment?::toPlayer) - }.orEmpty(), - ) -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/mappers/EventPlayerMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/mappers/EventPlayerMapper.kt deleted file mode 100644 index 35968b22a..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/smashgg/mappers/EventPlayerMapper.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.adammcneilly.pocketleague.shared.data.smashgg.mappers - -import com.adammcneilly.pocketleague.core.models.Player -import com.adammcneilly.pocketleague.shared.graphql.fragment.EventPlayerFragment - -/** - * Converting an [EventPlayerFragment] from the smash.gg API into a [Player] from our domain. - */ -fun EventPlayerFragment?.toPlayer(): Player { - return Player( - countryCode = "", - gamerTag = this?.gamerTag.orEmpty(), - realName = "", - ) -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/domain/GetEventOverviewUseCase.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/domain/GetEventOverviewUseCase.kt deleted file mode 100644 index 9de626ede..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/domain/GetEventOverviewUseCase.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.adammcneilly.pocketleague.shared.eventoverview.domain - -import com.adammcneilly.pocketleague.core.models.EventOverview -import kotlinx.coroutines.flow.Flow - -/** - * Fetches [EventOverview] information for a specific event ID. - */ -interface GetEventOverviewUseCase { - - /** - * @see [GetEventOverviewUseCase] - */ - fun invoke(eventId: String): Flow - - /** - * All possible response variations for the [GetEventOverviewUseCase]. - */ - sealed class Result { - /** - * This is returned when our use case is successful and we have an [eventOverview] to - * provide. - */ - data class Success(val eventOverview: EventOverview) : Result() - - /** - * This is returned when our use case is unsuccessful and some [errorMessage] occurred. - */ - data class Error(val errorMessage: String?) : Result() - } -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/domain/GetEventOverviewUseCaseImpl.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/domain/GetEventOverviewUseCaseImpl.kt deleted file mode 100644 index 7cc99b362..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/domain/GetEventOverviewUseCaseImpl.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.adammcneilly.pocketleague.shared.eventoverview.domain - -import com.adammcneilly.pocketleague.shared.data.Result -import com.adammcneilly.pocketleague.shared.data.event.EventRepository -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map - -/** - * A concrete implementation of [GetEventOverviewUseCase] that will request information - * from the supplied [repository]. - */ -class GetEventOverviewUseCaseImpl( - private val repository: EventRepository, -) : GetEventOverviewUseCase { - - override fun invoke(eventId: String): Flow { - return repository.fetchEventOverview(eventId).map { repoResult -> - when (repoResult) { - is Result.Success -> { - GetEventOverviewUseCase.Result.Success(repoResult.data) - } - is Result.Error -> { - GetEventOverviewUseCase.Result.Error(repoResult.error.message) - } - } - } - } -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/state/EventOverviewAction.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/state/EventOverviewAction.kt deleted file mode 100644 index 91f3095d3..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/state/EventOverviewAction.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.adammcneilly.pocketleague.shared.eventoverview.state - -/** - * A collection of possible actions that can occur on the event overview screen. - */ -sealed class EventOverviewAction { - /** - * When this action is triggered we should load an event overview with the given [eventId]. - */ - data class FetchEventOverview( - val eventId: String, - ) : EventOverviewAction() - - /** - * Handle a user click on a specific [phaseId]. - */ - data class SelectPhase( - val phaseId: String, - ) : EventOverviewAction() - - /** - * When we have navigated away to a phase detail, we should clear the selected phase. - */ - object NavigatedToPhaseDetail : EventOverviewAction() -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/state/EventOverviewStateMutator.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/state/EventOverviewStateMutator.kt deleted file mode 100644 index dd5128b9a..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/state/EventOverviewStateMutator.kt +++ /dev/null @@ -1,164 +0,0 @@ -@file:Suppress("TooManyFunctions") - -package com.adammcneilly.pocketleague.shared.eventoverview.state - -import com.adammcneilly.pocketleague.core.datetime.DateTimeFormatter -import com.adammcneilly.pocketleague.core.models.BracketType -import com.adammcneilly.pocketleague.core.models.EventOverview -import com.adammcneilly.pocketleague.core.models.PhaseOverview -import com.adammcneilly.pocketleague.core.models.Player -import com.adammcneilly.pocketleague.core.models.Standings -import com.adammcneilly.pocketleague.core.models.StandingsPlacement -import com.adammcneilly.pocketleague.shared.core.ui.UIImage -import com.adammcneilly.pocketleague.shared.core.ui.UIText -import com.adammcneilly.pocketleague.shared.eventoverview.domain.GetEventOverviewUseCase -import com.adammcneilly.pocketleague.shared.eventoverview.ui.EventOverviewDisplayModel -import com.adammcneilly.pocketleague.shared.eventoverview.ui.EventOverviewPhaseDisplayModel -import com.adammcneilly.pocketleague.shared.standings.StandingsDisplayModel -import com.adammcneilly.pocketleague.shared.standings.StandingsPlacementDisplayModel -import com.tunjid.mutator.Mutation -import com.tunjid.mutator.coroutines.stateFlowMutator -import com.tunjid.mutator.coroutines.toMutationStream -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.onStart - -/** - * A state management controller for the event overview screen that consumes [EventOverviewAction]s - * and maps them into [EventOverviewViewState] entities. - */ -fun eventOverviewStateMutator( - scope: CoroutineScope, - getEventOverviewUseCase: GetEventOverviewUseCase, -) = stateFlowMutator( - scope = scope, - initialState = EventOverviewViewState(), - actionTransform = { actions -> - actions.toMutationStream { - when (val action = type()) { - is EventOverviewAction.FetchEventOverview -> - action.flow - .fetchEventOverviewMutations( - getEventOverviewUseCase, - ) - is EventOverviewAction.SelectPhase -> action.flow.selectPhaseMutations() - is EventOverviewAction.NavigatedToPhaseDetail -> action.flow.clearPhaseMutations() - } - } - } -) - -private fun Flow.selectPhaseMutations(): - Flow> { - - return this.map { action -> - Mutation { - copy( - selectedPhaseId = action.phaseId, - ) - } - } -} - -private fun Flow.clearPhaseMutations(): - Flow> { - - return this.map { action -> - Mutation { - copy( - selectedPhaseId = null, - ) - } - } -} - -private fun Flow.fetchEventOverviewMutations( - getEventOverviewUseCase: GetEventOverviewUseCase, -): Flow> { - return this.flatMapLatest { action -> - getEventOverviewUseCase.invoke(action.eventId) - .map { result -> - when (result) { - is GetEventOverviewUseCase.Result.Success -> { - successMutation( - event = result.eventOverview, - ) - } - is GetEventOverviewUseCase.Result.Error -> { - errorMutation() - } - } - } - .onStart { - emit(loadingMutation()) - } - } -} - -private fun loadingMutation() = Mutation { - copy( - showLoading = true, - ) -} - -private fun errorMutation() = Mutation { - copy( - showLoading = false, - errorMessage = UIText.StringText( - "Fetching event overview failed.", - ), - ) -} - -private fun successMutation( - event: EventOverview, -) = Mutation { - copy( - showLoading = false, - event = event.toDisplayModel(), - ) -} - -private fun EventOverview.toDisplayModel(): EventOverviewDisplayModel { - return EventOverviewDisplayModel( - eventName = this.name, - phases = this.phases.map(PhaseOverview::toDisplayModel), - startDate = DateTimeFormatter().formatLocalDateTime( - this.startDate, - EventOverviewDisplayModel.EVENT_DATE_FORMAT, - ).orEmpty(), - standings = this.standings.toDisplayModel(), - ) -} - -private fun PhaseOverview.toDisplayModel(): EventOverviewPhaseDisplayModel { - return EventOverviewPhaseDisplayModel( - phaseId = this.id, - phaseName = this.name, - numPools = this.numPools.toString(), - bracketType = when (this.bracketType) { - BracketType.CUSTOM -> "Custom" - BracketType.SINGLE_ELIMINATION -> "SE" - BracketType.DOUBLE_ELIMINATION -> "DE" - BracketType.UNKNOWN -> "Unknown" - }, - numEntrants = this.numEntrants.toString(), - ) -} - -private fun Standings.toDisplayModel(): StandingsDisplayModel { - return StandingsDisplayModel( - placements = this.placements.map(StandingsPlacement::toDisplayModel) - ) -} - -private fun StandingsPlacement.toDisplayModel(): StandingsPlacementDisplayModel { - return StandingsPlacementDisplayModel( - placement = this.placement.toString(), - teamName = this.team.name, - roster = this.team.roster.map(Player::gamerTag).joinToString(separator = " / "), - teamLogo = this.team.lightThemeLogoImageUrl?.let(UIImage::Remote), - ) -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/state/EventOverviewViewState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/state/EventOverviewViewState.kt deleted file mode 100644 index da8c59e02..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/state/EventOverviewViewState.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.adammcneilly.pocketleague.shared.eventoverview.state - -import com.adammcneilly.pocketleague.shared.core.ui.UIText -import com.adammcneilly.pocketleague.shared.eventoverview.ui.EventOverviewDisplayModel - -/** - * A collection of possible view states for [EventOverviewScreen]. - */ -data class EventOverviewViewState( - val showLoading: Boolean = true, - val event: EventOverviewDisplayModel? = null, - val selectedPhaseId: String? = null, - val errorMessage: UIText? = null, -) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/ui/EventOverviewDisplayModel.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/ui/EventOverviewDisplayModel.kt deleted file mode 100644 index 8857b5891..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/ui/EventOverviewDisplayModel.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.adammcneilly.pocketleague.shared.eventoverview.ui - -import com.adammcneilly.pocketleague.core.models.EventOverview -import com.adammcneilly.pocketleague.shared.standings.StandingsDisplayModel - -/** - * A user friendly representation of an [EventOverview] to be shown on the UI. - */ -data class EventOverviewDisplayModel( - val eventName: String, - val startDate: String, - val phases: List, - val standings: StandingsDisplayModel, -) { - - companion object { - const val EVENT_DATE_FORMAT = "MMM dd, yyyy" - } -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/ui/EventOverviewPhaseDisplayModel.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/ui/EventOverviewPhaseDisplayModel.kt deleted file mode 100644 index b27a9fe7c..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventoverview/ui/EventOverviewPhaseDisplayModel.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.adammcneilly.pocketleague.shared.eventoverview.ui - -import com.adammcneilly.pocketleague.core.models.PhaseOverview - -/** - * A user friendly representation of a [PhaseOverview] to be displayed on the UI. - */ -data class EventOverviewPhaseDisplayModel( - val phaseId: String, - val phaseName: String, - val numPools: String, - val bracketType: String, - val numEntrants: String, -) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/domain/GetPhaseDetailUseCase.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/domain/GetPhaseDetailUseCase.kt deleted file mode 100644 index 8d8ec7428..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/domain/GetPhaseDetailUseCase.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.adammcneilly.pocketleague.shared.phasedetail.domain - -import com.adammcneilly.pocketleague.core.models.PhaseDetail -import kotlinx.coroutines.flow.Flow - -/** - * A use case to request detailed information about a phase given its ID. - */ -interface GetPhaseDetailUseCase { - - /** - * @see [GetPhaseDetailUseCase] - */ - suspend operator fun invoke(phaseId: String): Flow - - /** - * A collection of possible return values for a [GetPhaseDetailUseCase]. - */ - sealed class Result { - /** - * This will be returned when we were able to successfully retrieve a [phaseDetail]. - */ - data class Success( - val phaseDetail: PhaseDetail, - ) : Result() - - /** - * This will be returned whenever we have an error requesting a phase detail, and the - * supplied [errorMessage] will tell us what went wrong. - */ - data class Error( - val errorMessage: String?, - ) : Result() - } -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/domain/GetPhaseDetailUseCaseImpl.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/domain/GetPhaseDetailUseCaseImpl.kt deleted file mode 100644 index 245786e97..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/domain/GetPhaseDetailUseCaseImpl.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.adammcneilly.pocketleague.shared.phasedetail.domain - -import com.adammcneilly.pocketleague.shared.data.Result -import com.adammcneilly.pocketleague.shared.data.phase.PhaseRepository -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map - -/** - * A concrete implementation of a [GetPhaseDetailUseCase] that requests the necessary information - * from the supplied [repository]. - */ -class GetPhaseDetailUseCaseImpl( - private val repository: PhaseRepository, -) : GetPhaseDetailUseCase { - - override suspend fun invoke(phaseId: String): Flow { - return repository.fetchPhaseDetail(phaseId).map { repoResult -> - when (repoResult) { - is Result.Success -> { - GetPhaseDetailUseCase.Result.Success( - phaseDetail = repoResult.data, - ) - } - is Result.Error -> { - GetPhaseDetailUseCase.Result.Error( - errorMessage = repoResult.error.message, - ) - } - } - } - } -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/state/PhaseDetailAction.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/state/PhaseDetailAction.kt deleted file mode 100644 index fe6213a13..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/state/PhaseDetailAction.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.adammcneilly.pocketleague.shared.phasedetail.state - -/** - * A collection of actions that can occur on the phase detail screen. - */ -sealed class PhaseDetailAction { - /** - * Triggered when we want to fetch detailed information about a phase. - */ - data class FetchPhaseDetail( - val phaseId: String, - ) : PhaseDetailAction() -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/state/PhaseDetailStateMutator.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/state/PhaseDetailStateMutator.kt deleted file mode 100644 index 492c6ae3d..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/state/PhaseDetailStateMutator.kt +++ /dev/null @@ -1,88 +0,0 @@ -package com.adammcneilly.pocketleague.shared.phasedetail.state - -import com.adammcneilly.pocketleague.core.models.PhaseDetail -import com.adammcneilly.pocketleague.shared.core.ui.UIText -import com.adammcneilly.pocketleague.shared.phasedetail.domain.GetPhaseDetailUseCase -import com.adammcneilly.pocketleague.shared.phasedetail.ui.PhaseDetailDisplayModel -import com.tunjid.mutator.Mutation -import com.tunjid.mutator.coroutines.stateFlowMutator -import com.tunjid.mutator.coroutines.toMutationStream -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.onStart - -/** - * Create a [stateFlowMutator] that will be used to manage our [PhaseDetailViewState]. - */ -fun phaseDetailStateMutator( - scope: CoroutineScope, - getPhaseDetailUseCase: GetPhaseDetailUseCase, -) = stateFlowMutator( - scope = scope, - initialState = PhaseDetailViewState(), - actionTransform = { actions -> - actions.toMutationStream { - when (val action = type()) { - is PhaseDetailAction.FetchPhaseDetail -> - action.flow - .fetchPhaseDetailMutations(getPhaseDetailUseCase) - } - } - } -) - -private fun Flow.fetchPhaseDetailMutations( - getPhaseDetailUseCase: GetPhaseDetailUseCase, -): Flow> { - return this.flatMapLatest { action -> - getPhaseDetailUseCase - .invoke(action.phaseId) - .map { result -> - when (result) { - is GetPhaseDetailUseCase.Result.Success -> { - successMutation( - phaseDetail = result.phaseDetail, - ) - } - is GetPhaseDetailUseCase.Result.Error -> { - errorMutation() - } - } - } - .onStart { - emit(loadingMutation()) - } - } -} - -private fun successMutation( - phaseDetail: PhaseDetail, -) = Mutation { - copy( - showLoading = false, - phase = phaseDetail.toDisplayModel(), - ) -} - -private fun loadingMutation() = Mutation { - copy( - showLoading = true, - ) -} - -private fun PhaseDetail.toDisplayModel(): PhaseDetailDisplayModel { - return PhaseDetailDisplayModel( - phaseName = this.name, - ) -} - -private fun errorMutation() = Mutation { - copy( - showLoading = false, - errorMessage = UIText.StringText( - "Fetching phase detail failed.", - ), - ) -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/state/PhaseDetailViewState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/state/PhaseDetailViewState.kt deleted file mode 100644 index 3fdc51e34..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/state/PhaseDetailViewState.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.adammcneilly.pocketleague.shared.phasedetail.state - -import com.adammcneilly.pocketleague.shared.core.ui.UIText -import com.adammcneilly.pocketleague.shared.phasedetail.ui.PhaseDetailDisplayModel - -/** - * A UI configuration for the phase detail screen. - */ -data class PhaseDetailViewState( - val showLoading: Boolean = true, - val phase: PhaseDetailDisplayModel? = null, - val errorMessage: UIText? = null, -) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/ui/PhaseDetailDisplayModel.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/ui/PhaseDetailDisplayModel.kt deleted file mode 100644 index 4c994635e..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/phasedetail/ui/PhaseDetailDisplayModel.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.adammcneilly.pocketleague.shared.phasedetail.ui - -/** - * User friendly representation of a phase detail. - */ -data class PhaseDetailDisplayModel( - val phaseName: String, -) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/standings/StandingsDisplayModel.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/standings/StandingsDisplayModel.kt deleted file mode 100644 index 4771cea8e..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/standings/StandingsDisplayModel.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.adammcneilly.pocketleague.shared.standings - -/** - * UI representation for a collection of [placements]. - */ -data class StandingsDisplayModel( - val placements: List, -) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/standings/StandingsPlacementDisplayModel.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/standings/StandingsPlacementDisplayModel.kt deleted file mode 100644 index e8b3b52c6..000000000 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/standings/StandingsPlacementDisplayModel.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.adammcneilly.pocketleague.shared.standings - -import com.adammcneilly.pocketleague.shared.core.ui.UIImage - -/** - * User friendly information to display a list item in a collection of standings. - */ -data class StandingsPlacementDisplayModel( - val placement: String, - val teamName: String, - val roster: String, - val teamLogo: UIImage?, -) diff --git a/team-api/build.gradle.kts b/team-api/build.gradle.kts deleted file mode 100644 index 179ebc398..000000000 --- a/team-api/build.gradle.kts +++ /dev/null @@ -1,62 +0,0 @@ -plugins { - kotlin("multiplatform") - id("com.android.library") -} - -kotlin { - android() - - listOf( - iosX64(), - iosArm64(), - iosSimulatorArm64() - ).forEach { - it.binaries.framework { - baseName = "team-api" - } - } - - sourceSets { - val commonMain by getting { - dependencies { - api(project(":core-models")) - api(project(":core-data")) - api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.coroutines}") - } - } - val commonTest by getting { - dependencies { - implementation(kotlin("test")) - } - } - val androidMain by getting - val androidTest by getting - val iosX64Main by getting - val iosArm64Main by getting - val iosSimulatorArm64Main by getting - val iosMain by creating { - dependsOn(commonMain) - iosX64Main.dependsOn(this) - iosArm64Main.dependsOn(this) - iosSimulatorArm64Main.dependsOn(this) - } - val iosX64Test by getting - val iosArm64Test by getting - val iosSimulatorArm64Test by getting - val iosTest by creating { - dependsOn(commonTest) - iosX64Test.dependsOn(this) - iosArm64Test.dependsOn(this) - iosSimulatorArm64Test.dependsOn(this) - } - } -} - -android { - compileSdk = AndroidConfig.compileSDK - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") - defaultConfig { - minSdk = AndroidConfig.minSDK - targetSdk = AndroidConfig.targetSDK - } -} diff --git a/team-api/src/androidMain/AndroidManifest.xml b/team-api/src/androidMain/AndroidManifest.xml deleted file mode 100644 index 38e5c3512..000000000 --- a/team-api/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/team-api/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/api/TeamRepository.kt b/team-api/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/api/TeamRepository.kt deleted file mode 100644 index a2c398c17..000000000 --- a/team-api/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/api/TeamRepository.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.adammcneilly.pocketleague.team.api - -import com.adammcneilly.pocketleague.core.data.DataResult -import com.adammcneilly.pocketleague.core.models.Team -import kotlinx.coroutines.flow.Flow - -/** - * An interface defining the data contract for all requests within the - * team domain. - */ -interface TeamRepository { - - /** - * Requests a list of [Team] entities for all of the active teams within RLCS. - */ - fun fetchActiveTeams(): Flow>> -} diff --git a/team-implementation/build.gradle.kts b/team-implementation/build.gradle.kts deleted file mode 100644 index 8e58ce14b..000000000 --- a/team-implementation/build.gradle.kts +++ /dev/null @@ -1,66 +0,0 @@ -plugins { - kotlin("multiplatform") - id("com.android.library") -} - -kotlin { - android() - - listOf( - iosX64(), - iosArm64(), - iosSimulatorArm64() - ).forEach { - it.binaries.framework { - baseName = "team-implementation" - } - } - - sourceSets { - val commonMain by getting { - dependencies { - implementation(project(":team-api")) - implementation(project(":octanegg")) - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2") - implementation("io.ktor:ktor-client-core:${Versions.ktor}") - implementation("io.ktor:ktor-client-json:${Versions.ktor}") - implementation("io.ktor:ktor-client-logging:${Versions.ktor}") - implementation("io.ktor:ktor-client-serialization:${Versions.ktor}") - } - } - val commonTest by getting { - dependencies { - implementation(kotlin("test")) - } - } - val androidMain by getting - val androidTest by getting - val iosX64Main by getting - val iosArm64Main by getting - val iosSimulatorArm64Main by getting - val iosMain by creating { - dependsOn(commonMain) - iosX64Main.dependsOn(this) - iosArm64Main.dependsOn(this) - iosSimulatorArm64Main.dependsOn(this) - } - val iosX64Test by getting - val iosArm64Test by getting - val iosSimulatorArm64Test by getting - val iosTest by creating { - dependsOn(commonTest) - iosX64Test.dependsOn(this) - iosArm64Test.dependsOn(this) - iosSimulatorArm64Test.dependsOn(this) - } - } -} - -android { - compileSdk = AndroidConfig.compileSDK - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") - defaultConfig { - minSdk = AndroidConfig.minSDK - targetSdk = AndroidConfig.targetSDK - } -} diff --git a/team-implementation/src/androidMain/AndroidManifest.xml b/team-implementation/src/androidMain/AndroidManifest.xml deleted file mode 100644 index 84b43244b..000000000 --- a/team-implementation/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/OctaneGGAPIClient.kt b/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/OctaneGGAPIClient.kt deleted file mode 100644 index ac005586f..000000000 --- a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/OctaneGGAPIClient.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.adammcneilly.pocketleague.team.implementation.octanegg - -import com.adammcneilly.pocketleague.core.data.DataResult -import io.ktor.client.HttpClient -import io.ktor.client.features.json.JsonFeature -import io.ktor.client.features.json.serializer.KotlinxSerializer -import io.ktor.client.request.HttpRequestBuilder -import io.ktor.client.request.get -import io.ktor.http.ContentType -import kotlinx.serialization.json.Json - -/** - * Defines the API client information for communicating with the octane.gg API. - */ -internal class OctaneGGAPIClient { - val baseURL = "https://zsr.octane.gg/" - - val httpClient = HttpClient { - install(JsonFeature) { - serializer = KotlinxSerializer( - Json { - ignoreUnknownKeys = true - acceptContentTypes = acceptContentTypes + ContentType.Any - } - ) - } - } - - /** - * A helper function to wrap all of our API requests in a try/catch and return a [DataResult] - * object. - */ - suspend inline fun getResponse( - endpoint: String, - requestBuilder: HttpRequestBuilder.() -> Unit = {}, - ): DataResult { - val url = "$baseURL$endpoint" - - return try { - // KTOR will switch to a different dispatcher, so we don't need to. - DataResult.Success(httpClient.get(url, requestBuilder)) - } catch (e: Exception) { - DataResult.Error(e) - } - } -} diff --git a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/OctaneGGTeamService.kt b/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/OctaneGGTeamService.kt deleted file mode 100644 index 0b1ca5b0b..000000000 --- a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/OctaneGGTeamService.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.adammcneilly.pocketleague.team.implementation.octanegg - -import com.adammcneilly.pocketleague.core.data.DataResult -import com.adammcneilly.pocketleague.core.models.Team -import com.adammcneilly.pocketleague.data.remote.octanegg.OctaneGGAPIClient -import com.adammcneilly.pocketleague.data.remote.octanegg.dtos.TeamDTO -import com.adammcneilly.pocketleague.data.remote.octanegg.dtos.TeamListResponseDTO -import com.adammcneilly.pocketleague.data.remote.octanegg.mappers.toTeam -import com.adammcneilly.pocketleague.team.api.TeamRepository -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow - -/** - * A concrete implementation of [TeamRepository] to request information from the octane.gg API. - */ -class OctaneGGTeamService : TeamRepository { - - private val apiClient = OctaneGGAPIClient() - - override fun fetchActiveTeams(): Flow>> { - return flow { - val apiResult = apiClient.getResponse("teams/active") - - val mappedResult: DataResult> = when (apiResult) { - is DataResult.Success -> { - val mappedTeams = apiResult.data.teams?.map(TeamDTO::toTeam).orEmpty() - - DataResult.Success(mappedTeams) - } - is DataResult.Error -> { - DataResult.Error(apiResult.error) - } - } - - emit(mappedResult) - } - } -} diff --git a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/AccountDTO.kt b/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/AccountDTO.kt deleted file mode 100644 index 21bf33245..000000000 --- a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/AccountDTO.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.adammcneilly.pocketleague.team.implementation.octanegg.dtos - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -/** - * Represents a [PlayerDTO] account within the octane.gg API. - */ -@Serializable -internal data class AccountDTO( - @SerialName("id") - val id: String? = null, - @SerialName("platform") - val platform: String? = null, -) diff --git a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/PlayerDTO.kt b/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/PlayerDTO.kt deleted file mode 100644 index 78f77e155..000000000 --- a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/PlayerDTO.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.adammcneilly.pocketleague.team.implementation.octanegg.dtos - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -/** - * Represents a person who is a player for a [TeamDTO] in the octane.gg API. - */ -@Serializable -internal data class PlayerDTO( - @SerialName("accounts") - val accounts: List? = null, - @SerialName("coach") - val coach: Boolean? = null, - @SerialName("country") - val country: String? = null, - @SerialName("_id") - val id: String? = null, - @SerialName("name") - val name: String? = null, - @SerialName("relevant") - val relevant: Boolean? = null, - @SerialName("slug") - val slug: String? = null, - @SerialName("substitute") - val substitute: Boolean? = null, - @SerialName("tag") - val tag: String? = null, - @SerialName("team") - val team: TeamOverviewDTO? = null, -) diff --git a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/TeamDTO.kt b/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/TeamDTO.kt deleted file mode 100644 index 20420c8eb..000000000 --- a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/TeamDTO.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.adammcneilly.pocketleague.team.implementation.octanegg.dtos - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -/** - * Represents a team within the octane.gg API domain. - */ -@Serializable -internal data class TeamDTO( - @SerialName("players") - val players: List? = null, - @SerialName("team") - val team: TeamOverviewDTO? = null, -) diff --git a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/TeamListResponseDTO.kt b/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/TeamListResponseDTO.kt deleted file mode 100644 index f4bf6dbee..000000000 --- a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/TeamListResponseDTO.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.adammcneilly.pocketleague.team.implementation.octanegg.dtos - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -/** - * A data response for a list of teams within the octane.gg API. - */ -@Serializable -internal data class TeamListResponseDTO( - @SerialName("teams") - val teams: List? = null, - @SerialName("page") - val page: Int? = null, - @SerialName("perPage") - val perPage: Int? = null, - @SerialName("pageSize") - val pageSize: Int? = null, -) diff --git a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/TeamOverviewDTO.kt b/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/TeamOverviewDTO.kt deleted file mode 100644 index e69963198..000000000 --- a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/dtos/TeamOverviewDTO.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.adammcneilly.pocketleague.team.implementation.octanegg.dtos - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -/** - * Overview information about a team, that does not include roster info. - */ -@Serializable -internal data class TeamOverviewDTO( - @SerialName("_id") - val id: String? = null, - @SerialName("image") - val image: String? = null, - @SerialName("name") - val name: String? = null, - @SerialName("region") - val region: String? = null, - @SerialName("relevant") - val relevant: Boolean? = null, - @SerialName("slug") - val slug: String? = null, -) diff --git a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/mappers/PlayerMapper.kt b/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/mappers/PlayerMapper.kt deleted file mode 100644 index 2c68b5e31..000000000 --- a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/mappers/PlayerMapper.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.adammcneilly.pocketleague.team.implementation.octanegg.mappers - -import com.adammcneilly.pocketleague.core.models.Player -import com.adammcneilly.pocketleague.team.implementation.octanegg.dtos.PlayerDTO - -/** - * Converts a [PlayerDTO] from octane.gg API into a [Player] entity. - */ -internal fun PlayerDTO.toPlayer(): Player { - return Player( - countryCode = this.country ?: "N/A", - gamerTag = this.tag ?: "N/A", - realName = this.name ?: "N/A", - ) -} diff --git a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/mappers/TeamMapper.kt b/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/mappers/TeamMapper.kt deleted file mode 100644 index ff04e260b..000000000 --- a/team-implementation/src/commonMain/kotlin/com/adammcneilly/pocketleague/team/implementation/octanegg/mappers/TeamMapper.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.adammcneilly.pocketleague.team.implementation.octanegg.mappers - -import com.adammcneilly.pocketleague.core.models.Team -import com.adammcneilly.pocketleague.team.implementation.octanegg.dtos.PlayerDTO -import com.adammcneilly.pocketleague.team.implementation.octanegg.dtos.TeamDTO - -/** - * Converts a [TeamDTO] from the octane.gg API to a [Team] entity. - */ -internal fun TeamDTO.toTeam(): Team { - return Team( - name = this.team?.name ?: "N/A", - lightThemeLogoImageUrl = this.team?.image, - darkThemeLogoImageUrl = this.team?.image, - roster = this.players?.map(PlayerDTO::toPlayer).orEmpty(), - ) -} From 81abcf7fde3a54113f159384d1b28aa25e4fa67a Mon Sep 17 00:00:00 2001 From: amcneilly Date: Fri, 15 Apr 2022 12:09:01 -0400 Subject: [PATCH 02/40] Updating octanegg module. --- .../pocketleague/android/design/UIText.kt | 30 -------------- app/build.gradle.kts | 1 + buildSrc/src/main/kotlin/Versions.kt | 2 + octanegg/build.gradle.kts | 5 +-- .../data/remote/octanegg/OctaneGGAPIClient.kt | 39 +++++++++---------- .../data/remote/octanegg/dtos/EventDTO.kt | 24 ------------ .../octanegg/dtos/EventListResponseDTO.kt | 14 ------- .../data/remote/octanegg/dtos/StageDTO.kt | 21 ---------- .../octanegg/mappers/EventSummaryMapper.kt | 22 ----------- .../remote/octanegg/mappers/PlayerMapper.kt | 15 ------- .../remote/octanegg/mappers/TeamMapper.kt | 17 -------- .../OctaneGGAccount.kt} | 4 +- .../remote/octanegg/models/OctaneGGEvent.kt | 35 +++++++++++++++++ .../models/OctaneGGEventListResponse.kt | 19 +++++++++ .../OctaneGGLocation.kt} | 8 +++- .../PlayerDTO.kt => models/OctaneGGPlayer.kt} | 8 ++-- .../PrizeDTO.kt => models/OctaneGGPrize.kt} | 7 +++- .../remote/octanegg/models/OctaneGGStage.kt | 29 ++++++++++++++ .../OctaneGGTeamDetail.kt} | 8 ++-- .../OctaneGGTeamListResponse.kt} | 6 +-- .../OctaneGGTeamOverview.kt} | 4 +- settings.gradle | 1 + 22 files changed, 132 insertions(+), 187 deletions(-) delete mode 100644 android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/UIText.kt delete mode 100644 octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/EventDTO.kt delete mode 100644 octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/EventListResponseDTO.kt delete mode 100644 octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/StageDTO.kt delete mode 100644 octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/mappers/EventSummaryMapper.kt delete mode 100644 octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/mappers/PlayerMapper.kt delete mode 100644 octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/mappers/TeamMapper.kt rename octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/{dtos/AccountDTO.kt => models/OctaneGGAccount.kt} (75%) create mode 100644 octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGEvent.kt create mode 100644 octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGEventListResponse.kt rename octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/{dtos/LocationDTO.kt => models/OctaneGGLocation.kt} (51%) rename octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/{dtos/PlayerDTO.kt => models/OctaneGGPlayer.kt} (78%) rename octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/{dtos/PrizeDTO.kt => models/OctaneGGPrize.kt} (51%) create mode 100644 octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGStage.kt rename octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/{dtos/TeamDTO.kt => models/OctaneGGTeamDetail.kt} (53%) rename octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/{dtos/TeamListResponseDTO.kt => models/OctaneGGTeamListResponse.kt} (70%) rename octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/{dtos/TeamOverviewDTO.kt => models/OctaneGGTeamOverview.kt} (83%) diff --git a/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/UIText.kt b/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/UIText.kt deleted file mode 100644 index f16714e8a..000000000 --- a/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/UIText.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.adammcneilly.pocketleague.android.design - -import android.content.Context -import androidx.compose.runtime.Composable -import androidx.compose.ui.platform.LocalContext -import com.adammcneilly.pocketleague.shared.core.ui.UIText - -/** - * Given a [context], look up the String res if necessary, or resolve it right from the - * [UIText.StringText] class. - */ -fun UIText.getValue(context: Context): String { - return when (this) { - is UIText.AndroidResourceText -> { - context.getString(this.stringRes) - } - is UIText.StringText -> { - this.string - } - } -} - -/** - * In a [Composable] context, provide a helper function to get the value which just proxies to - * the other [getValue] method. - */ -@Composable -fun UIText.getValue(): String { - return this.getValue(LocalContext.current) -} diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3cdee44b3..864cf3e33 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -84,6 +84,7 @@ android { dependencies { + implementation(project(":android-design-system")) implementation("androidx.core:core-ktx:${Versions.ktxCore}") implementation("androidx.appcompat:appcompat:${Versions.appCompat}") implementation("com.google.android.material:material:${Versions.material}") diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 136078ba4..9121954ca 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -79,4 +79,6 @@ object Versions { // https://github.com/ktorio/ktor/releases const val ktor = "1.6.8" + + const val kotlinxSerialization = "1.3.2" } diff --git a/octanegg/build.gradle.kts b/octanegg/build.gradle.kts index b52457212..909990f96 100644 --- a/octanegg/build.gradle.kts +++ b/octanegg/build.gradle.kts @@ -20,10 +20,7 @@ kotlin { sourceSets { val commonMain by getting { dependencies { - implementation(project(":core-data")) - implementation(project(":core-models")) - implementation(project(":core-datetime")) - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:${Versions.kotlinxSerialization}") implementation("io.ktor:ktor-client-core:${Versions.ktor}") implementation("io.ktor:ktor-client-json:${Versions.ktor}") implementation("io.ktor:ktor-client-logging:${Versions.ktor}") diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/OctaneGGAPIClient.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/OctaneGGAPIClient.kt index e2e81a6c7..68285ed40 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/OctaneGGAPIClient.kt +++ b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/OctaneGGAPIClient.kt @@ -1,11 +1,8 @@ package com.adammcneilly.pocketleague.data.remote.octanegg -import com.adammcneilly.pocketleague.core.data.DataResult import io.ktor.client.HttpClient import io.ktor.client.features.json.JsonFeature import io.ktor.client.features.json.serializer.KotlinxSerializer -import io.ktor.client.request.HttpRequestBuilder -import io.ktor.client.request.get import io.ktor.http.ContentType import kotlinx.serialization.json.Json @@ -25,22 +22,22 @@ class OctaneGGAPIClient { ) } } - - /** - * A helper function to wrap all of our API requests in a try/catch and return a [DataResult] - * object. - */ - suspend inline fun getResponse( - endpoint: String, - requestBuilder: HttpRequestBuilder.() -> Unit = {}, - ): DataResult { - val url = "$baseURL$endpoint" - - return try { - // KTOR will switch to a different dispatcher, so we don't need to. - DataResult.Success(httpClient.get(url, requestBuilder)) - } catch (e: Exception) { - DataResult.Error(e) - } - } +// +// /** +// * A helper function to wrap all of our API requests in a try/catch and return a [DataResult] +// * object. +// */ +// suspend inline fun getResponse( +// endpoint: String, +// requestBuilder: HttpRequestBuilder.() -> Unit = {}, +// ): DataResult { +// val url = "$baseURL$endpoint" +// +// return try { +// // KTOR will switch to a different dispatcher, so we don't need to. +// DataResult.Success(httpClient.get(url, requestBuilder)) +// } catch (e: Exception) { +// DataResult.Error(e) +// } +// } } diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/EventDTO.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/EventDTO.kt deleted file mode 100644 index e1b2dcf3f..000000000 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/EventDTO.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.dtos - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -/** - * A data class mapping to an Event from the octane.gg API. - */ -@Serializable -data class EventDTO( - @SerialName("_id") - val id: String, - val endDate: String? = null, - val image: String? = null, - val mode: Int? = null, - val name: String? = null, - val prize: PrizeDTO? = null, - val region: String? = null, - val slug: String? = null, - val stages: List? = null, - val startDate: String? = null, - val tier: String? = null, - val groups: List? = null, -) diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/EventListResponseDTO.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/EventListResponseDTO.kt deleted file mode 100644 index 6cbde88a7..000000000 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/EventListResponseDTO.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.dtos - -import kotlinx.serialization.Serializable - -/** - * A DTO that maps to an event list response from the octane.gg API. - */ -@Serializable -data class EventListResponseDTO( - val events: List, - val page: Int, - val perPage: Int, - val pageSize: Int, -) diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/StageDTO.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/StageDTO.kt deleted file mode 100644 index 3e4089121..000000000 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/StageDTO.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.dtos - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -/** - * A data class mapping to a stage from the octane.gg API. - */ -@Serializable -data class StageDTO( - @SerialName("_id") - val id: Int, - val endDate: String? = null, - val name: String? = null, - val startDate: String? = null, - val prize: PrizeDTO? = null, - val location: LocationDTO? = null, - val lan: Boolean? = null, - val liquipedia: String? = null, - val region: String? = null, -) diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/mappers/EventSummaryMapper.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/mappers/EventSummaryMapper.kt deleted file mode 100644 index 7fc3ec082..000000000 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/mappers/EventSummaryMapper.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.mappers - -import com.adammcneilly.pocketleague.core.datetime.DateTimeParser -import com.adammcneilly.pocketleague.core.models.EventSummary -import com.adammcneilly.pocketleague.data.remote.octanegg.dtos.EventDTO -import kotlinx.datetime.TimeZone - -/** - * Converts an [EventDTO] from octane.gg into an [EventSummary]. - */ -fun EventDTO.toEventSummary(): EventSummary { - return EventSummary( - id = this.id, - eventName = this.name ?: "N/A", - tournamentName = this.name ?: "N/A", - tournamentImageUrl = this.image, - startDate = DateTimeParser().parseOrToday(this.startDate), - timeZone = TimeZone.UTC, - numEntrants = null, - isOnline = false, - ) -} diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/mappers/PlayerMapper.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/mappers/PlayerMapper.kt deleted file mode 100644 index 7d0680258..000000000 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/mappers/PlayerMapper.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.mappers - -import com.adammcneilly.pocketleague.core.models.Player -import com.adammcneilly.pocketleague.data.remote.octanegg.dtos.PlayerDTO - -/** - * Converts a [PlayerDTO] from octane.gg API into a [Player] entity. - */ -fun PlayerDTO.toPlayer(): Player { - return Player( - countryCode = this.country ?: "N/A", - gamerTag = this.tag ?: "N/A", - realName = this.name ?: "N/A", - ) -} diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/mappers/TeamMapper.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/mappers/TeamMapper.kt deleted file mode 100644 index 780594a51..000000000 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/mappers/TeamMapper.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.mappers - -import com.adammcneilly.pocketleague.core.models.Team -import com.adammcneilly.pocketleague.data.remote.octanegg.dtos.PlayerDTO -import com.adammcneilly.pocketleague.data.remote.octanegg.dtos.TeamDTO - -/** - * Converts a [TeamDTO] from the octane.gg API to a [Team] entity. - */ -fun TeamDTO.toTeam(): Team { - return Team( - name = this.team?.name ?: "N/A", - lightThemeLogoImageUrl = this.team?.image, - darkThemeLogoImageUrl = this.team?.image, - roster = this.players?.map(PlayerDTO::toPlayer).orEmpty(), - ) -} diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/AccountDTO.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGAccount.kt similarity index 75% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/AccountDTO.kt rename to octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGAccount.kt index ccfaa87bf..a2575dc0c 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/AccountDTO.kt +++ b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGAccount.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.dtos +package com.adammcneilly.pocketleague.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -7,7 +7,7 @@ import kotlinx.serialization.Serializable * Represents a [PlayerDTO] account within the octane.gg API. */ @Serializable -data class AccountDTO( +data class OctaneGGAccount( @SerialName("id") val id: String? = null, @SerialName("platform") diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGEvent.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGEvent.kt new file mode 100644 index 000000000..2d79c7297 --- /dev/null +++ b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGEvent.kt @@ -0,0 +1,35 @@ +package com.adammcneilly.pocketleague.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * A data class mapping to an Event from the octane.gg API. + */ +@Serializable +data class OctaneGGEvent( + @SerialName("_id") + val id: String? = null, + @SerialName("endDate") + val endDate: String? = null, + @SerialName("image") + val image: String? = null, + @SerialName("mode") + val mode: Int? = null, + @SerialName("name") + val name: String? = null, + @SerialName("prize") + val prize: OctaneGGPrize? = null, + @SerialName("region") + val region: String? = null, + @SerialName("slug") + val slug: String? = null, + @SerialName("stages") + val stages: List? = null, + @SerialName("startDate") + val startDate: String? = null, + @SerialName("tier") + val tier: String? = null, + @SerialName("groups") + val groups: List? = null, +) diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGEventListResponse.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGEventListResponse.kt new file mode 100644 index 000000000..a0c8790c3 --- /dev/null +++ b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGEventListResponse.kt @@ -0,0 +1,19 @@ +package com.adammcneilly.pocketleague.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * A DTO that maps to an event list response from the octane.gg API. + */ +@Serializable +data class OctaneGGEventListResponse( + @SerialName("events") + val events: List? = null, + @SerialName("page") + val page: Int? = null, + @SerialName("perPage") + val perPage: Int? = null, + @SerialName("pageSize") + val pageSize: Int? = null, +) diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/LocationDTO.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGLocation.kt similarity index 51% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/LocationDTO.kt rename to octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGLocation.kt index 6ccc62d4b..13aeb5857 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/LocationDTO.kt +++ b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGLocation.kt @@ -1,13 +1,17 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.dtos +package com.adammcneilly.pocketleague.data.remote.octanegg.models +import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable /** * A data class mapping to a location from the octane.gg API. */ @Serializable -data class LocationDTO( +data class OctaneGGLocation( + @SerialName("city") val city: String? = null, + @SerialName("country") val country: String? = null, + @SerialName("venue") val venue: String? = null, ) diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/PlayerDTO.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGPlayer.kt similarity index 78% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/PlayerDTO.kt rename to octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGPlayer.kt index 869df60aa..86aa4091f 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/PlayerDTO.kt +++ b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGPlayer.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.dtos +package com.adammcneilly.pocketleague.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -7,9 +7,9 @@ import kotlinx.serialization.Serializable * Represents a person who is a player for a [TeamDTO] in the octane.gg API. */ @Serializable -data class PlayerDTO( +data class OctaneGGPlayer( @SerialName("accounts") - val accounts: List? = null, + val accounts: List? = null, @SerialName("coach") val coach: Boolean? = null, @SerialName("country") @@ -27,5 +27,5 @@ data class PlayerDTO( @SerialName("tag") val tag: String? = null, @SerialName("team") - val team: TeamOverviewDTO? = null, + val team: OctaneGGTeamOverview? = null, ) diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/PrizeDTO.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGPrize.kt similarity index 51% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/PrizeDTO.kt rename to octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGPrize.kt index 0aef283c3..9033c414b 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/PrizeDTO.kt +++ b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGPrize.kt @@ -1,12 +1,15 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.dtos +package com.adammcneilly.pocketleague.data.remote.octanegg.models +import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable /** * A data class mapping to a prize entity from the octane.gg API. */ @Serializable -data class PrizeDTO( +data class OctaneGGPrize( + @SerialName("amount") val amount: Double? = null, + @SerialName("currency") val currency: String? = null, ) diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGStage.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGStage.kt new file mode 100644 index 000000000..0a00a4167 --- /dev/null +++ b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGStage.kt @@ -0,0 +1,29 @@ +package com.adammcneilly.pocketleague.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * A data class mapping to a stage from the octane.gg API. + */ +@Serializable +data class OctaneGGStage( + @SerialName("_id") + val id: Int? = null, + @SerialName("endDate") + val endDate: String? = null, + @SerialName("name") + val name: String? = null, + @SerialName("startDate") + val startDate: String? = null, + @SerialName("prize") + val prize: OctaneGGPrize? = null, + @SerialName("location") + val location: OctaneGGLocation? = null, + @SerialName("lan") + val lan: Boolean? = null, + @SerialName("liquipedia") + val liquipedia: String? = null, + @SerialName("region") + val region: String? = null, +) diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/TeamDTO.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamDetail.kt similarity index 53% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/TeamDTO.kt rename to octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamDetail.kt index d080aa38d..4b0ec87d5 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/TeamDTO.kt +++ b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamDetail.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.dtos +package com.adammcneilly.pocketleague.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -7,9 +7,9 @@ import kotlinx.serialization.Serializable * Represents a team within the octane.gg API domain. */ @Serializable -data class TeamDTO( +data class OctaneGGTeamDetail( @SerialName("players") - val players: List? = null, + val players: List? = null, @SerialName("team") - val team: TeamOverviewDTO? = null, + val team: OctaneGGTeamOverview? = null, ) diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/TeamListResponseDTO.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamListResponse.kt similarity index 70% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/TeamListResponseDTO.kt rename to octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamListResponse.kt index 8d654aa1b..aed313d5f 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/TeamListResponseDTO.kt +++ b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamListResponse.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.dtos +package com.adammcneilly.pocketleague.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -7,9 +7,9 @@ import kotlinx.serialization.Serializable * A data response for a list of teams within the octane.gg API. */ @Serializable -data class TeamListResponseDTO( +data class OctaneGGTeamListResponse( @SerialName("teams") - val teams: List? = null, + val teams: List? = null, @SerialName("page") val page: Int? = null, @SerialName("perPage") diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/TeamOverviewDTO.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamOverview.kt similarity index 83% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/TeamOverviewDTO.kt rename to octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamOverview.kt index faa992ae6..034da6f76 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/dtos/TeamOverviewDTO.kt +++ b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamOverview.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.dtos +package com.adammcneilly.pocketleague.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -7,7 +7,7 @@ import kotlinx.serialization.Serializable * Overview information about a team, that does not include roster info. */ @Serializable -data class TeamOverviewDTO( +data class OctaneGGTeamOverview( @SerialName("_id") val id: String? = null, @SerialName("image") diff --git a/settings.gradle b/settings.gradle index 8e0c7ed01..5b203d93f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,3 +2,4 @@ rootProject.name = "PocketLeague" include ':app' include ':android-design-system' +include ':octanegg' From a24e2ed2540d7631411937efafa6cea9f45f2fed Mon Sep 17 00:00:00 2001 From: amcneilly Date: Fri, 15 Apr 2022 16:53:50 -0400 Subject: [PATCH 03/40] Moving into shared module. --- .gitignore | 2 +- octanegg/src/androidMain/AndroidManifest.xml | 2 - .../data/remote/octanegg/OctaneGGAPIClient.kt | 43 ----------------- settings.gradle | 2 +- {octanegg => shared}/build.gradle.kts | 6 +-- shared/src/androidMain/AndroidManifest.xml | 2 + .../pocketleague/shared/data/DataResult.kt | 21 +++++++++ .../data/remote/octanegg/OctaneGGAPIClient.kt | 46 +++++++++++++++++++ .../data/remote/octanegg/OctaneGGEndpoints.kt | 8 ++++ .../octanegg/mappers/OctaneGGEventMapper.kt | 14 ++++++ .../remote/octanegg/models/OctaneGGAccount.kt | 2 +- .../remote/octanegg/models/OctaneGGEvent.kt | 2 +- .../models/OctaneGGEventListResponse.kt | 2 +- .../octanegg/models/OctaneGGLocation.kt | 2 +- .../remote/octanegg/models/OctaneGGPlayer.kt | 2 +- .../remote/octanegg/models/OctaneGGPrize.kt | 2 +- .../remote/octanegg/models/OctaneGGStage.kt | 2 +- .../octanegg/models/OctaneGGTeamDetail.kt | 2 +- .../models/OctaneGGTeamListResponse.kt | 2 +- .../octanegg/models/OctaneGGTeamOverview.kt | 2 +- .../octanegg/services/OctaneGGEventService.kt | 40 ++++++++++++++++ .../data/repositories/EventRepository.kt | 17 +++++++ .../pocketleague/shared/models/Event.kt | 13 ++++++ 23 files changed, 176 insertions(+), 60 deletions(-) delete mode 100644 octanegg/src/androidMain/AndroidManifest.xml delete mode 100644 octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/OctaneGGAPIClient.kt rename {octanegg => shared}/build.gradle.kts (98%) create mode 100644 shared/src/androidMain/AndroidManifest.xml create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/DataResult.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGAPIClient.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGEndpoints.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGEventMapper.kt rename {octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague => shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared}/data/remote/octanegg/models/OctaneGGAccount.kt (80%) rename {octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague => shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared}/data/remote/octanegg/models/OctaneGGEvent.kt (92%) rename {octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague => shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared}/data/remote/octanegg/models/OctaneGGEventListResponse.kt (86%) rename {octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague => shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared}/data/remote/octanegg/models/OctaneGGLocation.kt (83%) rename {octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague => shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared}/data/remote/octanegg/models/OctaneGGPlayer.kt (91%) rename {octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague => shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared}/data/remote/octanegg/models/OctaneGGPrize.kt (81%) rename {octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague => shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared}/data/remote/octanegg/models/OctaneGGStage.kt (90%) rename {octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague => shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared}/data/remote/octanegg/models/OctaneGGTeamDetail.kt (82%) rename {octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague => shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared}/data/remote/octanegg/models/OctaneGGTeamListResponse.kt (86%) rename {octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague => shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared}/data/remote/octanegg/models/OctaneGGTeamOverview.kt (88%) create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/EventRepository.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt diff --git a/.gitignore b/.gitignore index 730942f7f..05c88ece3 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,5 @@ .cxx local.properties /buildSrc/build/ -/octanegg/build/ +/shared/build/ /app/src/main/graphql/com/adammcneilly/pocketleague/.graphqlconfig diff --git a/octanegg/src/androidMain/AndroidManifest.xml b/octanegg/src/androidMain/AndroidManifest.xml deleted file mode 100644 index 5377c4ce1..000000000 --- a/octanegg/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/OctaneGGAPIClient.kt b/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/OctaneGGAPIClient.kt deleted file mode 100644 index 68285ed40..000000000 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/OctaneGGAPIClient.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg - -import io.ktor.client.HttpClient -import io.ktor.client.features.json.JsonFeature -import io.ktor.client.features.json.serializer.KotlinxSerializer -import io.ktor.http.ContentType -import kotlinx.serialization.json.Json - -/** - * Defines the API client information for communicating with the octane.gg API. - */ -class OctaneGGAPIClient { - val baseURL = "https://zsr.octane.gg/" - - val httpClient = HttpClient { - install(JsonFeature) { - serializer = KotlinxSerializer( - Json { - ignoreUnknownKeys = true - acceptContentTypes = acceptContentTypes + ContentType.Any - } - ) - } - } -// -// /** -// * A helper function to wrap all of our API requests in a try/catch and return a [DataResult] -// * object. -// */ -// suspend inline fun getResponse( -// endpoint: String, -// requestBuilder: HttpRequestBuilder.() -> Unit = {}, -// ): DataResult { -// val url = "$baseURL$endpoint" -// -// return try { -// // KTOR will switch to a different dispatcher, so we don't need to. -// DataResult.Success(httpClient.get(url, requestBuilder)) -// } catch (e: Exception) { -// DataResult.Error(e) -// } -// } -} diff --git a/settings.gradle b/settings.gradle index 5b203d93f..6945a5f6b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,4 +2,4 @@ rootProject.name = "PocketLeague" include ':app' include ':android-design-system' -include ':octanegg' +include ':shared' diff --git a/octanegg/build.gradle.kts b/shared/build.gradle.kts similarity index 98% rename from octanegg/build.gradle.kts rename to shared/build.gradle.kts index 909990f96..fd6dca0f6 100644 --- a/octanegg/build.gradle.kts +++ b/shared/build.gradle.kts @@ -6,14 +6,14 @@ plugins { kotlin { android() - + listOf( iosX64(), iosArm64(), iosSimulatorArm64() ).forEach { it.binaries.framework { - baseName = "octanegg" + baseName = "shared" } } @@ -70,4 +70,4 @@ android { minSdk = AndroidConfig.minSDK targetSdk = AndroidConfig.targetSDK } -} +} \ No newline at end of file diff --git a/shared/src/androidMain/AndroidManifest.xml b/shared/src/androidMain/AndroidManifest.xml new file mode 100644 index 000000000..df7238178 --- /dev/null +++ b/shared/src/androidMain/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/DataResult.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/DataResult.kt new file mode 100644 index 000000000..689b3082f --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/DataResult.kt @@ -0,0 +1,21 @@ +package com.adammcneilly.pocketleague.shared.data + +/** + * This is a sealed class that represents two options for a data response, where the response is + * either successful or a failure. + * + * By wrapping a response into this single type, we can provide a way for asynchronous streams to + * handle both success and failure scenarios, without having to catch exceptions. This is because any + * exceptions will be wrapped inside an [Error] class. + */ +sealed class DataResult { + /** + * A successful result which implies we will have some [data] returned. + */ + data class Success(val data: T) : DataResult() + + /** + * An unsuccessful result because some [error] occurred. + */ + data class Error(val error: Throwable) : DataResult() +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGAPIClient.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGAPIClient.kt new file mode 100644 index 000000000..ae634986d --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGAPIClient.kt @@ -0,0 +1,46 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg + +import com.adammcneilly.pocketleague.shared.data.DataResult +import io.ktor.client.HttpClient +import io.ktor.client.features.json.JsonFeature +import io.ktor.client.features.json.serializer.KotlinxSerializer +import io.ktor.client.request.HttpRequestBuilder +import io.ktor.client.request.get +import io.ktor.http.ContentType +import kotlinx.serialization.json.Json + +/** + * Defines the API client information for communicating with the octane.gg API. + */ +class OctaneGGAPIClient { + val baseURL = "https://zsr.octane.gg/" + + val httpClient = HttpClient { + install(JsonFeature) { + serializer = KotlinxSerializer( + Json { + ignoreUnknownKeys = true + acceptContentTypes = acceptContentTypes + ContentType.Any + } + ) + } + } + + /** + * A helper function to build the [baseURL] and [endpoint] operation and performs a get request. + * Will also pass in the supplied [requestBuilder] as necessary. + */ + suspend inline fun getResponse( + endpoint: String, + requestBuilder: HttpRequestBuilder.() -> Unit = {}, + ): DataResult { + val url = "$baseURL$endpoint" + + return try { + val apiResult: T = httpClient.get(url, requestBuilder) + DataResult.Success(apiResult) + } catch (e: Exception) { + DataResult.Error(e) + } + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGEndpoints.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGEndpoints.kt new file mode 100644 index 000000000..c3d8c4a63 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGEndpoints.kt @@ -0,0 +1,8 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg + +/** + * Defines all the statis endpoints for various octane.gg domains. + */ +object OctaneGGEndpoints { + const val EVENTS = "/events" +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGEventMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGEventMapper.kt new file mode 100644 index 000000000..286f0d1a4 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGEventMapper.kt @@ -0,0 +1,14 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.mappers + +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGEvent +import com.adammcneilly.pocketleague.shared.models.Event + +/** + * Converts an [OctaneGGEvent] entity into an [Event] within the Pocket League domain. + */ +fun OctaneGGEvent.toEvent(): Event { + return Event( + id = this.id ?: "ID Not Available", + name = this.name ?: "Name Not Available", + ) +} diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGAccount.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGAccount.kt similarity index 80% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGAccount.kt rename to shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGAccount.kt index a2575dc0c..27e3a90b7 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGAccount.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGAccount.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.models +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGEvent.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGEvent.kt similarity index 92% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGEvent.kt rename to shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGEvent.kt index 2d79c7297..35809d8a9 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGEvent.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGEvent.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.models +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGEventListResponse.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGEventListResponse.kt similarity index 86% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGEventListResponse.kt rename to shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGEventListResponse.kt index a0c8790c3..04c95895c 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGEventListResponse.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGEventListResponse.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.models +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGLocation.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGLocation.kt similarity index 83% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGLocation.kt rename to shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGLocation.kt index 13aeb5857..fa8dc8f68 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGLocation.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGLocation.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.models +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGPlayer.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPlayer.kt similarity index 91% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGPlayer.kt rename to shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPlayer.kt index 86aa4091f..21429c09a 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGPlayer.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPlayer.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.models +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGPrize.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPrize.kt similarity index 81% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGPrize.kt rename to shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPrize.kt index 9033c414b..dd72ad97b 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGPrize.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPrize.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.models +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGStage.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStage.kt similarity index 90% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGStage.kt rename to shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStage.kt index 0a00a4167..84b0bb0fe 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGStage.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStage.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.models +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamDetail.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamDetail.kt similarity index 82% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamDetail.kt rename to shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamDetail.kt index 4b0ec87d5..573e06b78 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamDetail.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamDetail.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.models +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamListResponse.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamListResponse.kt similarity index 86% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamListResponse.kt rename to shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamListResponse.kt index aed313d5f..f47f6fba7 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamListResponse.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamListResponse.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.models +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamOverview.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamOverview.kt similarity index 88% rename from octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamOverview.kt rename to shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamOverview.kt index 034da6f76..ded29fcd7 100644 --- a/octanegg/src/commonMain/kotlin/com/adammcneilly/pocketleague/data/remote/octanegg/models/OctaneGGTeamOverview.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamOverview.kt @@ -1,4 +1,4 @@ -package com.adammcneilly.pocketleague.data.remote.octanegg.models +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt new file mode 100644 index 000000000..01b429170 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt @@ -0,0 +1,40 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.services + +import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGAPIClient +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGEndpoints +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.mappers.toEvent +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGEvent +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGEventListResponse +import com.adammcneilly.pocketleague.shared.data.repositories.EventRepository +import com.adammcneilly.pocketleague.shared.models.Event +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow + +/** + * A concrete implementation of an [EventRepository] that will request data using the supplied [apiClient]. + */ +class OctaneGGEventService( + private val apiClient: OctaneGGAPIClient, +) : EventRepository { + + override fun fetchEvents(): Flow>> { + return flow { + val apiResult = apiClient.getResponse( + endpoint = OctaneGGEndpoints.EVENTS, + ) + + val mappedResult = when (apiResult) { + is DataResult.Success -> { + val mappedEvents = apiResult.data.events?.map(OctaneGGEvent::toEvent).orEmpty() + DataResult.Success(mappedEvents) + } + is DataResult.Error -> { + DataResult.Error(apiResult.error) + } + } + + emit(mappedResult) + } + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/EventRepository.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/EventRepository.kt new file mode 100644 index 000000000..f7fc77101 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/EventRepository.kt @@ -0,0 +1,17 @@ +package com.adammcneilly.pocketleague.shared.data.repositories + +import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.models.Event +import kotlinx.coroutines.flow.Flow + +/** + * Defines the data contract for dealing with data within the event space. + */ +interface EventRepository { + /** + * Returns a stream of [Event] entities inside of a list. In the future, we'll + * modify this to consume a request & intend to return events that meet certain + * conditions. + */ + fun fetchEvents(): Flow>> +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt new file mode 100644 index 000000000..a2d2cbf44 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt @@ -0,0 +1,13 @@ +package com.adammcneilly.pocketleague.shared.models + +/** + * Defines any Rocket League event that can occur to allow a number of teams or players + * to compete. + * + * @property[id] A unique identifier for this event. + * @property[name] The description of this event, such as "RLCS Winter Split Regional 1". + */ +data class Event( + val id: String, + val name: String, +) From 59db04e7f521f832f3315eae8e3b752a952a5cae Mon Sep 17 00:00:00 2001 From: amcneilly Date: Sat, 16 Apr 2022 14:41:03 -0400 Subject: [PATCH 04/40] Adding request body, adding use case for upcoming events. --- shared/build.gradle.kts | 11 +++++- .../shared/datetime/DateTimeFormatter.kt | 23 +++++++++++ .../shared/data/models/EventListRequest.kt | 15 ++++++++ .../octanegg/services/OctaneGGEventService.kt | 34 ++++++++++++++++- .../data/repositories/EventRepository.kt | 10 +++-- .../shared/datetime/DateTimeFormatter.kt | 19 ++++++++++ .../eventlist/GetUpcomingEventsUseCase.kt | 34 +++++++++++++++++ .../eventlist/GetUpcomingEventsUseCaseImpl.kt | 38 +++++++++++++++++++ .../shared/datetime/DateTimeFormatter.kt | 31 +++++++++++++++ 9 files changed, 208 insertions(+), 7 deletions(-) create mode 100644 shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/datetime/DateTimeFormatter.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/models/EventListRequest.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/datetime/DateTimeFormatter.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCase.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCaseImpl.kt create mode 100644 shared/src/iosMain/kotlin/com/adammcneilly/pocketleague/shared/datetime/DateTimeFormatter.kt diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index fd6dca0f6..19f948685 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -6,7 +6,7 @@ plugins { kotlin { android() - + listOf( iosX64(), iosArm64(), @@ -20,6 +20,7 @@ kotlin { sourceSets { val commonMain by getting { dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-datetime:${Versions.kotlinxDatetime}") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:${Versions.kotlinxSerialization}") implementation("io.ktor:ktor-client-core:${Versions.ktor}") implementation("io.ktor:ktor-client-json:${Versions.ktor}") @@ -70,4 +71,10 @@ android { minSdk = AndroidConfig.minSDK targetSdk = AndroidConfig.targetSDK } -} \ No newline at end of file + + compileOptions { + sourceCompatibility(JavaVersion.VERSION_1_8) + targetCompatibility(JavaVersion.VERSION_1_8) + isCoreLibraryDesugaringEnabled = true + } +} diff --git a/shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/datetime/DateTimeFormatter.kt b/shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/datetime/DateTimeFormatter.kt new file mode 100644 index 000000000..7e55107be --- /dev/null +++ b/shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/datetime/DateTimeFormatter.kt @@ -0,0 +1,23 @@ +package com.adammcneilly.pocketleague.shared.datetime + +import kotlinx.datetime.LocalDateTime +import kotlinx.datetime.toJavaLocalDateTime +import java.time.format.DateTimeFormatter + +/** + * See commonMain documentation. + */ +actual class DateTimeFormatter actual constructor() { + + /** + * See commonMain documentation. + */ + actual fun formatLocalDateTime( + localDateTime: LocalDateTime, + formatPattern: String, + ): String? { + val dateTimeFormatter = DateTimeFormatter.ofPattern(formatPattern) + + return localDateTime.toJavaLocalDateTime().format(dateTimeFormatter) + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/models/EventListRequest.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/models/EventListRequest.kt new file mode 100644 index 000000000..70943cc7b --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/models/EventListRequest.kt @@ -0,0 +1,15 @@ +package com.adammcneilly.pocketleague.shared.data.models + +import kotlinx.datetime.LocalDateTime + +/** + * Defines all of the information that will be passed into a request for a list of events. + * + * If the information is null, it won't be used to filter a response at all. + */ +data class EventListRequest( + val group: String? = null, + val tiers: List? = null, + val after: LocalDateTime? = null, + val before: LocalDateTime? = null, +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt index 01b429170..4b35f9c5e 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt @@ -1,13 +1,17 @@ package com.adammcneilly.pocketleague.shared.data.remote.octanegg.services import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.data.models.EventListRequest import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGAPIClient import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGEndpoints import com.adammcneilly.pocketleague.shared.data.remote.octanegg.mappers.toEvent import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGEvent import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGEventListResponse import com.adammcneilly.pocketleague.shared.data.repositories.EventRepository +import com.adammcneilly.pocketleague.shared.datetime.DateTimeFormatter import com.adammcneilly.pocketleague.shared.models.Event +import io.ktor.client.request.HttpRequestBuilder +import io.ktor.client.request.parameter import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow @@ -18,10 +22,15 @@ class OctaneGGEventService( private val apiClient: OctaneGGAPIClient, ) : EventRepository { - override fun fetchEvents(): Flow>> { + override fun fetchEvents( + request: EventListRequest, + ): Flow>> { return flow { val apiResult = apiClient.getResponse( endpoint = OctaneGGEndpoints.EVENTS, + requestBuilder = { + addEventParameters(request) + }, ) val mappedResult = when (apiResult) { @@ -38,3 +47,26 @@ class OctaneGGEventService( } } } + +private fun HttpRequestBuilder.addEventParameters(request: EventListRequest) { + val dateTimeFormatter = DateTimeFormatter() + val octaneGGDateFormat = "yyyy-mm-dd" + + if (request.group != null) { + this.parameter("group", request.group) + } + + if (request.tiers != null) { + this.parameter("tier", request.tiers) + } + + if (request.after != null) { + val afterString = dateTimeFormatter.formatLocalDateTime(request.after, octaneGGDateFormat) + this.parameter("after", afterString) + } + + if (request.before != null) { + val beforeString = dateTimeFormatter.formatLocalDateTime(request.before, octaneGGDateFormat) + this.parameter("before", beforeString) + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/EventRepository.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/EventRepository.kt index f7fc77101..2e2086788 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/EventRepository.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/EventRepository.kt @@ -1,6 +1,7 @@ package com.adammcneilly.pocketleague.shared.data.repositories import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.data.models.EventListRequest import com.adammcneilly.pocketleague.shared.models.Event import kotlinx.coroutines.flow.Flow @@ -9,9 +10,10 @@ import kotlinx.coroutines.flow.Flow */ interface EventRepository { /** - * Returns a stream of [Event] entities inside of a list. In the future, we'll - * modify this to consume a request & intend to return events that meet certain - * conditions. + * Returns a stream of [Event] entities as a list. We should only return events that meet + * the criteria defined by the given [request]. */ - fun fetchEvents(): Flow>> + fun fetchEvents( + request: EventListRequest, + ): Flow>> } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/datetime/DateTimeFormatter.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/datetime/DateTimeFormatter.kt new file mode 100644 index 000000000..46122ca9b --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/datetime/DateTimeFormatter.kt @@ -0,0 +1,19 @@ +package com.adammcneilly.pocketleague.shared.datetime + +import kotlinx.datetime.LocalDateTime + +/** + * A shared class between platforms that is used to format a date into a user friendly string. + */ +expect class DateTimeFormatter constructor() { + + /** + * Given a [localDateTime], apply the [formatPattern] to it to convert it into a user readable string. + * + * @return The user friendly string for the [localDateTime], or null if unable to parse correctly. + */ + fun formatLocalDateTime( + localDateTime: LocalDateTime, + formatPattern: String, + ): String? +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCase.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCase.kt new file mode 100644 index 000000000..0a0f259c4 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCase.kt @@ -0,0 +1,34 @@ +package com.adammcneilly.pocketleague.shared.eventlist + +import com.adammcneilly.pocketleague.shared.models.Event +import kotlinx.coroutines.flow.Flow + +/** + * Fetches a list of upcoming [Event] entities. This is not specific to any season, group, tier, etc. + */ +interface GetUpcomingEventsUseCase { + + /** + * @see [GetUpcomingEventsUseCase]. + */ + operator fun invoke(): Flow + + /** + * Defines all possible result types for a [GetUpcomingEventsUseCase]. + */ + sealed class Result { + /** + * This will be returned if we can successfully request upcoming [events]. + */ + data class Success( + val events: List, + ) : Result() + + /** + * Should any [error] occur while requesting upcoming events, this will be returned. + */ + data class Error( + val error: Throwable, + ) : Result() + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCaseImpl.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCaseImpl.kt new file mode 100644 index 000000000..5d3dbadeb --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCaseImpl.kt @@ -0,0 +1,38 @@ +package com.adammcneilly.pocketleague.shared.eventlist + +import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.data.models.EventListRequest +import com.adammcneilly.pocketleague.shared.data.repositories.EventRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import kotlinx.datetime.Clock +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toLocalDateTime + +/** + * A concrete implementation of [GetUpcomingEventsUseCase] that will return information from + * the supplied [repository]. + */ +class GetUpcomingEventsUseCaseImpl( + private val repository: EventRepository, +) : GetUpcomingEventsUseCase { + + override fun invoke(): Flow { + val today = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()) + + val request = EventListRequest( + after = today, + ) + + return repository.fetchEvents(request).map { repoResult -> + when (repoResult) { + is DataResult.Success -> { + GetUpcomingEventsUseCase.Result.Success(repoResult.data) + } + is DataResult.Error -> { + GetUpcomingEventsUseCase.Result.Error(repoResult.error) + } + } + } + } +} diff --git a/shared/src/iosMain/kotlin/com/adammcneilly/pocketleague/shared/datetime/DateTimeFormatter.kt b/shared/src/iosMain/kotlin/com/adammcneilly/pocketleague/shared/datetime/DateTimeFormatter.kt new file mode 100644 index 000000000..aaf61b7bd --- /dev/null +++ b/shared/src/iosMain/kotlin/com/adammcneilly/pocketleague/shared/datetime/DateTimeFormatter.kt @@ -0,0 +1,31 @@ +package com.adammcneilly.pocketleague.shared.datetime + +import kotlinx.datetime.LocalDateTime +import kotlinx.datetime.toNSDateComponents +import platform.Foundation.NSCalendar +import platform.Foundation.NSDateFormatter + +/** + * See commonMain documentation. + */ +actual class DateTimeFormatter actual constructor() { + + /** + * See commonMain documentation. + */ + actual fun formatLocalDateTime( + localDateTime: LocalDateTime, + formatPattern: String, + ): String? { + val nsComponents = localDateTime.toNSDateComponents() + val nsDate = NSCalendar.currentCalendar.dateFromComponents(nsComponents) + + val formatter = NSDateFormatter().apply { + dateFormat = formatPattern + } + + return nsDate?.let { date -> + formatter.stringFromDate(date) + } + } +} From b44e3eb7f7957b048e73c3ae31d36314203f2f8a Mon Sep 17 00:00:00 2001 From: amcneilly Date: Sat, 16 Apr 2022 16:12:50 -0400 Subject: [PATCH 05/40] Adding all of the DKMP logic. --- .../shared/screens/DKMPViewModelForAndroid.kt | 8 + .../pocketleague/shared/screens/AppState.kt | 13 + .../shared/screens/DKMPViewModel.kt | 21 ++ .../shared/screens/Level1Navigation.kt | 15 + .../pocketleague/shared/screens/Navigation.kt | 153 ++++++++ .../shared/screens/NavigationSettings.kt | 10 + .../shared/screens/ScreenIdentifier.kt | 106 ++++++ .../shared/screens/ScreenInitSettings.kt | 24 ++ .../shared/screens/ScreenParams.kt | 7 + .../shared/screens/ScreenState.kt | 6 + .../pocketleague/shared/screens/Screens.kt | 32 ++ .../shared/screens/StateManager.kt | 355 ++++++++++++++++++ .../shared/screens/feed/FeedInitSettings.kt | 20 + .../shared/screens/feed/FeedState.kt | 12 + 14 files changed, 782 insertions(+) create mode 100644 shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModelForAndroid.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/AppState.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModel.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Level1Navigation.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/NavigationSettings.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenIdentifier.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenInitSettings.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenParams.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenState.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedState.kt diff --git a/shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModelForAndroid.kt b/shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModelForAndroid.kt new file mode 100644 index 000000000..6502daae5 --- /dev/null +++ b/shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModelForAndroid.kt @@ -0,0 +1,8 @@ +package com.adammcneilly.pocketleague.shared.screens + +/** + * Creates an instance of a [DKMPViewModel] to be used within an Android application. + */ +fun DKMPViewModel.Factory.getAndroidInstance(): DKMPViewModel { + return DKMPViewModel() +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/AppState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/AppState.kt new file mode 100644 index 000000000..e1966ad6a --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/AppState.kt @@ -0,0 +1,13 @@ +package com.adammcneilly.pocketleague.shared.screens + +/** + * Defines the overall state of our application. We just track the [recompositionIndex] and we can + * modify this any time we want our application to be recomposed. + */ +data class AppState( + val recompositionIndex: Int = 0, +) { + fun getNavigation(model: DKMPViewModel): Navigation { + return model.navigation + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModel.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModel.kt new file mode 100644 index 000000000..a7fedb70f --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModel.kt @@ -0,0 +1,21 @@ +package com.adammcneilly.pocketleague.shared.screens + +import kotlinx.coroutines.flow.StateFlow + +/** + * Root view model for the application that exposes a [stateFlow] of our application's state. + */ +class DKMPViewModel { + + private val stateManager by lazy { StateManager() } + + val stateFlow: StateFlow + get() = stateManager.mutableStateFlow + + val navigation by lazy { Navigation(stateManager) } + + /** + * Factory methods are defined in the platform-specific domains. + */ + companion object Factory +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Level1Navigation.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Level1Navigation.kt new file mode 100644 index 000000000..7382b01e7 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Level1Navigation.kt @@ -0,0 +1,15 @@ +package com.adammcneilly.pocketleague.shared.screens + +/** + * Defines a collection of [screenIdentifier] entities that will show up as our level 1 navigation options. + * + * In the application, this basically maps to the tabs that appear on the bottom menu. + */ +enum class Level1Navigation( + val screenIdentifier: ScreenIdentifier, + val rememberVerticalStack: Boolean = false, +) { + Feed( + screenIdentifier = ScreenIdentifier.get(screen = Screen.Feed, params = null), + ), +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt new file mode 100644 index 000000000..37f339a7a --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt @@ -0,0 +1,153 @@ +package com.adammcneilly.pocketleague.shared.screens + +/** + * This class manages all of the navigation logic within the pocket league app. + */ +class Navigation( + val stateManager: StateManager, +) { + // val stateProvider by lazy { StateProvider(stateManager) } + // val events by lazy { Events(stateManager) } + // val dataRepository = stateManager.dataRepository + + init { + val startScreenIdentifier = NavigationSettings.homeScreen.screenIdentifier + navigateByScreenIdentifier(startScreenIdentifier) + } + + /** + * Returns the user friendly title for the given [screenIdentifier]. + */ + fun getTitle(screenIdentifier: ScreenIdentifier): String { + val screenInitSettings = screenIdentifier.getScreenInitSettings(this) + return screenInitSettings.title + } + + /** + * Pulls the [ScreenIdentifier] for the current screen from our [stateManager]. + */ + val currentScreenIdentifier: ScreenIdentifier + get() = stateManager.currentScreenIdentifier + + /** + * Gets the [ScreenIdentifier] of the currently selected tab from our [stateManager]. + */ + val currentLevel1ScreenIdentifier: ScreenIdentifier + get() = stateManager.currentLevel1ScreenIdentifier + + /** + * Determines if there is only 1 screen within our backstacks. + */ + val only1ScreenInBackstack: Boolean + get() = stateManager.only1ScreenInBackstack + + /** + * This is used by the router in compose apps, so we can remove screens from compose's + * SaveableStateHolder. + */ + val screenStatesToRemove: List + get() = stateManager.getScreenStatesToRemove() + + /** + * This is used by SwiftUI apps to get the list of level1 screens to add to a SwiftUI's + * ZStack. + */ + val level1ScreenIdentifiers: List + get() = stateManager.getLevel1ScreenIdentifiers() + + /** + * Gets the vertical navigation levels for a given [level1ScreenIdentifier]. + */ + fun getNavigationLevelsMap(level1ScreenIdentifier: ScreenIdentifier): Map? { + return stateManager.verticalNavigationLevels[level1ScreenIdentifier.uri] + } + + /** + * Determines if the given [screenIdentifier] is inside our current vertical stack. + */ + fun isInCurrentVerticalBackstack(screenIdentifier: ScreenIdentifier): Boolean { + stateManager.currentVerticalBackstack.forEach { + if (it.uri == screenIdentifier.uri) { + return true + } + } + + return false + } + + /** + * Navigates to a given [screen] with the provides [params]. + */ + fun navigate(screen: Screen, params: ScreenParams? = null) { + navigateByScreenIdentifier(ScreenIdentifier.get(screen, params)) + } + + /** + * Navigate to a different level 1 menu item. + */ + fun navigateByLevel1Menu(level1NavigationItem: Level1Navigation) { + val navigationLevelsMap = getNavigationLevelsMap(level1NavigationItem.screenIdentifier) + + if (navigationLevelsMap == null) { + navigateByScreenIdentifier(level1NavigationItem.screenIdentifier) + } else { + navigationLevelsMap.keys.sorted().forEach { + navigateByScreenIdentifier(navigationLevelsMap[it]!!) + } + } + } + + /** + * Navigate to a screen using the given [screenIdentifier]. + */ + fun navigateByScreenIdentifier(screenIdentifier: ScreenIdentifier) { + val screenInitSettings = screenIdentifier.getScreenInitSettings(this) + stateManager.addScreen(screenIdentifier, screenInitSettings) + + if (NavigationSettings.saveLastLevel1Screen && screenIdentifier.screen.navigationLevel == 1) { + // Saving screen coming soon + } + } + + /** + * Exit the screen with the given [screenIdentifier] or the current screen if this is null. + */ + fun exitScreen(screenIdentifier: ScreenIdentifier? = null, triggerRecomposition: Boolean = true) { + val screenId = screenIdentifier ?: currentScreenIdentifier + + stateManager.removeScreen(screenId) + + if (triggerRecomposition) { + navigateByScreenIdentifier(currentScreenIdentifier) + } + } + + /** + * This is not called at app startup, but only when reentering the app after it was in the background. + */ + fun onReEnterForeground() { + val reInitializedScreens = stateManager.reInitScreenScopes() + stateManager.triggerRecomposition() + reInitializedScreens.forEach { + it.getScreenInitSettings(this).apply { + if (callOnInitAlsoAfterBackground) { + stateManager.runInScreenScope { callOnInit(stateManager) } + } + } + } + } + + /** + * Cancel any screen scopes when we enter the background. + */ + fun onEnterBackground() { + stateManager.cancelScreenScopes() + } + + /** + * If the user changes device orientation we should recompose our application. + */ + fun onChangeOrientation() { + stateManager.triggerRecomposition() + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/NavigationSettings.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/NavigationSettings.kt new file mode 100644 index 000000000..6d7b57c7c --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/NavigationSettings.kt @@ -0,0 +1,10 @@ +package com.adammcneilly.pocketleague.shared.screens + +/** + * Defines some settings to be used to manage navigation within this application. + */ +object NavigationSettings { + val homeScreen = Level1Navigation.Feed + const val saveLastLevel1Screen = true + const val alwaysQuitOnHomeScreen = true +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenIdentifier.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenIdentifier.kt new file mode 100644 index 000000000..af857bd94 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenIdentifier.kt @@ -0,0 +1,106 @@ +package com.adammcneilly.pocketleague.shared.screens + +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json + +/** + * This defines a unique identifier for a [screen] within the app. This is different from [Screen] + * because the underlying UI might be identical, but the [params] could be different and as such + * should be treated as a new identifier. + */ +class ScreenIdentifier private constructor( + val screen: Screen, + var params: ScreenParams? = null, + val paramsAsString: String? = null, +) { + /** + * Builds a string that represents a unique URI for this [screen] and its [params]. + */ + val uri: String + get() = returnURI() + + private fun returnURI(): String { + if (paramsAsString != null) { + return screen.asString + ":" + paramsAsString + } + + // Returns ClassParams(A=1&B=2) + val toString = params.toString() + + val startIndex = toString.indexOf("(") + + val paramsString = toString.substring(startIndex + 1, toString.length - 1) + + return screen.asString + ":" + paramsString + } + + /** + * Unlike the [params] property, this reified function returns the specific type of params and + * not the generic [ScreenParams] interface type. + */ + inline fun params(): T { + if (params == null && paramsAsString != null) { + val jsonValues = paramsStrToJson(paramsAsString) + params = Json.decodeFromString(jsonValues) + } + + return params as T + } + + /** + * Converts the [paramsAsString] into a JSON string. + */ + fun paramsStrToJson(paramsAsString: String): String { + // Converts `A=1&B=2` into `"A":"1","B":"2"` + val elements = paramsAsString.split("&") + var jsonValues = "" + elements.forEach { + if (jsonValues != "") { + jsonValues += "," + } + + val parts = it.split("=") + jsonValues += "\"${parts[0]}\":\"${parts[1]}\"" + } + + return jsonValues + } + + /** + * Given some [navigation], get the [ScreenInitSettings] for this identifier. + */ + fun getScreenInitSettings(navigation: Navigation): ScreenInitSettings { + return screen.initSettings(navigation, this) + } + + /** + * Determines if, for this screen, we support a vertical backstack. + */ + fun level1VerticalBackstackEnabled(): Boolean { + Level1Navigation.values().forEach { + if (it.screenIdentifier.uri == this.uri && it.rememberVerticalStack) { + return true + } + } + + return false + } + + companion object Factory { + fun get(screen: Screen, params: ScreenParams?): ScreenIdentifier { + return ScreenIdentifier(screen, params, null) + } + + fun getByURI(uri: String): ScreenIdentifier? { + val parts = uri.split(":") + + Screen.values().forEach { + if (it.asString == parts[0]) { + return ScreenIdentifier(it, null, parts[1]) + } + } + + return null + } + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenInitSettings.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenInitSettings.kt new file mode 100644 index 000000000..1f03eb7ba --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenInitSettings.kt @@ -0,0 +1,24 @@ +package com.adammcneilly.pocketleague.shared.screens + +/** + * When a screen is initialized, the following flow occurs. + * + * First, the screen state is initialized with the value defined in [initState] (usually a loading UI). + * Second, the FIRST recomposition will be triggered, so that the UI layer displays the [initState]. + * Third, after this recomposition, the [callOnInit] function is invoked. This will typically load data. + * Fourth, the [callOnInit] function likely makes a call to the [StateManager] to update the screen, which will update + * and trigger the SECOND recomposition. + * + * @property[reInitOnEachNavigation] If true, the [callOnInit] function is invoked each time the + * user returns to this screen. + * @property[callOnInitAlsoAfterBackground] If true, the [callOnInit] function will be invoked if + * we return to this screen from the background. This is useful if our screen was doing some polling, + * for example. + */ +class ScreenInitSettings( + val title: String, + val initState: (ScreenIdentifier) -> ScreenState, + val callOnInit: suspend (StateManager) -> Unit, + val reInitOnEachNavigation: Boolean = false, + val callOnInitAlsoAfterBackground: Boolean = false, +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenParams.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenParams.kt new file mode 100644 index 000000000..ef9b8e404 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenParams.kt @@ -0,0 +1,7 @@ +package com.adammcneilly.pocketleague.shared.screens + +/** + * This interface is empty but exists to provide type safety for defining any set of parameters + * that should be passed into a screen. + */ +interface ScreenParams diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenState.kt new file mode 100644 index 000000000..187530b39 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenState.kt @@ -0,0 +1,6 @@ +package com.adammcneilly.pocketleague.shared.screens + +/** + * An empty interface used to provide type safety for the current UI state of any screen in the application. + */ +interface ScreenState diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt new file mode 100644 index 000000000..2c4dea6a5 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt @@ -0,0 +1,32 @@ +package com.adammcneilly.pocketleague.shared.screens + +import com.adammcneilly.pocketleague.shared.screens.feed.initFeed + +/** + * An enumeration of all screens that appear somewhere in our application. + */ +enum class Screen( + val asString: String, + val navigationLevel: Int = 1, + val initSettings: Navigation.(ScreenIdentifier) -> ScreenInitSettings, + val stackableInstances: Boolean = false, +) { + Feed( + asString = "feed", + navigationLevel = 1, + initSettings = { + initFeed() + }, + stackableInstances = true, + ) +} + +// enum class Screen( +// val asString: String, +// val navigationLevel : Int = 1, +// val initSettings: Navigation.(ScreenIdentifier) -> ScreenInitSettings, +// val stackableInstances : Boolean = false, +// ) { +// CountriesList("countrieslist", 1, { initCountriesList(it.params()) }, true), +// CountryDetail("country", 2, { initCountryDetail(it.params()) }), +// } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt new file mode 100644 index 000000000..9765eeadc --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt @@ -0,0 +1,355 @@ +package com.adammcneilly.pocketleague.shared.screens + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import kotlin.reflect.KClass + +/** + * Manages our current [AppState] as well as the backstacks and screen scopes for everything in memory + * at any given moment. + */ +class StateManager { + internal val mutableStateFlow = MutableStateFlow(AppState()) + + /** + * A map of all screens and their current [ScreenState] in memory. + */ + val screenStatesMap: MutableMap = mutableMapOf() + + /** + * A map of all screens and coroutine scopes associated with them in memory. + */ + val screenScopesMap: MutableMap = mutableMapOf() + + /** + * The vertical backstack that the user has navigated to. These should all map to [Level1Navigation] + * screen identifiers. + */ + val level1Backstack: MutableList = mutableListOf() + + /** + * Tracks the vertical backstack for all tabs. The key is the identifier of the [Level1Navigation], + * and the value is the backstack within that screen. + */ + val verticalBackstacks: MutableMap> = mutableMapOf() + + /** + * The key for this map is the [Level1Navigation] screen identifier, and the value is the current + * navigation levels within that backstack. + */ + val verticalNavigationLevels: MutableMap> = mutableMapOf() + + /** + * Keeping track of the screens recently removed from memory. This will be used by the mobile apps + * to make sure they are removed from composition. + */ + val lastRemovedScreens: MutableList = mutableListOf() + + /** + * Checks our [level1Backstack] and uses whatever was most recently added to it. + */ + val currentLevel1ScreenIdentifier: ScreenIdentifier + get() = level1Backstack.last() + + /** + * Pulls the [currentLevel1ScreenIdentifier] and gets the vertical backstack for that tab. + */ + val currentVerticalBackstack: MutableList + get() = verticalBackstacks[currentLevel1ScreenIdentifier.uri]!! + + /** + * Checks the current screen by looking at our [currentVerticalBackstack] or falling back on + * the [currentLevel1ScreenIdentifier] if no vertical stack. + */ + val currentScreenIdentifier: ScreenIdentifier + get() = currentVerticalBackstack.lastOrNull() ?: currentLevel1ScreenIdentifier + + /** + * Checks the [verticalNavigationLevels] for the backstack mapping to our [currentLevel1ScreenIdentifier] + */ + val currentVerticalNavigationLevelsMap: MutableMap + get() = verticalNavigationLevels[currentLevel1ScreenIdentifier.uri]!! + + /** + * If there's only one screen in our [level1Backstack] as well as only one screen in the [currentVerticalBackstack] + * then we know we only have one screen total. + */ + val only1ScreenInBackstack: Boolean + get() = level1Backstack.size + currentVerticalBackstack.size == 2 + + /** + * This is used by Compose apps to remove screens from memory. + */ + fun getScreenStatesToRemove(): List { + val screenStatesToRemove = lastRemovedScreens.toList() + lastRemovedScreens.clear() + return screenStatesToRemove + } + + /** + * This is used by SwiftUI apps to build the level1 navigation. + */ + fun getLevel1ScreenIdentifiers(): List { + val screenIdentifiers = verticalNavigationLevels.values.map { + it[1]!! + }.toMutableList() + + // Remove any screens that do not currently have state stored. + screenIdentifiers.removeAll { + !screenStatesMap.containsKey(it.uri) + } + + return screenIdentifiers + } + + /** + * Checks to see if we've stored the screen state for a given [screenIdentifier]. + */ + fun isInTheStatesMap(screenIdentifier: ScreenIdentifier): Boolean { + return screenStatesMap.containsKey(screenIdentifier.uri) + } + + /** + * Determines if the given [screenIdentifier] is in any of our vertical backstacks within + * the application. + */ + fun isInAnyVerticalBackstack(screenIdentifier: ScreenIdentifier): Boolean { + verticalBackstacks.forEach { verticalBackstack -> + verticalBackstack.value.forEach { screen -> + if (screen.uri == screenIdentifier.uri) { + return true + } + } + } + + return false + } + + inline fun updateScreen( + stateClass: KClass, + update: (T) -> T, + ) { + lateinit var screenIdentifier: ScreenIdentifier + var screenState: T? = null + + for (index in currentVerticalNavigationLevelsMap.keys.sortedDescending()) { + screenState = screenStatesMap[currentVerticalNavigationLevelsMap[index]?.uri] as? T + + if (screenState != null) { + screenIdentifier = currentVerticalNavigationLevelsMap[index]!! + break + } + } + + // This ensures we only perform a screen state update if the screen is currently + // visible. + if (screenState != null) { + screenStatesMap[screenIdentifier.uri] = update(screenState) + triggerRecomposition() + } + } + + /** + * Update our [mutableStateFlow] with a new value so that we can force a recomposition + * in our application. + */ + fun triggerRecomposition() { + mutableStateFlow.update { + AppState(it.recompositionIndex + 1) + } + } + + /** + * Adds this screen to the app and trigger compositions as necessary. + */ + fun addScreen(screenIdentifier: ScreenIdentifier, screenInitSettings: ScreenInitSettings) { + addScreenToBackstack(screenIdentifier) + initScreenScope(screenIdentifier) + + if (!isInTheStatesMap(screenIdentifier) || screenInitSettings.reInitOnEachNavigation) { + screenStatesMap[screenIdentifier.uri] = screenInitSettings.initState(screenIdentifier) + // First UI Recomposition + triggerRecomposition() + + runInScreenScope(screenIdentifier) { + // Second UI Recomposition + screenInitSettings.callOnInit(this) + } + } else { + // Just One UI Recomposition + triggerRecomposition() + } + } + + /** + * Adds a screen to our backstack, based on its navigation level it will get added to the correct + * one. + */ + fun addScreenToBackstack(screenIdentifier: ScreenIdentifier) { + if (screenIdentifier.screen.navigationLevel == 1) { + if (level1Backstack.size > 0) { + val sameAsNewScreen = screenIdentifier.screen == currentLevel1ScreenIdentifier.screen + clearLevel1Screen(currentLevel1ScreenIdentifier, sameAsNewScreen) + } + + setupNewLevel1Screen(screenIdentifier) + } else { + if (currentScreenIdentifier.uri == screenIdentifier.uri) { + return + } + + if (currentScreenIdentifier.screen == screenIdentifier.screen && !screenIdentifier.screen.stackableInstances) { + val currentScreenId = currentScreenIdentifier + currentVerticalNavigationLevelsMap.remove(currentScreenId.screen.navigationLevel) + currentVerticalBackstack.remove(currentScreenId) + + if (!isInAnyVerticalBackstack(currentScreenId)) { + removeScreenStateAndScope(currentScreenId) + } + } + + if (currentVerticalBackstack.lastOrNull()?.uri != screenIdentifier.uri) { + currentVerticalBackstack.add(screenIdentifier) + } + } + + currentVerticalNavigationLevelsMap[screenIdentifier.screen.navigationLevel] = screenIdentifier + } + + /** + * Remove this screen from memory. + */ + fun removeScreen(screenIdentifier: ScreenIdentifier) { + if (screenIdentifier.screen.navigationLevel == 1) { + level1Backstack.remove(screenIdentifier) + removeScreenStateAndScope(screenIdentifier) + } else { + currentVerticalNavigationLevelsMap.remove(screenIdentifier.screen.navigationLevel) + currentVerticalBackstack.removeAll { + it.uri == screenIdentifier.uri + } + currentVerticalNavigationLevelsMap[currentScreenIdentifier.screen.navigationLevel] = currentScreenIdentifier + + if (!isInAnyVerticalBackstack(screenIdentifier)) { + removeScreenStateAndScope(screenIdentifier) + } + } + } + + /** + * Remove the in memory state and coroutine scope for the given screen. + */ + fun removeScreenStateAndScope(screenIdentifier: ScreenIdentifier) { + screenScopesMap[screenIdentifier.uri]?.cancel() + screenScopesMap.remove(screenIdentifier.uri) + screenStatesMap.remove(screenIdentifier.uri) + lastRemovedScreens.add(screenIdentifier) + } + + /** + * Clear a level 1 screen's backstack and remove from [level1Backstack] if necessary. + */ + fun clearLevel1Screen(screenIdentifier: ScreenIdentifier, sameAsNewScreen: Boolean) { + if (!screenIdentifier.level1VerticalBackstackEnabled()) { + currentVerticalBackstack.forEach { + if (it.screen.navigationLevel > 1) { + removeScreenStateAndScope(it) + } + } + + currentVerticalBackstack.removeAll { + it.uri != screenIdentifier.uri + } + currentVerticalNavigationLevelsMap.keys.removeAll { + it != 1 + } + } + + if (sameAsNewScreen && !screenIdentifier.screen.stackableInstances) { + removeScreenStateAndScope(screenIdentifier) + currentVerticalBackstack.clear() + currentVerticalNavigationLevelsMap.clear() + level1Backstack.remove(screenIdentifier) + } + } + + /** + * Setup a new level 1 screen when it's visited for the first time. + */ + fun setupNewLevel1Screen(screenIdentifier: ScreenIdentifier) { + level1Backstack.removeAll { + it.uri == screenIdentifier.uri + } + + if (NavigationSettings.alwaysQuitOnHomeScreen) { + if (screenIdentifier.uri == NavigationSettings.homeScreen.screenIdentifier.uri) { + // Remove all elements + level1Backstack.clear() + } else if (level1Backstack.size == 0) { + addLevel1ScreenToBackstack(NavigationSettings.homeScreen.screenIdentifier) + } + } + + addLevel1ScreenToBackstack(screenIdentifier) + } + + /** + * Adds a level 1 screen to our backstack, will clear the vertical backstack for this screen + * if one was there. + */ + private fun addLevel1ScreenToBackstack(screenIdentifier: ScreenIdentifier) { + level1Backstack.add(screenIdentifier) + + if (verticalBackstacks[screenIdentifier.uri] == null) { + verticalBackstacks[screenIdentifier.uri] = mutableListOf(screenIdentifier) + verticalNavigationLevels[screenIdentifier.uri] = mutableMapOf(1 to screenIdentifier) + } + } + + /** + * Initializes a coroutine scope for a given screen. + */ + fun initScreenScope(screenIdentifier: ScreenIdentifier) { + screenScopesMap[screenIdentifier.uri]?.cancel() + screenScopesMap[screenIdentifier.uri] = CoroutineScope(Job() + Dispatchers.Main) + } + + /** + * Reinitializes all scopes for our current vertical navigation screens. + */ + fun reInitScreenScopes(): List { + currentVerticalNavigationLevelsMap.forEach { + screenScopesMap[it.value.uri] = CoroutineScope(Job() + Dispatchers.Main) + } + + return currentVerticalNavigationLevelsMap.values.toList() + } + + /** + * Runs the supplied [block] within the coroutine scope of the given [screenIdentifier], + * or the current screen if one not passed. + */ + fun runInScreenScope(screenIdentifier: ScreenIdentifier? = null, block: suspend () -> Unit) { + val uri = screenIdentifier?.uri ?: currentScreenIdentifier.uri + + val screenScope = screenScopesMap[uri] + + screenScope?.launch { + block() + } + } + + /** + * Cancel all of our coroutine scopes. + */ + fun cancelScreenScopes() { + screenScopesMap.forEach { + it.value.cancel() + } + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt new file mode 100644 index 000000000..370fa121c --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt @@ -0,0 +1,20 @@ +package com.adammcneilly.pocketleague.shared.screens.feed + +import com.adammcneilly.pocketleague.shared.screens.Navigation +import com.adammcneilly.pocketleague.shared.screens.ScreenInitSettings + +/** + * Returns the [ScreenInitSettings] for our [com.adammcneilly.pocketleague.shared.screens.Screen.Feed] screen. + */ +fun Navigation.initFeed(): ScreenInitSettings { + return ScreenInitSettings( + title = "Feed", + initState = { + FeedState() + }, + callOnInit = { + // Coming soon? + }, + reInitOnEachNavigation = true, + ) +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedState.kt new file mode 100644 index 000000000..d50548b39 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedState.kt @@ -0,0 +1,12 @@ +package com.adammcneilly.pocketleague.shared.screens.feed + +import com.adammcneilly.pocketleague.shared.models.Event +import com.adammcneilly.pocketleague.shared.screens.ScreenState + +/** + * Defines the UI configuration for the [com.adammcneilly.pocketleague.shared.screens.Screen.Feed] screen. + */ +data class FeedState( + val showLoading: Boolean = true, + val upcomingEvents: List? = null, +) : ScreenState From 3c208b43334d031002345c1399706d1569bca2cc Mon Sep 17 00:00:00 2001 From: amcneilly Date: Sat, 16 Apr 2022 16:25:17 -0400 Subject: [PATCH 06/40] Adding composables. --- app/build.gradle.kts | 2 + .../pocketleague/PocketLeagueApp.kt | 39 +++++++++- .../pocketleague/ui/Level1BottomBar.kt | 29 ++++++++ .../pocketleague/ui/Level1NavigationRail.kt | 68 ++++++++++++++++++ .../pocketleague/ui/MainComposable.kt | 13 ++++ .../adammcneilly/pocketleague/ui/OnePane.kt | 25 +++++++ .../adammcneilly/pocketleague/ui/Router.kt | 33 +++++++++ .../pocketleague/ui/ScreenPicker.kt | 19 +++++ .../adammcneilly/pocketleague/ui/TopBar.kt | 25 +++++++ .../adammcneilly/pocketleague/ui/TwoPane.kt | 72 +++++++++++++++++++ 10 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/Level1NavigationRail.kt create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/MainComposable.kt create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/Router.kt create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/TopBar.kt create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/TwoPane.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 864cf3e33..23ee9c5ef 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -85,6 +85,7 @@ android { dependencies { implementation(project(":android-design-system")) + implementation(project(":shared")) implementation("androidx.core:core-ktx:${Versions.ktxCore}") implementation("androidx.appcompat:appcompat:${Versions.appCompat}") implementation("com.google.android.material:material:${Versions.material}") @@ -98,6 +99,7 @@ dependencies { implementation("com.google.accompanist:accompanist-insets-ui:${Versions.accompanist}") implementation("com.google.accompanist:accompanist-systemuicontroller:${Versions.accompanist}") implementation("androidx.window:window:${Versions.windowManager}") + implementation("androidx.lifecycle:lifecycle-process:2.4.1") kapt("com.google.dagger:hilt-compiler:${Versions.hilt}") testImplementation("junit:junit:${Versions.junit}") testImplementation("com.google.truth:truth:${Versions.truth}") diff --git a/app/src/main/java/com/adammcneilly/pocketleague/PocketLeagueApp.kt b/app/src/main/java/com/adammcneilly/pocketleague/PocketLeagueApp.kt index fc4b8fe32..0c47db655 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/PocketLeagueApp.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/PocketLeagueApp.kt @@ -1,6 +1,12 @@ package com.adammcneilly.pocketleague import android.app.Application +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleEventObserver +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.ProcessLifecycleOwner +import com.adammcneilly.pocketleague.shared.screens.DKMPViewModel +import com.adammcneilly.pocketleague.shared.screens.getAndroidInstance import dagger.hilt.android.HiltAndroidApp /** @@ -8,4 +14,35 @@ import dagger.hilt.android.HiltAndroidApp * or third party initializations that must occur at app startup. */ @HiltAndroidApp -class PocketLeagueApp : Application() +class PocketLeagueApp : Application() { + + lateinit var viewModel: DKMPViewModel + + override fun onCreate() { + super.onCreate() + viewModel = DKMPViewModel.Factory.getAndroidInstance() + + val appLifecycleObserver = AppLifecycleObserver(viewModel) + ProcessLifecycleOwner.get().lifecycle.addObserver(appLifecycleObserver) + } +} + +class AppLifecycleObserver(private val viewModel: DKMPViewModel) : LifecycleEventObserver { + + override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { + when (event) { + Lifecycle.Event.ON_START -> { + // Avoid calling at app startup + if (viewModel.stateFlow.value.recompositionIndex > 0) { + viewModel.navigation.onReEnterForeground() + } + } + Lifecycle.Event.ON_STOP -> { + viewModel.navigation.onEnterBackground() + } + else -> { + // Don't care + } + } + } +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt new file mode 100644 index 000000000..6b1076585 --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt @@ -0,0 +1,29 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.material.BottomAppBar +import androidx.compose.material.BottomNavigationItem +import androidx.compose.material.Icon +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Menu +import androidx.compose.runtime.Composable +import androidx.compose.ui.unit.sp +import com.adammcneilly.pocketleague.shared.screens.Level1Navigation +import com.adammcneilly.pocketleague.shared.screens.Navigation +import com.adammcneilly.pocketleague.shared.screens.ScreenIdentifier + +@Composable +fun Navigation.Level1BottomBar( + selectedTab: ScreenIdentifier +) { + BottomAppBar( + content = { + BottomNavigationItem( + icon = { Icon(Icons.Default.Menu, "Feed") }, + label = { Text("FEED", fontSize = 13.sp) }, + selected = selectedTab.uri == Level1Navigation.Feed.screenIdentifier.uri, + onClick = { navigateByLevel1Menu(Level1Navigation.Feed) } + ) + } + ) +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1NavigationRail.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1NavigationRail.kt new file mode 100644 index 000000000..df66492a4 --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1NavigationRail.kt @@ -0,0 +1,68 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Icon +import androidx.compose.material.LocalContentColor +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Menu +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.adammcneilly.pocketleague.shared.screens.Level1Navigation +import com.adammcneilly.pocketleague.shared.screens.Navigation +import com.adammcneilly.pocketleague.shared.screens.ScreenIdentifier + +@Composable +fun Navigation.Level1NavigationRail( + selectedTab: ScreenIdentifier +) { + Column( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight() + .background(MaterialTheme.colors.primary), + verticalArrangement = Arrangement.Center + ) { + NavigationRailItem( + icon = { Icon(Icons.Default.Menu, "Feed") }, + label = { Text("FEED", fontSize = 13.sp) }, + selected = selectedTab.uri == Level1Navigation.Feed.screenIdentifier.uri, + onClick = { navigateByLevel1Menu(Level1Navigation.Feed) } + ) + } +} + +@Composable +fun ColumnScope.NavigationRailItem(icon: @Composable () -> Unit, label: @Composable () -> Unit, selected: Boolean, onClick: () -> Unit) { + CompositionLocalProvider( + LocalContentColor provides if (selected) MaterialTheme.colors.background else MaterialTheme.colors.primaryVariant + ) { + Row( + modifier = Modifier + .clickable { onClick() } + .padding(top = 25.dp, bottom = 25.dp) + ) { + Column( + modifier = Modifier + .fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + icon() + label() + } + } + } +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/MainComposable.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/MainComposable.kt new file mode 100644 index 000000000..0d693d136 --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/MainComposable.kt @@ -0,0 +1,13 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import com.adammcneilly.pocketleague.shared.screens.DKMPViewModel + +@Composable +fun MainComposable(viewModel: DKMPViewModel) { + val appState by viewModel.stateFlow.collectAsState() + val dkmpNav = appState.getNavigation(viewModel) + dkmpNav.Router() +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt new file mode 100644 index 000000000..ca9046fca --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt @@ -0,0 +1,25 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.material.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.saveable.SaveableStateHolder +import com.adammcneilly.pocketleague.shared.screens.Navigation + +@Composable +fun Navigation.OnePane( + saveableStateHolder: SaveableStateHolder +) { + Scaffold( + topBar = { TopBar(getTitle(currentScreenIdentifier)) }, + content = { + saveableStateHolder.SaveableStateProvider(currentScreenIdentifier.uri) { + ScreenPicker(currentScreenIdentifier) + } + }, + bottomBar = { + if (currentScreenIdentifier.screen.navigationLevel == 1) { + Level1BottomBar(currentScreenIdentifier) + } + }, + ) +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/Router.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/Router.kt new file mode 100644 index 000000000..9952cf3e7 --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/Router.kt @@ -0,0 +1,33 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.runtime.Composable +import androidx.compose.runtime.saveable.rememberSaveableStateHolder +import androidx.compose.ui.unit.dp +import com.adammcneilly.pocketleague.shared.screens.Navigation + +@Composable +fun Navigation.Router() { + val screenUIsStateHolder = rememberSaveableStateHolder() + + val twoPaneWidthThreshold = 1000.dp + + BoxWithConstraints() { + if (maxWidth < maxHeight || maxWidth < twoPaneWidthThreshold) { + OnePane(screenUIsStateHolder) + } else { + TwoPane(screenUIsStateHolder) + } + } + + screenStatesToRemove.forEach { + screenUIsStateHolder.removeState(it.uri) + } + + if (!only1ScreenInBackstack) { + BackHandler { + exitScreen() + } + } +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt new file mode 100644 index 000000000..e6d5af86f --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt @@ -0,0 +1,19 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import com.adammcneilly.pocketleague.shared.screens.Navigation +import com.adammcneilly.pocketleague.shared.screens.Screen +import com.adammcneilly.pocketleague.shared.screens.ScreenIdentifier + +@Composable +fun Navigation.ScreenPicker( + screenIdentifier: ScreenIdentifier +) { + + when (screenIdentifier.screen) { + Screen.Feed -> { + Text(text = "Feed Screen") + } + } +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/TopBar.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/TopBar.kt new file mode 100644 index 000000000..c6a0b7b04 --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/TopBar.kt @@ -0,0 +1,25 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.Text +import androidx.compose.material.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.sp + +@Composable +fun TopBar( + title: String +) { + TopAppBar( + title = { + Text( + text = title, + fontSize = 20.sp, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() + ) + }, + ) +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/TwoPane.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/TwoPane.kt new file mode 100644 index 000000000..84458d218 --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/TwoPane.kt @@ -0,0 +1,72 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.saveable.SaveableStateHolder +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.adammcneilly.pocketleague.shared.screens.Navigation +import com.adammcneilly.pocketleague.shared.screens.ScreenIdentifier + +@Composable +fun Navigation.TwoPane( + saveableStateHolder: SaveableStateHolder +) { + val navigationLevelsMap = getNavigationLevelsMap(currentLevel1ScreenIdentifier)!! + Scaffold( + topBar = { TopBar(getTitle(currentScreenIdentifier)) }, + content = { + Row { + Column( + Modifier + .fillMaxHeight() + .width(80.dp) + ) { + Level1NavigationRail(selectedTab = navigationLevelsMap[1]!!) + } + Column( + Modifier + .weight(0.4f) + ) { + saveableStateHolder.SaveableStateProvider(navigationLevelsMap[1]!!.uri) { + ScreenPicker(navigationLevelsMap[1]!!) + } + } + Column( + Modifier + .weight(0.6f) + .padding(20.dp) + ) { + if (navigationLevelsMap[2] == null) { + TwoPaneDefaultDetail(navigationLevelsMap[1]!!) + } else { + saveableStateHolder.SaveableStateProvider(navigationLevelsMap[2]!!.uri) { + ScreenPicker(navigationLevelsMap[2]!!) + } + } + } + } + } + ) +} + +@Composable +fun Navigation.TwoPaneDefaultDetail( + screenIdentifier: ScreenIdentifier +) { +// when (screenIdentifier.screen) { +// +// CountriesList -> +// CountriesListTwoPaneDefaultDetail() +// +// else -> Box{} +// } + Box { + } +} From d337c24567d2de2ee14f073b33e8943088ce1550 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Sat, 16 Apr 2022 16:27:31 -0400 Subject: [PATCH 07/40] POC. --- .../main/java/com/adammcneilly/pocketleague/MainActivity.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/MainActivity.kt b/app/src/main/java/com/adammcneilly/pocketleague/MainActivity.kt index e58be714a..d82b8ba5f 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/MainActivity.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/MainActivity.kt @@ -10,6 +10,7 @@ import androidx.compose.runtime.SideEffect import androidx.compose.ui.graphics.Color import androidx.core.view.WindowCompat import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme +import com.adammcneilly.pocketleague.ui.MainComposable import com.google.accompanist.insets.ProvideWindowInsets import com.google.accompanist.systemuicontroller.rememberSystemUiController import dagger.hilt.android.AndroidEntryPoint @@ -31,7 +32,8 @@ class MainActivity : ComponentActivity() { SetSystemBarsTransparent() ProvideWindowInsets { - // Coming soon + val viewModel = (this.application as PocketLeagueApp).viewModel + MainComposable(viewModel = viewModel) } } } From 9df3b0d5286f597dd0ff86ed270563bcebe05c72 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Sat, 16 Apr 2022 16:30:15 -0400 Subject: [PATCH 08/40] Code cleanup. --- app/src/main/java/com/adammcneilly/pocketleague/ui/Router.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/Router.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/Router.kt index 9952cf3e7..87fa6d27f 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/Router.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/Router.kt @@ -13,7 +13,7 @@ fun Navigation.Router() { val twoPaneWidthThreshold = 1000.dp - BoxWithConstraints() { + BoxWithConstraints { if (maxWidth < maxHeight || maxWidth < twoPaneWidthThreshold) { OnePane(screenUIsStateHolder) } else { From 3c5390f44b5754c2262a793bd3bc36e4c426606b Mon Sep 17 00:00:00 2001 From: amcneilly Date: Sun, 17 Apr 2022 09:48:27 -0400 Subject: [PATCH 09/40] Using M2 again. --- android-design-system/build.gradle.kts | 1 - .../components/Material3VerticalDivider.kt | 32 ---- .../components/togglebutton/ToggleButton.kt | 65 -------- .../togglebutton/ToggleButtonOption.kt | 10 -- .../togglebutton/ToggleButtonRow.kt | 151 ------------------ .../android/design/theme/Theme.kt | 44 +---- .../pocketleague/android/design/theme/Type.kt | 118 -------------- app/build.gradle.kts | 1 - .../adammcneilly/pocketleague/MainActivity.kt | 2 - .../pocketleague/ui/Level1BottomBar.kt | 21 ++- .../adammcneilly/pocketleague/ui/OnePane.kt | 7 +- .../pocketleague/ui/ScreenPicker.kt | 2 +- .../adammcneilly/pocketleague/ui/TopBar.kt | 7 - buildSrc/src/main/kotlin/Versions.kt | 3 - 14 files changed, 30 insertions(+), 434 deletions(-) delete mode 100644 android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/Material3VerticalDivider.kt delete mode 100644 android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/togglebutton/ToggleButton.kt delete mode 100644 android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/togglebutton/ToggleButtonOption.kt delete mode 100644 android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/togglebutton/ToggleButtonRow.kt delete mode 100644 android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/theme/Type.kt diff --git a/android-design-system/build.gradle.kts b/android-design-system/build.gradle.kts index a90a57124..b7b6880de 100644 --- a/android-design-system/build.gradle.kts +++ b/android-design-system/build.gradle.kts @@ -44,7 +44,6 @@ dependencies { implementation("androidx.compose.ui:ui:${Versions.compose}") implementation("androidx.compose.material:material:${Versions.compose}") - implementation("androidx.compose.material3:material3:${Versions.composeMaterial3}") implementation("androidx.compose.ui:ui-tooling-preview:${Versions.compose}") androidTestImplementation("androidx.compose.ui:ui-test-junit4:${Versions.compose}") debugImplementation("androidx.compose.ui:ui-tooling:${Versions.compose}") diff --git a/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/Material3VerticalDivider.kt b/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/Material3VerticalDivider.kt deleted file mode 100644 index b5145973f..000000000 --- a/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/Material3VerticalDivider.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.adammcneilly.pocketleague.android.design.components - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.width -import androidx.compose.material.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp - -/** - * A custom implementation of a divider that uses the Material 3 theme and also applies a - * vertical orientation to the divider. - */ -@Composable -fun Material3VerticalDivider( - modifier: Modifier = Modifier, - color: Color = MaterialTheme.colors.onSurface, - thickness: Dp = 1.dp, -) { - Box( - modifier - .fillMaxHeight() - .width(thickness) - .background(color = color.copy(alpha = DIVIDER_ALPHA)) - ) -} - -private const val DIVIDER_ALPHA = 0.12F diff --git a/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/togglebutton/ToggleButton.kt b/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/togglebutton/ToggleButton.kt deleted file mode 100644 index 183bd849a..000000000 --- a/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/togglebutton/ToggleButton.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.adammcneilly.pocketleague.android.design.components.togglebutton - -import androidx.compose.foundation.BorderStroke -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.text.intl.Locale -import androidx.compose.ui.text.toUpperCase -import androidx.compose.ui.unit.dp - -/** - * A single button component that appears inside of our [ToggleButtonRow]. - * - * @param[shape] The bounding shape of the button. This will be rounded at the ends, but flat in the - * middle. - * @param[onClick] A callback invoked when the user clicks on this button. - * @param[text] The text to display inside this button. - * @param[selected] True if this is the currently selected option in the button row, false otherwise. - * @param[modifier] An optional [Modifier] to configure this button. - */ -@Composable -fun ToggleButton( - shape: Shape, - onClick: () -> Unit, - text: String, - selected: Boolean, - modifier: Modifier = Modifier, -) { - val colorsToUse = if (selected) { - ButtonDefaults.outlinedButtonColors( - containerColor = MaterialTheme.colorScheme.primaryContainer, - contentColor = MaterialTheme.colorScheme.onPrimaryContainer, - ) - } else { - ButtonDefaults.outlinedButtonColors( - containerColor = MaterialTheme.colorScheme.background, - contentColor = MaterialTheme.colorScheme.onBackground, - ) - } - - val borderColor = if (selected) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.outline - } - - OutlinedButton( - onClick = onClick, - shape = shape, - colors = colorsToUse, - modifier = modifier, - border = BorderStroke( - width = 1.dp, - color = borderColor, - ) - ) { - Text( - text = text.toUpperCase(Locale.current), - ) - } -} diff --git a/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/togglebutton/ToggleButtonOption.kt b/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/togglebutton/ToggleButtonOption.kt deleted file mode 100644 index fb52410f2..000000000 --- a/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/togglebutton/ToggleButtonOption.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.adammcneilly.pocketleague.android.design.components.togglebutton - -/** - * Defines any option that can appear inside a [ToggleButtonRow]. - * - * @property[text] The string that should be displayed to the user inside this button. - */ -data class ToggleButtonOption( - val text: String, -) diff --git a/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/togglebutton/ToggleButtonRow.kt b/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/togglebutton/ToggleButtonRow.kt deleted file mode 100644 index 220b101d0..000000000 --- a/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/components/togglebutton/ToggleButtonRow.kt +++ /dev/null @@ -1,151 +0,0 @@ -package com.adammcneilly.pocketleague.android.design.components.togglebutton - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.offset -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.zIndex -import com.adammcneilly.pocketleague.android.design.adaptiveWidth -import com.adammcneilly.pocketleague.android.design.theme.PocketLeagueTheme - -/** - * A row of [ToggleButton] entities that allows the user to select one of the supplied [options]. - * - * @param[options] All possible selections the user can make in this button row. - * @param[onOptionSelected] A callback triggered whenever we want to change the [selectedOption]. - * @param[modifier] An optional [Modifier] to configure this button row. - * @param[selectedOption] The currently selected choice by the user. Defaults to the first item in - * the [options] list. - * @param[cornerRadiusPercent] The percentage of our height to use as the radius for the corners. Defaults - * to 50% to give a rounded pill shape. - */ -@Composable -fun ToggleButtonRow( - options: List, - onOptionSelected: (ToggleButtonOption) -> Unit, - modifier: Modifier = Modifier, - selectedOption: ToggleButtonOption = options.first(), - cornerRadiusPercent: Int = 50, -) { - val startShape = RoundedCornerShape( - topStartPercent = cornerRadiusPercent, - topEndPercent = 0, - bottomStartPercent = cornerRadiusPercent, - bottomEndPercent = 0, - ) - - val middleShape = RoundedCornerShape(0.dp) - - val endShape = RoundedCornerShape( - topStartPercent = 0, - topEndPercent = cornerRadiusPercent, - bottomStartPercent = 0, - bottomEndPercent = cornerRadiusPercent, - ) - - Row( - modifier = modifier - .adaptiveWidth( - mediumWidthRatio = 0.5F, - ), - ) { - options.forEachIndexed { index, option -> - val shapeToUse = when (index) { - 0 -> startShape - options.lastIndex -> endShape - else -> middleShape - } - - val isOptionSelected = (option == selectedOption) - - ToggleButton( - shape = shapeToUse, - onClick = { - onOptionSelected.invoke(option) - }, - text = option.text, - selected = isOptionSelected, - modifier = Modifier - .adjustOffsetZIndex( - indexInRow = index, - isIndexSelected = isOptionSelected, - ) - .weight(1F), - ) - } - } -} - -/** - * A custom [Modifier] that will adjust the offset of the current item (if necessary), as well as - * it's Z index. This prevents seeing a double width divider on two buttons next to each other. - * - * Inspiration: https://stackoverflow.com/a/67036710/3131147 - */ -private fun Modifier.adjustOffsetZIndex( - indexInRow: Int, - isIndexSelected: Boolean, -): Modifier { - val zIndex = if (isIndexSelected) { - 1F - } else { - 0F - } - - return when (indexInRow) { - 0 -> { - this - .offset(0.dp, 0.dp) - .zIndex(zIndex) - } - else -> { - val offset = -1 * indexInRow - - this - .offset(offset.dp, 0.dp) - .zIndex(zIndex) - } - } -} - -@Preview( - name = "Night Mode", - uiMode = Configuration.UI_MODE_NIGHT_YES, -) -@Preview( - name = "Day Mode", - uiMode = Configuration.UI_MODE_NIGHT_NO, -) -@Preview( - name = "Medium", - uiMode = Configuration.UI_MODE_NIGHT_NO, - widthDp = 800, -) -@Preview( - name = "Expanded", - uiMode = Configuration.UI_MODE_NIGHT_NO, - widthDp = 900, -) -@Composable -private fun ToggleButtonRowPreview() { - val upcoming = ToggleButtonOption("Upcoming") - val past = ToggleButtonOption("Past") - - PocketLeagueTheme { - Surface { - ToggleButtonRow( - options = listOf(upcoming, past), - selectedOption = upcoming, - modifier = Modifier - .padding(16.dp), - onOptionSelected = {}, - ) - } - } -} diff --git a/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/theme/Theme.kt b/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/theme/Theme.kt index bca40ef9c..980d1176e 100644 --- a/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/theme/Theme.kt +++ b/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/theme/Theme.kt @@ -1,66 +1,35 @@ package com.adammcneilly.pocketleague.android.design.theme import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.lightColorScheme +import androidx.compose.material.MaterialTheme +import androidx.compose.material.darkColors +import androidx.compose.material.lightColors import androidx.compose.runtime.Composable -private val LightThemeColors = lightColorScheme( - +private val LightThemeColors = lightColors( primary = md_theme_light_primary, onPrimary = md_theme_light_onPrimary, - primaryContainer = md_theme_light_primaryContainer, - onPrimaryContainer = md_theme_light_onPrimaryContainer, secondary = md_theme_light_secondary, onSecondary = md_theme_light_onSecondary, - secondaryContainer = md_theme_light_secondaryContainer, - onSecondaryContainer = md_theme_light_onSecondaryContainer, - tertiary = md_theme_light_tertiary, - onTertiary = md_theme_light_onTertiary, - tertiaryContainer = md_theme_light_tertiaryContainer, - onTertiaryContainer = md_theme_light_onTertiaryContainer, error = md_theme_light_error, - errorContainer = md_theme_light_errorContainer, onError = md_theme_light_onError, - onErrorContainer = md_theme_light_onErrorContainer, background = md_theme_light_background, onBackground = md_theme_light_onBackground, surface = md_theme_light_surface, onSurface = md_theme_light_onSurface, - surfaceVariant = md_theme_light_surfaceVariant, - onSurfaceVariant = md_theme_light_onSurfaceVariant, - outline = md_theme_light_outline, - inverseOnSurface = md_theme_light_inverseOnSurface, - inverseSurface = md_theme_light_inverseSurface, ) -private val DarkThemeColors = darkColorScheme( +private val DarkThemeColors = darkColors( primary = md_theme_dark_primary, onPrimary = md_theme_dark_onPrimary, - primaryContainer = md_theme_dark_primaryContainer, - onPrimaryContainer = md_theme_dark_onPrimaryContainer, secondary = md_theme_dark_secondary, onSecondary = md_theme_dark_onSecondary, - secondaryContainer = md_theme_dark_secondaryContainer, - onSecondaryContainer = md_theme_dark_onSecondaryContainer, - tertiary = md_theme_dark_tertiary, - onTertiary = md_theme_dark_onTertiary, - tertiaryContainer = md_theme_dark_tertiaryContainer, - onTertiaryContainer = md_theme_dark_onTertiaryContainer, error = md_theme_dark_error, - errorContainer = md_theme_dark_errorContainer, onError = md_theme_dark_onError, - onErrorContainer = md_theme_dark_onErrorContainer, background = md_theme_dark_background, onBackground = md_theme_dark_onBackground, surface = md_theme_dark_surface, onSurface = md_theme_dark_onSurface, - surfaceVariant = md_theme_dark_surfaceVariant, - onSurfaceVariant = md_theme_dark_onSurfaceVariant, - outline = md_theme_dark_outline, - inverseOnSurface = md_theme_dark_inverseOnSurface, - inverseSurface = md_theme_dark_inverseSurface, ) /** @@ -78,8 +47,7 @@ fun PocketLeagueTheme( } MaterialTheme( - colorScheme = colors, - typography = AppTypography, + colors = colors, content = content ) } diff --git a/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/theme/Type.kt b/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/theme/Type.kt deleted file mode 100644 index 90f598232..000000000 --- a/android-design-system/src/main/java/com/adammcneilly/pocketleague/android/design/theme/Type.kt +++ /dev/null @@ -1,118 +0,0 @@ -package com.adammcneilly.pocketleague.android.design.theme - -import androidx.compose.material3.Typography -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.sp - -// Replace with your font locations -val Roboto = FontFamily.Default - -val AppTypography = Typography( - displayLarge = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.W400, - fontSize = 57.sp, - lineHeight = 64.sp, - letterSpacing = -0.25.sp, - ), - displayMedium = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.W400, - fontSize = 45.sp, - lineHeight = 52.sp, - letterSpacing = 0.sp, - ), - displaySmall = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.W400, - fontSize = 36.sp, - lineHeight = 44.sp, - letterSpacing = 0.sp, - ), - headlineLarge = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.W400, - fontSize = 32.sp, - lineHeight = 40.sp, - letterSpacing = 0.sp, - ), - headlineMedium = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.W400, - fontSize = 28.sp, - lineHeight = 36.sp, - letterSpacing = 0.sp, - ), - headlineSmall = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.W400, - fontSize = 24.sp, - lineHeight = 32.sp, - letterSpacing = 0.sp, - ), - titleLarge = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.W400, - fontSize = 22.sp, - lineHeight = 28.sp, - letterSpacing = 0.sp, - ), - titleMedium = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.Medium, - fontSize = 16.sp, - lineHeight = 24.sp, - letterSpacing = 0.1.sp, - ), - titleSmall = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.Medium, - fontSize = 14.sp, - lineHeight = 20.sp, - letterSpacing = 0.1.sp, - ), - labelLarge = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.Medium, - fontSize = 14.sp, - lineHeight = 20.sp, - letterSpacing = 0.1.sp, - ), - bodyLarge = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.W400, - fontSize = 16.sp, - lineHeight = 24.sp, - letterSpacing = 0.5.sp, - ), - bodyMedium = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.W400, - fontSize = 14.sp, - lineHeight = 20.sp, - letterSpacing = 0.25.sp, - ), - bodySmall = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.W400, - fontSize = 12.sp, - lineHeight = 16.sp, - letterSpacing = 0.4.sp, - ), - labelMedium = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.Medium, - fontSize = 12.sp, - lineHeight = 16.sp, - letterSpacing = 0.5.sp, - ), - labelSmall = TextStyle( - fontFamily = Roboto, - fontWeight = FontWeight.Medium, - fontSize = 11.sp, - lineHeight = 16.sp, - letterSpacing = 0.5.sp, - ), -) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 23ee9c5ef..b763287dd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -91,7 +91,6 @@ dependencies { implementation("com.google.android.material:material:${Versions.material}") implementation("androidx.compose.ui:ui:${Versions.compose}") implementation("androidx.compose.material:material:${Versions.compose}") - implementation("androidx.compose.material3:material3:${Versions.composeMaterial3}") implementation("androidx.compose.ui:ui-tooling-preview:${Versions.compose}") implementation("androidx.lifecycle:lifecycle-runtime-ktx:${Versions.lifecycle}") implementation("androidx.activity:activity-compose:${Versions.activityCompose}") diff --git a/app/src/main/java/com/adammcneilly/pocketleague/MainActivity.kt b/app/src/main/java/com/adammcneilly/pocketleague/MainActivity.kt index d82b8ba5f..c26196e5d 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/MainActivity.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/MainActivity.kt @@ -4,7 +4,6 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.runtime.SideEffect import androidx.compose.ui.graphics.Color @@ -21,7 +20,6 @@ import dagger.hilt.android.AndroidEntryPoint */ @AndroidEntryPoint class MainActivity : ComponentActivity() { - @OptIn(ExperimentalMaterial3Api::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt index 6b1076585..27fa090dd 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt @@ -5,9 +5,10 @@ import androidx.compose.material.BottomNavigationItem import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Menu +import androidx.compose.material.icons.filled.AccountCircle +import androidx.compose.material.icons.filled.Home +import androidx.compose.material.icons.filled.Star import androidx.compose.runtime.Composable -import androidx.compose.ui.unit.sp import com.adammcneilly.pocketleague.shared.screens.Level1Navigation import com.adammcneilly.pocketleague.shared.screens.Navigation import com.adammcneilly.pocketleague.shared.screens.ScreenIdentifier @@ -19,11 +20,23 @@ fun Navigation.Level1BottomBar( BottomAppBar( content = { BottomNavigationItem( - icon = { Icon(Icons.Default.Menu, "Feed") }, - label = { Text("FEED", fontSize = 13.sp) }, + icon = { Icon(Icons.Default.Home, "Feed") }, + label = { Text("FEED") }, selected = selectedTab.uri == Level1Navigation.Feed.screenIdentifier.uri, onClick = { navigateByLevel1Menu(Level1Navigation.Feed) } ) + BottomNavigationItem( + icon = { Icon(Icons.Default.Star, "Teams") }, + label = { Text("MY TEAMS") }, + selected = false, + onClick = { }, + ) + BottomNavigationItem( + icon = { Icon(Icons.Default.AccountCircle, "Account") }, + label = { Text("ACCOUNT") }, + selected = false, + onClick = { }, + ) } ) } diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt index ca9046fca..948f937ff 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt @@ -3,11 +3,14 @@ package com.adammcneilly.pocketleague.ui import androidx.compose.material.Scaffold import androidx.compose.runtime.Composable import androidx.compose.runtime.saveable.SaveableStateHolder +import androidx.compose.ui.Modifier import com.adammcneilly.pocketleague.shared.screens.Navigation +import com.google.accompanist.insets.systemBarsPadding @Composable fun Navigation.OnePane( - saveableStateHolder: SaveableStateHolder + saveableStateHolder: SaveableStateHolder, + modifier: Modifier = Modifier, ) { Scaffold( topBar = { TopBar(getTitle(currentScreenIdentifier)) }, @@ -21,5 +24,7 @@ fun Navigation.OnePane( Level1BottomBar(currentScreenIdentifier) } }, + modifier = modifier + .systemBarsPadding(), ) } diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt index e6d5af86f..ecf2f2aff 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt @@ -1,6 +1,6 @@ package com.adammcneilly.pocketleague.ui -import androidx.compose.material3.Text +import androidx.compose.material.Text import androidx.compose.runtime.Composable import com.adammcneilly.pocketleague.shared.screens.Navigation import com.adammcneilly.pocketleague.shared.screens.Screen diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/TopBar.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/TopBar.kt index c6a0b7b04..5e1657559 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/TopBar.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/TopBar.kt @@ -1,12 +1,8 @@ package com.adammcneilly.pocketleague.ui -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.Text import androidx.compose.material.TopAppBar import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.sp @Composable fun TopBar( @@ -16,9 +12,6 @@ fun TopBar( title = { Text( text = title, - fontSize = 20.sp, - textAlign = TextAlign.Center, - modifier = Modifier.fillMaxWidth() ) }, ) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 9121954ca..0805ecaf6 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -29,9 +29,6 @@ object Versions { // https://github.com/material-components/material-components-android/releases const val material = "1.5.0" - // https://developer.android.com/jetpack/androidx/releases/compose-material3 - const val composeMaterial3 = "1.0.0-alpha05" - // https://github.com/google/truth/releases const val truth = "1.1.3" From a9b13c40d978876c2d7490257e529178b306c5e1 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Sun, 17 Apr 2022 13:43:44 -0400 Subject: [PATCH 10/40] Docs. --- .../pocketleague/PocketLeagueApp.kt | 4 ++++ .../pocketleague/ui/Level1BottomBar.kt | 3 +++ .../pocketleague/ui/Level1NavigationRail.kt | 22 +++++++++++++++++-- .../pocketleague/ui/MainComposable.kt | 3 +++ .../adammcneilly/pocketleague/ui/OnePane.kt | 3 +++ .../adammcneilly/pocketleague/ui/Router.kt | 4 ++++ .../pocketleague/ui/ScreenPicker.kt | 7 ++++-- .../adammcneilly/pocketleague/ui/TopBar.kt | 3 +++ .../adammcneilly/pocketleague/ui/TwoPane.kt | 9 ++++++++ .../pocketleague/shared/screens/AppState.kt | 7 ++++-- .../shared/screens/Level1Navigation.kt | 2 +- .../pocketleague/shared/screens/Navigation.kt | 2 +- .../shared/screens/ScreenIdentifier.kt | 18 +++++++++++---- .../shared/screens/ScreenInitSettings.kt | 3 +++ .../pocketleague/shared/screens/Screens.kt | 2 +- .../shared/screens/StateManager.kt | 8 ++++++- .../shared/screens/feed/FeedInitSettings.kt | 2 +- .../shared/screens/feed/FeedState.kt | 2 +- 18 files changed, 88 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/PocketLeagueApp.kt b/app/src/main/java/com/adammcneilly/pocketleague/PocketLeagueApp.kt index 0c47db655..08664f541 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/PocketLeagueApp.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/PocketLeagueApp.kt @@ -27,6 +27,10 @@ class PocketLeagueApp : Application() { } } +/** + * Observes lifecycle events of the Android app and calls appropriate methods on the [viewModel] + * to manage screen states. + */ class AppLifecycleObserver(private val viewModel: DKMPViewModel) : LifecycleEventObserver { override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt index 27fa090dd..aa92b243b 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt @@ -13,6 +13,9 @@ import com.adammcneilly.pocketleague.shared.screens.Level1Navigation import com.adammcneilly.pocketleague.shared.screens.Navigation import com.adammcneilly.pocketleague.shared.screens.ScreenIdentifier +/** + * Creates a [BottomAppBar] to manage the menu items on a phone or other compact screen size. + */ @Composable fun Navigation.Level1BottomBar( selectedTab: ScreenIdentifier diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1NavigationRail.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1NavigationRail.kt index df66492a4..621d305ed 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1NavigationRail.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1NavigationRail.kt @@ -25,6 +25,10 @@ import com.adammcneilly.pocketleague.shared.screens.Level1Navigation import com.adammcneilly.pocketleague.shared.screens.Navigation import com.adammcneilly.pocketleague.shared.screens.ScreenIdentifier +/** + * A navigation rail is similar to a [Level1BottomBar] except it will show up on the left side of the + * screen, used on foldable or other large screen devices. + */ @Composable fun Navigation.Level1NavigationRail( selectedTab: ScreenIdentifier @@ -45,10 +49,24 @@ fun Navigation.Level1NavigationRail( } } +/** + * Creates a single menu item to appear inside of a [Level1NavigationRail]. + */ @Composable -fun ColumnScope.NavigationRailItem(icon: @Composable () -> Unit, label: @Composable () -> Unit, selected: Boolean, onClick: () -> Unit) { +fun ColumnScope.NavigationRailItem( + icon: @Composable () -> Unit, + label: @Composable () -> Unit, + selected: Boolean, + onClick: () -> Unit, +) { + val contentColor = if (selected) { + MaterialTheme.colors.background + } else { + MaterialTheme.colors.primaryVariant + } + CompositionLocalProvider( - LocalContentColor provides if (selected) MaterialTheme.colors.background else MaterialTheme.colors.primaryVariant + LocalContentColor provides contentColor ) { Row( modifier = Modifier diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/MainComposable.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/MainComposable.kt index 0d693d136..be8b47557 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/MainComposable.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/MainComposable.kt @@ -5,6 +5,9 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import com.adammcneilly.pocketleague.shared.screens.DKMPViewModel +/** + * The main entry point of any compose based application. + */ @Composable fun MainComposable(viewModel: DKMPViewModel) { val appState by viewModel.stateFlow.collectAsState() diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt index 948f937ff..f6bb2fbd9 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt @@ -7,6 +7,9 @@ import androidx.compose.ui.Modifier import com.adammcneilly.pocketleague.shared.screens.Navigation import com.google.accompanist.insets.systemBarsPadding +/** + * A [OnePane] layout is used any time we want to show a single piece of content, typically on phones or other compact screens. + */ @Composable fun Navigation.OnePane( saveableStateHolder: SaveableStateHolder, diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/Router.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/Router.kt index 87fa6d27f..83d44873f 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/Router.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/Router.kt @@ -7,6 +7,10 @@ import androidx.compose.runtime.saveable.rememberSaveableStateHolder import androidx.compose.ui.unit.dp import com.adammcneilly.pocketleague.shared.screens.Navigation +/** + * The Router is used to track screen states and show a [OnePane] or [TwoPane] layout based on + * available space. + */ @Composable fun Navigation.Router() { val screenUIsStateHolder = rememberSaveableStateHolder() diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt index ecf2f2aff..c637a71b3 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt @@ -3,16 +3,19 @@ package com.adammcneilly.pocketleague.ui import androidx.compose.material.Text import androidx.compose.runtime.Composable import com.adammcneilly.pocketleague.shared.screens.Navigation -import com.adammcneilly.pocketleague.shared.screens.Screen import com.adammcneilly.pocketleague.shared.screens.ScreenIdentifier +import com.adammcneilly.pocketleague.shared.screens.Screens +/** + * The screen picker tacks a current [screenIdentifier] and renders the content for that screen. + */ @Composable fun Navigation.ScreenPicker( screenIdentifier: ScreenIdentifier ) { when (screenIdentifier.screen) { - Screen.Feed -> { + Screens.Feed -> { Text(text = "Feed Screen") } } diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/TopBar.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/TopBar.kt index 5e1657559..2fc66a189 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/TopBar.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/TopBar.kt @@ -4,6 +4,9 @@ import androidx.compose.material.Text import androidx.compose.material.TopAppBar import androidx.compose.runtime.Composable +/** + * This shows the top toolbar at the top of an application. + */ @Composable fun TopBar( title: String diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/TwoPane.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/TwoPane.kt index 84458d218..ce2440ead 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/TwoPane.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/TwoPane.kt @@ -14,6 +14,11 @@ import androidx.compose.ui.unit.dp import com.adammcneilly.pocketleague.shared.screens.Navigation import com.adammcneilly.pocketleague.shared.screens.ScreenIdentifier +/** + * A [TwoPane] layout is used to show two selections of content side by side. Something like this + * is helpful on tablets or large screens to use up available screen space. + */ +@Suppress("MagicNumber") @Composable fun Navigation.TwoPane( saveableStateHolder: SaveableStateHolder @@ -56,6 +61,10 @@ fun Navigation.TwoPane( ) } +/** + * For a given [screenIdentifier], create a default UI for the detail pane of a two pane layout. + * If there's no default data to supply, we can just use a Box. + */ @Composable fun Navigation.TwoPaneDefaultDetail( screenIdentifier: ScreenIdentifier diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/AppState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/AppState.kt index e1966ad6a..5ee80f797 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/AppState.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/AppState.kt @@ -7,7 +7,10 @@ package com.adammcneilly.pocketleague.shared.screens data class AppState( val recompositionIndex: Int = 0, ) { - fun getNavigation(model: DKMPViewModel): Navigation { - return model.navigation + /** + * Returns the [Navigation] instance for the given [viewModel]. + */ + fun getNavigation(viewModel: DKMPViewModel): Navigation { + return viewModel.navigation } } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Level1Navigation.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Level1Navigation.kt index 7382b01e7..1b1a07cb0 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Level1Navigation.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Level1Navigation.kt @@ -10,6 +10,6 @@ enum class Level1Navigation( val rememberVerticalStack: Boolean = false, ) { Feed( - screenIdentifier = ScreenIdentifier.get(screen = Screen.Feed, params = null), + screenIdentifier = ScreenIdentifier.get(screen = Screens.Feed, params = null), ), } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt index 37f339a7a..b39df1696 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt @@ -78,7 +78,7 @@ class Navigation( /** * Navigates to a given [screen] with the provides [params]. */ - fun navigate(screen: Screen, params: ScreenParams? = null) { + fun navigate(screen: Screens, params: ScreenParams? = null) { navigateByScreenIdentifier(ScreenIdentifier.get(screen, params)) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenIdentifier.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenIdentifier.kt index af857bd94..bb2346b3b 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenIdentifier.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenIdentifier.kt @@ -4,12 +4,12 @@ import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json /** - * This defines a unique identifier for a [screen] within the app. This is different from [Screen] + * This defines a unique identifier for a [screen] within the app. This is different from [Screens] * because the underlying UI might be identical, but the [params] could be different and as such * should be treated as a new identifier. */ class ScreenIdentifier private constructor( - val screen: Screen, + val screen: Screens, var params: ScreenParams? = null, val paramsAsString: String? = null, ) { @@ -86,15 +86,25 @@ class ScreenIdentifier private constructor( return false } + /** + * Factory methods used to create an instance of a [ScreenIdentifier]. + */ companion object Factory { - fun get(screen: Screen, params: ScreenParams?): ScreenIdentifier { + /** + * Create a new [ScreenIdentifier] for the supplied [screen] and its optional [params]. + */ + fun get(screen: Screens, params: ScreenParams?): ScreenIdentifier { return ScreenIdentifier(screen, params, null) } + /** + * Given some [uri], split it up to screen:params and use that to generate a [ScreenIdentifier] + * if possible. + */ fun getByURI(uri: String): ScreenIdentifier? { val parts = uri.split(":") - Screen.values().forEach { + Screens.values().forEach { if (it.asString == parts[0]) { return ScreenIdentifier(it, null, parts[1]) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenInitSettings.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenInitSettings.kt index 1f03eb7ba..b6c1119f1 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenInitSettings.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/ScreenInitSettings.kt @@ -9,6 +9,9 @@ package com.adammcneilly.pocketleague.shared.screens * Fourth, the [callOnInit] function likely makes a call to the [StateManager] to update the screen, which will update * and trigger the SECOND recomposition. * + * @property[title] The user friendly description of this screen. + * @property[initState] A function used to create the initial [ScreenState]. + * @property[callOnInit] A function invoked when this screen is initialized. * @property[reInitOnEachNavigation] If true, the [callOnInit] function is invoked each time the * user returns to this screen. * @property[callOnInitAlsoAfterBackground] If true, the [callOnInit] function will be invoked if diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt index 2c4dea6a5..c94d8bca5 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt @@ -5,7 +5,7 @@ import com.adammcneilly.pocketleague.shared.screens.feed.initFeed /** * An enumeration of all screens that appear somewhere in our application. */ -enum class Screen( +enum class Screens( val asString: String, val navigationLevel: Int = 1, val initSettings: Navigation.(ScreenIdentifier) -> ScreenInitSettings, diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt index 9765eeadc..d22d588e6 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt @@ -13,6 +13,7 @@ import kotlin.reflect.KClass * Manages our current [AppState] as well as the backstacks and screen scopes for everything in memory * at any given moment. */ +@Suppress("TooManyFunctions") class StateManager { internal val mutableStateFlow = MutableStateFlow(AppState()) @@ -130,6 +131,10 @@ class StateManager { return false } + /** + * Updates any screens with the matching [stateClass]. The update is calculated through the + * given [update] lambda. + */ inline fun updateScreen( stateClass: KClass, update: (T) -> T, @@ -203,7 +208,8 @@ class StateManager { return } - if (currentScreenIdentifier.screen == screenIdentifier.screen && !screenIdentifier.screen.stackableInstances) { + val isCurrentScreen = (currentScreenIdentifier.screen == screenIdentifier.screen) + if (isCurrentScreen && !screenIdentifier.screen.stackableInstances) { val currentScreenId = currentScreenIdentifier currentVerticalNavigationLevelsMap.remove(currentScreenId.screen.navigationLevel) currentVerticalBackstack.remove(currentScreenId) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt index 370fa121c..c91663642 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt @@ -4,7 +4,7 @@ import com.adammcneilly.pocketleague.shared.screens.Navigation import com.adammcneilly.pocketleague.shared.screens.ScreenInitSettings /** - * Returns the [ScreenInitSettings] for our [com.adammcneilly.pocketleague.shared.screens.Screen.Feed] screen. + * Returns the [ScreenInitSettings] for our [com.adammcneilly.pocketleague.shared.screens.Screens.Feed] screen. */ fun Navigation.initFeed(): ScreenInitSettings { return ScreenInitSettings( diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedState.kt index d50548b39..eedf3fb48 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedState.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedState.kt @@ -4,7 +4,7 @@ import com.adammcneilly.pocketleague.shared.models.Event import com.adammcneilly.pocketleague.shared.screens.ScreenState /** - * Defines the UI configuration for the [com.adammcneilly.pocketleague.shared.screens.Screen.Feed] screen. + * Defines the UI configuration for the [com.adammcneilly.pocketleague.shared.screens.Screens.Feed] screen. */ data class FeedState( val showLoading: Boolean = true, From 458dacd3dde75415d00f9ba1248cb5db12911813 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Sun, 17 Apr 2022 14:03:04 -0400 Subject: [PATCH 11/40] Loading feed. --- .../pocketleague/ui/FeedContent.kt | 19 +++++++++ .../adammcneilly/pocketleague/ui/OnePane.kt | 4 +- .../pocketleague/ui/ScreenPicker.kt | 5 ++- .../shared/screens/DKMPViewModelForAndroid.kt | 6 ++- .../pocketleague/shared/data/Repository.kt | 33 +++++++++++++++ .../shared/screens/DKMPViewModel.kt | 9 +++- .../pocketleague/shared/screens/Events.kt | 20 +++++++++ .../pocketleague/shared/screens/Navigation.kt | 20 +++++++-- .../shared/screens/StateManager.kt | 5 ++- .../shared/screens/StateProvider.kt | 22 ++++++++++ .../shared/screens/feed/FeedInitSettings.kt | 4 +- .../feed/{FeedState.kt => FeedViewState.kt} | 3 +- .../shared/screens/feed/LoadFeedEvent.kt | 42 +++++++++++++++++++ 13 files changed, 178 insertions(+), 14 deletions(-) create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Events.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateProvider.kt rename shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/{FeedState.kt => FeedViewState.kt} (86%) create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt new file mode 100644 index 000000000..3195286b0 --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt @@ -0,0 +1,19 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.adammcneilly.pocketleague.shared.screens.feed.FeedViewState + +/** + * Shows content inside the feed screen for the given [viewState]. + */ +@Composable +fun FeedContent( + viewState: FeedViewState, + modifier: Modifier = Modifier, +) { + Text( + text = viewState.toString(), + ) +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt index f6bb2fbd9..34eef8edc 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt @@ -16,7 +16,9 @@ fun Navigation.OnePane( modifier: Modifier = Modifier, ) { Scaffold( - topBar = { TopBar(getTitle(currentScreenIdentifier)) }, + topBar = { + TopBar(getTitle(currentScreenIdentifier)) + }, content = { saveableStateHolder.SaveableStateProvider(currentScreenIdentifier.uri) { ScreenPicker(currentScreenIdentifier) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt index c637a71b3..6d5d6b9a8 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt @@ -1,6 +1,5 @@ package com.adammcneilly.pocketleague.ui -import androidx.compose.material.Text import androidx.compose.runtime.Composable import com.adammcneilly.pocketleague.shared.screens.Navigation import com.adammcneilly.pocketleague.shared.screens.ScreenIdentifier @@ -16,7 +15,9 @@ fun Navigation.ScreenPicker( when (screenIdentifier.screen) { Screens.Feed -> { - Text(text = "Feed Screen") + FeedContent( + viewState = stateProvider.get(screenIdentifier), + ) } } } diff --git a/shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModelForAndroid.kt b/shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModelForAndroid.kt index 6502daae5..d0aedc20a 100644 --- a/shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModelForAndroid.kt +++ b/shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModelForAndroid.kt @@ -1,8 +1,12 @@ package com.adammcneilly.pocketleague.shared.screens +import com.adammcneilly.pocketleague.shared.data.Repository + /** * Creates an instance of a [DKMPViewModel] to be used within an Android application. */ fun DKMPViewModel.Factory.getAndroidInstance(): DKMPViewModel { - return DKMPViewModel() + return DKMPViewModel( + repository = Repository(), + ) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt new file mode 100644 index 000000000..ba6df87ab --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt @@ -0,0 +1,33 @@ +package com.adammcneilly.pocketleague.shared.data + +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGAPIClient +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.services.OctaneGGEventService +import com.adammcneilly.pocketleague.shared.data.repositories.EventRepository +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +/** + * This class combines all of the relevant data sources used by the pocket league application. + * + * @property[useDefaultDispatcher] Defaults to true, meaning we run async work on Dispatchers.Default. + * We can supply a value of false to be used for testing. + */ +class Repository( + private val useDefaultDispatcher: Boolean = true, +) { + internal val eventRepository: EventRepository by lazy { + OctaneGGEventService( + apiClient = OctaneGGAPIClient(), + ) + } + + suspend fun withRepoContext(block: suspend () -> T): T { + return if (useDefaultDispatcher) { + withContext(Dispatchers.Default) { + block() + } + } else { + block() + } + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModel.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModel.kt index a7fedb70f..fd8f95592 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModel.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModel.kt @@ -1,13 +1,18 @@ package com.adammcneilly.pocketleague.shared.screens +import com.adammcneilly.pocketleague.shared.data.Repository import kotlinx.coroutines.flow.StateFlow /** * Root view model for the application that exposes a [stateFlow] of our application's state. */ -class DKMPViewModel { +class DKMPViewModel( + private val repository: Repository, +) { - private val stateManager by lazy { StateManager() } + private val stateManager by lazy { + StateManager(repository) + } val stateFlow: StateFlow get() = stateManager.mutableStateFlow diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Events.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Events.kt new file mode 100644 index 000000000..b8cd18780 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Events.kt @@ -0,0 +1,20 @@ +package com.adammcneilly.pocketleague.shared.screens + +import com.adammcneilly.pocketleague.shared.data.Repository + +/** + * This class manages all of the event handling for various screens, specifically + * exposing the [screenCoroutine] function to run asynchronous work. + */ +class Events( + val stateManager: StateManager, +) { + val dataRepository: Repository + get() = stateManager.repository + + fun screenCoroutine(block: suspend () -> Unit) { + stateManager.runInScreenScope { + block() + } + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt index b39df1696..a3c18a3db 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt @@ -4,11 +4,23 @@ package com.adammcneilly.pocketleague.shared.screens * This class manages all of the navigation logic within the pocket league app. */ class Navigation( - val stateManager: StateManager, + private val stateManager: StateManager, ) { - // val stateProvider by lazy { StateProvider(stateManager) } - // val events by lazy { Events(stateManager) } - // val dataRepository = stateManager.dataRepository + /** + * Creates a [StateProvider] allowing apps to get the state of necessary + * screens during navigation. + */ + val stateProvider by lazy { + StateProvider(stateManager) + } + + /** + * Creates an [Events] instance which we can use to trigger actions and state + * updates for screen. + */ + val events by lazy { + Events(stateManager) + } init { val startScreenIdentifier = NavigationSettings.homeScreen.screenIdentifier diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt index d22d588e6..f5011702b 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt @@ -1,5 +1,6 @@ package com.adammcneilly.pocketleague.shared.screens +import com.adammcneilly.pocketleague.shared.data.Repository import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -14,7 +15,9 @@ import kotlin.reflect.KClass * at any given moment. */ @Suppress("TooManyFunctions") -class StateManager { +class StateManager( + val repository: Repository, +) { internal val mutableStateFlow = MutableStateFlow(AppState()) /** diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateProvider.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateProvider.kt new file mode 100644 index 000000000..793c66f1b --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateProvider.kt @@ -0,0 +1,22 @@ +package com.adammcneilly.pocketleague.shared.screens + +/** + * This class provides a way to get the [ScreenState] of a specific screen as needed. + */ +class StateProvider(val stateManager: StateManager) { + /** + * Pulls the current [ScreenState] from the given [screenIdentifier]. + */ + inline fun get(screenIdentifier: ScreenIdentifier): T { + return stateManager.screenStatesMap[screenIdentifier.uri] as T + } + + /** + * Reified functions cannot be exported to iOS, so we use this function + * to return the [ScreenState] interface type, which we then need to cast to the + * specific state class. + */ + fun getToCast(screenIdentifier: ScreenIdentifier): ScreenState? { + return stateManager.screenStatesMap[screenIdentifier.uri] + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt index c91663642..3d3edda08 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt @@ -10,10 +10,10 @@ fun Navigation.initFeed(): ScreenInitSettings { return ScreenInitSettings( title = "Feed", initState = { - FeedState() + FeedViewState() }, callOnInit = { - // Coming soon? + events.loadFeed() }, reInitOnEachNavigation = true, ) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt similarity index 86% rename from shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedState.kt rename to shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt index eedf3fb48..a389800c9 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedState.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt @@ -6,7 +6,8 @@ import com.adammcneilly.pocketleague.shared.screens.ScreenState /** * Defines the UI configuration for the [com.adammcneilly.pocketleague.shared.screens.Screens.Feed] screen. */ -data class FeedState( +data class FeedViewState( val showLoading: Boolean = true, val upcomingEvents: List? = null, + val errorMessage: String? = null, ) : ScreenState diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt new file mode 100644 index 000000000..0291bb51b --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt @@ -0,0 +1,42 @@ +package com.adammcneilly.pocketleague.shared.screens.feed + +import com.adammcneilly.pocketleague.shared.eventlist.GetUpcomingEventsUseCase +import com.adammcneilly.pocketleague.shared.eventlist.GetUpcomingEventsUseCaseImpl +import com.adammcneilly.pocketleague.shared.screens.Events +import kotlinx.coroutines.flow.collect + +/** + * Loads the information for the feed state. + */ +fun Events.loadFeed() = screenCoroutine { + val upcomingEventsUseCase = GetUpcomingEventsUseCaseImpl(dataRepository.eventRepository) + + val upcomingEventsFlow = upcomingEventsUseCase.invoke() + + upcomingEventsFlow.collect { useCaseResult -> + stateManager.updateScreen(FeedViewState::class) { + when (useCaseResult) { + is GetUpcomingEventsUseCase.Result.Success -> { + it.copy( + showLoading = false, + upcomingEvents = useCaseResult.events, + ) + } + is GetUpcomingEventsUseCase.Result.Error -> { + it.copy( + showLoading = false, + errorMessage = useCaseResult.error.message, + ) + } + } + } + } +} + +// fun Events.selectFavorite(countryName: String) = screenCoroutine { +// val favorites = dataRepository.getFavoriteCountriesMap(alsoToggleCountry = countryName) +// // update state with new favorites map, after toggling the value for the specified country +// stateManager.updateScreen(CountriesListState::class) { +// it.copy(favoriteCountries = favorites) +// } +// } From 6812e53f7b781e6d5de873c6a6124e7dcfeb8b9e Mon Sep 17 00:00:00 2001 From: amcneilly Date: Sun, 17 Apr 2022 14:04:09 -0400 Subject: [PATCH 12/40] Docs. --- .../com/adammcneilly/pocketleague/shared/data/Repository.kt | 4 ++++ .../com/adammcneilly/pocketleague/shared/screens/Events.kt | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt index ba6df87ab..ed409c780 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt @@ -21,6 +21,10 @@ class Repository( ) } + /** + * This will run the supplied [block] using the coroutine context of a default + * dispatcher if [useDefaultDispatcher] is true. + */ suspend fun withRepoContext(block: suspend () -> T): T { return if (useDefaultDispatcher) { withContext(Dispatchers.Default) { diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Events.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Events.kt index b8cd18780..b51c2031a 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Events.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Events.kt @@ -12,6 +12,10 @@ class Events( val dataRepository: Repository get() = stateManager.repository + /** + * This will run the supplied [block] inside the coroutine scope of the current + * screen. + */ fun screenCoroutine(block: suspend () -> Unit) { stateManager.runInScreenScope { block() From d72abd3b28d4ae3146f709e96d4871b6de811af5 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Sun, 17 Apr 2022 14:17:05 -0400 Subject: [PATCH 13/40] Showing events on feed. --- .../adammcneilly/pocketleague/ui/EventList.kt | 29 +++++++++++++++++ .../pocketleague/ui/EventListItem.kt | 24 ++++++++++++++ .../pocketleague/ui/FeedContent.kt | 31 ++++++++++++++++--- .../pocketleague/ui/ScreenPicker.kt | 2 +- .../octanegg/services/OctaneGGEventService.kt | 2 +- .../shared/screens/feed/LoadFeedEvent.kt | 8 ----- 6 files changed, 82 insertions(+), 14 deletions(-) create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/EventList.kt create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/EventList.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventList.kt new file mode 100644 index 000000000..8bf5e88f4 --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventList.kt @@ -0,0 +1,29 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.material.Divider +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.adammcneilly.pocketleague.shared.models.Event + +/** + * Show a list of [events] inside of a lazy column. + */ +@Composable +fun EventList( + events: List, + modifier: Modifier = Modifier, +) { + LazyColumn( + modifier = modifier, + ) { + itemsIndexed(events) { index, event -> + EventListItem(event = event) + + if (index != events.lastIndex) { + Divider() + } + } + } +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt new file mode 100644 index 000000000..6a2fb4e3e --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt @@ -0,0 +1,24 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.ListItem +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import com.adammcneilly.pocketleague.shared.models.Event + +/** + * Used to show a specific [event] inside of a list. + */ +@OptIn(ExperimentalMaterialApi::class) +@Composable +fun EventListItem( + event: Event, +) { + ListItem( + text = { + Text( + text = event.name, + ) + }, + ) +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt index 3195286b0..3995bfa23 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt @@ -1,7 +1,12 @@ package com.adammcneilly.pocketleague.ui -import androidx.compose.material.Text +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.material.CircularProgressIndicator import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import com.adammcneilly.pocketleague.shared.screens.feed.FeedViewState @@ -13,7 +18,25 @@ fun FeedContent( viewState: FeedViewState, modifier: Modifier = Modifier, ) { - Text( - text = viewState.toString(), - ) + Box( + modifier = modifier.fillMaxSize(), + ) { + if (viewState.showLoading) { + CircularProgressIndicator( + modifier = Modifier + .wrapContentSize() + .align(Alignment.Center), + ) + } + + val upcomingEvents = viewState.upcomingEvents + + if (upcomingEvents != null) { + EventList( + events = upcomingEvents, + modifier = Modifier + .fillMaxWidth() + ) + } + } } diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt index 6d5d6b9a8..88de34037 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt @@ -10,7 +10,7 @@ import com.adammcneilly.pocketleague.shared.screens.Screens */ @Composable fun Navigation.ScreenPicker( - screenIdentifier: ScreenIdentifier + screenIdentifier: ScreenIdentifier, ) { when (screenIdentifier.screen) { diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt index 4b35f9c5e..5dc2bfb3b 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt @@ -50,7 +50,7 @@ class OctaneGGEventService( private fun HttpRequestBuilder.addEventParameters(request: EventListRequest) { val dateTimeFormatter = DateTimeFormatter() - val octaneGGDateFormat = "yyyy-mm-dd" + val octaneGGDateFormat = "yyyy-MM-dd" if (request.group != null) { this.parameter("group", request.group) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt index 0291bb51b..9eda3faf2 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt @@ -32,11 +32,3 @@ fun Events.loadFeed() = screenCoroutine { } } } - -// fun Events.selectFavorite(countryName: String) = screenCoroutine { -// val favorites = dataRepository.getFavoriteCountriesMap(alsoToggleCountry = countryName) -// // update state with new favorites map, after toggling the value for the specified country -// stateManager.updateScreen(CountriesListState::class) { -// it.copy(favoriteCountries = favorites) -// } -// } From 91c8cc0f87fd94ad6f1fbb5e5aaa151d5bcbcce8 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Sun, 17 Apr 2022 14:37:17 -0400 Subject: [PATCH 14/40] Showing upcoming events. --- app/build.gradle.kts | 1 + .../adammcneilly/pocketleague/ui/EventListItem.kt | 13 +++++++++++++ .../remote/octanegg/mappers/OctaneGGEventMapper.kt | 9 +++++++++ .../octanegg/services/OctaneGGEventService.kt | 5 ++++- .../pocketleague/shared/models/Event.kt | 4 ++++ 5 files changed, 31 insertions(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b763287dd..12fe17cce 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -86,6 +86,7 @@ dependencies { implementation(project(":android-design-system")) implementation(project(":shared")) + implementation("org.jetbrains.kotlinx:kotlinx-datetime:${Versions.kotlinxDatetime}") implementation("androidx.core:core-ktx:${Versions.ktxCore}") implementation("androidx.appcompat:appcompat:${Versions.appCompat}") implementation("com.google.android.material:material:${Versions.material}") diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt index 6a2fb4e3e..5255da9ea 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt @@ -4,6 +4,7 @@ import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ListItem import androidx.compose.material.Text import androidx.compose.runtime.Composable +import com.adammcneilly.pocketleague.shared.datetime.DateTimeFormatter import com.adammcneilly.pocketleague.shared.models.Event /** @@ -14,11 +15,23 @@ import com.adammcneilly.pocketleague.shared.models.Event fun EventListItem( event: Event, ) { + val startDateString = event.startDate?.let { startDate -> + DateTimeFormatter().formatLocalDateTime( + localDateTime = startDate, + formatPattern = "MMM dd, yyyy" + ) + } + ListItem( text = { Text( text = event.name, ) }, + overlineText = startDateString?.let { + @Composable { + Text(text = startDateString) + } + }, ) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGEventMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGEventMapper.kt index 286f0d1a4..74f0b81a6 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGEventMapper.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGEventMapper.kt @@ -2,6 +2,9 @@ package com.adammcneilly.pocketleague.shared.data.remote.octanegg.mappers import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGEvent import com.adammcneilly.pocketleague.shared.models.Event +import kotlinx.datetime.Instant +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toLocalDateTime /** * Converts an [OctaneGGEvent] entity into an [Event] within the Pocket League domain. @@ -10,5 +13,11 @@ fun OctaneGGEvent.toEvent(): Event { return Event( id = this.id ?: "ID Not Available", name = this.name ?: "Name Not Available", + startDate = this.startDate?.let { + Instant.parse(it) + }?.toLocalDateTime(TimeZone.UTC), + endDate = this.endDate?.let { + Instant.parse(it) + }?.toLocalDateTime(TimeZone.UTC), ) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt index 5dc2bfb3b..d36c7010a 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt @@ -36,7 +36,10 @@ class OctaneGGEventService( val mappedResult = when (apiResult) { is DataResult.Success -> { val mappedEvents = apiResult.data.events?.map(OctaneGGEvent::toEvent).orEmpty() - DataResult.Success(mappedEvents) + + val sortedEvents = mappedEvents.sortedBy(Event::startDate) + + DataResult.Success(sortedEvents) } is DataResult.Error -> { DataResult.Error(apiResult.error) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt index a2d2cbf44..677e0e551 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt @@ -1,5 +1,7 @@ package com.adammcneilly.pocketleague.shared.models +import kotlinx.datetime.LocalDateTime + /** * Defines any Rocket League event that can occur to allow a number of teams or players * to compete. @@ -10,4 +12,6 @@ package com.adammcneilly.pocketleague.shared.models data class Event( val id: String, val name: String, + val startDate: LocalDateTime?, + val endDate: LocalDateTime?, ) From 63be4271fa72af1c9f8dc0ba34739707a13a4aca Mon Sep 17 00:00:00 2001 From: amcneilly Date: Sun, 17 Apr 2022 14:48:38 -0400 Subject: [PATCH 15/40] docs. --- .../kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt index 677e0e551..683d4232c 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt @@ -8,6 +8,8 @@ import kotlinx.datetime.LocalDateTime * * @property[id] A unique identifier for this event. * @property[name] The description of this event, such as "RLCS Winter Split Regional 1". + * @property[startDate] The date that this event begins. + * @property[endDate] The date that this event stops. */ data class Event( val id: String, From 815adbe391888214d99318ce4e2e4974e304b71d Mon Sep 17 00:00:00 2001 From: amcneilly Date: Mon, 18 Apr 2022 10:28:41 -0400 Subject: [PATCH 16/40] Event images. --- app/build.gradle.kts | 1 + .../pocketleague/ui/EventListItem.kt | 34 +++++++++++++------ .../adammcneilly/pocketleague/ui/OnePane.kt | 7 ++-- .../pocketleague/ui/ScreenPicker.kt | 6 ++++ .../octanegg/mappers/OctaneGGEventMapper.kt | 1 + .../pocketleague/shared/models/Event.kt | 2 ++ 6 files changed, 39 insertions(+), 12 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 12fe17cce..9e26bb0ab 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -100,6 +100,7 @@ dependencies { implementation("com.google.accompanist:accompanist-systemuicontroller:${Versions.accompanist}") implementation("androidx.window:window:${Versions.windowManager}") implementation("androidx.lifecycle:lifecycle-process:2.4.1") + implementation("io.coil-kt:coil-compose:2.0.0-rc03") kapt("com.google.dagger:hilt-compiler:${Versions.hilt}") testImplementation("junit:junit:${Versions.junit}") testImplementation("com.google.truth:truth:${Versions.truth}") diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt index 5255da9ea..74c3f800c 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt @@ -1,9 +1,15 @@ package com.adammcneilly.pocketleague.ui +import androidx.compose.foundation.layout.size import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ListItem import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage +import coil.request.ImageRequest import com.adammcneilly.pocketleague.shared.datetime.DateTimeFormatter import com.adammcneilly.pocketleague.shared.models.Event @@ -15,23 +21,31 @@ import com.adammcneilly.pocketleague.shared.models.Event fun EventListItem( event: Event, ) { - val startDateString = event.startDate?.let { startDate -> - DateTimeFormatter().formatLocalDateTime( - localDateTime = startDate, - formatPattern = "MMM dd, yyyy" - ) - } - ListItem( text = { Text( text = event.name, ) }, - overlineText = startDateString?.let { - @Composable { - Text(text = startDateString) + overlineText = { + val startDateString = event.startDate?.let { startDate -> + DateTimeFormatter().formatLocalDateTime( + localDateTime = startDate, + formatPattern = "MMM dd, yyyy", + ) } + + Text(text = startDateString.orEmpty()) + }, + icon = { + AsyncImage( + model = ImageRequest.Builder(LocalContext.current) + .data(event.imageUrl) + .crossfade(true) + .build(), + contentDescription = "Event Image", + modifier = Modifier.size(48.dp), + ) }, ) } diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt index 34eef8edc..0376218d7 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/OnePane.kt @@ -19,9 +19,12 @@ fun Navigation.OnePane( topBar = { TopBar(getTitle(currentScreenIdentifier)) }, - content = { + content = { paddingValues -> saveableStateHolder.SaveableStateProvider(currentScreenIdentifier.uri) { - ScreenPicker(currentScreenIdentifier) + ScreenPicker( + currentScreenIdentifier, + paddingValues = paddingValues, + ) } }, bottomBar = { diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt index 88de34037..eb14a20c1 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt @@ -1,6 +1,9 @@ package com.adammcneilly.pocketleague.ui +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import com.adammcneilly.pocketleague.shared.screens.Navigation import com.adammcneilly.pocketleague.shared.screens.ScreenIdentifier import com.adammcneilly.pocketleague.shared.screens.Screens @@ -11,12 +14,15 @@ import com.adammcneilly.pocketleague.shared.screens.Screens @Composable fun Navigation.ScreenPicker( screenIdentifier: ScreenIdentifier, + paddingValues: PaddingValues = PaddingValues(), ) { when (screenIdentifier.screen) { Screens.Feed -> { FeedContent( viewState = stateProvider.get(screenIdentifier), + modifier = Modifier + .padding(paddingValues), ) } } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGEventMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGEventMapper.kt index 74f0b81a6..d3320f3b7 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGEventMapper.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGEventMapper.kt @@ -19,5 +19,6 @@ fun OctaneGGEvent.toEvent(): Event { endDate = this.endDate?.let { Instant.parse(it) }?.toLocalDateTime(TimeZone.UTC), + imageUrl = this.image, ) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt index 683d4232c..8a8669552 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt @@ -10,10 +10,12 @@ import kotlinx.datetime.LocalDateTime * @property[name] The description of this event, such as "RLCS Winter Split Regional 1". * @property[startDate] The date that this event begins. * @property[endDate] The date that this event stops. + * @property[imageUrl] The URL to the remotely hosted image for this event. */ data class Event( val id: String, val name: String, val startDate: LocalDateTime?, val endDate: LocalDateTime?, + val imageUrl: String?, ) From a9cc8e33be5eb6e1a101614db71a503f1f052656 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Mon, 18 Apr 2022 10:48:03 -0400 Subject: [PATCH 17/40] Adding match models & mappers. --- .../octanegg/mappers/OctaneGGMatchMapper.kt | 22 +++++++++++++++++++ .../mappers/OctaneGGMatchTeamResultMapper.kt | 15 +++++++++++++ .../mappers/OctaneGGTeamOverviewMapper.kt | 15 +++++++++++++ .../octanegg/models/OctaneGGCoreStats.kt | 21 ++++++++++++++++++ .../remote/octanegg/models/OctaneGGMatch.kt | 21 ++++++++++++++++++ .../models/OctaneGGMatchTeamResult.kt | 19 ++++++++++++++++ .../remote/octanegg/models/OctaneGGStats.kt | 11 ++++++++++ .../octanegg/models/OctaneGGTeamStats.kt | 13 +++++++++++ .../pocketleague/shared/models/Match.kt | 15 +++++++++++++ .../shared/models/MatchTeamResult.kt | 10 +++++++++ .../pocketleague/shared/models/Team.kt | 11 ++++++++++ 11 files changed, 173 insertions(+) create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchMapper.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchTeamResultMapper.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGTeamOverviewMapper.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGCoreStats.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatch.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchTeamResult.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStats.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamStats.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Match.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/MatchTeamResult.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Team.kt diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchMapper.kt new file mode 100644 index 000000000..dd22ab729 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchMapper.kt @@ -0,0 +1,22 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.mappers + +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGMatch +import com.adammcneilly.pocketleague.shared.models.Match +import kotlinx.datetime.Instant +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toLocalDateTime + +/** + * Converts an [OctaneGGMatch] to a [Match] entity. + */ +fun OctaneGGMatch.toMatch(): Match { + return Match( + id = this.id!!, + event = this.event?.toEvent()!!, + date = this.date?.let { date -> + Instant.parse(date) + }?.toLocalDateTime(TimeZone.UTC), + blueTeam = this.blue?.toMatchTeamResult()!!, + orangeTeam = this.orange?.toMatchTeamResult()!!, + ) +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchTeamResultMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchTeamResultMapper.kt new file mode 100644 index 000000000..14ea2267a --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchTeamResultMapper.kt @@ -0,0 +1,15 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.mappers + +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGMatchTeamResult +import com.adammcneilly.pocketleague.shared.models.MatchTeamResult + +/** + * Converts an [OctaneGGMatchTeamResult] to a [MatchTeamResult] entity. + */ +fun OctaneGGMatchTeamResult.toMatchTeamResult(): MatchTeamResult { + return MatchTeamResult( + score = this.score ?: 0, + winner = this.winner == true, + team = this.team?.team?.toTeam()!!, + ) +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGTeamOverviewMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGTeamOverviewMapper.kt new file mode 100644 index 000000000..188fb5f6e --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGTeamOverviewMapper.kt @@ -0,0 +1,15 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.mappers + +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGTeamOverview +import com.adammcneilly.pocketleague.shared.models.Team + +/** + * Converts an [OctaneGGTeamOverview] to a [Team] entity. + */ +fun OctaneGGTeamOverview.toTeam(): Team { + return Team( + id = this.id!!, + name = this.name!!, + imageUrl = this.image, + ) +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGCoreStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGCoreStats.kt new file mode 100644 index 000000000..f9a8d93a9 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGCoreStats.kt @@ -0,0 +1,21 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName + +/** + * The core stats to track for a player or a team in any given match or stretch of time. + */ +data class OctaneGGCoreStats( + @SerialName("shots") + val shots: Int? = null, + @SerialName("goals") + val goals: Int? = null, + @SerialName("saves") + val saves: Int? = null, + @SerialName("assists") + val assists: Int? = null, + @SerialName("score") + val score: Int? = null, + @SerialName("shootingPercentage") + val shootingPercentage: Float? = null, +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatch.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatch.kt new file mode 100644 index 000000000..3968fcd0b --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatch.kt @@ -0,0 +1,21 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName + +/** + * Represents a match between two teams, [blue] and [orange]. + */ +data class OctaneGGMatch( + @SerialName("_id") + val id: String? = null, + @SerialName("slug") + val slug: String? = null, + @SerialName("event") + val event: OctaneGGEvent? = null, + @SerialName("date") + val date: String? = null, + @SerialName("blue") + val blue: OctaneGGMatchTeamResult? = null, + @SerialName("orange") + val orange: OctaneGGMatchTeamResult? = null, +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchTeamResult.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchTeamResult.kt new file mode 100644 index 000000000..19075d753 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchTeamResult.kt @@ -0,0 +1,19 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName + +/** + * Shows the result of a specific [team] within a match. + * + * @property[score] The score for this [team] during the match. + * @property[winner] If true, this [team] is the winner of the match. + * @property[team] Information about the team and their stats. + */ +data class OctaneGGMatchTeamResult( + @SerialName("score") + val score: Int? = null, + @SerialName("winner") + val winner: Boolean? = null, + @SerialName("team") + val team: OctaneGGTeamStats? = null, +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStats.kt new file mode 100644 index 000000000..e7e683a20 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStats.kt @@ -0,0 +1,11 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName + +/** + * Tracks any number of statistics relevant to a player or team. + */ +data class OctaneGGStats( + @SerialName("core") + val core: OctaneGGCoreStats? = null, +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamStats.kt new file mode 100644 index 000000000..47320b38e --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamStats.kt @@ -0,0 +1,13 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName + +/** + * Combination of a [team] and their [stats] for a match or event. + */ +data class OctaneGGTeamStats( + @SerialName("team") + val team: OctaneGGTeamOverview? = null, + @SerialName("stats") + val stats: OctaneGGStats? = null, +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Match.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Match.kt new file mode 100644 index 000000000..bedd8bc2e --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Match.kt @@ -0,0 +1,15 @@ +package com.adammcneilly.pocketleague.shared.models + +import kotlinx.datetime.LocalDateTime + +/** + * A [Match] is any competition between two teams. Could be a single game, a series, + * or even a best of set. + */ +data class Match( + val id: String, + val event: Event, + val date: LocalDateTime?, + val blueTeam: MatchTeamResult, + val orangeTeam: MatchTeamResult, +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/MatchTeamResult.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/MatchTeamResult.kt new file mode 100644 index 000000000..67c878cd7 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/MatchTeamResult.kt @@ -0,0 +1,10 @@ +package com.adammcneilly.pocketleague.shared.models + +/** + * The result of a particular [team] within a [Match]. + */ +data class MatchTeamResult( + val score: Int, + val winner: Boolean, + val team: Team, +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Team.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Team.kt new file mode 100644 index 000000000..cf23bc6b4 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Team.kt @@ -0,0 +1,11 @@ +package com.adammcneilly.pocketleague.shared.models + +/** + * Represents a team that either actively or has in the past participated in a Rocket + * League event. + */ +data class Team( + val id: String, + val name: String, + val imageUrl: String?, +) From 3252472c37249a051197f8fd1154c95ad4e97642 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Mon, 18 Apr 2022 11:13:13 -0400 Subject: [PATCH 18/40] Fetching events. --- .../pocketleague/shared/data/Repository.kt | 6 ++ .../shared/data/models/MatchListRequest.kt | 14 ++++ .../data/remote/octanegg/OctaneGGEndpoints.kt | 1 + .../octanegg/models/OctaneGGCoreStats.kt | 2 + .../remote/octanegg/models/OctaneGGMatch.kt | 2 + .../models/OctaneGGMatchListResponse.kt | 19 ++++++ .../models/OctaneGGMatchTeamResult.kt | 2 + .../remote/octanegg/models/OctaneGGStats.kt | 2 + .../octanegg/models/OctaneGGTeamStats.kt | 2 + .../octanegg/services/OctaneGGMatchService.kt | 64 +++++++++++++++++++ .../data/repositories/MatchRepository.kt | 20 ++++++ .../matchlist/GetRecentMatchesUseCase.kt | 37 +++++++++++ .../matchlist/GetRecentMatchesUseCaseImpl.kt | 46 +++++++++++++ .../shared/screens/feed/FeedViewState.kt | 2 + .../shared/screens/feed/LoadFeedEvent.kt | 25 ++++++++ 15 files changed, 244 insertions(+) create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/models/MatchListRequest.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchListResponse.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/MatchRepository.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCase.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCaseImpl.kt diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt index ed409c780..0c0a8fc4a 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt @@ -2,7 +2,9 @@ package com.adammcneilly.pocketleague.shared.data import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGAPIClient import com.adammcneilly.pocketleague.shared.data.remote.octanegg.services.OctaneGGEventService +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.services.OctaneGGMatchService import com.adammcneilly.pocketleague.shared.data.repositories.EventRepository +import com.adammcneilly.pocketleague.shared.data.repositories.MatchRepository import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -21,6 +23,10 @@ class Repository( ) } + internal val matchRepository: MatchRepository by lazy { + OctaneGGMatchService() + } + /** * This will run the supplied [block] using the coroutine context of a default * dispatcher if [useDefaultDispatcher] is true. diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/models/MatchListRequest.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/models/MatchListRequest.kt new file mode 100644 index 000000000..220ff6ed0 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/models/MatchListRequest.kt @@ -0,0 +1,14 @@ +package com.adammcneilly.pocketleague.shared.data.models + +import kotlinx.datetime.LocalDateTime + +/** + * Defines all of the information that will be passed into a request + * for a list of matches. + * + * If the information is null, it won't be used to filter a response at all. + */ +data class MatchListRequest( + val after: LocalDateTime? = null, + val before: LocalDateTime? = null, +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGEndpoints.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGEndpoints.kt index c3d8c4a63..9d32d2858 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGEndpoints.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGEndpoints.kt @@ -5,4 +5,5 @@ package com.adammcneilly.pocketleague.shared.data.remote.octanegg */ object OctaneGGEndpoints { const val EVENTS = "/events" + const val MATCHES = "/matches" } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGCoreStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGCoreStats.kt index f9a8d93a9..b51038f7b 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGCoreStats.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGCoreStats.kt @@ -1,10 +1,12 @@ package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable /** * The core stats to track for a player or a team in any given match or stretch of time. */ +@Serializable data class OctaneGGCoreStats( @SerialName("shots") val shots: Int? = null, diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatch.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatch.kt index 3968fcd0b..087e82f8e 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatch.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatch.kt @@ -1,10 +1,12 @@ package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable /** * Represents a match between two teams, [blue] and [orange]. */ +@Serializable data class OctaneGGMatch( @SerialName("_id") val id: String? = null, diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchListResponse.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchListResponse.kt new file mode 100644 index 000000000..4d91fbeb5 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchListResponse.kt @@ -0,0 +1,19 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * A DTO that maps to a match list response from the octane.gg API. + */ +@Serializable +data class OctaneGGMatchListResponse( + @SerialName("matches") + val matches: List? = null, + @SerialName("page") + val page: Int? = null, + @SerialName("perPage") + val perPage: Int? = null, + @SerialName("pageSize") + val pageSize: Int? = null, +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchTeamResult.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchTeamResult.kt index 19075d753..4154e2288 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchTeamResult.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchTeamResult.kt @@ -1,6 +1,7 @@ package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable /** * Shows the result of a specific [team] within a match. @@ -9,6 +10,7 @@ import kotlinx.serialization.SerialName * @property[winner] If true, this [team] is the winner of the match. * @property[team] Information about the team and their stats. */ +@Serializable data class OctaneGGMatchTeamResult( @SerialName("score") val score: Int? = null, diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStats.kt index e7e683a20..2c3ab6a91 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStats.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStats.kt @@ -1,10 +1,12 @@ package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable /** * Tracks any number of statistics relevant to a player or team. */ +@Serializable data class OctaneGGStats( @SerialName("core") val core: OctaneGGCoreStats? = null, diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamStats.kt index 47320b38e..5d79733fd 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamStats.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGTeamStats.kt @@ -1,10 +1,12 @@ package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable /** * Combination of a [team] and their [stats] for a match or event. */ +@Serializable data class OctaneGGTeamStats( @SerialName("team") val team: OctaneGGTeamOverview? = null, diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt new file mode 100644 index 000000000..342025d8c --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt @@ -0,0 +1,64 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.services + +import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.data.models.MatchListRequest +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGAPIClient +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGEndpoints +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.mappers.toMatch +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGMatch +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGMatchListResponse +import com.adammcneilly.pocketleague.shared.data.repositories.MatchRepository +import com.adammcneilly.pocketleague.shared.datetime.DateTimeFormatter +import com.adammcneilly.pocketleague.shared.models.Match +import io.ktor.client.request.HttpRequestBuilder +import io.ktor.client.request.parameter +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow + +/** + * A concrete implementation of a [MatchRepository] that will request data using + * the supplied [apiClient]. + */ +class OctaneGGMatchService( + private val apiClient: OctaneGGAPIClient = OctaneGGAPIClient(), +) : MatchRepository { + + override fun fetchMatches(request: MatchListRequest): Flow>> { + return flow { + val apiResult = apiClient.getResponse( + endpoint = OctaneGGEndpoints.MATCHES, + requestBuilder = { + addMatchParameters(request) + }, + ) + + val mappedResult = when (apiResult) { + is DataResult.Success -> { + val mappedMatches = apiResult.data.matches?.map(OctaneGGMatch::toMatch).orEmpty() + + DataResult.Success(mappedMatches) + } + is DataResult.Error -> { + DataResult.Error(apiResult.error) + } + } + + emit(mappedResult) + } + } +} + +private fun HttpRequestBuilder.addMatchParameters(request: MatchListRequest) { + val dateTimeFormatter = DateTimeFormatter() + val octaneGGDateFormat = "yyyy-MM-dd" + + if (request.after != null) { + val afterString = dateTimeFormatter.formatLocalDateTime(request.after, octaneGGDateFormat) + this.parameter("after", afterString) + } + + if (request.before != null) { + val beforeString = dateTimeFormatter.formatLocalDateTime(request.before, octaneGGDateFormat) + this.parameter("before", beforeString) + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/MatchRepository.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/MatchRepository.kt new file mode 100644 index 000000000..d2b2140c3 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/MatchRepository.kt @@ -0,0 +1,20 @@ +package com.adammcneilly.pocketleague.shared.data.repositories + +import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.data.models.MatchListRequest +import com.adammcneilly.pocketleague.shared.models.Match +import kotlinx.coroutines.flow.Flow + +/** + * Defines the data contract for dealing with data within the match space. + */ +interface MatchRepository { + + /** + * Returns a stream of [Match] entities as a list. We should only return + * events that meet the criteria defined by the given [request]. + */ + fun fetchMatches( + request: MatchListRequest, + ): Flow>> +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCase.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCase.kt new file mode 100644 index 000000000..b0f2d9a0e --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCase.kt @@ -0,0 +1,37 @@ +package com.adammcneilly.pocketleague.shared.matchlist + +import com.adammcneilly.pocketleague.shared.models.Match +import kotlinx.coroutines.flow.Flow + +/** + * A use case to fetch recent matches. The caller can customize within how many + * days "recent" is. + */ +interface GetRecentMatchesUseCase { + + /** + * @see [GetRecentMatchesUseCase] + * + * @param[numDays] The number of days back to pull recent events for. + */ + operator fun invoke(numDays: Int): Flow + + /** + * Defines all possible return types for a [GetRecentMatchesUseCase]. + */ + sealed class Result { + /** + * This will be returned when we've successfully retrieved a list of [matches]. + */ + data class Success( + val matches: List, + ) : Result() + + /** + * This will be returned if some [error] occurs when requesting a list of matches. + */ + data class Error( + val error: Throwable, + ) : Result() + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCaseImpl.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCaseImpl.kt new file mode 100644 index 000000000..735d8ca74 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCaseImpl.kt @@ -0,0 +1,46 @@ +package com.adammcneilly.pocketleague.shared.matchlist + +import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.data.models.MatchListRequest +import com.adammcneilly.pocketleague.shared.data.repositories.MatchRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import kotlinx.datetime.Clock +import kotlinx.datetime.DateTimeUnit +import kotlinx.datetime.TimeZone +import kotlinx.datetime.atStartOfDayIn +import kotlinx.datetime.minus +import kotlinx.datetime.toLocalDateTime + +/** + * A concrete implementation of a [GetRecentMatchesUseCase] that requests matches + * from the given [repository]. + */ +class GetRecentMatchesUseCaseImpl( + private val repository: MatchRepository, +) : GetRecentMatchesUseCase { + + override fun invoke(numDays: Int): Flow { + val today = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()) + + val startDate = today.date.minus(numDays, DateTimeUnit.DAY) + .atStartOfDayIn(TimeZone.currentSystemDefault()) + .toLocalDateTime(TimeZone.currentSystemDefault()) + + val request = MatchListRequest( + after = startDate, + before = today, + ) + + return repository.fetchMatches(request).map { repoResult -> + when (repoResult) { + is DataResult.Success -> { + GetRecentMatchesUseCase.Result.Success(repoResult.data) + } + is DataResult.Error -> { + GetRecentMatchesUseCase.Result.Error(repoResult.error) + } + } + } + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt index a389800c9..8c5114053 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt @@ -1,6 +1,7 @@ package com.adammcneilly.pocketleague.shared.screens.feed import com.adammcneilly.pocketleague.shared.models.Event +import com.adammcneilly.pocketleague.shared.models.Match import com.adammcneilly.pocketleague.shared.screens.ScreenState /** @@ -9,5 +10,6 @@ import com.adammcneilly.pocketleague.shared.screens.ScreenState data class FeedViewState( val showLoading: Boolean = true, val upcomingEvents: List? = null, + val recentMatches: List? = null, val errorMessage: String? = null, ) : ScreenState diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt index 9eda3faf2..f4bd3589c 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt @@ -2,16 +2,22 @@ package com.adammcneilly.pocketleague.shared.screens.feed import com.adammcneilly.pocketleague.shared.eventlist.GetUpcomingEventsUseCase import com.adammcneilly.pocketleague.shared.eventlist.GetUpcomingEventsUseCaseImpl +import com.adammcneilly.pocketleague.shared.matchlist.GetRecentMatchesUseCase +import com.adammcneilly.pocketleague.shared.matchlist.GetRecentMatchesUseCaseImpl import com.adammcneilly.pocketleague.shared.screens.Events import kotlinx.coroutines.flow.collect +const val NUM_DAYS_RECENT_MATCHES = 7 + /** * Loads the information for the feed state. */ fun Events.loadFeed() = screenCoroutine { val upcomingEventsUseCase = GetUpcomingEventsUseCaseImpl(dataRepository.eventRepository) + val recentMatchesUseCase = GetRecentMatchesUseCaseImpl(dataRepository.matchRepository) val upcomingEventsFlow = upcomingEventsUseCase.invoke() + val recentMatchesFlow = recentMatchesUseCase.invoke(NUM_DAYS_RECENT_MATCHES) upcomingEventsFlow.collect { useCaseResult -> stateManager.updateScreen(FeedViewState::class) { @@ -31,4 +37,23 @@ fun Events.loadFeed() = screenCoroutine { } } } + + recentMatchesFlow.collect { useCaseResult -> + stateManager.updateScreen(FeedViewState::class) { + when (useCaseResult) { + is GetRecentMatchesUseCase.Result.Success -> { + it.copy( + showLoading = false, + recentMatches = useCaseResult.matches, + ) + } + is GetRecentMatchesUseCase.Result.Error -> { + it.copy( + showLoading = false, + errorMessage = useCaseResult.error.message, + ) + } + } + } + } } From 2817e0c8453aae4af6a3ce4601ba5ac29ec20305 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Mon, 18 Apr 2022 11:32:55 -0400 Subject: [PATCH 19/40] Starting on feed. --- .../pocketleague/ui/FeedContent.kt | 75 +++++++++++++++++-- .../pocketleague/ui/MatchListItem.kt | 32 ++++++++ .../shared/screens/feed/LoadFeedEvent.kt | 2 +- 3 files changed, 100 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt index 3995bfa23..00399d504 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt @@ -1,13 +1,25 @@ package com.adammcneilly.pocketleague.ui +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.Divider +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp import com.adammcneilly.pocketleague.shared.screens.feed.FeedViewState /** @@ -22,21 +34,68 @@ fun FeedContent( modifier = modifier.fillMaxSize(), ) { if (viewState.showLoading) { - CircularProgressIndicator( + LoadingIndicator() + } + + SuccessContent(viewState) + } +} + +@Composable +private fun SuccessContent(viewState: FeedViewState) { + LazyColumn( + modifier = Modifier.fillMaxSize(), + ) { + + item { + Text( + text = "Recent Matches", + style = MaterialTheme.typography.h6, modifier = Modifier - .wrapContentSize() - .align(Alignment.Center), + .padding(16.dp), ) } - val upcomingEvents = viewState.upcomingEvents + item { + LazyRow( + contentPadding = PaddingValues( + horizontal = 16.dp, + ), + horizontalArrangement = Arrangement.spacedBy(16.dp), + ) { + items(viewState.recentMatches.orEmpty()) { match -> + MatchListItem( + match = match, + modifier = Modifier.fillMaxWidth(), + ) + } + } + } - if (upcomingEvents != null) { - EventList( - events = upcomingEvents, + item { + Text( + text = "Upcoming Events", + style = MaterialTheme.typography.h6, modifier = Modifier - .fillMaxWidth() + .padding(16.dp), ) } + + itemsIndexed(viewState.upcomingEvents.orEmpty()) { index, event -> + EventListItem(event = event) + + if (index != viewState.upcomingEvents?.lastIndex) { + Divider() + } + } } } + +@Composable +private fun BoxScope.LoadingIndicator() { + CircularProgressIndicator( + modifier = Modifier + .wrapContentSize() + .align(Alignment.Center), + ) +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt new file mode 100644 index 000000000..c1a2dba72 --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt @@ -0,0 +1,32 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.foundation.layout.Column +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import com.adammcneilly.pocketleague.shared.models.Match + +/** + * Displays a match between two teams inside a list item. + */ +@Composable +fun MatchListItem( + match: Match, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier, + ) { + Text( + text = match.event.name, + fontWeight = FontWeight.Bold, + ) + + Text( + text = "TODO: Date", + style = MaterialTheme.typography.caption, + ) + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt index f4bd3589c..d0e44e319 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt @@ -7,7 +7,7 @@ import com.adammcneilly.pocketleague.shared.matchlist.GetRecentMatchesUseCaseImp import com.adammcneilly.pocketleague.shared.screens.Events import kotlinx.coroutines.flow.collect -const val NUM_DAYS_RECENT_MATCHES = 7 +const val NUM_DAYS_RECENT_MATCHES = 3 /** * Loads the information for the feed state. From 738b27dd64b29b9527f5e66c05bc10bfbba52e42 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Mon, 18 Apr 2022 13:42:08 -0400 Subject: [PATCH 20/40] Moving recent matches into cards. --- .../pocketleague/ui/FeedContent.kt | 3 +- .../pocketleague/ui/MatchListItem.kt | 61 +++++++++++++++++-- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt index 00399d504..aa903e7ce 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt @@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.lazy.LazyColumn @@ -66,7 +65,7 @@ private fun SuccessContent(viewState: FeedViewState) { items(viewState.recentMatches.orEmpty()) { match -> MatchListItem( match = match, - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.fillParentMaxWidth(0.8F), ) } } diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt index c1a2dba72..b8510f646 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt @@ -1,12 +1,22 @@ package com.adammcneilly.pocketleague.ui +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Card import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp import com.adammcneilly.pocketleague.shared.models.Match +import com.adammcneilly.pocketleague.shared.models.MatchTeamResult /** * Displays a match between two teams inside a list item. @@ -16,17 +26,58 @@ fun MatchListItem( match: Match, modifier: Modifier = Modifier, ) { - Column( + Card( modifier = modifier, + ) { + Column( + modifier = Modifier.padding(16.dp), + ) { + Text( + text = match.event.name, + fontWeight = FontWeight.Bold, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + + Text( + text = "TODO: Date", + style = MaterialTheme.typography.caption, + ) + + Spacer( + modifier = Modifier.height(16.dp), + ) + + MatchTeamResultRow(teamResult = match.blueTeam) + + MatchTeamResultRow(teamResult = match.orangeTeam) + } + } +} + +@Composable +private fun MatchTeamResultRow( + teamResult: MatchTeamResult, +) { + Row( + horizontalArrangement = Arrangement.spacedBy(16.dp), ) { Text( - text = match.event.name, - fontWeight = FontWeight.Bold, + text = teamResult.score.toString(), + color = if (teamResult.winner) { + Color.Green + } else { + Color.Red + }, ) Text( - text = "TODO: Date", - style = MaterialTheme.typography.caption, + text = teamResult.team.name, + fontWeight = if (teamResult.winner) { + FontWeight.Bold + } else { + null + }, ) } } From ec51a71767f6485781540fd5b2c0875e385ba3d7 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Mon, 18 Apr 2022 13:49:06 -0400 Subject: [PATCH 21/40] Fixing magic numbers. --- .../java/com/adammcneilly/pocketleague/ui/FeedContent.kt | 4 +++- .../main/java/com/adammcneilly/pocketleague/ui/TwoPane.kt | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt index aa903e7ce..4dc692e1f 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt @@ -21,6 +21,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.adammcneilly.pocketleague.shared.screens.feed.FeedViewState +private const val MATCH_CARD_WIDTH_RATIO = 0.8F + /** * Shows content inside the feed screen for the given [viewState]. */ @@ -65,7 +67,7 @@ private fun SuccessContent(viewState: FeedViewState) { items(viewState.recentMatches.orEmpty()) { match -> MatchListItem( match = match, - modifier = Modifier.fillParentMaxWidth(0.8F), + modifier = Modifier.fillParentMaxWidth(MATCH_CARD_WIDTH_RATIO), ) } } diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/TwoPane.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/TwoPane.kt index ce2440ead..a778598ea 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/TwoPane.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/TwoPane.kt @@ -14,11 +14,13 @@ import androidx.compose.ui.unit.dp import com.adammcneilly.pocketleague.shared.screens.Navigation import com.adammcneilly.pocketleague.shared.screens.ScreenIdentifier +private const val LIST_PANE_WIDTH_RATIO = 0.4F +private const val DETAIL_PANE_WIDTH_RATIO = 0.6F + /** * A [TwoPane] layout is used to show two selections of content side by side. Something like this * is helpful on tablets or large screens to use up available screen space. */ -@Suppress("MagicNumber") @Composable fun Navigation.TwoPane( saveableStateHolder: SaveableStateHolder @@ -37,7 +39,7 @@ fun Navigation.TwoPane( } Column( Modifier - .weight(0.4f) + .weight(LIST_PANE_WIDTH_RATIO) ) { saveableStateHolder.SaveableStateProvider(navigationLevelsMap[1]!!.uri) { ScreenPicker(navigationLevelsMap[1]!!) @@ -45,7 +47,7 @@ fun Navigation.TwoPane( } Column( Modifier - .weight(0.6f) + .weight(DETAIL_PANE_WIDTH_RATIO) .padding(20.dp) ) { if (navigationLevelsMap[2] == null) { From 7e47db1c9c7913d51af3764d8bc5fb22f319607c Mon Sep 17 00:00:00 2001 From: amcneilly Date: Mon, 18 Apr 2022 13:59:40 -0400 Subject: [PATCH 22/40] Switching to dependencies. --- .../shared/screens/DKMPViewModelForAndroid.kt | 4 +- .../pocketleague/shared/data/Repository.kt | 47 +++++++------------ .../octanegg/services/OctaneGGEventService.kt | 2 +- .../shared/screens/DKMPViewModel.kt | 6 +-- .../pocketleague/shared/screens/Events.kt | 6 +-- .../shared/screens/StateManager.kt | 4 +- .../shared/screens/feed/LoadFeedEvent.kt | 9 +--- 7 files changed, 30 insertions(+), 48 deletions(-) diff --git a/shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModelForAndroid.kt b/shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModelForAndroid.kt index d0aedc20a..aa8a69f10 100644 --- a/shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModelForAndroid.kt +++ b/shared/src/androidMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModelForAndroid.kt @@ -1,12 +1,12 @@ package com.adammcneilly.pocketleague.shared.screens -import com.adammcneilly.pocketleague.shared.data.Repository +import com.adammcneilly.pocketleague.shared.data.AppDependencies /** * Creates an instance of a [DKMPViewModel] to be used within an Android application. */ fun DKMPViewModel.Factory.getAndroidInstance(): DKMPViewModel { return DKMPViewModel( - repository = Repository(), + dependencies = AppDependencies(), ) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt index 0c0a8fc4a..1d6550923 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt @@ -1,43 +1,30 @@ package com.adammcneilly.pocketleague.shared.data -import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGAPIClient import com.adammcneilly.pocketleague.shared.data.remote.octanegg.services.OctaneGGEventService import com.adammcneilly.pocketleague.shared.data.remote.octanegg.services.OctaneGGMatchService import com.adammcneilly.pocketleague.shared.data.repositories.EventRepository import com.adammcneilly.pocketleague.shared.data.repositories.MatchRepository -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext +import com.adammcneilly.pocketleague.shared.eventlist.GetUpcomingEventsUseCase +import com.adammcneilly.pocketleague.shared.eventlist.GetUpcomingEventsUseCaseImpl +import com.adammcneilly.pocketleague.shared.matchlist.GetRecentMatchesUseCase +import com.adammcneilly.pocketleague.shared.matchlist.GetRecentMatchesUseCaseImpl -/** - * This class combines all of the relevant data sources used by the pocket league application. - * - * @property[useDefaultDispatcher] Defaults to true, meaning we run async work on Dispatchers.Default. - * We can supply a value of false to be used for testing. - */ -class Repository( - private val useDefaultDispatcher: Boolean = true, -) { - internal val eventRepository: EventRepository by lazy { - OctaneGGEventService( - apiClient = OctaneGGAPIClient(), - ) +class AppDependencies { + private val eventRepository: EventRepository by lazy { + OctaneGGEventService() } - internal val matchRepository: MatchRepository by lazy { + private val matchRepository: MatchRepository by lazy { OctaneGGMatchService() } - /** - * This will run the supplied [block] using the coroutine context of a default - * dispatcher if [useDefaultDispatcher] is true. - */ - suspend fun withRepoContext(block: suspend () -> T): T { - return if (useDefaultDispatcher) { - withContext(Dispatchers.Default) { - block() - } - } else { - block() - } - } + internal val getUpcomingEventsUseCase: GetUpcomingEventsUseCase + get() = GetUpcomingEventsUseCaseImpl( + repository = eventRepository, + ) + + internal val getRecentMatchesUseCase: GetRecentMatchesUseCase + get() = GetRecentMatchesUseCaseImpl( + repository = matchRepository, + ) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt index d36c7010a..b013de057 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt @@ -19,7 +19,7 @@ import kotlinx.coroutines.flow.flow * A concrete implementation of an [EventRepository] that will request data using the supplied [apiClient]. */ class OctaneGGEventService( - private val apiClient: OctaneGGAPIClient, + private val apiClient: OctaneGGAPIClient = OctaneGGAPIClient(), ) : EventRepository { override fun fetchEvents( diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModel.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModel.kt index fd8f95592..1db02c6f2 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModel.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/DKMPViewModel.kt @@ -1,17 +1,17 @@ package com.adammcneilly.pocketleague.shared.screens -import com.adammcneilly.pocketleague.shared.data.Repository +import com.adammcneilly.pocketleague.shared.data.AppDependencies import kotlinx.coroutines.flow.StateFlow /** * Root view model for the application that exposes a [stateFlow] of our application's state. */ class DKMPViewModel( - private val repository: Repository, + private val dependencies: AppDependencies ) { private val stateManager by lazy { - StateManager(repository) + StateManager(dependencies) } val stateFlow: StateFlow diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Events.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Events.kt index b51c2031a..accc89207 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Events.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Events.kt @@ -1,6 +1,6 @@ package com.adammcneilly.pocketleague.shared.screens -import com.adammcneilly.pocketleague.shared.data.Repository +import com.adammcneilly.pocketleague.shared.data.AppDependencies /** * This class manages all of the event handling for various screens, specifically @@ -9,8 +9,8 @@ import com.adammcneilly.pocketleague.shared.data.Repository class Events( val stateManager: StateManager, ) { - val dataRepository: Repository - get() = stateManager.repository + val dependencies: AppDependencies + get() = stateManager.dependencies /** * This will run the supplied [block] inside the coroutine scope of the current diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt index f5011702b..ae5c6f36b 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/StateManager.kt @@ -1,6 +1,6 @@ package com.adammcneilly.pocketleague.shared.screens -import com.adammcneilly.pocketleague.shared.data.Repository +import com.adammcneilly.pocketleague.shared.data.AppDependencies import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -16,7 +16,7 @@ import kotlin.reflect.KClass */ @Suppress("TooManyFunctions") class StateManager( - val repository: Repository, + val dependencies: AppDependencies, ) { internal val mutableStateFlow = MutableStateFlow(AppState()) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt index d0e44e319..d383ce935 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt @@ -1,9 +1,7 @@ package com.adammcneilly.pocketleague.shared.screens.feed import com.adammcneilly.pocketleague.shared.eventlist.GetUpcomingEventsUseCase -import com.adammcneilly.pocketleague.shared.eventlist.GetUpcomingEventsUseCaseImpl import com.adammcneilly.pocketleague.shared.matchlist.GetRecentMatchesUseCase -import com.adammcneilly.pocketleague.shared.matchlist.GetRecentMatchesUseCaseImpl import com.adammcneilly.pocketleague.shared.screens.Events import kotlinx.coroutines.flow.collect @@ -13,11 +11,8 @@ const val NUM_DAYS_RECENT_MATCHES = 3 * Loads the information for the feed state. */ fun Events.loadFeed() = screenCoroutine { - val upcomingEventsUseCase = GetUpcomingEventsUseCaseImpl(dataRepository.eventRepository) - val recentMatchesUseCase = GetRecentMatchesUseCaseImpl(dataRepository.matchRepository) - - val upcomingEventsFlow = upcomingEventsUseCase.invoke() - val recentMatchesFlow = recentMatchesUseCase.invoke(NUM_DAYS_RECENT_MATCHES) + val upcomingEventsFlow = dependencies.getUpcomingEventsUseCase.invoke() + val recentMatchesFlow = dependencies.getRecentMatchesUseCase.invoke(NUM_DAYS_RECENT_MATCHES) upcomingEventsFlow.collect { useCaseResult -> stateManager.updateScreen(FeedViewState::class) { From 4aaa45b50d20ff2159173724a112333f6ae6ced8 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Mon, 18 Apr 2022 14:00:46 -0400 Subject: [PATCH 23/40] Fixing static checks. --- .../shared/data/{Repository.kt => AppDependencies.kt} | 5 +++++ 1 file changed, 5 insertions(+) rename shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/{Repository.kt => AppDependencies.kt} (86%) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/AppDependencies.kt similarity index 86% rename from shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt rename to shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/AppDependencies.kt index 1d6550923..a780f8c9d 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/Repository.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/AppDependencies.kt @@ -9,6 +9,11 @@ import com.adammcneilly.pocketleague.shared.eventlist.GetUpcomingEventsUseCaseIm import com.adammcneilly.pocketleague.shared.matchlist.GetRecentMatchesUseCase import com.adammcneilly.pocketleague.shared.matchlist.GetRecentMatchesUseCaseImpl +/** + * Defines the collection of dependencies used throughout the application. This should + * expose interfaces so that the callers don't have to concern themselves + * with the implementation. + */ class AppDependencies { private val eventRepository: EventRepository by lazy { OctaneGGEventService() From 1830a0c9b184e0aad42de734bdc6a37474d20f0a Mon Sep 17 00:00:00 2001 From: amcneilly Date: Mon, 18 Apr 2022 14:08:05 -0400 Subject: [PATCH 24/40] Sorting, showing date. --- .../pocketleague/ui/MatchListItem.kt | 22 ++++++++++++++++++- .../octanegg/services/OctaneGGMatchService.kt | 4 +++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt index b8510f646..228847742 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt @@ -17,6 +17,10 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.adammcneilly.pocketleague.shared.models.Match import com.adammcneilly.pocketleague.shared.models.MatchTeamResult +import kotlinx.datetime.Clock +import kotlinx.datetime.LocalDateTime +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toInstant /** * Displays a match between two teams inside a list item. @@ -40,7 +44,7 @@ fun MatchListItem( ) Text( - text = "TODO: Date", + text = match.date?.getRelativeTimestamp().orEmpty(), style = MaterialTheme.typography.caption, ) @@ -81,3 +85,19 @@ private fun MatchTeamResultRow( ) } } + +private fun LocalDateTime.getRelativeTimestamp(): String { + val now = Clock.System.now() + val matchInstant = this.toInstant(TimeZone.currentSystemDefault()) + + val duration = now.minus(matchInstant) + + return when { + duration.inWholeHours < 24 -> { + "${duration.inWholeHours}h ago" + } + else -> { + "${duration.inWholeDays}d ago" + } + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt index 342025d8c..ff0b27889 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt @@ -36,7 +36,9 @@ class OctaneGGMatchService( is DataResult.Success -> { val mappedMatches = apiResult.data.matches?.map(OctaneGGMatch::toMatch).orEmpty() - DataResult.Success(mappedMatches) + val sortedMatches = mappedMatches.sortedByDescending(Match::date) + + DataResult.Success(sortedMatches) } is DataResult.Error -> { DataResult.Error(apiResult.error) From 04e4bd7735e271455cbc9925832479df5b64dfec Mon Sep 17 00:00:00 2001 From: amcneilly Date: Mon, 18 Apr 2022 14:09:05 -0400 Subject: [PATCH 25/40] Fix. --- .../java/com/adammcneilly/pocketleague/ui/MatchListItem.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt index 228847742..aa5b898ad 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt @@ -91,9 +91,10 @@ private fun LocalDateTime.getRelativeTimestamp(): String { val matchInstant = this.toInstant(TimeZone.currentSystemDefault()) val duration = now.minus(matchInstant) + val hoursInDay = 24 return when { - duration.inWholeHours < 24 -> { + duration.inWholeHours < hoursInDay -> { "${duration.inWholeHours}h ago" } else -> { From 9952eb0317744e47a29dec94eb86a9874bd046cc Mon Sep 17 00:00:00 2001 From: amcneilly Date: Mon, 18 Apr 2022 14:09:47 -0400 Subject: [PATCH 26/40] Fix. --- .../java/com/adammcneilly/pocketleague/ui/MatchListItem.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt index aa5b898ad..7475fe339 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt @@ -86,15 +86,16 @@ private fun MatchTeamResultRow( } } +private const val HOURS_IN_DAY = 24 + private fun LocalDateTime.getRelativeTimestamp(): String { val now = Clock.System.now() val matchInstant = this.toInstant(TimeZone.currentSystemDefault()) val duration = now.minus(matchInstant) - val hoursInDay = 24 return when { - duration.inWholeHours < hoursInDay -> { + duration.inWholeHours < HOURS_IN_DAY -> { "${duration.inWholeHours}h ago" } else -> { From cc055cfb31627f029534a1644ef19e1b88a3c92a Mon Sep 17 00:00:00 2001 From: amcneilly Date: Mon, 18 Apr 2022 14:22:03 -0400 Subject: [PATCH 27/40] Recent matches placeholder. --- app/build.gradle.kts | 1 + .../pocketleague/ui/FeedContent.kt | 4 --- .../pocketleague/ui/MatchListItem.kt | 31 ++++++++++++++++- .../shared/screens/feed/FeedViewState.kt | 34 ++++++++++++++++++- 4 files changed, 64 insertions(+), 6 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9e26bb0ab..e04f57b62 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -98,6 +98,7 @@ dependencies { implementation("com.google.dagger:hilt-android:${Versions.hilt}") implementation("com.google.accompanist:accompanist-insets-ui:${Versions.accompanist}") implementation("com.google.accompanist:accompanist-systemuicontroller:${Versions.accompanist}") + implementation("com.google.accompanist:accompanist-placeholder-material:${Versions.accompanist}") implementation("androidx.window:window:${Versions.windowManager}") implementation("androidx.lifecycle:lifecycle-process:2.4.1") implementation("io.coil-kt:coil-compose:2.0.0-rc03") diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt index 4dc692e1f..e96b8d159 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt @@ -34,10 +34,6 @@ fun FeedContent( Box( modifier = modifier.fillMaxSize(), ) { - if (viewState.showLoading) { - LoadingIndicator() - } - SuccessContent(viewState) } } diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt index 7475fe339..2987a5e84 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchListItem.kt @@ -4,8 +4,11 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Card import androidx.compose.material.MaterialTheme import androidx.compose.material.Text @@ -17,6 +20,8 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.adammcneilly.pocketleague.shared.models.Match import com.adammcneilly.pocketleague.shared.models.MatchTeamResult +import com.google.accompanist.placeholder.material.placeholder +import com.google.accompanist.placeholder.placeholder import kotlinx.datetime.Clock import kotlinx.datetime.LocalDateTime import kotlinx.datetime.TimeZone @@ -35,21 +40,34 @@ fun MatchListItem( ) { Column( modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(4.dp), ) { Text( text = match.event.name, fontWeight = FontWeight.Bold, maxLines = 1, overflow = TextOverflow.Ellipsis, + modifier = Modifier + .fillMaxWidth() + .placeholder( + visible = match.event.name.isBlank(), + shape = CircleShape, + ) ) Text( text = match.date?.getRelativeTimestamp().orEmpty(), style = MaterialTheme.typography.caption, + modifier = Modifier + .defaultMinSize(minWidth = 50.dp) + .placeholder( + visible = match.date == null, + shape = CircleShape, + ) ) Spacer( - modifier = Modifier.height(16.dp), + modifier = Modifier.height(8.dp), ) MatchTeamResultRow(teamResult = match.blueTeam) @@ -73,6 +91,11 @@ private fun MatchTeamResultRow( } else { Color.Red }, + modifier = Modifier + .placeholder( + visible = teamResult.score == -1, + shape = CircleShape, + ) ) Text( @@ -82,6 +105,12 @@ private fun MatchTeamResultRow( } else { null }, + modifier = Modifier + .defaultMinSize(minWidth = 100.dp) + .placeholder( + visible = teamResult.team.name.isBlank(), + shape = CircleShape, + ) ) } } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt index 8c5114053..63ae79c27 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt @@ -2,14 +2,46 @@ package com.adammcneilly.pocketleague.shared.screens.feed import com.adammcneilly.pocketleague.shared.models.Event import com.adammcneilly.pocketleague.shared.models.Match +import com.adammcneilly.pocketleague.shared.models.MatchTeamResult +import com.adammcneilly.pocketleague.shared.models.Team import com.adammcneilly.pocketleague.shared.screens.ScreenState +private val placeholderMatch = Match( + id = "", + event = Event( + id = "", + name = "", + startDate = null, + endDate = null, + imageUrl = null, + ), + date = null, + blueTeam = MatchTeamResult( + score = -1, + winner = false, + team = Team( + id = "", + name = "", + imageUrl = null, + ), + ), + orangeTeam = MatchTeamResult( + score = -1, + winner = false, + team = Team( + id = "", + name = "", + imageUrl = null, + ), + ), +) + /** * Defines the UI configuration for the [com.adammcneilly.pocketleague.shared.screens.Screens.Feed] screen. */ data class FeedViewState( val showLoading: Boolean = true, val upcomingEvents: List? = null, - val recentMatches: List? = null, + val recentMatches: List? = listOf(placeholderMatch, placeholderMatch, placeholderMatch), val errorMessage: String? = null, ) : ScreenState From c387f70daa9cc555a36cf759b0bb681df142973a Mon Sep 17 00:00:00 2001 From: amcneilly Date: Tue, 19 Apr 2022 21:33:32 -0400 Subject: [PATCH 28/40] Showing placeholder. --- .../pocketleague/ui/EventListItem.kt | 20 +++++- .../pocketleague/ui/FeedContent.kt | 19 +---- .../data/{DataResult.kt => DataState.kt} | 10 ++- .../data/remote/octanegg/OctaneGGAPIClient.kt | 8 +-- .../octanegg/mappers/OctaneGGMatchMapper.kt | 21 ++++-- .../mappers/OctaneGGTeamOverviewMapper.kt | 4 +- .../octanegg/services/OctaneGGEventService.kt | 13 ++-- .../octanegg/services/OctaneGGMatchService.kt | 15 ++-- .../data/repositories/EventRepository.kt | 4 +- .../data/repositories/MatchRepository.kt | 4 +- .../eventlist/GetUpcomingEventsUseCase.kt | 22 +----- .../eventlist/GetUpcomingEventsUseCaseImpl.kt | 17 ++--- .../matchlist/GetRecentMatchesUseCase.kt | 22 +----- .../matchlist/GetRecentMatchesUseCaseImpl.kt | 17 ++--- .../pocketleague/shared/models/Event.kt | 10 +-- .../pocketleague/shared/models/Match.kt | 10 +-- .../shared/models/MatchTeamResult.kt | 6 +- .../pocketleague/shared/models/Team.kt | 6 +- .../shared/screens/feed/FeedViewState.kt | 72 +++++++++---------- .../shared/screens/feed/LoadFeedEvent.kt | 36 ++-------- 20 files changed, 138 insertions(+), 198 deletions(-) rename shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/{DataResult.kt => DataState.kt} (68%) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt index 74c3f800c..dbcaae9cc 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt @@ -1,6 +1,8 @@ package com.adammcneilly.pocketleague.ui +import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ListItem import androidx.compose.material.Text @@ -12,6 +14,7 @@ import coil.compose.AsyncImage import coil.request.ImageRequest import com.adammcneilly.pocketleague.shared.datetime.DateTimeFormatter import com.adammcneilly.pocketleague.shared.models.Event +import com.google.accompanist.placeholder.material.placeholder /** * Used to show a specific [event] inside of a list. @@ -25,6 +28,12 @@ fun EventListItem( text = { Text( text = event.name, + modifier = Modifier + .defaultMinSize(minWidth = 150.dp) + .placeholder( + visible = event.name.isEmpty(), + shape = CircleShape, + ) ) }, overlineText = { @@ -35,7 +44,9 @@ fun EventListItem( ) } - Text(text = startDateString.orEmpty()) + Text( + text = startDateString.orEmpty(), + ) }, icon = { AsyncImage( @@ -44,7 +55,12 @@ fun EventListItem( .crossfade(true) .build(), contentDescription = "Event Image", - modifier = Modifier.size(48.dp), + modifier = Modifier + .size(48.dp) + .placeholder( + visible = event.imageUrl == null, + shape = CircleShape, + ), ) }, ) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt index e96b8d159..e96718719 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt @@ -2,21 +2,17 @@ package com.adammcneilly.pocketleague.ui import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.Divider import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.adammcneilly.pocketleague.shared.screens.feed.FeedViewState @@ -60,7 +56,7 @@ private fun SuccessContent(viewState: FeedViewState) { ), horizontalArrangement = Arrangement.spacedBy(16.dp), ) { - items(viewState.recentMatches.orEmpty()) { match -> + items(viewState.recentMatches) { match -> MatchListItem( match = match, modifier = Modifier.fillParentMaxWidth(MATCH_CARD_WIDTH_RATIO), @@ -78,21 +74,12 @@ private fun SuccessContent(viewState: FeedViewState) { ) } - itemsIndexed(viewState.upcomingEvents.orEmpty()) { index, event -> + itemsIndexed(viewState.upcomingEvents) { index, event -> EventListItem(event = event) - if (index != viewState.upcomingEvents?.lastIndex) { + if (index != viewState.upcomingEvents.lastIndex) { Divider() } } } } - -@Composable -private fun BoxScope.LoadingIndicator() { - CircularProgressIndicator( - modifier = Modifier - .wrapContentSize() - .align(Alignment.Center), - ) -} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/DataResult.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/DataState.kt similarity index 68% rename from shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/DataResult.kt rename to shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/DataState.kt index 689b3082f..b7d607244 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/DataResult.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/DataState.kt @@ -8,14 +8,18 @@ package com.adammcneilly.pocketleague.shared.data * handle both success and failure scenarios, without having to catch exceptions. This is because any * exceptions will be wrapped inside an [Error] class. */ -sealed class DataResult { +sealed class DataState { + /** + * This is used to imply we are still loading a piece of data. + */ + object Loading : DataState() /** * A successful result which implies we will have some [data] returned. */ - data class Success(val data: T) : DataResult() + data class Success(val data: T) : DataState() /** * An unsuccessful result because some [error] occurred. */ - data class Error(val error: Throwable) : DataResult() + data class Error(val error: Throwable) : DataState() } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGAPIClient.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGAPIClient.kt index ae634986d..9c2e4f504 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGAPIClient.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGAPIClient.kt @@ -1,6 +1,6 @@ package com.adammcneilly.pocketleague.shared.data.remote.octanegg -import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.data.DataState import io.ktor.client.HttpClient import io.ktor.client.features.json.JsonFeature import io.ktor.client.features.json.serializer.KotlinxSerializer @@ -33,14 +33,14 @@ class OctaneGGAPIClient { suspend inline fun getResponse( endpoint: String, requestBuilder: HttpRequestBuilder.() -> Unit = {}, - ): DataResult { + ): DataState { val url = "$baseURL$endpoint" return try { val apiResult: T = httpClient.get(url, requestBuilder) - DataResult.Success(apiResult) + DataState.Success(apiResult) } catch (e: Exception) { - DataResult.Error(e) + DataState.Error(e) } } } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchMapper.kt index dd22ab729..6f7c06251 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchMapper.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchMapper.kt @@ -9,14 +9,25 @@ import kotlinx.datetime.toLocalDateTime /** * Converts an [OctaneGGMatch] to a [Match] entity. */ -fun OctaneGGMatch.toMatch(): Match { +fun OctaneGGMatch.toMatch(): Match? { + // Right now we just filter out items with invalid data. We need a way to log + // or notify of this in the future. + if ( + this.id == null || + this.event == null || + this.blue == null || + this.orange == null + ) { + return null + } + return Match( - id = this.id!!, - event = this.event?.toEvent()!!, + id = this.id, + event = this.event.toEvent(), date = this.date?.let { date -> Instant.parse(date) }?.toLocalDateTime(TimeZone.UTC), - blueTeam = this.blue?.toMatchTeamResult()!!, - orangeTeam = this.orange?.toMatchTeamResult()!!, + blueTeam = this.blue.toMatchTeamResult(), + orangeTeam = this.orange.toMatchTeamResult(), ) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGTeamOverviewMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGTeamOverviewMapper.kt index 188fb5f6e..ac6dbf81d 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGTeamOverviewMapper.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGTeamOverviewMapper.kt @@ -8,8 +8,8 @@ import com.adammcneilly.pocketleague.shared.models.Team */ fun OctaneGGTeamOverview.toTeam(): Team { return Team( - id = this.id!!, - name = this.name!!, + id = this.id.orEmpty(), + name = this.name.orEmpty(), imageUrl = this.image, ) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt index b013de057..294fcc884 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGEventService.kt @@ -1,6 +1,6 @@ package com.adammcneilly.pocketleague.shared.data.remote.octanegg.services -import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.data.DataState import com.adammcneilly.pocketleague.shared.data.models.EventListRequest import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGAPIClient import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGEndpoints @@ -24,7 +24,7 @@ class OctaneGGEventService( override fun fetchEvents( request: EventListRequest, - ): Flow>> { + ): Flow>> { return flow { val apiResult = apiClient.getResponse( endpoint = OctaneGGEndpoints.EVENTS, @@ -34,15 +34,16 @@ class OctaneGGEventService( ) val mappedResult = when (apiResult) { - is DataResult.Success -> { + is DataState.Loading -> DataState.Loading + is DataState.Success -> { val mappedEvents = apiResult.data.events?.map(OctaneGGEvent::toEvent).orEmpty() val sortedEvents = mappedEvents.sortedBy(Event::startDate) - DataResult.Success(sortedEvents) + DataState.Success(sortedEvents) } - is DataResult.Error -> { - DataResult.Error(apiResult.error) + is DataState.Error -> { + DataState.Error(apiResult.error) } } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt index ff0b27889..5ab3baa37 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt @@ -1,6 +1,6 @@ package com.adammcneilly.pocketleague.shared.data.remote.octanegg.services -import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.data.DataState import com.adammcneilly.pocketleague.shared.data.models.MatchListRequest import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGAPIClient import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGEndpoints @@ -23,7 +23,7 @@ class OctaneGGMatchService( private val apiClient: OctaneGGAPIClient = OctaneGGAPIClient(), ) : MatchRepository { - override fun fetchMatches(request: MatchListRequest): Flow>> { + override fun fetchMatches(request: MatchListRequest): Flow>> { return flow { val apiResult = apiClient.getResponse( endpoint = OctaneGGEndpoints.MATCHES, @@ -33,15 +33,16 @@ class OctaneGGMatchService( ) val mappedResult = when (apiResult) { - is DataResult.Success -> { - val mappedMatches = apiResult.data.matches?.map(OctaneGGMatch::toMatch).orEmpty() + is DataState.Loading -> DataState.Loading + is DataState.Success -> { + val mappedMatches = apiResult.data.matches?.mapNotNull(OctaneGGMatch::toMatch).orEmpty() val sortedMatches = mappedMatches.sortedByDescending(Match::date) - DataResult.Success(sortedMatches) + DataState.Success(sortedMatches) } - is DataResult.Error -> { - DataResult.Error(apiResult.error) + is DataState.Error -> { + DataState.Error(apiResult.error) } } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/EventRepository.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/EventRepository.kt index 2e2086788..8d80082b1 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/EventRepository.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/EventRepository.kt @@ -1,6 +1,6 @@ package com.adammcneilly.pocketleague.shared.data.repositories -import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.data.DataState import com.adammcneilly.pocketleague.shared.data.models.EventListRequest import com.adammcneilly.pocketleague.shared.models.Event import kotlinx.coroutines.flow.Flow @@ -15,5 +15,5 @@ interface EventRepository { */ fun fetchEvents( request: EventListRequest, - ): Flow>> + ): Flow>> } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/MatchRepository.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/MatchRepository.kt index d2b2140c3..317e5ee3a 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/MatchRepository.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/MatchRepository.kt @@ -1,6 +1,6 @@ package com.adammcneilly.pocketleague.shared.data.repositories -import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.data.DataState import com.adammcneilly.pocketleague.shared.data.models.MatchListRequest import com.adammcneilly.pocketleague.shared.models.Match import kotlinx.coroutines.flow.Flow @@ -16,5 +16,5 @@ interface MatchRepository { */ fun fetchMatches( request: MatchListRequest, - ): Flow>> + ): Flow>> } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCase.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCase.kt index 0a0f259c4..cffe18b13 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCase.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCase.kt @@ -1,5 +1,6 @@ package com.adammcneilly.pocketleague.shared.eventlist +import com.adammcneilly.pocketleague.shared.data.DataState import com.adammcneilly.pocketleague.shared.models.Event import kotlinx.coroutines.flow.Flow @@ -11,24 +12,5 @@ interface GetUpcomingEventsUseCase { /** * @see [GetUpcomingEventsUseCase]. */ - operator fun invoke(): Flow - - /** - * Defines all possible result types for a [GetUpcomingEventsUseCase]. - */ - sealed class Result { - /** - * This will be returned if we can successfully request upcoming [events]. - */ - data class Success( - val events: List, - ) : Result() - - /** - * Should any [error] occur while requesting upcoming events, this will be returned. - */ - data class Error( - val error: Throwable, - ) : Result() - } + operator fun invoke(): Flow>> } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCaseImpl.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCaseImpl.kt index 5d3dbadeb..689505994 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCaseImpl.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/eventlist/GetUpcomingEventsUseCaseImpl.kt @@ -1,10 +1,10 @@ package com.adammcneilly.pocketleague.shared.eventlist -import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.data.DataState import com.adammcneilly.pocketleague.shared.data.models.EventListRequest import com.adammcneilly.pocketleague.shared.data.repositories.EventRepository +import com.adammcneilly.pocketleague.shared.models.Event import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map import kotlinx.datetime.Clock import kotlinx.datetime.TimeZone import kotlinx.datetime.toLocalDateTime @@ -17,22 +17,13 @@ class GetUpcomingEventsUseCaseImpl( private val repository: EventRepository, ) : GetUpcomingEventsUseCase { - override fun invoke(): Flow { + override fun invoke(): Flow>> { val today = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()) val request = EventListRequest( after = today, ) - return repository.fetchEvents(request).map { repoResult -> - when (repoResult) { - is DataResult.Success -> { - GetUpcomingEventsUseCase.Result.Success(repoResult.data) - } - is DataResult.Error -> { - GetUpcomingEventsUseCase.Result.Error(repoResult.error) - } - } - } + return repository.fetchEvents(request) } } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCase.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCase.kt index b0f2d9a0e..e96492c29 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCase.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCase.kt @@ -1,5 +1,6 @@ package com.adammcneilly.pocketleague.shared.matchlist +import com.adammcneilly.pocketleague.shared.data.DataState import com.adammcneilly.pocketleague.shared.models.Match import kotlinx.coroutines.flow.Flow @@ -14,24 +15,5 @@ interface GetRecentMatchesUseCase { * * @param[numDays] The number of days back to pull recent events for. */ - operator fun invoke(numDays: Int): Flow - - /** - * Defines all possible return types for a [GetRecentMatchesUseCase]. - */ - sealed class Result { - /** - * This will be returned when we've successfully retrieved a list of [matches]. - */ - data class Success( - val matches: List, - ) : Result() - - /** - * This will be returned if some [error] occurs when requesting a list of matches. - */ - data class Error( - val error: Throwable, - ) : Result() - } + operator fun invoke(numDays: Int): Flow>> } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCaseImpl.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCaseImpl.kt index 735d8ca74..748186332 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCaseImpl.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchlist/GetRecentMatchesUseCaseImpl.kt @@ -1,10 +1,10 @@ package com.adammcneilly.pocketleague.shared.matchlist -import com.adammcneilly.pocketleague.shared.data.DataResult +import com.adammcneilly.pocketleague.shared.data.DataState import com.adammcneilly.pocketleague.shared.data.models.MatchListRequest import com.adammcneilly.pocketleague.shared.data.repositories.MatchRepository +import com.adammcneilly.pocketleague.shared.models.Match import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map import kotlinx.datetime.Clock import kotlinx.datetime.DateTimeUnit import kotlinx.datetime.TimeZone @@ -20,7 +20,7 @@ class GetRecentMatchesUseCaseImpl( private val repository: MatchRepository, ) : GetRecentMatchesUseCase { - override fun invoke(numDays: Int): Flow { + override fun invoke(numDays: Int): Flow>> { val today = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()) val startDate = today.date.minus(numDays, DateTimeUnit.DAY) @@ -32,15 +32,6 @@ class GetRecentMatchesUseCaseImpl( before = today, ) - return repository.fetchMatches(request).map { repoResult -> - when (repoResult) { - is DataResult.Success -> { - GetRecentMatchesUseCase.Result.Success(repoResult.data) - } - is DataResult.Error -> { - GetRecentMatchesUseCase.Result.Error(repoResult.error) - } - } - } + return repository.fetchMatches(request) } } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt index 8a8669552..0894c4f75 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Event.kt @@ -13,9 +13,9 @@ import kotlinx.datetime.LocalDateTime * @property[imageUrl] The URL to the remotely hosted image for this event. */ data class Event( - val id: String, - val name: String, - val startDate: LocalDateTime?, - val endDate: LocalDateTime?, - val imageUrl: String?, + val id: String = "", + val name: String = "", + val startDate: LocalDateTime? = null, + val endDate: LocalDateTime? = null, + val imageUrl: String? = null, ) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Match.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Match.kt index bedd8bc2e..fdf00e976 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Match.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Match.kt @@ -7,9 +7,9 @@ import kotlinx.datetime.LocalDateTime * or even a best of set. */ data class Match( - val id: String, - val event: Event, - val date: LocalDateTime?, - val blueTeam: MatchTeamResult, - val orangeTeam: MatchTeamResult, + val id: String = "", + val event: Event = Event(), + val date: LocalDateTime? = null, + val blueTeam: MatchTeamResult = MatchTeamResult(), + val orangeTeam: MatchTeamResult = MatchTeamResult(), ) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/MatchTeamResult.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/MatchTeamResult.kt index 67c878cd7..40ec67446 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/MatchTeamResult.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/MatchTeamResult.kt @@ -4,7 +4,7 @@ package com.adammcneilly.pocketleague.shared.models * The result of a particular [team] within a [Match]. */ data class MatchTeamResult( - val score: Int, - val winner: Boolean, - val team: Team, + val score: Int = -1, + val winner: Boolean = false, + val team: Team = Team(), ) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Team.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Team.kt index cf23bc6b4..85f9c8f60 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Team.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Team.kt @@ -5,7 +5,7 @@ package com.adammcneilly.pocketleague.shared.models * League event. */ data class Team( - val id: String, - val name: String, - val imageUrl: String?, + val id: String = "", + val name: String = "", + val imageUrl: String? = null, ) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt index 63ae79c27..538ea32cc 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt @@ -1,47 +1,45 @@ package com.adammcneilly.pocketleague.shared.screens.feed +import com.adammcneilly.pocketleague.shared.data.DataState import com.adammcneilly.pocketleague.shared.models.Event import com.adammcneilly.pocketleague.shared.models.Match -import com.adammcneilly.pocketleague.shared.models.MatchTeamResult -import com.adammcneilly.pocketleague.shared.models.Team import com.adammcneilly.pocketleague.shared.screens.ScreenState -private val placeholderMatch = Match( - id = "", - event = Event( - id = "", - name = "", - startDate = null, - endDate = null, - imageUrl = null, - ), - date = null, - blueTeam = MatchTeamResult( - score = -1, - winner = false, - team = Team( - id = "", - name = "", - imageUrl = null, - ), - ), - orangeTeam = MatchTeamResult( - score = -1, - winner = false, - team = Team( - id = "", - name = "", - imageUrl = null, - ), - ), -) - /** * Defines the UI configuration for the [com.adammcneilly.pocketleague.shared.screens.Screens.Feed] screen. */ data class FeedViewState( - val showLoading: Boolean = true, - val upcomingEvents: List? = null, - val recentMatches: List? = listOf(placeholderMatch, placeholderMatch, placeholderMatch), - val errorMessage: String? = null, -) : ScreenState + val upcomingEventsState: DataState> = DataState.Loading, + val recentMatchesState: DataState> = DataState.Loading, +) : ScreenState { + + val upcomingEvents: List + get() = when (upcomingEventsState) { + is DataState.Loading -> { + // Here, we return a list of empty Event objects which will be mapped + // to a placeholder loading UI. + listOf(Event(), Event(), Event()) + } + is DataState.Success -> { + upcomingEventsState.data + } + is DataState.Error -> { + emptyList() + } + } + + val recentMatches: List + get() = when (recentMatchesState) { + is DataState.Loading -> { + // Here, we return a list of empty match objects which will be mapped + // to a placeholder loading UI. + listOf(Match(), Match(), Match()) + } + is DataState.Success -> { + recentMatchesState.data + } + is DataState.Error -> { + emptyList() + } + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt index d383ce935..248b5a9b9 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt @@ -1,7 +1,5 @@ package com.adammcneilly.pocketleague.shared.screens.feed -import com.adammcneilly.pocketleague.shared.eventlist.GetUpcomingEventsUseCase -import com.adammcneilly.pocketleague.shared.matchlist.GetRecentMatchesUseCase import com.adammcneilly.pocketleague.shared.screens.Events import kotlinx.coroutines.flow.collect @@ -16,39 +14,17 @@ fun Events.loadFeed() = screenCoroutine { upcomingEventsFlow.collect { useCaseResult -> stateManager.updateScreen(FeedViewState::class) { - when (useCaseResult) { - is GetUpcomingEventsUseCase.Result.Success -> { - it.copy( - showLoading = false, - upcomingEvents = useCaseResult.events, - ) - } - is GetUpcomingEventsUseCase.Result.Error -> { - it.copy( - showLoading = false, - errorMessage = useCaseResult.error.message, - ) - } - } + it.copy( + upcomingEventsState = useCaseResult, + ) } } recentMatchesFlow.collect { useCaseResult -> stateManager.updateScreen(FeedViewState::class) { - when (useCaseResult) { - is GetRecentMatchesUseCase.Result.Success -> { - it.copy( - showLoading = false, - recentMatches = useCaseResult.matches, - ) - } - is GetRecentMatchesUseCase.Result.Error -> { - it.copy( - showLoading = false, - errorMessage = useCaseResult.error.message, - ) - } - } + it.copy( + recentMatchesState = useCaseResult, + ) } } } From 363e56b55f3314b4a97ace804437e9e47ad4fcc5 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Tue, 19 Apr 2022 21:36:30 -0400 Subject: [PATCH 29/40] Suppressing complex condition. --- .../shared/data/remote/octanegg/mappers/OctaneGGMatchMapper.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchMapper.kt index 6f7c06251..db0a3cc29 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchMapper.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGMatchMapper.kt @@ -12,6 +12,7 @@ import kotlinx.datetime.toLocalDateTime fun OctaneGGMatch.toMatch(): Match? { // Right now we just filter out items with invalid data. We need a way to log // or notify of this in the future. + @Suppress("ComplexCondition") if ( this.id == null || this.event == null || From b97732f694755f4d39698e1262d8059cc79c478e Mon Sep 17 00:00:00 2001 From: amcneilly Date: Tue, 19 Apr 2022 22:31:32 -0400 Subject: [PATCH 30/40] Adding more level1 items. --- app/build.gradle.kts | 1 + .../pocketleague/ui/Level1BottomBar.kt | 24 +++++++-------- .../pocketleague/ui/RecordsContent.kt | 20 +++++++++++++ .../pocketleague/ui/ScreenPicker.kt | 14 +++++++++ .../pocketleague/ui/StatsContent.kt | 20 +++++++++++++ .../shared/screens/Level1Navigation.kt | 6 ++++ .../pocketleague/shared/screens/Navigation.kt | 4 +++ .../pocketleague/shared/screens/Screens.kt | 30 ++++++++++++------- .../shared/screens/feed/FeedInitSettings.kt | 2 +- .../screens/records/RecordsInitSettings.kt | 20 +++++++++++++ .../screens/records/RecordsViewState.kt | 10 +++++++ .../shared/screens/stats/StatsInitSettings.kt | 20 +++++++++++++ .../shared/screens/stats/StatsViewState.kt | 10 +++++++ 13 files changed, 157 insertions(+), 24 deletions(-) create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/RecordsContent.kt create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/StatsContent.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/records/RecordsInitSettings.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/records/RecordsViewState.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/stats/StatsInitSettings.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/stats/StatsViewState.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e04f57b62..bb000b4b1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -93,6 +93,7 @@ dependencies { implementation("androidx.compose.ui:ui:${Versions.compose}") implementation("androidx.compose.material:material:${Versions.compose}") implementation("androidx.compose.ui:ui-tooling-preview:${Versions.compose}") + implementation("androidx.compose.material:material-icons-extended:${Versions.compose}") implementation("androidx.lifecycle:lifecycle-runtime-ktx:${Versions.lifecycle}") implementation("androidx.activity:activity-compose:${Versions.activityCompose}") implementation("com.google.dagger:hilt-android:${Versions.hilt}") diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt index aa92b243b..4924592fd 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1BottomBar.kt @@ -5,9 +5,9 @@ import androidx.compose.material.BottomNavigationItem import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.AccountCircle -import androidx.compose.material.icons.filled.Home -import androidx.compose.material.icons.filled.Star +import androidx.compose.material.icons.filled.BarChart +import androidx.compose.material.icons.filled.Feed +import androidx.compose.material.icons.filled.Leaderboard import androidx.compose.runtime.Composable import com.adammcneilly.pocketleague.shared.screens.Level1Navigation import com.adammcneilly.pocketleague.shared.screens.Navigation @@ -23,22 +23,22 @@ fun Navigation.Level1BottomBar( BottomAppBar( content = { BottomNavigationItem( - icon = { Icon(Icons.Default.Home, "Feed") }, + icon = { Icon(Icons.Default.Feed, "Feed") }, label = { Text("FEED") }, selected = selectedTab.uri == Level1Navigation.Feed.screenIdentifier.uri, onClick = { navigateByLevel1Menu(Level1Navigation.Feed) } ) BottomNavigationItem( - icon = { Icon(Icons.Default.Star, "Teams") }, - label = { Text("MY TEAMS") }, - selected = false, - onClick = { }, + icon = { Icon(Icons.Default.BarChart, "Stats") }, + label = { Text("STATS") }, + selected = selectedTab.uri == Level1Navigation.Stats.screenIdentifier.uri, + onClick = { navigateByLevel1Menu(Level1Navigation.Stats) }, ) BottomNavigationItem( - icon = { Icon(Icons.Default.AccountCircle, "Account") }, - label = { Text("ACCOUNT") }, - selected = false, - onClick = { }, + icon = { Icon(Icons.Default.Leaderboard, "Records") }, + label = { Text("RECORDS") }, + selected = selectedTab.uri == Level1Navigation.Records.screenIdentifier.uri, + onClick = { navigateByLevel1Menu(Level1Navigation.Records) }, ) } ) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/RecordsContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/RecordsContent.kt new file mode 100644 index 000000000..0d1d41967 --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/RecordsContent.kt @@ -0,0 +1,20 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.foundation.layout.Box +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.adammcneilly.pocketleague.shared.screens.records.RecordsViewState + +/** + * The composable to render the [viewState] of the records screen. + */ +@Composable +fun RecordsContent( + viewState: RecordsViewState, + modifier: Modifier = Modifier, +) { + Box(modifier) { + Text(text = "Records screen: $viewState") + } +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt index eb14a20c1..1d7f2210d 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt @@ -25,5 +25,19 @@ fun Navigation.ScreenPicker( .padding(paddingValues), ) } + Screens.Stats -> { + StatsContent( + viewState = stateProvider.get(screenIdentifier), + modifier = Modifier + .padding(paddingValues), + ) + } + Screens.Records -> { + RecordsContent( + viewState = stateProvider.get(screenIdentifier), + modifier = Modifier + .padding(paddingValues), + ) + } } } diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/StatsContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/StatsContent.kt new file mode 100644 index 000000000..e4719f9ed --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/StatsContent.kt @@ -0,0 +1,20 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.foundation.layout.Box +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.adammcneilly.pocketleague.shared.screens.stats.StatsViewState + +/** + * The content that renders the [viewState] for the stats screen. + */ +@Composable +fun StatsContent( + viewState: StatsViewState, + modifier: Modifier = Modifier, +) { + Box(modifier) { + Text(text = "Stats screen: $viewState") + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Level1Navigation.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Level1Navigation.kt index 1b1a07cb0..80f956c98 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Level1Navigation.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Level1Navigation.kt @@ -12,4 +12,10 @@ enum class Level1Navigation( Feed( screenIdentifier = ScreenIdentifier.get(screen = Screens.Feed, params = null), ), + Stats( + screenIdentifier = ScreenIdentifier.get(screen = Screens.Stats, params = null), + ), + Records( + screenIdentifier = ScreenIdentifier.get(screen = Screens.Records, params = null), + ), } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt index a3c18a3db..41bf3f2e1 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Navigation.kt @@ -98,6 +98,10 @@ class Navigation( * Navigate to a different level 1 menu item. */ fun navigateByLevel1Menu(level1NavigationItem: Level1Navigation) { + if (level1NavigationItem.screenIdentifier == currentLevel1ScreenIdentifier) { + return + } + val navigationLevelsMap = getNavigationLevelsMap(level1NavigationItem.screenIdentifier) if (navigationLevelsMap == null) { diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt index c94d8bca5..cbd662b11 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt @@ -1,6 +1,8 @@ package com.adammcneilly.pocketleague.shared.screens import com.adammcneilly.pocketleague.shared.screens.feed.initFeed +import com.adammcneilly.pocketleague.shared.screens.records.initRecords +import com.adammcneilly.pocketleague.shared.screens.stats.initStats /** * An enumeration of all screens that appear somewhere in our application. @@ -18,15 +20,21 @@ enum class Screens( initFeed() }, stackableInstances = true, - ) + ), + Stats( + asString = "stats", + navigationLevel = 1, + initSettings = { + initStats() + }, + stackableInstances = true, + ), + Records( + asString = "records", + navigationLevel = 1, + initSettings = { + initRecords() + }, + stackableInstances = true, + ), } - -// enum class Screen( -// val asString: String, -// val navigationLevel : Int = 1, -// val initSettings: Navigation.(ScreenIdentifier) -> ScreenInitSettings, -// val stackableInstances : Boolean = false, -// ) { -// CountriesList("countrieslist", 1, { initCountriesList(it.params()) }, true), -// CountryDetail("country", 2, { initCountryDetail(it.params()) }), -// } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt index 3d3edda08..f803d0cc6 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedInitSettings.kt @@ -15,6 +15,6 @@ fun Navigation.initFeed(): ScreenInitSettings { callOnInit = { events.loadFeed() }, - reInitOnEachNavigation = true, + reInitOnEachNavigation = false, ) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/records/RecordsInitSettings.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/records/RecordsInitSettings.kt new file mode 100644 index 000000000..3c83ae200 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/records/RecordsInitSettings.kt @@ -0,0 +1,20 @@ +package com.adammcneilly.pocketleague.shared.screens.records + +import com.adammcneilly.pocketleague.shared.screens.Navigation +import com.adammcneilly.pocketleague.shared.screens.ScreenInitSettings + +/** + * Returns the [ScreenInitSettings] for our [com.adammcneilly.pocketleague.shared.screens.Screens.Records] screen. + */ +fun Navigation.initRecords(): ScreenInitSettings { + return ScreenInitSettings( + title = "Records", + initState = { + RecordsViewState() + }, + callOnInit = { + // Coming soon. + }, + reInitOnEachNavigation = false, + ) +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/records/RecordsViewState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/records/RecordsViewState.kt new file mode 100644 index 000000000..fe2db2f2d --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/records/RecordsViewState.kt @@ -0,0 +1,10 @@ +package com.adammcneilly.pocketleague.shared.screens.records + +import com.adammcneilly.pocketleague.shared.screens.ScreenState + +/** + * The UI state of the records screen. + */ +data class RecordsViewState( + val showLoading: Boolean = true, +) : ScreenState diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/stats/StatsInitSettings.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/stats/StatsInitSettings.kt new file mode 100644 index 000000000..2893bf370 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/stats/StatsInitSettings.kt @@ -0,0 +1,20 @@ +package com.adammcneilly.pocketleague.shared.screens.stats + +import com.adammcneilly.pocketleague.shared.screens.Navigation +import com.adammcneilly.pocketleague.shared.screens.ScreenInitSettings + +/** + * Returns the [ScreenInitSettings] for our [com.adammcneilly.pocketleague.shared.screens.Screens.Stats] screen. + */ +fun Navigation.initStats(): ScreenInitSettings { + return ScreenInitSettings( + title = "Stats", + initState = { + StatsViewState() + }, + callOnInit = { + // Coming soon. + }, + reInitOnEachNavigation = false, + ) +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/stats/StatsViewState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/stats/StatsViewState.kt new file mode 100644 index 000000000..5a02233ea --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/stats/StatsViewState.kt @@ -0,0 +1,10 @@ +package com.adammcneilly.pocketleague.shared.screens.stats + +import com.adammcneilly.pocketleague.shared.screens.ScreenState + +/** + * The view state for the stats screen. + */ +data class StatsViewState( + val showLoading: Boolean = true, +) : ScreenState From 9ff0602af564c8da57b6f792f015b7f43a57bfab Mon Sep 17 00:00:00 2001 From: amcneilly Date: Tue, 19 Apr 2022 22:39:14 -0400 Subject: [PATCH 31/40] Handling nav rail. --- .../pocketleague/ui/Level1NavigationRail.kt | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1NavigationRail.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1NavigationRail.kt index 621d305ed..244994c20 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1NavigationRail.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/Level1NavigationRail.kt @@ -4,23 +4,24 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.material.ContentAlpha import androidx.compose.material.Icon import androidx.compose.material.LocalContentColor import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Menu +import androidx.compose.material.icons.filled.BarChart +import androidx.compose.material.icons.filled.Feed +import androidx.compose.material.icons.filled.Leaderboard import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import com.adammcneilly.pocketleague.shared.screens.Level1Navigation import com.adammcneilly.pocketleague.shared.screens.Navigation import com.adammcneilly.pocketleague.shared.screens.ScreenIdentifier @@ -41,10 +42,24 @@ fun Navigation.Level1NavigationRail( verticalArrangement = Arrangement.Center ) { NavigationRailItem( - icon = { Icon(Icons.Default.Menu, "Feed") }, - label = { Text("FEED", fontSize = 13.sp) }, + icon = { Icon(Icons.Default.Feed, "Feed") }, + label = { Text("FEED") }, selected = selectedTab.uri == Level1Navigation.Feed.screenIdentifier.uri, - onClick = { navigateByLevel1Menu(Level1Navigation.Feed) } + onClick = { navigateByLevel1Menu(Level1Navigation.Feed) }, + ) + + NavigationRailItem( + icon = { Icon(Icons.Default.BarChart, "Stats") }, + label = { Text("STATS") }, + selected = selectedTab.uri == Level1Navigation.Stats.screenIdentifier.uri, + onClick = { navigateByLevel1Menu(Level1Navigation.Stats) }, + ) + + NavigationRailItem( + icon = { Icon(Icons.Default.Leaderboard, "Records") }, + label = { Text("RECORDS") }, + selected = selectedTab.uri == Level1Navigation.Records.screenIdentifier.uri, + onClick = { navigateByLevel1Menu(Level1Navigation.Records) }, ) } } @@ -53,16 +68,19 @@ fun Navigation.Level1NavigationRail( * Creates a single menu item to appear inside of a [Level1NavigationRail]. */ @Composable -fun ColumnScope.NavigationRailItem( +fun NavigationRailItem( icon: @Composable () -> Unit, label: @Composable () -> Unit, selected: Boolean, onClick: () -> Unit, ) { + val selectedContentColor = MaterialTheme.colors.onPrimary + val unselectedContentColor = selectedContentColor.copy(alpha = ContentAlpha.medium) + val contentColor = if (selected) { - MaterialTheme.colors.background + selectedContentColor } else { - MaterialTheme.colors.primaryVariant + unselectedContentColor } CompositionLocalProvider( From 1a774a97fc2406a5a6eb50680a5e22c204f7155e Mon Sep 17 00:00:00 2001 From: amcneilly Date: Wed, 20 Apr 2022 14:48:03 -0400 Subject: [PATCH 32/40] Adding octaneGG game models. --- .../octanegg/models/OctaneGGAdvancedStats.kt | 17 +++++ .../octanegg/models/OctaneGGBallStats.kt | 15 +++++ .../octanegg/models/OctaneGGBoostStats.kt | 67 +++++++++++++++++++ .../octanegg/models/OctaneGGDemoStats.kt | 15 +++++ .../remote/octanegg/models/OctaneGGGame.kt | 31 +++++++++ .../octanegg/models/OctaneGGGameTeamResult.kt | 17 +++++ .../remote/octanegg/models/OctaneGGMap.kt | 15 +++++ .../octanegg/models/OctaneGGMatchFormat.kt | 18 +++++ .../octanegg/models/OctaneGGMovementStats.kt | 47 +++++++++++++ .../octanegg/models/OctaneGGPlayerStats.kt | 17 +++++ .../models/OctaneGGPositioningStats.kt | 65 ++++++++++++++++++ .../remote/octanegg/models/OctaneGGStats.kt | 8 +++ 12 files changed, 332 insertions(+) create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGAdvancedStats.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGBallStats.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGBoostStats.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGDemoStats.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGame.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGameTeamResult.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMap.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchFormat.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMovementStats.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPlayerStats.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPositioningStats.kt diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGAdvancedStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGAdvancedStats.kt new file mode 100644 index 000000000..fc3cfd637 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGAdvancedStats.kt @@ -0,0 +1,17 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Advanced statistics for a player or a team. + */ +@Serializable +data class OctaneGGAdvancedStats( + @SerialName("goalParticipation") + val goalParticipation: Int? = null, + @SerialName("mvp") + val mvp: Boolean? = null, + @SerialName("rating") + val rating: Double? = null +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGBallStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGBallStats.kt new file mode 100644 index 000000000..5233257ab --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGBallStats.kt @@ -0,0 +1,15 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Ball and possession related stats for a player or team. + */ +@Serializable +data class OctaneGGBallStats( + @SerialName("possessionTime") + val possessionTime: Double? = null, + @SerialName("timeInSide") + val timeInSide: Double? = null +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGBoostStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGBoostStats.kt new file mode 100644 index 000000000..c05a52ea5 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGBoostStats.kt @@ -0,0 +1,67 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Statistics about boost management for a player or team. + */ +@Serializable +data class OctaneGGBoostStats( + @SerialName("amountCollected") + val amountCollected: Int? = null, + @SerialName("amountCollectedBig") + val amountCollectedBig: Int? = null, + @SerialName("amountCollectedSmall") + val amountCollectedSmall: Int? = null, + @SerialName("amountOverfill") + val amountOverfill: Int? = null, + @SerialName("amountOverfillStolen") + val amountOverfillStolen: Int? = null, + @SerialName("amountStolen") + val amountStolen: Int? = null, + @SerialName("amountStolenBig") + val amountStolenBig: Int? = null, + @SerialName("amountStolenSmall") + val amountStolenSmall: Int? = null, + @SerialName("amountUsedWhileSupersonic") + val amountUsedWhileSupersonic: Int? = null, + @SerialName("avgAmount") + val avgAmount: Double? = null, + @SerialName("bcpm") + val bcpm: Double? = null, + @SerialName("bpm") + val bpm: Int? = null, + @SerialName("countCollectedBig") + val countCollectedBig: Int? = null, + @SerialName("countCollectedSmall") + val countCollectedSmall: Int? = null, + @SerialName("countStolenBig") + val countStolenBig: Int? = null, + @SerialName("countStolenSmall") + val countStolenSmall: Int? = null, + @SerialName("percentBoost0To25") + val percentBoost0To25: Double? = null, + @SerialName("percentBoost25To50") + val percentBoost25To50: Double? = null, + @SerialName("percentBoost50To75") + val percentBoost50To75: Double? = null, + @SerialName("percentBoost75To100") + val percentBoost75To100: Double? = null, + @SerialName("percentFullBoost") + val percentFullBoost: Double? = null, + @SerialName("percentZeroBoost") + val percentZeroBoost: Double? = null, + @SerialName("timeBoost0To25") + val timeBoost0To25: Double? = null, + @SerialName("timeBoost25To50") + val timeBoost25To50: Double? = null, + @SerialName("timeBoost50To75") + val timeBoost50To75: Double? = null, + @SerialName("timeBoost75To100") + val timeBoost75To100: Double? = null, + @SerialName("timeFullBoost") + val timeFullBoost: Double? = null, + @SerialName("timeZeroBoost") + val timeZeroBoost: Double? = null +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGDemoStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGDemoStats.kt new file mode 100644 index 000000000..4767d7b01 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGDemoStats.kt @@ -0,0 +1,15 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Statistics for demolitions for a player or team. + */ +@Serializable +data class OctaneGGDemoStats( + @SerialName("inflicted") + val inflicted: Int? = null, + @SerialName("taken") + val taken: Int? = null +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGame.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGame.kt new file mode 100644 index 000000000..5da9883f8 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGame.kt @@ -0,0 +1,31 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * A game played within a [OctaneGGMatch]. + */ +@Serializable +data class OctaneGGGame( + @SerialName("ballchasing") + val ballchasing: String? = null, + @SerialName("blue") + val blue: OctaneGGGameTeamResult? = null, + @SerialName("date") + val date: String? = null, + @SerialName("duration") + val duration: Int? = null, + @SerialName("_id") + val id: String? = null, + @SerialName("map") + val map: OctaneGGMap? = null, + @SerialName("match") + val match: OctaneGGMatch? = null, + @SerialName("number") + val number: Int? = null, + @SerialName("octane_id") + val octaneId: String? = null, + @SerialName("orange") + val orange: OctaneGGGameTeamResult? = null +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGameTeamResult.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGameTeamResult.kt new file mode 100644 index 000000000..24e4afa2a --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGameTeamResult.kt @@ -0,0 +1,17 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * The result of a [team] inside an [OctaneGGGame]. + */ +@Serializable +data class OctaneGGGameTeamResult( + @SerialName("matchWinner") + val matchWinner: Boolean? = null, + @SerialName("players") + val players: List? = null, + @SerialName("team") + val team: OctaneGGTeamStats? = null +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMap.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMap.kt new file mode 100644 index 000000000..8b9bc7d7c --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMap.kt @@ -0,0 +1,15 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Information about a map that a game was played on. + */ +@Serializable +data class OctaneGGMap( + @SerialName("id") + val id: String? = null, + @SerialName("name") + val name: String? = null +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchFormat.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchFormat.kt new file mode 100644 index 000000000..5ca5e0dbd --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMatchFormat.kt @@ -0,0 +1,18 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Defines a format of a match between two teams. + * + * @property[length] The length of the format, so in a best of 7, this value would be seven. + * @property[type] The type of format, for example "best" would mean a best of X series. + */ +@Serializable +data class OctaneGGMatchFormat( + @SerialName("length") + val length: Int? = null, + @SerialName("type") + val type: String? = null +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMovementStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMovementStats.kt new file mode 100644 index 000000000..376e23f27 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMovementStats.kt @@ -0,0 +1,47 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Detailed statistics about the movement for a given player or team. + */ +@Serializable +data class OctaneGGMovementStats( + @SerialName("avgPowerslideDuration") + val avgPowerslideDuration: Double? = null, + @SerialName("avgSpeed") + val avgSpeed: Int? = null, + @SerialName("avgSpeedPercentage") + val avgSpeedPercentage: Int? = null, + @SerialName("countPowerslide") + val countPowerslide: Int? = null, + @SerialName("percentBoostSpeed") + val percentBoostSpeed: Double? = null, + @SerialName("percentGround") + val percentGround: Double? = null, + @SerialName("percentHighAir") + val percentHighAir: Double? = null, + @SerialName("percentLowAir") + val percentLowAir: Double? = null, + @SerialName("percentSlowSpeed") + val percentSlowSpeed: Double? = null, + @SerialName("percentSupersonicSpeed") + val percentSupersonicSpeed: Double? = null, + @SerialName("timeBoostSpeed") + val timeBoostSpeed: Double? = null, + @SerialName("timeGround") + val timeGround: Double? = null, + @SerialName("timeHighAir") + val timeHighAir: Double? = null, + @SerialName("timeLowAir") + val timeLowAir: Double? = null, + @SerialName("timePowerslide") + val timePowerslide: Double? = null, + @SerialName("timeSlowSpeed") + val timeSlowSpeed: Double? = null, + @SerialName("timeSupersonicSpeed") + val timeSupersonicSpeed: Double? = null, + @SerialName("totalDistance") + val totalDistance: Int? = null +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPlayerStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPlayerStats.kt new file mode 100644 index 000000000..18b465e9f --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPlayerStats.kt @@ -0,0 +1,17 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Contains the core [stats] and [advanced] stats for a [player]. + */ +@Serializable +data class OctaneGGPlayerStats( + @SerialName("advanced") + val advanced: OctaneGGAdvancedStats? = null, + @SerialName("player") + val player: OctaneGGPlayer? = null, + @SerialName("stats") + val stats: OctaneGGStats? = null +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPositioningStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPositioningStats.kt new file mode 100644 index 000000000..42ebf4929 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPositioningStats.kt @@ -0,0 +1,65 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Detailed stats about the positioning of a player or team. + */ +@Serializable +data class OctaneGGPositioningStats( + @SerialName("avgDistanceToBall") + val avgDistanceToBall: Int? = null, + @SerialName("avgDistanceToBallNoPossession") + val avgDistanceToBallNoPossession: Int? = null, + @SerialName("avgDistanceToBallPossession") + val avgDistanceToBallPossession: Int? = null, + @SerialName("avgDistanceToMates") + val avgDistanceToMates: Int? = null, + @SerialName("goalsAgainstWhileLastDefender") + val goalsAgainstWhileLastDefender: Int? = null, + @SerialName("percentBehindBall") + val percentBehindBall: Double? = null, + @SerialName("percentClosestToBall") + val percentClosestToBall: Double? = null, + @SerialName("percentDefensiveHalf") + val percentDefensiveHalf: Double? = null, + @SerialName("percentDefensiveThird") + val percentDefensiveThird: Double? = null, + @SerialName("percentFarthestFromBall") + val percentFarthestFromBall: Double? = null, + @SerialName("percentInfrontBall") + val percentInfrontBall: Double? = null, + @SerialName("percentMostBack") + val percentMostBack: Double? = null, + @SerialName("percentMostForward") + val percentMostForward: Double? = null, + @SerialName("percentNeutralThird") + val percentNeutralThird: Double? = null, + @SerialName("percentOffensiveHalf") + val percentOffensiveHalf: Double? = null, + @SerialName("percentOffensiveThird") + val percentOffensiveThird: Double? = null, + @SerialName("timeBehindBall") + val timeBehindBall: Double? = null, + @SerialName("timeClosestToBall") + val timeClosestToBall: Double? = null, + @SerialName("timeDefensiveHalf") + val timeDefensiveHalf: Double? = null, + @SerialName("timeDefensiveThird") + val timeDefensiveThird: Double? = null, + @SerialName("timeFarthestFromBall") + val timeFarthestFromBall: Double? = null, + @SerialName("timeInfrontBall") + val timeInfrontBall: Double? = null, + @SerialName("timeMostBack") + val timeMostBack: Double? = null, + @SerialName("timeMostForward") + val timeMostForward: Int? = null, + @SerialName("timeNeutralThird") + val timeNeutralThird: Double? = null, + @SerialName("timeOffensiveHalf") + val timeOffensiveHalf: Double? = null, + @SerialName("timeOffensiveThird") + val timeOffensiveThird: Double? = null +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStats.kt index 2c3ab6a91..0b0ecc6e3 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStats.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGStats.kt @@ -8,6 +8,14 @@ import kotlinx.serialization.Serializable */ @Serializable data class OctaneGGStats( + @SerialName("boost") + val boost: OctaneGGBoostStats? = null, @SerialName("core") val core: OctaneGGCoreStats? = null, + @SerialName("demo") + val demo: OctaneGGDemoStats? = null, + @SerialName("movement") + val movement: OctaneGGMovementStats? = null, + @SerialName("positioning") + val positioning: OctaneGGPositioningStats? = null ) From d1be3119928693b196ee981a0f59d420cbe16773 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Wed, 20 Apr 2022 15:07:36 -0400 Subject: [PATCH 33/40] Adding game data layer. --- .../shared/data/models/MatchGamesRequest.kt | 8 ++++ .../data/remote/octanegg/OctaneGGEndpoints.kt | 7 +++ .../models/OctaneGGGameListResponse.kt | 13 ++++++ .../octanegg/services/OctaneGGGameService.kt | 44 +++++++++++++++++++ .../data/repositories/GameRepository.kt | 17 +++++++ .../pocketleague/shared/models/Game.kt | 10 +++++ .../shared/models/GameTeamResult.kt | 16 +++++++ 7 files changed, 115 insertions(+) create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/models/MatchGamesRequest.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGameListResponse.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGGameService.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/GameRepository.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Game.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/GameTeamResult.kt diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/models/MatchGamesRequest.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/models/MatchGamesRequest.kt new file mode 100644 index 000000000..d6a8b5dc2 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/models/MatchGamesRequest.kt @@ -0,0 +1,8 @@ +package com.adammcneilly.pocketleague.shared.data.models + +/** + * Used to request a list of games for the given [matchId]. + */ +data class MatchGamesRequest( + val matchId: String, +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGEndpoints.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGEndpoints.kt index 9d32d2858..ee1175949 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGEndpoints.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/OctaneGGEndpoints.kt @@ -6,4 +6,11 @@ package com.adammcneilly.pocketleague.shared.data.remote.octanegg object OctaneGGEndpoints { const val EVENTS = "/events" const val MATCHES = "/matches" + + /** + * Builds and endpoint for retrieving games by [matchId]. + */ + fun gamesByMatchEndpoint(matchId: String): String { + return "/matches/$matchId/games" + } } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGameListResponse.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGameListResponse.kt new file mode 100644 index 000000000..e3b66247b --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGameListResponse.kt @@ -0,0 +1,13 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.models + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Returns a list of [games] from the API. + */ +@Serializable +data class OctaneGGGameListResponse( + @SerialName("games") + val games: List? = null, +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGGameService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGGameService.kt new file mode 100644 index 000000000..dc3fa30a7 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGGameService.kt @@ -0,0 +1,44 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.services + +import com.adammcneilly.pocketleague.shared.data.DataState +import com.adammcneilly.pocketleague.shared.data.models.MatchGamesRequest +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGAPIClient +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGEndpoints +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGGameListResponse +import com.adammcneilly.pocketleague.shared.data.repositories.GameRepository +import com.adammcneilly.pocketleague.shared.models.Game +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow + +/** + * A concrete implementation of [GameRepository] that requests information via the supplied + * [apiClient]. + */ +class OctaneGGGameService( + private val apiClient: OctaneGGAPIClient = OctaneGGAPIClient(), +) : GameRepository { + + override fun fetchGamesForMatch(request: MatchGamesRequest): Flow>> { + return flow { + val apiResult = apiClient.getResponse( + endpoint = OctaneGGEndpoints.gamesByMatchEndpoint(request.matchId), + ) + + val mappedResult = when (apiResult) { + is DataState.Loading -> DataState.Loading + is DataState.Success -> { + val mappedGames = apiResult.data.games?.map { + Game() + }.orEmpty() + + DataState.Success(mappedGames) + } + is DataState.Error -> { + DataState.Error(apiResult.error) + } + } + + emit(mappedResult) + } + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/GameRepository.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/GameRepository.kt new file mode 100644 index 000000000..2779ca59c --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/repositories/GameRepository.kt @@ -0,0 +1,17 @@ +package com.adammcneilly.pocketleague.shared.data.repositories + +import com.adammcneilly.pocketleague.shared.data.DataState +import com.adammcneilly.pocketleague.shared.data.models.MatchGamesRequest +import com.adammcneilly.pocketleague.shared.models.Game +import kotlinx.coroutines.flow.Flow + +/** + * Defines the data contract for all requests within the game space. + */ +interface GameRepository { + + /** + * Requests a list of [Game] entities for the given [request]. + */ + fun fetchGamesForMatch(request: MatchGamesRequest): Flow>> +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Game.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Game.kt new file mode 100644 index 000000000..be6c84891 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Game.kt @@ -0,0 +1,10 @@ +package com.adammcneilly.pocketleague.shared.models + +/** + * Information about a single [Game] inside a [Match] between two teams. + */ +data class Game( + val id: String = "", + val blue: GameTeamResult = GameTeamResult(), + val orange: GameTeamResult = GameTeamResult(), +) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/GameTeamResult.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/GameTeamResult.kt new file mode 100644 index 000000000..22db5fe06 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/GameTeamResult.kt @@ -0,0 +1,16 @@ +package com.adammcneilly.pocketleague.shared.models + +/** + * Defines information about the reuslt of a [team] within a game. + * + * @property[goals] The number of goals scored by this team during the game. + * @property[winner] True if this team won the specific game. + * @property[matchWinner] True if this team won the match between both teams. + * @property[team] Detailed information about the [Team] playing in the match. + */ +data class GameTeamResult( + val goals: Int = -1, + val winner: Boolean = false, + val matchWinner: Boolean = false, + val team: Team = Team(), +) From 3b386bdbe1e6c7f8ace1cb95fad5d7c761eb014b Mon Sep 17 00:00:00 2001 From: amcneilly Date: Wed, 20 Apr 2022 20:19:33 -0400 Subject: [PATCH 34/40] Setup for match detail screen. --- .../pocketleague/ui/FeedContent.kt | 19 ++++++++-- .../pocketleague/ui/MatchDetailContent.kt | 20 +++++++++++ .../pocketleague/ui/ScreenPicker.kt | 16 +++++++++ .../shared/data/AppDependencies.kt | 13 +++++++ .../octanegg/models/OctaneGGAdvancedStats.kt | 2 +- .../octanegg/models/OctaneGGMovementStats.kt | 8 ++--- .../models/OctaneGGPositioningStats.kt | 12 +++---- .../matchdetail/GetMatchGamesUseCase.kt | 16 +++++++++ .../matchdetail/GetMatchGamesUseCaseImpl.kt | 23 ++++++++++++ .../pocketleague/shared/screens/Screens.kt | 9 +++++ .../matchdetail/GetGamesForMatchEvent.kt | 36 +++++++++++++++++++ .../matchdetail/MatchDetailInitSettings.kt | 24 +++++++++++++ .../screens/matchdetail/MatchDetailParams.kt | 13 +++++++ .../matchdetail/MatchDetailViewState.kt | 15 ++++++++ 14 files changed, 212 insertions(+), 14 deletions(-) create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchdetail/GetMatchGamesUseCase.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchdetail/GetMatchGamesUseCaseImpl.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/GetGamesForMatchEvent.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailInitSettings.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailParams.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailViewState.kt diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt index e96718719..0985fb13d 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt @@ -1,5 +1,6 @@ package com.adammcneilly.pocketleague.ui +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues @@ -15,6 +16,7 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import com.adammcneilly.pocketleague.shared.models.Match import com.adammcneilly.pocketleague.shared.screens.feed.FeedViewState private const val MATCH_CARD_WIDTH_RATIO = 0.8F @@ -26,16 +28,23 @@ private const val MATCH_CARD_WIDTH_RATIO = 0.8F fun FeedContent( viewState: FeedViewState, modifier: Modifier = Modifier, + onMatchClicked: (Match) -> Unit = {}, ) { Box( modifier = modifier.fillMaxSize(), ) { - SuccessContent(viewState) + SuccessContent( + viewState = viewState, + onMatchClicked = onMatchClicked, + ) } } @Composable -private fun SuccessContent(viewState: FeedViewState) { +private fun SuccessContent( + viewState: FeedViewState, + onMatchClicked: (Match) -> Unit, +) { LazyColumn( modifier = Modifier.fillMaxSize(), ) { @@ -59,7 +68,11 @@ private fun SuccessContent(viewState: FeedViewState) { items(viewState.recentMatches) { match -> MatchListItem( match = match, - modifier = Modifier.fillParentMaxWidth(MATCH_CARD_WIDTH_RATIO), + modifier = Modifier + .fillParentMaxWidth(MATCH_CARD_WIDTH_RATIO) + .clickable { + onMatchClicked.invoke(match) + }, ) } } diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt new file mode 100644 index 000000000..7235e45d1 --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt @@ -0,0 +1,20 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.foundation.layout.Box +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.adammcneilly.pocketleague.shared.screens.matchdetail.MatchDetailViewState + +/** + * The UI content of the match detail screen. + */ +@Composable +fun MatchDetailContent( + viewState: MatchDetailViewState, + modifier: Modifier = Modifier, +) { + Box(modifier = modifier) { + Text(text = viewState.toString()) + } +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt index 1d7f2210d..8c340b2a0 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/ScreenPicker.kt @@ -7,6 +7,7 @@ import androidx.compose.ui.Modifier import com.adammcneilly.pocketleague.shared.screens.Navigation import com.adammcneilly.pocketleague.shared.screens.ScreenIdentifier import com.adammcneilly.pocketleague.shared.screens.Screens +import com.adammcneilly.pocketleague.shared.screens.matchdetail.MatchDetailParams /** * The screen picker tacks a current [screenIdentifier] and renders the content for that screen. @@ -23,6 +24,14 @@ fun Navigation.ScreenPicker( viewState = stateProvider.get(screenIdentifier), modifier = Modifier .padding(paddingValues), + onMatchClicked = { match -> + navigate( + screen = Screens.MatchDetail, + params = MatchDetailParams( + match = match, + ), + ) + } ) } Screens.Stats -> { @@ -39,5 +48,12 @@ fun Navigation.ScreenPicker( .padding(paddingValues), ) } + Screens.MatchDetail -> { + MatchDetailContent( + viewState = stateProvider.get(screenIdentifier), + modifier = Modifier + .padding(paddingValues), + ) + } } } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/AppDependencies.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/AppDependencies.kt index a780f8c9d..777051d4f 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/AppDependencies.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/AppDependencies.kt @@ -1,11 +1,15 @@ package com.adammcneilly.pocketleague.shared.data import com.adammcneilly.pocketleague.shared.data.remote.octanegg.services.OctaneGGEventService +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.services.OctaneGGGameService import com.adammcneilly.pocketleague.shared.data.remote.octanegg.services.OctaneGGMatchService import com.adammcneilly.pocketleague.shared.data.repositories.EventRepository +import com.adammcneilly.pocketleague.shared.data.repositories.GameRepository import com.adammcneilly.pocketleague.shared.data.repositories.MatchRepository import com.adammcneilly.pocketleague.shared.eventlist.GetUpcomingEventsUseCase import com.adammcneilly.pocketleague.shared.eventlist.GetUpcomingEventsUseCaseImpl +import com.adammcneilly.pocketleague.shared.matchdetail.GetMatchGamesUseCase +import com.adammcneilly.pocketleague.shared.matchdetail.GetMatchGamesUseCaseImpl import com.adammcneilly.pocketleague.shared.matchlist.GetRecentMatchesUseCase import com.adammcneilly.pocketleague.shared.matchlist.GetRecentMatchesUseCaseImpl @@ -23,6 +27,10 @@ class AppDependencies { OctaneGGMatchService() } + private val gameRepository: GameRepository by lazy { + OctaneGGGameService() + } + internal val getUpcomingEventsUseCase: GetUpcomingEventsUseCase get() = GetUpcomingEventsUseCaseImpl( repository = eventRepository, @@ -32,4 +40,9 @@ class AppDependencies { get() = GetRecentMatchesUseCaseImpl( repository = matchRepository, ) + + internal val getMatchGamesUseCase: GetMatchGamesUseCase + get() = GetMatchGamesUseCaseImpl( + repository = gameRepository, + ) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGAdvancedStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGAdvancedStats.kt index fc3cfd637..42f4e9afc 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGAdvancedStats.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGAdvancedStats.kt @@ -9,7 +9,7 @@ import kotlinx.serialization.Serializable @Serializable data class OctaneGGAdvancedStats( @SerialName("goalParticipation") - val goalParticipation: Int? = null, + val goalParticipation: Double? = null, @SerialName("mvp") val mvp: Boolean? = null, @SerialName("rating") diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMovementStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMovementStats.kt index 376e23f27..b53284bb2 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMovementStats.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGMovementStats.kt @@ -11,11 +11,11 @@ data class OctaneGGMovementStats( @SerialName("avgPowerslideDuration") val avgPowerslideDuration: Double? = null, @SerialName("avgSpeed") - val avgSpeed: Int? = null, + val avgSpeed: Double? = null, @SerialName("avgSpeedPercentage") - val avgSpeedPercentage: Int? = null, + val avgSpeedPercentage: Double? = null, @SerialName("countPowerslide") - val countPowerslide: Int? = null, + val countPowerslide: Double? = null, @SerialName("percentBoostSpeed") val percentBoostSpeed: Double? = null, @SerialName("percentGround") @@ -43,5 +43,5 @@ data class OctaneGGMovementStats( @SerialName("timeSupersonicSpeed") val timeSupersonicSpeed: Double? = null, @SerialName("totalDistance") - val totalDistance: Int? = null + val totalDistance: Double? = null ) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPositioningStats.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPositioningStats.kt index 42ebf4929..bf5eee31f 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPositioningStats.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGPositioningStats.kt @@ -9,15 +9,15 @@ import kotlinx.serialization.Serializable @Serializable data class OctaneGGPositioningStats( @SerialName("avgDistanceToBall") - val avgDistanceToBall: Int? = null, + val avgDistanceToBall: Double? = null, @SerialName("avgDistanceToBallNoPossession") - val avgDistanceToBallNoPossession: Int? = null, + val avgDistanceToBallNoPossession: Double? = null, @SerialName("avgDistanceToBallPossession") - val avgDistanceToBallPossession: Int? = null, + val avgDistanceToBallPossession: Double? = null, @SerialName("avgDistanceToMates") - val avgDistanceToMates: Int? = null, + val avgDistanceToMates: Double? = null, @SerialName("goalsAgainstWhileLastDefender") - val goalsAgainstWhileLastDefender: Int? = null, + val goalsAgainstWhileLastDefender: Double? = null, @SerialName("percentBehindBall") val percentBehindBall: Double? = null, @SerialName("percentClosestToBall") @@ -55,7 +55,7 @@ data class OctaneGGPositioningStats( @SerialName("timeMostBack") val timeMostBack: Double? = null, @SerialName("timeMostForward") - val timeMostForward: Int? = null, + val timeMostForward: Double? = null, @SerialName("timeNeutralThird") val timeNeutralThird: Double? = null, @SerialName("timeOffensiveHalf") diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchdetail/GetMatchGamesUseCase.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchdetail/GetMatchGamesUseCase.kt new file mode 100644 index 000000000..434eb146f --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchdetail/GetMatchGamesUseCase.kt @@ -0,0 +1,16 @@ +package com.adammcneilly.pocketleague.shared.matchdetail + +import com.adammcneilly.pocketleague.shared.data.DataState +import com.adammcneilly.pocketleague.shared.models.Game +import kotlinx.coroutines.flow.Flow + +/** + * Consumes a match ID and requests a list of [Game] entities for that match. + */ +interface GetMatchGamesUseCase { + + /** + * @see [GetMatchGamesUseCase] + */ + operator fun invoke(matchId: String): Flow>> +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchdetail/GetMatchGamesUseCaseImpl.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchdetail/GetMatchGamesUseCaseImpl.kt new file mode 100644 index 000000000..5fc39999a --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/matchdetail/GetMatchGamesUseCaseImpl.kt @@ -0,0 +1,23 @@ +package com.adammcneilly.pocketleague.shared.matchdetail + +import com.adammcneilly.pocketleague.shared.data.DataState +import com.adammcneilly.pocketleague.shared.data.models.MatchGamesRequest +import com.adammcneilly.pocketleague.shared.data.repositories.GameRepository +import com.adammcneilly.pocketleague.shared.models.Game +import kotlinx.coroutines.flow.Flow + +/** + * A concrete implementation of [GetMatchGamesUseCase] to request the games from the given [repository]. + */ +class GetMatchGamesUseCaseImpl( + private val repository: GameRepository, +) : GetMatchGamesUseCase { + + override fun invoke(matchId: String): Flow>> { + val request = MatchGamesRequest( + matchId = matchId, + ) + + return repository.fetchGamesForMatch(request) + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt index cbd662b11..feefe5f67 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/Screens.kt @@ -1,6 +1,7 @@ package com.adammcneilly.pocketleague.shared.screens import com.adammcneilly.pocketleague.shared.screens.feed.initFeed +import com.adammcneilly.pocketleague.shared.screens.matchdetail.initMatchDetail import com.adammcneilly.pocketleague.shared.screens.records.initRecords import com.adammcneilly.pocketleague.shared.screens.stats.initStats @@ -37,4 +38,12 @@ enum class Screens( }, stackableInstances = true, ), + MatchDetail( + asString = "match_detail", + navigationLevel = 2, + initSettings = { + initMatchDetail(it.params()) + }, + stackableInstances = false, + ) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/GetGamesForMatchEvent.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/GetGamesForMatchEvent.kt new file mode 100644 index 000000000..1a016ebd3 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/GetGamesForMatchEvent.kt @@ -0,0 +1,36 @@ +package com.adammcneilly.pocketleague.shared.screens.matchdetail + +import com.adammcneilly.pocketleague.shared.data.DataState +import com.adammcneilly.pocketleague.shared.screens.Events +import kotlinx.coroutines.flow.collect + +/** + * Requests the games for the given [matchId]. + */ +fun Events.getGamesForMatch(matchId: String) = screenCoroutine { + val useCase = this.dependencies.getMatchGamesUseCase + + useCase.invoke(matchId).collect { useCaseResult -> + stateManager.updateScreen(MatchDetailViewState::class) { + when (useCaseResult) { + is DataState.Loading -> { + it.copy( + showLoading = true, + ) + } + is DataState.Success -> { + it.copy( + showLoading = false, + games = useCaseResult.data, + ) + } + is DataState.Error -> { + it.copy( + showLoading = false, + errorMessage = useCaseResult.error.message, + ) + } + } + } + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailInitSettings.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailInitSettings.kt new file mode 100644 index 000000000..e909191b0 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailInitSettings.kt @@ -0,0 +1,24 @@ +package com.adammcneilly.pocketleague.shared.screens.matchdetail + +import com.adammcneilly.pocketleague.shared.screens.Navigation +import com.adammcneilly.pocketleague.shared.screens.ScreenInitSettings + +/** + * Returns the [ScreenInitSettings] for our [com.adammcneilly.pocketleague.shared.screens.Screens.MatchDetail] screen. + */ +fun Navigation.initMatchDetail( + params: MatchDetailParams, +): ScreenInitSettings { + return ScreenInitSettings( + title = "Match Detail", + initState = { + MatchDetailViewState( + match = params.match, + ) + }, + callOnInit = { + events.getGamesForMatch(params.match.id) + }, + reInitOnEachNavigation = false, + ) +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailParams.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailParams.kt new file mode 100644 index 000000000..965152e46 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailParams.kt @@ -0,0 +1,13 @@ +package com.adammcneilly.pocketleague.shared.screens.matchdetail + +import com.adammcneilly.pocketleague.shared.models.Match +import com.adammcneilly.pocketleague.shared.screens.ScreenParams + +/** + * Parameters that will be passed into the match detail screen. + * + * @property[match] The [Match] entity to request detailed information for. + */ +data class MatchDetailParams( + val match: Match, +) : ScreenParams diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailViewState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailViewState.kt new file mode 100644 index 000000000..3c113cb96 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailViewState.kt @@ -0,0 +1,15 @@ +package com.adammcneilly.pocketleague.shared.screens.matchdetail + +import com.adammcneilly.pocketleague.shared.models.Game +import com.adammcneilly.pocketleague.shared.models.Match +import com.adammcneilly.pocketleague.shared.screens.ScreenState + +/** + * The UI state for detailed information about a [Match]. + */ +data class MatchDetailViewState( + val showLoading: Boolean = true, + val match: Match = Match(), + val games: List = emptyList(), + val errorMessage: String? = null, +) : ScreenState From 357fa533d72112f7c2c179248e2afae1b5981471 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Wed, 20 Apr 2022 20:32:29 -0400 Subject: [PATCH 35/40] Match detail stubbing. --- .../pocketleague/ui/GameListItem.kt | 45 +++++++++++++++++++ .../pocketleague/ui/MatchDetailContent.kt | 19 ++++++-- .../octanegg/mappers/OctaneGGGameMapper.kt | 17 +++++++ .../mappers/OctaneGGGameTeamResultMapper.kt | 16 +++++++ .../octanegg/models/OctaneGGGameTeamResult.kt | 2 + .../octanegg/services/OctaneGGGameService.kt | 6 +-- .../octanegg/services/OctaneGGMatchService.kt | 6 ++- .../pocketleague/shared/models/Game.kt | 1 + 8 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/GameListItem.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGGameMapper.kt create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGGameTeamResultMapper.kt diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/GameListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/GameListItem.kt new file mode 100644 index 000000000..85000422b --- /dev/null +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/GameListItem.kt @@ -0,0 +1,45 @@ +package com.adammcneilly.pocketleague.ui + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.adammcneilly.pocketleague.shared.models.Game +import com.adammcneilly.pocketleague.shared.models.GameTeamResult + +/** + * Displays a [game] entity as a list item, just showing the teams and their results. + */ +@Composable +fun GameListItem( + game: Game, +) { + Column { + Text(text = "Game X: ${game.map}") + Row( + modifier = Modifier + .fillMaxWidth(), + ) { + GameTeamResult(result = game.blue) + + GameTeamResult(result = game.orange) + } + } +} + +@Composable +private fun RowScope.GameTeamResult( + result: GameTeamResult, +) { + Column( + modifier = Modifier + .weight(1F), + ) { + Text(text = result.team.name) + + Text(text = result.goals.toString()) + } +} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt index 7235e45d1..399141f17 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt @@ -1,7 +1,9 @@ package com.adammcneilly.pocketleague.ui -import androidx.compose.foundation.layout.Box -import androidx.compose.material.Text +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.material.Divider import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.adammcneilly.pocketleague.shared.screens.matchdetail.MatchDetailViewState @@ -14,7 +16,16 @@ fun MatchDetailContent( viewState: MatchDetailViewState, modifier: Modifier = Modifier, ) { - Box(modifier = modifier) { - Text(text = viewState.toString()) + LazyColumn( + modifier = modifier + .fillMaxWidth(), + ) { + itemsIndexed(viewState.games) { index, game -> + GameListItem(game = game) + + if (index != viewState.games.lastIndex) { + Divider() + } + } } } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGGameMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGGameMapper.kt new file mode 100644 index 000000000..6f0d10632 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGGameMapper.kt @@ -0,0 +1,17 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.mappers + +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGGame +import com.adammcneilly.pocketleague.shared.models.Game +import com.adammcneilly.pocketleague.shared.models.GameTeamResult + +/** + * Converts an [OctaneGGGame] to a [Game] in our domain. + */ +fun OctaneGGGame.toGame(): Game { + return Game( + id = this.id.orEmpty(), + blue = this.blue?.toGameTeamResult() ?: GameTeamResult(), + orange = this.orange?.toGameTeamResult() ?: GameTeamResult(), + map = this.map?.name.orEmpty(), + ) +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGGameTeamResultMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGGameTeamResultMapper.kt new file mode 100644 index 000000000..2afe5287c --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGGameTeamResultMapper.kt @@ -0,0 +1,16 @@ +package com.adammcneilly.pocketleague.shared.data.remote.octanegg.mappers + +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGGameTeamResult +import com.adammcneilly.pocketleague.shared.models.GameTeamResult +import com.adammcneilly.pocketleague.shared.models.Team + +/** + * Converts an [OctaneGGGameTeamResult] to a [GameTeamResult] in our domain. + */ +fun OctaneGGGameTeamResult.toGameTeamResult(): GameTeamResult { + return GameTeamResult( + goals = this.team?.stats?.core?.goals ?: 0, + winner = this.gameWinner == true, + team = this.team?.team?.toTeam() ?: Team(), + ) +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGameTeamResult.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGameTeamResult.kt index 24e4afa2a..221f1d958 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGameTeamResult.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/models/OctaneGGGameTeamResult.kt @@ -8,6 +8,8 @@ import kotlinx.serialization.Serializable */ @Serializable data class OctaneGGGameTeamResult( + @SerialName("winner") + val gameWinner: Boolean? = null, @SerialName("matchWinner") val matchWinner: Boolean? = null, @SerialName("players") diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGGameService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGGameService.kt index dc3fa30a7..6390fca72 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGGameService.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGGameService.kt @@ -4,6 +4,8 @@ import com.adammcneilly.pocketleague.shared.data.DataState import com.adammcneilly.pocketleague.shared.data.models.MatchGamesRequest import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGAPIClient import com.adammcneilly.pocketleague.shared.data.remote.octanegg.OctaneGGEndpoints +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.mappers.toGame +import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGGame import com.adammcneilly.pocketleague.shared.data.remote.octanegg.models.OctaneGGGameListResponse import com.adammcneilly.pocketleague.shared.data.repositories.GameRepository import com.adammcneilly.pocketleague.shared.models.Game @@ -27,9 +29,7 @@ class OctaneGGGameService( val mappedResult = when (apiResult) { is DataState.Loading -> DataState.Loading is DataState.Success -> { - val mappedGames = apiResult.data.games?.map { - Game() - }.orEmpty() + val mappedGames = apiResult.data.games?.map(OctaneGGGame::toGame).orEmpty() DataState.Success(mappedGames) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt index 5ab3baa37..6369d465f 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGMatchService.kt @@ -35,9 +35,11 @@ class OctaneGGMatchService( val mappedResult = when (apiResult) { is DataState.Loading -> DataState.Loading is DataState.Success -> { - val mappedMatches = apiResult.data.matches?.mapNotNull(OctaneGGMatch::toMatch).orEmpty() + val mappedMatches = + apiResult.data.matches?.mapNotNull(OctaneGGMatch::toMatch).orEmpty() - val sortedMatches = mappedMatches.sortedByDescending(Match::date) +// val sortedMatches = mappedMatches.sortedByDescending(Match::date) + val sortedMatches = mappedMatches.sortedBy(Match::date) DataState.Success(sortedMatches) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Game.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Game.kt index be6c84891..c92a62ebb 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Game.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Game.kt @@ -7,4 +7,5 @@ data class Game( val id: String = "", val blue: GameTeamResult = GameTeamResult(), val orange: GameTeamResult = GameTeamResult(), + val map: String = "", ) From b6fd291179cc3a370b00d30c1fb5258ca351d3ff Mon Sep 17 00:00:00 2001 From: amcneilly Date: Wed, 20 Apr 2022 20:47:06 -0400 Subject: [PATCH 36/40] More game parsing and detail tinkering. --- .../pocketleague/ui/MatchDetailContent.kt | 61 +++++++++++++++++-- .../octanegg/mappers/OctaneGGGameMapper.kt | 1 + .../octanegg/services/OctaneGGGameService.kt | 4 +- .../pocketleague/shared/models/Game.kt | 1 + 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt index 399141f17..86a031408 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt @@ -1,12 +1,24 @@ package com.adammcneilly.pocketleague.ui +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Divider +import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage +import coil.request.ImageRequest +import com.adammcneilly.pocketleague.shared.models.Team import com.adammcneilly.pocketleague.shared.screens.matchdetail.MatchDetailViewState +import com.google.accompanist.placeholder.material.placeholder /** * The UI content of the match detail screen. @@ -16,11 +28,24 @@ fun MatchDetailContent( viewState: MatchDetailViewState, modifier: Modifier = Modifier, ) { - LazyColumn( + Column( modifier = modifier .fillMaxWidth(), ) { - itemsIndexed(viewState.games) { index, game -> + Row( + modifier = Modifier + .fillMaxWidth(), + ) { + TeamNameLogo( + team = viewState.match.blueTeam.team, + ) + + TeamNameLogo( + team = viewState.match.orangeTeam.team, + ) + } + + viewState.games.forEachIndexed { index, game -> GameListItem(game = game) if (index != viewState.games.lastIndex) { @@ -29,3 +54,31 @@ fun MatchDetailContent( } } } + +@Composable +private fun RowScope.TeamNameLogo( + team: Team, +) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(12.dp), + modifier = Modifier + .weight(1F), + ) { + Text(text = team.name) + + AsyncImage( + model = ImageRequest.Builder(LocalContext.current) + .data(team.imageUrl) + .crossfade(true) + .build(), + contentDescription = "Event Image", + modifier = Modifier + .size(48.dp) + .placeholder( + visible = team.imageUrl == null, + shape = CircleShape, + ), + ) + } +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGGameMapper.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGGameMapper.kt index 6f0d10632..d9c3c4ebe 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGGameMapper.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/mappers/OctaneGGGameMapper.kt @@ -13,5 +13,6 @@ fun OctaneGGGame.toGame(): Game { blue = this.blue?.toGameTeamResult() ?: GameTeamResult(), orange = this.orange?.toGameTeamResult() ?: GameTeamResult(), map = this.map?.name.orEmpty(), + number = this.number ?: 0, ) } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGGameService.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGGameService.kt index 6390fca72..5a7d12ab6 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGGameService.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/data/remote/octanegg/services/OctaneGGGameService.kt @@ -31,7 +31,9 @@ class OctaneGGGameService( is DataState.Success -> { val mappedGames = apiResult.data.games?.map(OctaneGGGame::toGame).orEmpty() - DataState.Success(mappedGames) + val sortedGames = mappedGames.sortedBy(Game::number) + + DataState.Success(sortedGames) } is DataState.Error -> { DataState.Error(apiResult.error) diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Game.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Game.kt index c92a62ebb..4cc619ee2 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Game.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/models/Game.kt @@ -8,4 +8,5 @@ data class Game( val blue: GameTeamResult = GameTeamResult(), val orange: GameTeamResult = GameTeamResult(), val map: String = "", + val number: Int = 0, ) From b8123a0b11d04d9f28bfa0afe057873028907c52 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Thu, 21 Apr 2022 20:57:23 -0400 Subject: [PATCH 37/40] Showing game detail placeholder. --- .../pocketleague/ui/GameListItem.kt | 62 ++++++++++++------- .../pocketleague/ui/MatchDetailContent.kt | 15 +++-- .../matchdetail/GetGamesForMatchEvent.kt | 23 +------ .../matchdetail/MatchDetailViewState.kt | 19 +++++- 4 files changed, 69 insertions(+), 50 deletions(-) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/GameListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/GameListItem.kt index 85000422b..c911595a0 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/GameListItem.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/GameListItem.kt @@ -1,14 +1,17 @@ package com.adammcneilly.pocketleague.ui -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp import com.adammcneilly.pocketleague.shared.models.Game -import com.adammcneilly.pocketleague.shared.models.GameTeamResult +import com.google.accompanist.placeholder.material.placeholder /** * Displays a [game] entity as a list item, just showing the teams and their results. @@ -17,29 +20,40 @@ import com.adammcneilly.pocketleague.shared.models.GameTeamResult fun GameListItem( game: Game, ) { - Column { - Text(text = "Game X: ${game.map}") - Row( - modifier = Modifier - .fillMaxWidth(), - ) { - GameTeamResult(result = game.blue) - - GameTeamResult(result = game.orange) - } - } -} - -@Composable -private fun RowScope.GameTeamResult( - result: GameTeamResult, -) { - Column( + Row( modifier = Modifier - .weight(1F), + .fillMaxWidth() + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically, ) { - Text(text = result.team.name) + Text( + text = game.blue.goals.toString(), + modifier = Modifier + .placeholder( + visible = game.blue.goals == -1, + shape = CircleShape, + ), + ) - Text(text = result.goals.toString()) + Text( + text = "Game ${game.number}\n${game.map}", + modifier = Modifier + .weight(1F) + .padding(horizontal = 16.dp) + .placeholder( + visible = game.map.isEmpty(), + shape = CircleShape, + ), + textAlign = TextAlign.Center, + ) + + Text( + text = game.orange.goals.toString(), + modifier = Modifier + .placeholder( + visible = game.orange.goals == -1, + shape = CircleShape, + ), + ) } } diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt index 86a031408..c5a914b1a 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/MatchDetailContent.kt @@ -4,9 +4,14 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.verticalScroll import androidx.compose.material.Divider import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -30,7 +35,9 @@ fun MatchDetailContent( ) { Column( modifier = modifier - .fillMaxWidth(), + .fillMaxWidth() + .padding(16.dp) + .verticalScroll(rememberScrollState()), ) { Row( modifier = Modifier @@ -45,12 +52,12 @@ fun MatchDetailContent( ) } + Spacer(modifier = Modifier.height(48.dp)) + viewState.games.forEachIndexed { index, game -> GameListItem(game = game) - if (index != viewState.games.lastIndex) { - Divider() - } + Divider() } } } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/GetGamesForMatchEvent.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/GetGamesForMatchEvent.kt index 1a016ebd3..d3e673320 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/GetGamesForMatchEvent.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/GetGamesForMatchEvent.kt @@ -1,6 +1,5 @@ package com.adammcneilly.pocketleague.shared.screens.matchdetail -import com.adammcneilly.pocketleague.shared.data.DataState import com.adammcneilly.pocketleague.shared.screens.Events import kotlinx.coroutines.flow.collect @@ -12,25 +11,9 @@ fun Events.getGamesForMatch(matchId: String) = screenCoroutine { useCase.invoke(matchId).collect { useCaseResult -> stateManager.updateScreen(MatchDetailViewState::class) { - when (useCaseResult) { - is DataState.Loading -> { - it.copy( - showLoading = true, - ) - } - is DataState.Success -> { - it.copy( - showLoading = false, - games = useCaseResult.data, - ) - } - is DataState.Error -> { - it.copy( - showLoading = false, - errorMessage = useCaseResult.error.message, - ) - } - } + it.copy( + gamesDataState = useCaseResult, + ) } } } diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailViewState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailViewState.kt index 3c113cb96..037a957db 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailViewState.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/matchdetail/MatchDetailViewState.kt @@ -1,5 +1,6 @@ package com.adammcneilly.pocketleague.shared.screens.matchdetail +import com.adammcneilly.pocketleague.shared.data.DataState import com.adammcneilly.pocketleague.shared.models.Game import com.adammcneilly.pocketleague.shared.models.Match import com.adammcneilly.pocketleague.shared.screens.ScreenState @@ -10,6 +11,20 @@ import com.adammcneilly.pocketleague.shared.screens.ScreenState data class MatchDetailViewState( val showLoading: Boolean = true, val match: Match = Match(), - val games: List = emptyList(), + val gamesDataState: DataState> = DataState.Loading, val errorMessage: String? = null, -) : ScreenState +) : ScreenState { + + val games: List + get() = when (gamesDataState) { + is DataState.Loading -> { + listOf(Game(), Game(), Game()) + } + is DataState.Success -> { + gamesDataState.data + } + is DataState.Error -> { + emptyList() + } + } +} From 2743b8db5814fecb872edcfad73ea8166f1b87c4 Mon Sep 17 00:00:00 2001 From: amcneilly Date: Thu, 21 Apr 2022 21:06:59 -0400 Subject: [PATCH 38/40] Using display model for events. --- .../adammcneilly/pocketleague/ui/EventList.kt | 29 ---------------- ...entListItem.kt => EventSummaryListItem.kt} | 23 +++++-------- .../pocketleague/ui/FeedContent.kt | 2 +- .../displaymodels/EventSummaryDisplayModel.kt | 33 +++++++++++++++++++ .../shared/screens/feed/FeedViewState.kt | 10 +++--- .../shared/screens/feed/LoadFeedEvent.kt | 19 ++++++++++- 6 files changed, 67 insertions(+), 49 deletions(-) delete mode 100644 app/src/main/java/com/adammcneilly/pocketleague/ui/EventList.kt rename app/src/main/java/com/adammcneilly/pocketleague/ui/{EventListItem.kt => EventSummaryListItem.kt} (75%) create mode 100644 shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/displaymodels/EventSummaryDisplayModel.kt diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/EventList.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventList.kt deleted file mode 100644 index 8bf5e88f4..000000000 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/EventList.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.adammcneilly.pocketleague.ui - -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.material.Divider -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.adammcneilly.pocketleague.shared.models.Event - -/** - * Show a list of [events] inside of a lazy column. - */ -@Composable -fun EventList( - events: List, - modifier: Modifier = Modifier, -) { - LazyColumn( - modifier = modifier, - ) { - itemsIndexed(events) { index, event -> - EventListItem(event = event) - - if (index != events.lastIndex) { - Divider() - } - } - } -} diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventSummaryListItem.kt similarity index 75% rename from app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt rename to app/src/main/java/com/adammcneilly/pocketleague/ui/EventSummaryListItem.kt index dbcaae9cc..489439af0 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/EventListItem.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventSummaryListItem.kt @@ -9,10 +9,12 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import coil.request.ImageRequest import com.adammcneilly.pocketleague.shared.datetime.DateTimeFormatter +import com.adammcneilly.pocketleague.shared.displaymodels.EventSummaryDisplayModel import com.adammcneilly.pocketleague.shared.models.Event import com.google.accompanist.placeholder.material.placeholder @@ -21,44 +23,37 @@ import com.google.accompanist.placeholder.material.placeholder */ @OptIn(ExperimentalMaterialApi::class) @Composable -fun EventListItem( - event: Event, +fun EventSummaryListItem( + displayModel: EventSummaryDisplayModel, ) { ListItem( text = { Text( - text = event.name, + text = displayModel.name, modifier = Modifier .defaultMinSize(minWidth = 150.dp) .placeholder( - visible = event.name.isEmpty(), + visible = displayModel.name.isEmpty(), shape = CircleShape, ) ) }, overlineText = { - val startDateString = event.startDate?.let { startDate -> - DateTimeFormatter().formatLocalDateTime( - localDateTime = startDate, - formatPattern = "MMM dd, yyyy", - ) - } - Text( - text = startDateString.orEmpty(), + text = displayModel.startDate, ) }, icon = { AsyncImage( model = ImageRequest.Builder(LocalContext.current) - .data(event.imageUrl) + .data(displayModel.imageUrl) .crossfade(true) .build(), contentDescription = "Event Image", modifier = Modifier .size(48.dp) .placeholder( - visible = event.imageUrl == null, + visible = displayModel.imageUrl == null, shape = CircleShape, ), ) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt index 0985fb13d..ac2e5fa2f 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/FeedContent.kt @@ -88,7 +88,7 @@ private fun SuccessContent( } itemsIndexed(viewState.upcomingEvents) { index, event -> - EventListItem(event = event) + EventSummaryListItem(displayModel = event) if (index != viewState.upcomingEvents.lastIndex) { Divider() diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/displaymodels/EventSummaryDisplayModel.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/displaymodels/EventSummaryDisplayModel.kt new file mode 100644 index 000000000..07423fd87 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/displaymodels/EventSummaryDisplayModel.kt @@ -0,0 +1,33 @@ +package com.adammcneilly.pocketleague.shared.displaymodels + +import com.adammcneilly.pocketleague.shared.datetime.DateTimeFormatter +import com.adammcneilly.pocketleague.shared.models.Event + +/** + * Provides summary information about an event in a user friendly manner. + */ +data class EventSummaryDisplayModel( + val startDate: String = "", + val name: String = "", + val imageUrl: String? = null, +) { + + companion object { + const val START_DATE_FORMAT = "MMM dd, yyyy" + } +} + +fun Event.toSummaryDisplayModel( + dateTimeFormatter: DateTimeFormatter = DateTimeFormatter(), +): EventSummaryDisplayModel { + return EventSummaryDisplayModel( + startDate = this.startDate?.let { startDate -> + dateTimeFormatter.formatLocalDateTime( + localDateTime = startDate, + formatPattern = EventSummaryDisplayModel.START_DATE_FORMAT, + ) + }.orEmpty(), + name = this.name, + imageUrl = this.imageUrl, + ) +} diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt index 538ea32cc..fabbc3d4e 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/FeedViewState.kt @@ -1,7 +1,7 @@ package com.adammcneilly.pocketleague.shared.screens.feed import com.adammcneilly.pocketleague.shared.data.DataState -import com.adammcneilly.pocketleague.shared.models.Event +import com.adammcneilly.pocketleague.shared.displaymodels.EventSummaryDisplayModel import com.adammcneilly.pocketleague.shared.models.Match import com.adammcneilly.pocketleague.shared.screens.ScreenState @@ -9,16 +9,18 @@ import com.adammcneilly.pocketleague.shared.screens.ScreenState * Defines the UI configuration for the [com.adammcneilly.pocketleague.shared.screens.Screens.Feed] screen. */ data class FeedViewState( - val upcomingEventsState: DataState> = DataState.Loading, + val upcomingEventsState: DataState> = DataState.Loading, val recentMatchesState: DataState> = DataState.Loading, ) : ScreenState { - val upcomingEvents: List + val upcomingEvents: List get() = when (upcomingEventsState) { is DataState.Loading -> { // Here, we return a list of empty Event objects which will be mapped // to a placeholder loading UI. - listOf(Event(), Event(), Event()) + (1..3).map { + EventSummaryDisplayModel() + } } is DataState.Success -> { upcomingEventsState.data diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt index 248b5a9b9..a03b8d970 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/screens/feed/LoadFeedEvent.kt @@ -1,5 +1,8 @@ package com.adammcneilly.pocketleague.shared.screens.feed +import com.adammcneilly.pocketleague.shared.data.DataState +import com.adammcneilly.pocketleague.shared.displaymodels.toSummaryDisplayModel +import com.adammcneilly.pocketleague.shared.models.Event import com.adammcneilly.pocketleague.shared.screens.Events import kotlinx.coroutines.flow.collect @@ -14,8 +17,22 @@ fun Events.loadFeed() = screenCoroutine { upcomingEventsFlow.collect { useCaseResult -> stateManager.updateScreen(FeedViewState::class) { + val mappedResult = when (useCaseResult) { + is DataState.Loading -> { + DataState.Loading + } + is DataState.Success -> { + DataState.Success( + data = useCaseResult.data.map(Event::toSummaryDisplayModel) + ) + } + is DataState.Error -> { + DataState.Error(useCaseResult.error) + } + } + it.copy( - upcomingEventsState = useCaseResult, + upcomingEventsState = mappedResult, ) } } From a111011af94b6376f947aff920ac57dc66d4918a Mon Sep 17 00:00:00 2001 From: amcneilly Date: Thu, 21 Apr 2022 21:07:51 -0400 Subject: [PATCH 39/40] detekt. --- config/detekt/detekt.yml | 2 +- .../shared/displaymodels/EventSummaryDisplayModel.kt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml index 309453dd9..a4679f1d9 100644 --- a/config/detekt/detekt.yml +++ b/config/detekt/detekt.yml @@ -618,7 +618,7 @@ style: MagicNumber: active: true excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] - ignoreNumbers: ['-1', '0', '1', '2', '10'] + ignoreNumbers: ['-1', '0', '1', '2', '3', '10'] ignoreHashCodeFunction: true ignorePropertyDeclaration: false ignoreLocalVariableDeclaration: false diff --git a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/displaymodels/EventSummaryDisplayModel.kt b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/displaymodels/EventSummaryDisplayModel.kt index 07423fd87..430c610f8 100644 --- a/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/displaymodels/EventSummaryDisplayModel.kt +++ b/shared/src/commonMain/kotlin/com/adammcneilly/pocketleague/shared/displaymodels/EventSummaryDisplayModel.kt @@ -17,6 +17,9 @@ data class EventSummaryDisplayModel( } } +/** + * Converts an [Event] entity to the user friendly [EventSummaryDisplayModel]. + */ fun Event.toSummaryDisplayModel( dateTimeFormatter: DateTimeFormatter = DateTimeFormatter(), ): EventSummaryDisplayModel { From f9db8f954a4312f2b9afce51b728dcfb364e53ce Mon Sep 17 00:00:00 2001 From: adammc331 Date: Sat, 23 Apr 2022 19:24:22 -0400 Subject: [PATCH 40/40] Formatting. --- .../com/adammcneilly/pocketleague/ui/EventSummaryListItem.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/com/adammcneilly/pocketleague/ui/EventSummaryListItem.kt b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventSummaryListItem.kt index 489439af0..29cad8a0f 100644 --- a/app/src/main/java/com/adammcneilly/pocketleague/ui/EventSummaryListItem.kt +++ b/app/src/main/java/com/adammcneilly/pocketleague/ui/EventSummaryListItem.kt @@ -9,13 +9,10 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import coil.request.ImageRequest -import com.adammcneilly.pocketleague.shared.datetime.DateTimeFormatter import com.adammcneilly.pocketleague.shared.displaymodels.EventSummaryDisplayModel -import com.adammcneilly.pocketleague.shared.models.Event import com.google.accompanist.placeholder.material.placeholder /**