From edbb66060d4d4313bed8ba486d567341799eecd7 Mon Sep 17 00:00:00 2001 From: Timo Dittmann Date: Sat, 7 Sep 2024 16:29:31 +0200 Subject: [PATCH] [6.6.0] Improvements for historic seasons --- android/app/build.gradle | 4 +- config.xml | 2 +- package.json | 2 +- requests.http | 8 ++++ .../soccer/matches/match.service.ts | 2 +- .../soccer/person/person.service.ts | 4 +- .../ranking/historicRankingJson.model.ts | 12 +++++ .../ranking/historicRankingMapper.spec.ts | 44 +++++++++++++++++++ .../soccer/ranking/historicRankingMapper.ts | 23 ++++++++++ .../soccer/ranking/ranking.service.ts | 21 +++++++++ .../pages/imprint/imprint.page.ts | 2 +- .../team-detail-ranking.component.html | 7 ++- .../ranking/team-detail-ranking.component.ts | 24 ++++++++-- .../pages/team-detail/team-detail.module.ts | 3 +- src/app/util/RankingUtil.ts | 7 +++ 15 files changed, 152 insertions(+), 13 deletions(-) create mode 100644 src/app/dataproviders/soccer/ranking/historicRankingJson.model.ts create mode 100644 src/app/dataproviders/soccer/ranking/historicRankingMapper.spec.ts create mode 100644 src/app/dataproviders/soccer/ranking/historicRankingMapper.ts create mode 100644 src/app/dataproviders/soccer/ranking/ranking.service.ts diff --git a/android/app/build.gradle b/android/app/build.gradle index c8d86a79..4bc93f34 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "de.timodittmann.scd" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 652000 - versionName "6.5.2" + versionCode 660000 + versionName "6.6.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/config.xml b/config.xml index 6466503b..aeab3a5d 100644 --- a/config.xml +++ b/config.xml @@ -1,5 +1,5 @@ - + SC Dahenfeld An awesome SC Dahenfeld app. Timo Dittmann diff --git a/package.json b/package.json index 4c0bf3c5..9ed3a58a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sc-dahenfeld", - "version": "6.5.2", + "version": "6.6.0", "author": "Timo Dittmann", "homepage": "http://timo-dittmann.de/", "scripts": { diff --git a/requests.http b/requests.http index 6192f6f8..86802b86 100644 --- a/requests.http +++ b/requests.http @@ -4,4 +4,12 @@ Authorization: Basic {{authUsername}} {{authPassword}} ### GET Persons by project ID GET https://sc-dahenfeld.de/components/com_tdwapp/v9/persons?teamId=200 +Authorization: Basic {{authUsername}} {{authPassword}} + +### GET Team Informations by project ID +GET https://sc-dahenfeld.de/components/com_tdwapp/v9/teamInformation?id=191 +Authorization: Basic {{authUsername}} {{authPassword}} + +### GET Historic Ranking by project ID +GET https://sc-dahenfeld.de/components/com_tdwapp/v9/historicRanking?projectId=191 Authorization: Basic {{authUsername}} {{authPassword}} \ No newline at end of file diff --git a/src/app/dataproviders/soccer/matches/match.service.ts b/src/app/dataproviders/soccer/matches/match.service.ts index 64c16d3b..9b349fcc 100644 --- a/src/app/dataproviders/soccer/matches/match.service.ts +++ b/src/app/dataproviders/soccer/matches/match.service.ts @@ -25,6 +25,6 @@ export class MatchService { return this.httpService .get(environment.backendUrl + 'matches?teamId=' + teamId + '&teamOnly=' + teamOnly) .pipe(map((pMatch) => pMatch.map(this.matchMapper.mapFrom))) - .pipe(tap((pMatch) => [...pMatch].sort((a, b) => a.compareTo(b)))); + .pipe(map((pMatch) => [...pMatch].sort((a, b) => a.compareTo(b)))); } } diff --git a/src/app/dataproviders/soccer/person/person.service.ts b/src/app/dataproviders/soccer/person/person.service.ts index 1427790c..b409f3a2 100644 --- a/src/app/dataproviders/soccer/person/person.service.ts +++ b/src/app/dataproviders/soccer/person/person.service.ts @@ -17,14 +17,14 @@ export class PersonService { return this.httpService .get(environment.backendUrl + 'persons') .pipe(map((players) => players.map((value) => this.playerMapper.mapFrom(value)))) - .pipe(tap((players) => players.sort((a, b) => a.compareTo(b)))); + .pipe(map((players) => [...players].sort((a, b) => a.compareTo(b)))); } loadPersonsByProjectId(projectId: number): Observable { return this.httpService .get(environment.backendUrl + 'persons?teamId=' + projectId) .pipe(map((players) => players.map((value) => this.playerMapper.mapFrom(value)))) - .pipe(tap((players) => players.sort((a, b) => a.compareTo(b)))); + .pipe(map((players) => [...players].sort((a, b) => a.compareTo(b)))); } loadPerson(personId: number, projectId: number): Observable { diff --git a/src/app/dataproviders/soccer/ranking/historicRankingJson.model.ts b/src/app/dataproviders/soccer/ranking/historicRankingJson.model.ts new file mode 100644 index 00000000..4a04e336 --- /dev/null +++ b/src/app/dataproviders/soccer/ranking/historicRankingJson.model.ts @@ -0,0 +1,12 @@ +export interface HistoricRankingJson { + id: string; + name: string; + logo: string; + matches: string; + won: string; + draw: string; + lost: string; + goalsFor: string; + goalsAgainst: string; + points: string; +} diff --git a/src/app/dataproviders/soccer/ranking/historicRankingMapper.spec.ts b/src/app/dataproviders/soccer/ranking/historicRankingMapper.spec.ts new file mode 100644 index 00000000..5d4b23c9 --- /dev/null +++ b/src/app/dataproviders/soccer/ranking/historicRankingMapper.spec.ts @@ -0,0 +1,44 @@ +import { HistoricRankingMapper } from './historicRankingMapper'; +import { HistoricRankingJson } from './historicRankingJson.model'; +import { RankingTeam } from '../../../core/domain/rankingTeam.model'; + +describe('Mapper', () => { + let mapper: HistoricRankingMapper; + + beforeEach(() => { + mapper = new HistoricRankingMapper(); + }); + + it('should handle null values for mapFrom', () => { + expect(mapper.mapFrom(null)).toBe(null); + }); + + it('should map from json to core model', () => { + const actual: HistoricRankingJson = { + id: '1', + name: 'SC Dahenfeld', + logo: '/images/scd.png', + matches: '30', + won: '29', + draw: '1', + lost: '0', + goalsFor: '100', + goalsAgainst: '12', + points: '90', + }; + + const expected: RankingTeam = new RankingTeam(); + expected.id = 1; + expected.name = 'SC Dahenfeld'; + expected.image = '/images/scd.png'; + expected.matches = 30; + expected.wins = 29; + expected.draws = 1; + expected.losses = 0; + expected.goalsFor = 100; + expected.goalsAgainst = 12; + expected.points = 90; + + expect(mapper.mapFrom(actual)).toEqual(expected); + }); +}); diff --git a/src/app/dataproviders/soccer/ranking/historicRankingMapper.ts b/src/app/dataproviders/soccer/ranking/historicRankingMapper.ts new file mode 100644 index 00000000..7f3878e6 --- /dev/null +++ b/src/app/dataproviders/soccer/ranking/historicRankingMapper.ts @@ -0,0 +1,23 @@ +import { HistoricRankingJson } from './historicRankingJson.model'; +import { RankingTeam } from '../../../core/domain/rankingTeam.model'; + +export class HistoricRankingMapper { + mapFrom(param: HistoricRankingJson): RankingTeam { + if (!param) { + return null; + } + + const rankingTeam = new RankingTeam(); + rankingTeam.id = parseInt(param.id, 10); + rankingTeam.name = param.name; + rankingTeam.image = param.logo; + rankingTeam.matches = parseInt(param.matches, 10); + rankingTeam.wins = parseInt(param.won, 10); + rankingTeam.draws = parseInt(param.draw, 10); + rankingTeam.losses = parseInt(param.lost, 10); + rankingTeam.goalsFor = parseInt(param.goalsFor, 10); + rankingTeam.goalsAgainst = parseInt(param.goalsAgainst, 10); + rankingTeam.points = parseInt(param.points, 10); + return rankingTeam; + } +} diff --git a/src/app/dataproviders/soccer/ranking/ranking.service.ts b/src/app/dataproviders/soccer/ranking/ranking.service.ts new file mode 100644 index 00000000..33bfdf26 --- /dev/null +++ b/src/app/dataproviders/soccer/ranking/ranking.service.ts @@ -0,0 +1,21 @@ +import { Observable } from 'rxjs'; +import { environment } from '../../../../environments/environment'; +import { map, tap } from 'rxjs/operators'; +import { Injectable } from '@angular/core'; +import { HttpService } from '../../http.service'; +import { HistoricRankingMapper } from './historicRankingMapper'; +import { RankingTeam } from '../../../core/domain/rankingTeam.model'; +import { HistoricRankingJson } from './historicRankingJson.model'; + +@Injectable() +export class RankingService { + private historicRankingMapper = new HistoricRankingMapper(); + + constructor(private httpService: HttpService) {} + + public loadHistoricRanking(projectId: number): Observable { + return this.httpService + .get(environment.backendUrl + 'historicRanking?projectId=' + projectId) + .pipe(map((ranking) => ranking.map(this.historicRankingMapper.mapFrom))); + } +} diff --git a/src/app/presentation/pages/imprint/imprint.page.ts b/src/app/presentation/pages/imprint/imprint.page.ts index 79b5d4bd..3eefb186 100644 --- a/src/app/presentation/pages/imprint/imprint.page.ts +++ b/src/app/presentation/pages/imprint/imprint.page.ts @@ -13,7 +13,7 @@ import { App } from '@capacitor/app'; }) export class ImprintPage implements OnInit { heading: string; - version = '6.5.2'; + version = '6.6.0'; developer = 'Timo Dittmann'; darkMode = false; diff --git a/src/app/presentation/pages/team-detail/ranking/team-detail-ranking.component.html b/src/app/presentation/pages/team-detail/ranking/team-detail-ranking.component.html index 0e8d04af..be5447bc 100644 --- a/src/app/presentation/pages/team-detail/ranking/team-detail-ranking.component.html +++ b/src/app/presentation/pages/team-detail/ranking/team-detail-ranking.component.html @@ -1,7 +1,12 @@
- + {{ rankingType.label }} diff --git a/src/app/presentation/pages/team-detail/ranking/team-detail-ranking.component.ts b/src/app/presentation/pages/team-detail/ranking/team-detail-ranking.component.ts index 27106b72..64bcefd4 100644 --- a/src/app/presentation/pages/team-detail/ranking/team-detail-ranking.component.ts +++ b/src/app/presentation/pages/team-detail/ranking/team-detail-ranking.component.ts @@ -3,6 +3,7 @@ import { MatchService } from '../../../../dataproviders/soccer/matches/match.ser import { Match } from '../../../../core/domain/match.model'; import { RankingTeam } from '../../../../core/domain/rankingTeam.model'; import { RankingUtil } from '../../../../util/RankingUtil'; +import { RankingService } from '../../../../dataproviders/soccer/ranking/ranking.service'; @Component({ selector: 'app-team-detail-ranking', @@ -20,20 +21,37 @@ export class TeamDetailRankingComponent implements OnInit { matches: Match[] = []; ranking: RankingTeam[] = []; + isHistoricRanking = false; isLoading = true; isError = false; - constructor(private fixtureService: MatchService) {} + constructor( + private matchService: MatchService, + private rankingService: RankingService, + ) {} ngOnInit(): void { if (this.projectId > 0) { - this.fixtureService.loadAllMatchesByTeamId(this.projectId).subscribe({ + this.matchService.loadAllMatchesByTeamId(this.projectId).subscribe({ next: (matches) => { this.matches = matches; - this.ranking = RankingUtil.calculateRanking(matches, null); + // For historic rankings we don't have matches and need to load the ranking separately. + if (matches.length === 0) { + this.isHistoricRanking = true; + this.rankingService.loadHistoricRanking(this.projectId).subscribe({ + next: (ranking) => { + this.ranking = RankingUtil.calculateHistoricRanking(ranking); + }, + error: (error) => { + this.isError = true; + console.error(error); + }, + }); + } + this.isLoading = false; }, error: (error) => { diff --git a/src/app/presentation/pages/team-detail/team-detail.module.ts b/src/app/presentation/pages/team-detail/team-detail.module.ts index 11546a9e..16ef0817 100644 --- a/src/app/presentation/pages/team-detail/team-detail.module.ts +++ b/src/app/presentation/pages/team-detail/team-detail.module.ts @@ -23,9 +23,10 @@ import { FormsModule } from '@angular/forms'; import { TeamDetailStatisticsModalComponent } from './statistics/statistics-modal/team-detail-statistics-modal.component'; import { PersonFilter } from './statistics/statistics-modal/person.filter'; import { DynamicContentModule } from '../../shared/dynamic-content/dynamic-content.module'; +import { RankingService } from '../../../dataproviders/soccer/ranking/ranking.service'; @NgModule({ - providers: [TeamInformationService, ArticleService, MatchService, PersonService], + providers: [TeamInformationService, ArticleService, MatchService, PersonService, RankingService], imports: [ CommonModule, FormsModule, diff --git a/src/app/util/RankingUtil.ts b/src/app/util/RankingUtil.ts index 4ac2a464..cf9216dc 100644 --- a/src/app/util/RankingUtil.ts +++ b/src/app/util/RankingUtil.ts @@ -21,6 +21,13 @@ export class RankingUtil { return ranking; } + static calculateHistoricRanking(ranking: RankingTeam[]) { + const finalRanking = [...ranking]; + finalRanking.sort((a, b) => a.compareTo(b)); + finalRanking.forEach((value, index) => (value.place = index + 1)); + return finalRanking; + } + private static handleMatch( ranking: RankingTeam[], teamId: number,