From 8a1c19e0115a0a078748196811a4a4689023c63c Mon Sep 17 00:00:00 2001 From: Julien Gautier Date: Thu, 27 Nov 2025 10:35:38 +0100 Subject: [PATCH] Ajout de composants Hero Wars --- src/app/app.component.html | 2 +- src/app/app.component.scss | 8 + src/app/app.component.ts | 9 +- .../herowars-guildraid.component.html | 114 +++++ .../herowars-guildraid.component.scss | 0 .../herowars-guildraid.component.spec.ts | 23 + .../herowars-guildraid.component.ts | 94 ++++ .../herowars-guildwar.component.html | 209 +++++++++ .../herowars-guildwar.component.scss | 8 + .../herowars-guildwar.component.spec.ts | 23 + .../herowars-guildwar.component.ts | 207 +++++++++ .../herowars/herowars.component.html | 66 +++ .../herowars/herowars.component.scss | 37 ++ .../herowars/herowars.component.spec.ts | 23 + .../components/herowars/herowars.component.ts | 84 ++++ src/app/components/index.ts | 2 + .../fortification-card-content.component.html | 37 ++ .../fortification-card-content.component.scss | 13 + .../fortification-card-content.component.ts | 83 ++++ .../guild-card/guild-card.component.html | 72 +++ .../guild-card/guild-card.component.scss | 0 .../guild-card/guild-card.component.spec.ts | 23 + .../guild-card/guild-card.component.ts | 36 ++ .../guildraids-log.component.html | 436 ++++++++++++++++++ .../guildraids-log.component.scss | 1 + .../guildraids-log.component.spec.ts | 23 + .../guildraids-log.component.ts | 214 +++++++++ .../guildwar-attack.component.html | 149 ++++++ .../guildwar-attack.component.scss | 0 .../guildwar-attack.component.spec.ts | 23 + .../guildwar-attack.component.ts | 285 ++++++++++++ .../guildwar-champions.component.html | 57 +++ .../guildwar-champions.component.scss | 1 + .../guildwar-champions.component.spec.ts | 23 + .../guildwar-champions.component.ts | 58 +++ .../guildwar-defence.component.html | 36 ++ .../guildwar-defence.component.scss | 0 .../guildwar-defence.component.spec.ts | 23 + .../guildwar-defence.component.ts | 191 ++++++++ .../guildwar-teams.component.html | 101 ++++ .../guildwar-teams.component.scss | 1 + .../guildwar-teams.component.spec.ts | 23 + .../guildwar-teams.component.ts | 78 ++++ .../shared/herowars-components/index.ts | 8 + .../members-statistics.component.html | 270 +++++++++++ .../members-statistics.component.scss | 5 + .../members-statistics.component.spec.ts | 23 + .../members-statistics.component.ts | 159 +++++++ src/app/components/shared/index.ts | 1 - src/app/components/shared/menu-items.ts | 4 +- .../models/herowars/clan-list-config.model.ts | 16 + .../core/models/herowars/clan-list.model.ts | 6 + src/app/core/models/herowars/clan.model.ts | 84 ++++ .../models/herowars/fortification.model.ts | 10 + .../core/models/herowars/guildwar.model.ts | 80 ++++ src/app/core/models/herowars/hw.model.ts | 264 +++++++++++ src/app/core/models/herowars/index.ts | 9 + src/app/core/models/herowars/member.model.ts | 57 +++ src/app/core/models/herowars/raid.model.ts | 38 ++ src/app/core/models/herowars/stat.model.ts | 42 ++ src/app/core/models/index.ts | 2 +- src/app/core/services/hwclan.service.ts | 60 +++ src/app/core/services/hwmember.service.ts | 60 +++ src/app/routes/auth.routes.ts | 13 +- src/styles/_palettes.scss | 34 ++ src/styles/app.scss | 3 + 66 files changed, 4137 insertions(+), 7 deletions(-) create mode 100644 src/app/components/herowars-guildraid/herowars-guildraid.component.html create mode 100644 src/app/components/herowars-guildraid/herowars-guildraid.component.scss create mode 100644 src/app/components/herowars-guildraid/herowars-guildraid.component.spec.ts create mode 100644 src/app/components/herowars-guildraid/herowars-guildraid.component.ts create mode 100644 src/app/components/herowars-guildwar/herowars-guildwar.component.html create mode 100644 src/app/components/herowars-guildwar/herowars-guildwar.component.scss create mode 100644 src/app/components/herowars-guildwar/herowars-guildwar.component.spec.ts create mode 100644 src/app/components/herowars-guildwar/herowars-guildwar.component.ts create mode 100644 src/app/components/herowars/herowars.component.html create mode 100644 src/app/components/herowars/herowars.component.scss create mode 100644 src/app/components/herowars/herowars.component.spec.ts create mode 100644 src/app/components/herowars/herowars.component.ts create mode 100644 src/app/components/shared/herowars-components/fortification-card-content/fortification-card-content.component.html create mode 100644 src/app/components/shared/herowars-components/fortification-card-content/fortification-card-content.component.scss create mode 100644 src/app/components/shared/herowars-components/fortification-card-content/fortification-card-content.component.ts create mode 100644 src/app/components/shared/herowars-components/guild-card/guild-card.component.html create mode 100644 src/app/components/shared/herowars-components/guild-card/guild-card.component.scss create mode 100644 src/app/components/shared/herowars-components/guild-card/guild-card.component.spec.ts create mode 100644 src/app/components/shared/herowars-components/guild-card/guild-card.component.ts create mode 100644 src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.html create mode 100644 src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.scss create mode 100644 src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.spec.ts create mode 100644 src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.ts create mode 100644 src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.html create mode 100644 src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.scss create mode 100644 src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.spec.ts create mode 100644 src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.ts create mode 100644 src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.html create mode 100644 src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.scss create mode 100644 src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.spec.ts create mode 100644 src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.ts create mode 100644 src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.html create mode 100644 src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.scss create mode 100644 src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.spec.ts create mode 100644 src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.ts create mode 100644 src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.html create mode 100644 src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.scss create mode 100644 src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.spec.ts create mode 100644 src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.ts create mode 100644 src/app/components/shared/herowars-components/index.ts create mode 100644 src/app/components/shared/herowars-components/members-statistics/members-statistics.component.html create mode 100644 src/app/components/shared/herowars-components/members-statistics/members-statistics.component.scss create mode 100644 src/app/components/shared/herowars-components/members-statistics/members-statistics.component.spec.ts create mode 100644 src/app/components/shared/herowars-components/members-statistics/members-statistics.component.ts create mode 100644 src/app/core/models/herowars/clan-list-config.model.ts create mode 100644 src/app/core/models/herowars/clan-list.model.ts create mode 100644 src/app/core/models/herowars/clan.model.ts create mode 100644 src/app/core/models/herowars/fortification.model.ts create mode 100644 src/app/core/models/herowars/guildwar.model.ts create mode 100644 src/app/core/models/herowars/hw.model.ts create mode 100644 src/app/core/models/herowars/index.ts create mode 100644 src/app/core/models/herowars/member.model.ts create mode 100644 src/app/core/models/herowars/raid.model.ts create mode 100644 src/app/core/models/herowars/stat.model.ts create mode 100644 src/app/core/services/hwclan.service.ts create mode 100644 src/app/core/services/hwmember.service.ts diff --git a/src/app/app.component.html b/src/app/app.component.html index 26bd9bf..e310aa3 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/app/app.component.scss b/src/app/app.component.scss index e69de29..9cae760 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -0,0 +1,8 @@ +.grayscale { + filter: grayscale(1); + transition: all 2s ease; +} +.colored { + filter: grayscale(0); + transition: all 5s ease; +} \ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 93135ac..6593469 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, AfterContentInit } from '@angular/core'; import { MAT_DATE_LOCALE, MAT_DATE_FORMATS, provideNativeDateAdapter } from '@angular/material/core'; import { Title } from '@angular/platform-browser'; @@ -31,8 +31,9 @@ export const MY_FORMATS = { templateUrl: './app.component.html', styleUrl: './app.component.scss' }) -export class AppComponent implements OnInit { +export class AppComponent implements OnInit, AfterContentInit { public title = 'Ad Astra'; + public appClass = 'grayscale'; constructor(private userService: UserService, private titleService: Title) { } @@ -40,4 +41,8 @@ export class AppComponent implements OnInit { this.userService.populate(); this.titleService.setTitle(this.title); } + + ngAfterContentInit() { + this.appClass = 'colored'; + } } \ No newline at end of file diff --git a/src/app/components/herowars-guildraid/herowars-guildraid.component.html b/src/app/components/herowars-guildraid/herowars-guildraid.component.html new file mode 100644 index 0000000..8bf741f --- /dev/null +++ b/src/app/components/herowars-guildraid/herowars-guildraid.component.html @@ -0,0 +1,114 @@ +
+
+
+

{{title}}

+
+ +
+ {{ now | date: 'dd/MM/yyyy' }} +
+
+ + +
+

{{description}}

+
+ + + +
+ + {{ title }} + +
+ +
+ {{ subtitle }} +
+
+ + + + Stage 1 +
+
+

Stage 1

+
+ +
+

Power limit: 320k

+
+
+ +
+ + +
+
+ + Stage 2 +
+
+

Stage 2

+
+ +
+

Power limit: 500k

+
+
+ +
+ + +
+
+ + Stage 3 +
+
+

Stage 3

+
+ +
+

No power limit

+
+
+ +
+ + +
+
+ + Statistics +
+
+

Statistics

+
+ +
+

variation ≥ {{ minVarPct }}%

+ + Variation + + percent + excess power in % + +
+
+ +
+ + +
+
+ + timeline + + + manage_search + +
+
+
+
diff --git a/src/app/components/herowars-guildraid/herowars-guildraid.component.scss b/src/app/components/herowars-guildraid/herowars-guildraid.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/components/herowars-guildraid/herowars-guildraid.component.spec.ts b/src/app/components/herowars-guildraid/herowars-guildraid.component.spec.ts new file mode 100644 index 0000000..9bdf140 --- /dev/null +++ b/src/app/components/herowars-guildraid/herowars-guildraid.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HerowarsGuildraidComponent } from './herowars-guildraid.component'; + +describe('HerowarsGuildraidComponent', () => { + let component: HerowarsGuildraidComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [HerowarsGuildraidComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(HerowarsGuildraidComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/herowars-guildraid/herowars-guildraid.component.ts b/src/app/components/herowars-guildraid/herowars-guildraid.component.ts new file mode 100644 index 0000000..6534dca --- /dev/null +++ b/src/app/components/herowars-guildraid/herowars-guildraid.component.ts @@ -0,0 +1,94 @@ +import { DatePipe } from '@angular/common'; +import { Title } from '@angular/platform-browser'; +import { trigger, state, style, animate, transition } from '@angular/animations'; +import { Component, DestroyRef, Injectable, inject, OnInit } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { STEPPER_GLOBAL_OPTIONS } from '@angular/cdk/stepper'; +import { MatCardModule } from '@angular/material/card'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatStepperIntl, MatStepperModule } from '@angular/material/stepper'; + +import { ListErrorsComponent } from 'src/app/components/shared'; +import { Errors } from 'src/app/core/models'; +import { HWGuildRaid, HWGuildRaidAttacker, HWGuildRaidAttackers, HWGuildRaidStage, HWMember } from 'src/app/core/models/herowars'; + +import guildRaids from 'src/files-data/hw-guild-raids.json'; // page Asgard -> Guild Raid -> Log + +@Injectable() +export class GuildRaidStepperIntl extends MatStepperIntl { + // the default optional label text, if unspecified is "Optional" + override optionalLabel = 'Optional Label'; +} +@Component({ + selector: 'app-herowars-guildraid', + standalone: true, + providers: [ + { + provide: STEPPER_GLOBAL_OPTIONS, + useValue: { displayDefaultIndicatorType: false }, + }, + ], + imports: [ + DatePipe, FormsModule, ListErrorsComponent, + MatButtonModule, MatCardModule, MatDividerModule, MatFormFieldModule, + MatIconModule, MatInputModule, MatStepperModule + ], + templateUrl: './herowars-guildraid.component.html', + styleUrl: './herowars-guildraid.component.scss', + animations: [ + trigger('flyInOut', [ + state('in', style({ transform: 'translateY(0)' })), + transition('void => *', [ + style({ transform: 'translateY(-100%)' }), + animate(200) + ]), + transition('* => void', [ + style({ transform: 'translateY(100%)' }), + animate(200) + ]) + ]) + ] +}) +export class HerowarsGuildraidComponent implements OnInit { + public title = 'Guild Raids'; + public subtitle = 'Log'; + public description = 'Tools in working progress.'; + public errors: Errors = { errors: {} }; + public destroyRef = inject(DestroyRef); + public minVarPct = 3; + public minValue = 0; + public now = new Date(); + private _guildMembers: HWMember[] = []; + private _matStepperIntl = inject(MatStepperIntl); + private _guildRaids: HWGuildRaid[] = []; + private _raidStages: HWGuildRaidStage[] = [ + { num: 1, name: 'Stage 1', maxPower: 320000, duration: 8, startTime: 0, endTime: 0 }, + { num: 2, name: 'Stage 2', maxPower: 500000, duration: 8, startTime: 0, endTime: 0 }, + { num: 3, name: 'Stage 3', maxPower: 0, duration: 0, startTime: 0, endTime: 0 } + ]; + + constructor( + private _titleService: Title + ) { } + + ngOnInit() { + this._titleService.setTitle(this.title); + this._guildMembers.map((data) => { + data.raids = []; + data.raidsInfo = { + variationAvg: 0, + variationSum: 0 + }; + return data; + }); + } + + getMembers(): HWMember[] { + return this._guildMembers; + } + +} diff --git a/src/app/components/herowars-guildwar/herowars-guildwar.component.html b/src/app/components/herowars-guildwar/herowars-guildwar.component.html new file mode 100644 index 0000000..e188710 --- /dev/null +++ b/src/app/components/herowars-guildwar/herowars-guildwar.component.html @@ -0,0 +1,209 @@ +
+
+
+

{{title}}

+
+ +
+ {{ now | date: 'dd/MM/yyyy' }} +
+
+ + +
+

{{description}}

+
+ + + + +
+
+ +
+
+

+ @if (clanLoaded) { + {{ getClan().title }} – Server {{ getClan().serverId }} + } +

+
+ +
+ Members: {{ getClan().membersCount }}/30 +
+
+
+
+
+ @if (clanLoaded) { + + } + @else { + + } + @if (membersLoaded) { + + } + @else { + + } +
+
+
+
+
country
+
{{ getClan().country }}
+
serverId
+
{{ getClan().serverId }}
+
description
+
{{ getClan().description }}
+
level
+
{{ getClan().level }}
+
minLevel
+
{{ getClan().minLevel }}
+
+
+
+
+
topActivity
+
{{ getClan().topActivity | number : '1.0' }}
+
topDungeon
+
{{ getClan().topDungeon | number : '1.0' }}
+
disbanding
+
{{ getClan().disbanding }}
+
frameId
+
{{ getClan().frameId }}
+
ownerId
+
{{ getClan().ownerId }}
+
+
+
+
+ + + + + + + + + + + + + + + + @for (member of getMembers(); track member; let index = $index) { + + + + + + + + + + + + } + +
+
+ # +
+
+
+ ID +
+
+
+ Name +
+
+
+ Clan +
+
+
+ Server +
+
+
+ Last Login +
+
+
+ Level +
+
+
+ Heroes +
+
+
+ Titans +
+
+ {{ (index+1) }} + + {{ member.id }} + + {{ member.name }} + + {{ member.clanTitle }} + + {{ member.serverId }} + + {{ member.lastLoginTime + '000' | date: 'dd/MM HH:mm' }} + + {{ member.level }} + + {{ member.heroes.power | number : '1.0' }} + + {{ member.titans.power | number : '1.0' }} +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+ + +
+ + {{ title }} + +
+ +
+ {{ subtitle }} +
+
+ + +
+
+
+
+ +
+
+
+
+
+
+
diff --git a/src/app/components/herowars-guildwar/herowars-guildwar.component.scss b/src/app/components/herowars-guildwar/herowars-guildwar.component.scss new file mode 100644 index 0000000..6323951 --- /dev/null +++ b/src/app/components/herowars-guildwar/herowars-guildwar.component.scss @@ -0,0 +1,8 @@ +.btn-group-vertical { + flex-direction: column; + align-items: flex-end; + justify-content: center; + button { + margin: 2px 0; + } +} \ No newline at end of file diff --git a/src/app/components/herowars-guildwar/herowars-guildwar.component.spec.ts b/src/app/components/herowars-guildwar/herowars-guildwar.component.spec.ts new file mode 100644 index 0000000..d1a3d24 --- /dev/null +++ b/src/app/components/herowars-guildwar/herowars-guildwar.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HerowarsGuildwarComponent } from './herowars-guildwar.component'; + +describe('HerowarsGuildwarComponent', () => { + let component: HerowarsGuildwarComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [HerowarsGuildwarComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(HerowarsGuildwarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/herowars-guildwar/herowars-guildwar.component.ts b/src/app/components/herowars-guildwar/herowars-guildwar.component.ts new file mode 100644 index 0000000..78ae9ef --- /dev/null +++ b/src/app/components/herowars-guildwar/herowars-guildwar.component.ts @@ -0,0 +1,207 @@ +import { DatePipe, DecimalPipe } from '@angular/common'; +import { Title } from '@angular/platform-browser'; +import { trigger, state, style, animate, transition } from '@angular/animations'; +import { Component, DestroyRef, inject, OnInit } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { MatCardModule } from '@angular/material/card'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatTabsModule } from '@angular/material/tabs'; + +import { ListErrorsComponent, GuildwarAttackComponent, GuildwarDefenceComponent } from 'src/app/components/shared'; +import { Errors, HWActivityStat, HWGuildClan, HWMember, HWMemberStat, HWWeekStat } from 'src/app/core/models'; +import { UtilitiesService } from 'src/app/core/services'; + +import guildData from 'src/files-data/hw-guild-data.json'; // page Membres +import guildStatistics from 'src/files-data/hw-guild-statistics.json'; // page Overview -> Statistics + +@Component({ + selector: 'app-herowars-guildwar', + standalone: true, + imports: [ + DatePipe, DecimalPipe, FormsModule, ListErrorsComponent, + MatButtonModule, MatCardModule, MatDividerModule, MatFormFieldModule, + MatIconModule, MatInputModule, MatTabsModule, + GuildwarAttackComponent, GuildwarDefenceComponent + ], + templateUrl: './herowars-guildwar.component.html', + styleUrl: './herowars-guildwar.component.scss', + animations: [ + trigger('flyInOut', [ + state('in', style({ transform: 'translateY(0)' })), + transition('void => *', [ + style({ transform: 'translateY(-100%)' }), + animate(200) + ]), + transition('* => void', [ + style({ transform: 'translateY(100%)' }), + animate(200) + ]) + ]) + ] +}) +export class HerowarsGuildwarComponent implements OnInit { + public title = 'Guild War'; + public subtitle = 'Log'; + public description = 'Tools in working progress.'; + public errors: Errors = { errors: {} }; + public destroyRef = inject(DestroyRef); + public now = new Date(); + public daysToWarn = 1; + public clanLoaded = false; + public membersLoaded = false; + private _guildClan: HWGuildClan = {} as HWGuildClan; + private _guildMembers: HWMember[] = []; + private _guildInfo: HWActivityStat = {} as HWActivityStat; + + constructor( + private _titleService: Title, + private _utilitiesService: UtilitiesService + ) { } + + ngOnInit() { + this._titleService.setTitle(this.title); + } + + private _resetActivity(): HWActivityStat { + const activity: HWActivityStat = { activity: 0, prestige: 0, titanite: 0, war: 0, adventure: 0, gifts: 0, score: 0, scoreGifts: 0, warGifts: 0, rewards: 0 }; + return activity; + } + + private _importMembers() { + try { + const oneDayInSec = (24 * 60 * 60); + const daysToKick = parseInt(guildData.clan.daysToKick); + this.daysToWarn = (parseInt(guildData.clan.daysToKick) / 2); + for (const data of Object.entries(guildData.clan.members)) { + const member: HWMember = {} as HWMember; + Object.assign(member, data[1]); + if (guildData.clan.warriors.indexOf(parseInt(member.id)) !== -1) { + member.champion = true; + } else { + member.champion = false; + } + member.heroes = { power: 0, teams: []}; + member.titans = { power: 0, teams: []}; + this._guildMembers.push(member); + } + this._guildMembers.map((data) => { + const last = new Date((parseInt(data.lastLoginTime) * 1000)); + const exp = new Date(last.getTime() + ((daysToKick * oneDayInSec) * 1000)); + const diff = Math.floor(((exp.getTime() - this.now.getTime()) / 1000)); + const daysLeft = Math.floor((diff / oneDayInSec)); + let timeLeft = diff; + if (daysLeft >= 1) { + timeLeft = (diff - (daysLeft * oneDayInSec)); + } + data.inactivity = { + daysLeft: daysLeft, + timeLeft: timeLeft, + dropDelay: `${daysLeft}d, ${this._utilitiesService.secondsToDuration(timeLeft)}`, + dropDate: Math.floor((exp.getTime() / 1000)) + }; + data.raids = []; + data.raidsInfo = { + variationAvg: 0, + variationSum: 0 + }; + data.stat = {} as HWMemberStat; + let index = guildData.membersStat.findIndex(stat => stat.userId === data.id); + if (index !== -1) { + delete (guildData.membersStat[index] as {userId?: string}).userId; + Object.assign(data.stat, guildData.membersStat[index]); + //data.stat = guildData.membersStat[index]; + } + index = guildStatistics.stat.findIndex(stat => stat.id === data.id); + if (index !== -1) { + delete (guildStatistics.stat[index] as {id?: string}).id; + const stat: HWWeekStat = {} as HWWeekStat; + Object.assign(stat, guildStatistics.stat[index]); + data.weekStat = stat; + data.adventureSum = guildStatistics.stat[index].adventureStat.reduce((accumulator, currentValue) => accumulator + currentValue, 0); + data.clanGiftsSum = guildStatistics.stat[index].clanGifts.reduce((accumulator, currentValue) => accumulator + currentValue, 0); + data.clanWarSum = guildStatistics.stat[index].clanWarStat.reduce((accumulator, currentValue) => accumulator + currentValue, 0); + this._guildClan.sumTotal.adventure += data.adventureSum; + this._guildClan.sumTotal.gifts += data.clanGiftsSum; + this._guildClan.sumTotal.war += data.clanWarSum; + } + + data.score = (data.stat.dungeonActivitySum + data.stat.activitySum + data.stat.prestigeSum); + data.warGifts = (((this._guildClan.giftsCount / 2) * ((data.clanWarSum * 10) / 100)) / 20); + + this._guildClan.todayTotal.activity += data.stat.todayActivity; + this._guildClan.todayTotal.prestige += data.stat.todayPrestige; + this._guildClan.todayTotal.titanite += data.stat.todayDungeonActivity; + this._guildClan.todayTotal.score += (data.stat.todayDungeonActivity + data.stat.todayActivity + data.stat.todayPrestige); + this._guildClan.sumTotal.activity += data.stat.activitySum; + this._guildClan.sumTotal.prestige += data.stat.prestigeSum; + this._guildClan.sumTotal.titanite += data.stat.dungeonActivitySum; + this._guildClan.sumTotal.score += data.score; + this._guildClan.sumTotal.warGifts += data.warGifts; + + data.scoreGifts = 0; + data.rewards = 0; + return data; + }); + this._guildClan.sumTotal.scoreGifts = (this._guildClan.giftsCount - Math.floor(this._guildClan.sumTotal.warGifts)); + this._guildClan.todayAverages.activity = (this._guildClan.todayTotal.activity / this._guildMembers.length); + this._guildClan.todayAverages.prestige = (this._guildClan.todayTotal.prestige / this._guildMembers.length); + this._guildClan.todayAverages.titanite = (this._guildClan.todayTotal.titanite / this._guildMembers.length); + this._guildClan.todayAverages.score = (this._guildClan.todayTotal.score / this._guildMembers.length); + this._guildClan.sumAverages.activity = (this._guildClan.sumTotal.activity / this._guildMembers.length); + this._guildClan.sumAverages.prestige = (this._guildClan.sumTotal.prestige / this._guildMembers.length); + this._guildClan.sumAverages.titanite = (this._guildClan.sumTotal.titanite / this._guildMembers.length); + this._guildClan.sumAverages.war = (this._guildClan.sumTotal.war / 20); + this._guildClan.sumAverages.adventure = (this._guildClan.sumTotal.adventure / this._guildMembers.length); + this._guildClan.sumAverages.gifts = (this._guildClan.sumTotal.gifts / this._guildMembers.length); + this._guildClan.sumAverages.score = (this._guildClan.sumTotal.score / this._guildMembers.length); + + this._guildMembers.map((data) => { + data.scoreGifts = ((data.score / this._guildClan.sumTotal.score) * this._guildClan.sumTotal.scoreGifts); + data.rewards = Math.floor((data.scoreGifts + data.warGifts)); + this._guildClan.sumTotal.rewards += data.rewards; + return data; + }); + this._guildClan.sumAverages.rewards = (this._guildClan.sumTotal.rewards / this._guildMembers.length); + + console.log(this._guildClan); + console.log(this._guildMembers); + } catch (error) { + console.error(error); + } + } + + getClan(): HWGuildClan { + return this._guildClan; + } + + loadClan(): void { + Object.assign(this._guildClan, guildData.clan); + this._guildClan.sumAverages = this._resetActivity(); + this._guildClan.sumTotal = this._resetActivity(); + this._guildClan.todayAverages = this._resetActivity(); + this._guildClan.todayTotal = this._resetActivity(); + this.clanLoaded = true; + } + + loadMembers(): void { + this._importMembers(); + this.membersLoaded = true; + } + + getMembers(): HWMember[] { + return this._guildMembers; + } + + syncClan(): void { + console.log(this._guildClan); + } + + syncMembers(): void { + console.log(this._guildMembers); + } + +} diff --git a/src/app/components/herowars/herowars.component.html b/src/app/components/herowars/herowars.component.html new file mode 100644 index 0000000..da187bf --- /dev/null +++ b/src/app/components/herowars/herowars.component.html @@ -0,0 +1,66 @@ +
+
+
+

{{title}}

+
+ +
+ {{ now | date: 'dd/MM/yyyy' }} +
+
+ + +
+

{{description}}

+
+ + + +
+
+ +
+
+ +
+
+
+
+ +
+
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+ +
+
+
+ +
+
+ +
+
+
+
+
\ No newline at end of file diff --git a/src/app/components/herowars/herowars.component.scss b/src/app/components/herowars/herowars.component.scss new file mode 100644 index 0000000..a4626cd --- /dev/null +++ b/src/app/components/herowars/herowars.component.scss @@ -0,0 +1,37 @@ +/* herowars */ +//@use 'variable' as var; +.icon-xxsmall { + transform: scale(0.25); +} +.icon-xsmall { + font-size: 16px; + height: 16px; + width: 16px; +} +.icon-small { + font-size: 18px; + height: 18px; + width: 18px; +} +.icon-medium { + font-size: 20px; + height: 20px; + width: 20px; +} +.hstack .value { + min-width: 56px; +} + +/* +#FF41F8 +#F0060B +#F0070C +#CC26D5 +#7702FF + +#35A2EB +#B7DDD0 +#B0D9CB +#D9CAAE +#9788C7 +*/ diff --git a/src/app/components/herowars/herowars.component.spec.ts b/src/app/components/herowars/herowars.component.spec.ts new file mode 100644 index 0000000..0636ce2 --- /dev/null +++ b/src/app/components/herowars/herowars.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HerowarsComponent } from './herowars.component'; + +describe('HerowarsComponent', () => { + let component: HerowarsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [HerowarsComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(HerowarsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/herowars/herowars.component.ts b/src/app/components/herowars/herowars.component.ts new file mode 100644 index 0000000..e182e3f --- /dev/null +++ b/src/app/components/herowars/herowars.component.ts @@ -0,0 +1,84 @@ +import { DatePipe } from '@angular/common'; +import { Title } from '@angular/platform-browser'; +import { trigger, state, style, animate, transition } from '@angular/animations'; +//import { Component, DestroyRef, inject, OnInit, computed, signal, Signal } from '@angular/core'; +import { Component, DestroyRef, inject, OnInit } from '@angular/core'; +import { MatCardModule } from '@angular/material/card'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatIconModule } from '@angular/material/icon'; +import { MatTabsModule } from '@angular/material/tabs'; + +import { + ListErrorsComponent, + GuildCardComponent, GuildraidsLogComponent, GuildwarChampionsComponent, + GuildwarAttackComponent, GuildwarDefenceComponent, GuildwarTeamsComponent, MembersStatisticsComponent +} from 'src/app/components/shared'; +import { Errors, HWMember } from 'src/app/core/models'; +import guildData from 'src/files-data/hw-guild-data.json'; // page Membres +//import guildWarData from 'src/files-data/hw-guild-war.json'; // page Overview -> Statistics | page Guild War -> Guild War +//import guildStatistics from 'src/files-data/hw-guild-statistics.json'; // page Overview -> Statistics +//import guildWarSlots from 'src/files-data/hw-guild-war-slots.json'; // no pages + +@Component({ + selector: 'app-herowars', + standalone: true, + imports: [ + DatePipe, + MatCardModule, MatDividerModule, MatIconModule, MatTabsModule, + ListErrorsComponent, + GuildCardComponent, GuildraidsLogComponent, GuildwarChampionsComponent, + GuildwarAttackComponent, GuildwarDefenceComponent, GuildwarTeamsComponent, MembersStatisticsComponent + ], + templateUrl: './herowars.component.html', + styleUrl: './herowars.component.scss', + animations: [ + trigger('flyInOut', [ + state('in', style({ transform: 'translateY(0)' })), + transition('void => *', [ + style({ transform: 'translateY(-100%)' }), + animate(200) + ]), + transition('* => void', [ + style({ transform: 'translateY(100%)' }), + animate(200) + ]) + ]) + ] +}) +export class HerowarsComponent implements OnInit { + public title = 'HeroWars GM Tools'; + public description = 'Tools in working progress.'; + public errors: Errors = { errors: {} }; + public destroyRef = inject(DestroyRef); + public now = new Date(); + private _guildMembers: HWMember[] = []; + + constructor( + private _titleService: Title + ) { } + + ngOnInit() { + try { + this._titleService.setTitle(this.title); + for (const data of Object.entries(guildData.clan.members)) { + const member: HWMember = {} as HWMember; + Object.assign(member, data[1]); + if (guildData.clan.warriors.indexOf(parseInt(member.id)) !== -1) { + member.champion = true; + } else { + member.champion = false; + } + member.heroes = { power: 0, teams: []}; + member.titans = { power: 0, teams: []}; + this._guildMembers.push(member); + } + } catch (error) { + console.error(error); + } + } + + getMembers(): HWMember[] { + return this._guildMembers; + } + +} diff --git a/src/app/components/index.ts b/src/app/components/index.ts index d0f6108..d539cc6 100644 --- a/src/app/components/index.ts +++ b/src/app/components/index.ts @@ -6,6 +6,8 @@ export * from './dashboard/dashboard.component'; export * from './demo/demo.component'; export * from './dropzones/dropzones.component'; export * from './herowars/herowars.component'; +export * from './herowars-guildwar/herowars-guildwar.component'; +export * from './herowars-guildraid/herowars-guildraid.component'; export * from './home/home.component'; export * from './jump/jump.component'; export * from './jumps/jumps.component'; diff --git a/src/app/components/shared/herowars-components/fortification-card-content/fortification-card-content.component.html b/src/app/components/shared/herowars-components/fortification-card-content/fortification-card-content.component.html new file mode 100644 index 0000000..1c6b4cc --- /dev/null +++ b/src/app/components/shared/herowars-components/fortification-card-content/fortification-card-content.component.html @@ -0,0 +1,37 @@ + + {{ data.name }} + [ {{ data.count | number : '1.0' }} ] + +
    + @for (champion of data.teams; track champion; let index = $index) { +
  • + slot {{data.slots[(index)]}} + @if (champion.id !== data.positions[data.slots[(index)]].toString()) { + {{ getMemberNameById(data.positions[data.slots[(index)]].toString()) }} + + } + {{ champion.name }} + + @switch (teamType) { + @case ('heroes') { + @if (champion.id !== data.positions[data.slots[(index)]].toString()) { + {{ getMemberHeroesPowerById(data.positions[data.slots[(index)]].toString()) | number : '1.0' }} + + } + {{ champion.heroes.power | number : '1.0' }} + } + @case ('titans') { + @if (champion.id !== data.positions[data.slots[(index)]].toString()) { + {{ getMemberTitansPowerById(data.positions[data.slots[(index)]].toString()) | number : '1.0' }} + + } + {{ champion.titans.power | number : '1.0' }} + } + @default { + 0 + } + } + +
  • + } +
diff --git a/src/app/components/shared/herowars-components/fortification-card-content/fortification-card-content.component.scss b/src/app/components/shared/herowars-components/fortification-card-content/fortification-card-content.component.scss new file mode 100644 index 0000000..8db5b13 --- /dev/null +++ b/src/app/components/shared/herowars-components/fortification-card-content/fortification-card-content.component.scss @@ -0,0 +1,13 @@ +.slot { + min-width: 60px; + display: inline-block; +} +.mat-mdc-standard-chip { + --mdc-chip-container-height: 28px; + --mdc-chip-container-shape-radius: 8px 8px 8px 8px; + --mdc-chip-label-text-color: inherit; + --mdc-chip-label-text-line-height: 20px; + --mdc-chip-label-text-size: 13px; + --mdc-chip-label-text-weight: 400; + --mdc-chip-with-avatar-avatar-shape-radius: 6px 6px 6px 6px; +} \ No newline at end of file diff --git a/src/app/components/shared/herowars-components/fortification-card-content/fortification-card-content.component.ts b/src/app/components/shared/herowars-components/fortification-card-content/fortification-card-content.component.ts new file mode 100644 index 0000000..611ef06 --- /dev/null +++ b/src/app/components/shared/herowars-components/fortification-card-content/fortification-card-content.component.ts @@ -0,0 +1,83 @@ +import { Component, Input } from '@angular/core'; +import { DecimalPipe } from '@angular/common'; +import { MatCardModule } from '@angular/material/card'; +import { MatChipsModule } from '@angular/material/chips'; +import { MatIconModule } from '@angular/material/icon'; + +//import { Errors } from 'src/app/core/models'; +//import { HWMember, HWGuildWarFortification, HWGuildWarHeroTeam, HWGuildWarTitanTeam } from 'src/app/core/models'; +import { HWGuildWarFortification, HWMember } from 'src/app/core/models'; + +@Component({ + selector: 'app-fortification-card-content', + templateUrl: './fortification-card-content.component.html', + styleUrl: './fortification-card-content.component.scss', + standalone: true, + imports: [ + DecimalPipe, + MatCardModule, MatChipsModule, MatIconModule + ] +}) +export class FortificationCardContentComponent { + public data: HWGuildWarFortification = {} as HWGuildWarFortification; + public teamType: string = ''; + public guildMembers: HWMember[] = []; + //public errorList: string[] = []; + + @Input() set fortification(data: HWGuildWarFortification) { + this.data = data; + } + + @Input() set type(value: string) { + this.teamType = value; + } + + @Input() set members(value: HWMember[]) { + this.guildMembers = value; + } + + getMemberNameById(id: string): string { + let name = ''; + this.guildMembers.some((item) => { + if (item.id === id) { + name = item.name; + return true; + } + return false; + }); + return name; + } + + getMemberHeroesPowerById(id: string): number { + let power = 0; + this.guildMembers.some((item) => { + if (item.id === id) { + power = item.heroes.power; + return true; + } + return false; + }); + return power; + } + + getMemberTitansPowerById(id: string): number { + let power = 0; + this.guildMembers.some((item) => { + if (item.id === id) { + power = item.titans.power; + return true; + } + return false; + }); + return power; + } + /* + @Input() set errors(errorList: Errors | null) { + this.errorList = errorList + ? Object.keys(errorList.errors || {}).map( + (key) => `${key} ${errorList.errors[key]}`, + ) + : []; + } + */ +} \ No newline at end of file diff --git a/src/app/components/shared/herowars-components/guild-card/guild-card.component.html b/src/app/components/shared/herowars-components/guild-card/guild-card.component.html new file mode 100644 index 0000000..4240049 --- /dev/null +++ b/src/app/components/shared/herowars-components/guild-card/guild-card.component.html @@ -0,0 +1,72 @@ + + +
+ + {{ guildData.clan.title }} |server {{ guildData.clan.serverId }} + +
+ +
+ {{ guildData.clan.membersCount }}/30 +
+
+ +
+
+ Server/Season Dates +
+
Server Reset Time
+
{{ (guildData.serverResetTime*1000) | date: 'dd/MM/yyyy HH:mm:ss' }}
+
War End Season Time
+
{{ (guildData.clanWarEndSeasonTime*1000) | date: 'dd/MM/yyyy HH:mm:ss' }}
+
Free Clan Change Start
+
{{ (guildData.freeClanChangeInterval.start * 1000) | date: 'dd/MM/yyyy HH:mm:ss' }}
+
Free Clan Change End
+
{{ (guildData.freeClanChangeInterval.end * 1000) | date: 'dd/MM/yyyy HH:mm:ss' }}
+
+
+
+ Guild Overview +
+
Members
+
{{ guildData.clan.membersCount }}/30
+
Champions
+
{{ guildData.clan.warriors.length }}/20
+
Top Activity
+
{{ guildData.clan.topActivity | number : '1.0' }}
+
Top Dungeon
+
{{ guildData.clan.topDungeon | number : '1.0' }}
+
+
+
+ +
+
+ Guild Settings +
+
Guild Min. Level
+
{{ guildData.clan.minLevel }}
+
Dismissal Delay
+
{{ guildData.clan.daysToKick }} days
+
Guild Master Gifts
+
{{ guildData.clan.giftsCount }}
+
Adventure Stat
+
{{ guildData.stat.adventureStat }}
+
+
+
+ Solide Overview +
+
Today Activity
+
{{ guildData.stat.todayActivity }}
+
Today Titanite
+
{{ guildData.stat.todayDungeonActivity }}
+
Activity Sum
+
{{ guildData.stat.activitySum }}
+
Titanite Sum
+
{{ guildData.stat.dungeonActivitySum }}
+
+
+
+
+
\ No newline at end of file diff --git a/src/app/components/shared/herowars-components/guild-card/guild-card.component.scss b/src/app/components/shared/herowars-components/guild-card/guild-card.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/components/shared/herowars-components/guild-card/guild-card.component.spec.ts b/src/app/components/shared/herowars-components/guild-card/guild-card.component.spec.ts new file mode 100644 index 0000000..f8c4e42 --- /dev/null +++ b/src/app/components/shared/herowars-components/guild-card/guild-card.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GuildCardComponent } from './guild-card.component'; + +describe('GuildCardComponent', () => { + let component: GuildCardComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [GuildCardComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(GuildCardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/shared/herowars-components/guild-card/guild-card.component.ts b/src/app/components/shared/herowars-components/guild-card/guild-card.component.ts new file mode 100644 index 0000000..3fc1d47 --- /dev/null +++ b/src/app/components/shared/herowars-components/guild-card/guild-card.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit } from '@angular/core'; +import { DatePipe, DecimalPipe } from '@angular/common'; +import { MatCardModule } from '@angular/material/card'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatIconModule } from '@angular/material/icon'; + +import { HWGuildData, HWGuildClan, HWGuildStat } from 'src/app/core/models'; + +import guildData from 'src/files-data/hw-guild-data.json'; // page Membres + +@Component({ + selector: 'app-guild-card', + standalone: true, + imports: [ + DatePipe, DecimalPipe, + MatCardModule, MatDividerModule, MatIconModule + ], + templateUrl: './guild-card.component.html', + styleUrl: './guild-card.component.scss' +}) +export class GuildCardComponent implements OnInit { + public guildData: HWGuildData = {} as HWGuildData; + private _guildClan: HWGuildClan = {} as HWGuildClan; + private _guildStat: HWGuildStat = {} as HWGuildStat; + + ngOnInit() { + Object.assign(this._guildClan, guildData.clan); + this.guildData.clan = this._guildClan; + Object.assign(this._guildStat, guildData.stat); + this.guildData.stat = this._guildStat; + this.guildData.serverResetTime = guildData.serverResetTime; + this.guildData.clanWarEndSeasonTime = guildData.clanWarEndSeasonTime; + this.guildData.freeClanChangeInterval = guildData.freeClanChangeInterval; + this.guildData.giftUids = guildData.giftUids; + } +} diff --git a/src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.html b/src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.html new file mode 100644 index 0000000..e96a810 --- /dev/null +++ b/src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.html @@ -0,0 +1,436 @@ + + +
+ + {{ title }} + +
+ +
+ {{ subtitle }} +
+
+ +
+ + Choisissez une date + + MM/DD/YYYY + + + + + + + + + + Duration + + Stage duration in hour + +
+ + + Stage 1 +
+
+

Stage 1

+

+ From {{ getStagesTime(0).startTime | date: 'dd/MM HH:mm' }} + to {{ getStagesTime(0).endTime | date: 'dd/MM HH:mm' }} +

+
+ +
+

Power limit: 320k

+
+
+ + + + + + + + + + + + + + + @for (raid of getRaidsLog(1); track raid; let index = $index) { + + + + + + + + + + + } + +
+
+ # +
+
+
+ Date + +
+
+
+ Member +
+
+
+ Level +
+
+
+ Damage +
+
+
+ Stage +
+
+
+ Power +
+
+
+ Variation +
+
+ {{ (index+1) }} + + {{ raid.startTime + '000' | date: 'dd/MM HH:mm:ss' }} + + {{ raid.userName }} + + {{ raid.level | number : '1.0' }} + +
+ @if (raid.damage["2"] > 0) { + + } + {{ (raid.damage["1"] + raid.damage["2"]) | number : '1.0' }} +
+
+ {{ raid.stage.name }}: {{ (raid.stage.maxPower / 1000) | number : '1.0' }}k + + {{ raid.power | number : '1.0' }} + + + {{ raid.variation.percent | number : '1.0-2' }}% + +
+
+ + +
+
+ + Stage 2 +
+
+

Stage 2

+

+ From {{ getStagesTime(1).startTime | date: 'dd/MM HH:mm' }} + to {{ getStagesTime(1).endTime | date: 'dd/MM HH:mm' }} +

+
+ +
+

Power limit: 500k

+
+
+ + + + + + + + + + + + + + + @for (raid of getRaidsLog(2); track raid; let index = $index) { + + + + + + + + + + + } + +
+
+ # +
+
+
+ Date + +
+
+
+ Member +
+
+
+ Level +
+
+
+ Damage +
+
+
+ Stage +
+
+
+ Power +
+
+
+ Variation +
+
+ {{ (index+1) }} + + {{ raid.startTime + '000' | date: 'dd/MM HH:mm:ss' }} + + {{ raid.userName }} + + {{ raid.level | number : '1.0' }} + +
+ @if (raid.damage["2"] > 0) { + + } + {{ (raid.damage["1"] + raid.damage["2"]) | number : '1.0' }} +
+
+ {{ raid.stage.name }}: {{ (raid.stage.maxPower / 1000) | number : '1.0' }}k + + {{ raid.power | number : '1.0' }} + + + {{ raid.variation.percent | number : '1.0-2' }}% + +
+
+ + +
+
+ + Stage 3 +
+
+

Stage 3

+

+ From {{ getStagesTime(2).startTime | date: 'dd/MM HH:mm' }} + to {{ getStagesTime(2).endTime | date: 'dd/MM HH:mm' }} +

+
+ +
+

No power limit

+
+
+ + + + + + + + + + + + + + + @for (raid of getRaidsLog(3); track raid; let index = $index) { + + + + + + + + + + + } + +
+
+ # +
+
+
+ Date + +
+
+
+ Member +
+
+
+ Level +
+
+
+ Damage +
+
+
+ Stage +
+
+
+ Power +
+
+
+ Variation +
+
+ {{ (index+1) }} + + {{ raid.startTime + '000' | date: 'dd/MM HH:mm:ss' }} + + {{ raid.userName }} + + {{ raid.level | number : '1.0' }} + +
+ @if (raid.damage["2"] > 0) { + + } + {{ (raid.damage["1"] + raid.damage["2"]) | number : '1.0' }} +
+
+ {{ raid.stage.name }}: {{ (raid.stage.maxPower / 1000) | number : '1.0' }}k + + {{ raid.power | number : '1.0' }} + + + {{ raid.variation.percent | number : '1.0-2' }}% + +
+
+ + +
+
+ + Statistics +
+
+

Statistics

+
+ +
+

variation ≥ {{ minVarPct }}%

+ + Variation + + percent + excess power in % + +
+
+ + + + + + + + + + + + @for (member of getMembers(); track member; let index = $index) { + + + + + + + + } + +
+
+ # +
+
+
+ Name +
+
+
+ Fights +
+
+
+ Variation moyenne + +
+
+
+ [] +
+
+ {{ (index+1) }} + + {{ member.name }} + + {{ member.raids.length }} + + {{ member.raidsInfo.variationAvg | number : '1.0-2' }}% + +
+ @for (raid of member.raids; track raid) { +
+ {{ raid.variation.percent | number : '1.2-2' }}% +
+ } +
+
+
+ + +
+
+ + timeline + + + manage_search + +
+
+
diff --git a/src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.scss b/src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.scss new file mode 100644 index 0000000..e685fc5 --- /dev/null +++ b/src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.scss @@ -0,0 +1 @@ +/* guildraids-log */ diff --git a/src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.spec.ts b/src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.spec.ts new file mode 100644 index 0000000..131e456 --- /dev/null +++ b/src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GuildraidsLogComponent } from './guildraids-log.component'; + +describe('GuildraidsLogComponent', () => { + let component: GuildraidsLogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [GuildraidsLogComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(GuildraidsLogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.ts b/src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.ts new file mode 100644 index 0000000..6237edf --- /dev/null +++ b/src/app/components/shared/herowars-components/guildraids-log/guildraids-log.component.ts @@ -0,0 +1,214 @@ +import { Component, Injectable, inject, Input, OnInit } from '@angular/core'; +import { DatePipe, DecimalPipe } from '@angular/common'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; +import { STEPPER_GLOBAL_OPTIONS } from '@angular/cdk/stepper'; +import { MatCardModule } from '@angular/material/card'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDatepickerModule } from '@angular/material/datepicker'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatStepperIntl, MatStepperModule } from '@angular/material/stepper'; +import { MatTooltipModule } from '@angular/material/tooltip'; + +import { HWGuildRaid, HWGuildRaidAttacker, HWGuildRaidAttackers, HWGuildRaidStage, HWMember } from 'src/app/core/models'; + +import guildRaids from 'src/files-data/hw-guild-raids.json'; // page Asgard -> Guild Raid -> Log + +@Injectable() +export class StepperIntl extends MatStepperIntl { + // the default optional label text, if unspecified is "Optional" + override optionalLabel = 'Optional Label'; +} +@Component({ + selector: 'app-guildraids-log', + standalone: true, + providers: [ + { + provide: STEPPER_GLOBAL_OPTIONS, + useValue: {displayDefaultIndicatorType: false}, + }, + ], + imports: [ + DatePipe, DecimalPipe, FormsModule, ReactiveFormsModule, + MatButtonModule, MatCardModule, MatDatepickerModule, MatDividerModule, + MatFormFieldModule, MatIconModule, MatInputModule, MatTooltipModule, + MatStepperModule + ], + templateUrl: './guildraids-log.component.html', + styleUrl: './guildraids-log.component.scss' +}) +export class GuildraidsLogComponent implements OnInit { + public now: Date; + public raidsForm: FormGroup; + public guildMembers: HWMember[] = []; + public title = 'Guild Raids'; + public subtitle = 'Log'; + public minVarPct = 3; + private _matStepperIntl = inject(MatStepperIntl); + private _guildRaids: HWGuildRaid[] = []; + private _raidStages: HWGuildRaidStage[] = [ + {num: 1, name: 'Stage 1', maxPower: 350000, duration: 8, startTime: 0, endTime: 0}, + {num: 2, name: 'Stage 2', maxPower: 550000, duration: 8, startTime: 0, endTime: 0}, + {num: 3, name: 'Stage 3', maxPower: 0, duration: 0, startTime: 0, endTime: 0} + ]; + + @Input() set members(value: HWMember[]) { + this.guildMembers = value; + } + + constructor( + private fb: FormBuilder + ) { + this.now = new Date(); + const raidsDate = new Date(); + const startHour = 4; + raidsDate.setHours(startHour, 0, 0, 0); + const controlsConfig = { + num: 1, + name: 'Stage 1', + maxPower: 350, + duration: 8, + startTime: [raidsDate.getTime(), Validators.required], + endTime: 0 + }; + this.raidsForm = this.fb.group(controlsConfig); + } + + _setStagesTime(startTime: number): void { + const raidsDate = new Date(startTime); + const startHour = 4; + raidsDate.setHours(startHour, 0, 0, 0); + this._raidStages[0].startTime = raidsDate.getTime(); + + raidsDate.setHours((startHour + this._raidStages[0].duration), 0, 0, 0); + this._raidStages[0].endTime = raidsDate.getTime(); + this._raidStages[1].startTime = raidsDate.getTime(); + + raidsDate.setHours((startHour + this._raidStages[0].duration + this._raidStages[1].duration), 0, 0, 0); + this._raidStages[1].endTime = raidsDate.getTime(); + this._raidStages[2].startTime = raidsDate.getTime(); + + raidsDate.setHours(startHour, 0, 0, 0); + raidsDate.setDate(raidsDate.getDate() + 4); + this._raidStages[2].endTime = raidsDate.getTime(); + this._matStepperIntl.optionalLabel = this._raidStages[1].duration.toString() + 'h'; + } + + ngOnInit() { + this.guildMembers.map((data) => { + data.raids = []; + data.raidsInfo = { + variationAvg: 0, + variationSum: 0 + }; + return data; + }); + + for (const member of Object.entries(guildRaids)) { + const index = this.guildMembers.findIndex(item => item.id === member[0]); + const memberRaids: HWGuildRaid[] = []; + if (index !== -1) { + for (const data of Object.entries(member[1])) { + const raid: HWGuildRaid = {} as HWGuildRaid; + Object.assign(raid, data[1]); + const startTime: number = (parseInt(raid.startTime) * 1000); + if (this._guildRaids.length === 0) { + this._setStagesTime(startTime); + } + const raidsDate = new Date(startTime); + if (raidsDate.getTime() > this._raidStages[1].endTime) { + raid.stage = this._raidStages[2]; + } else if (raidsDate.getTime() > this._raidStages[0].endTime) { + raid.stage = this._raidStages[1]; + } else { + raid.stage = this._raidStages[0]; + } + + raid.damage = data[1].result.damage; + raid.level = data[1].result.level; + raid.userName = this.guildMembers[index].name; + + const attackers: HWGuildRaidAttackers = {} as HWGuildRaidAttackers; + Object.assign(attackers, data[1].attackers); + //Object.assign(raid.attackers, data[1].attackers); + raid.attackers = []; + raid.power = 0; + for (const item of Object.entries(attackers)) { + const attacker: HWGuildRaidAttacker = { + id: item[1].id, + power: item[1].power, + type: item[1].type + } as HWGuildRaidAttacker; + raid.power += attacker.power; + raid.attackers.push(attacker); + } + let percent = 0; + if (raid.stage.maxPower > 0) { + percent = (((raid.power / raid.stage.maxPower) - 1) * 100); + } + let color = 'default'; + let value = 0; + if (raid.stage.maxPower > 0) { + if (percent > 15) { + color = 'raspberry'; + } else if (percent > 10) { + color = 'red'; + } else if (percent > 5) { + color = 'orange'; + } + value = (raid.power - raid.stage.maxPower) + } + raid.variation = { + value: value, + percent: percent, + color: color + }; + raid.tooltip = Math.floor(raid.variation.value / 1000) + 'k'; + //console.log(raid.attackers); + + memberRaids.push(raid); + this._guildRaids.push(raid); + } + this.guildMembers[index].raids = memberRaids; + const varSum = memberRaids.reduce((accumulator, currentValue) => accumulator + currentValue.variation.percent, 0); + this.guildMembers[index].raidsInfo = { + variationAvg: (varSum / memberRaids.length), + variationSum: varSum + }; + } + } + this._guildRaids.sort((a, b) => (a.startTime < b.startTime ? -1 : 1)).map((data) => { + return data; + }); + this.guildMembers.sort((a, b) => (a.raidsInfo.variationAvg > b.raidsInfo.variationAvg ? -1 : 1));/*.map((data) => { + console.log(data.name, data.raidsInfo.variationAvg, data.raids.length); + return data; + });*/ + } + + public getMembers(): HWMember[] { + //return this.guildMembers; + return this.minVarPct ? this.guildMembers.filter(member => (member.raidsInfo.variationAvg >= this.minVarPct) === true) : this.guildMembers; + } + + public getRaidsLog(stageNum: number): HWGuildRaid[] { + return this._guildRaids.filter(raid => (raid.stage.num === stageNum) === true); + } + + public getStagesTime(stageNum: number): HWGuildRaidStage { + return this._raidStages[stageNum]; + } + + public onDateChange(): void { + const timestamp: number = Date.parse(this.raidsForm.controls['startTime'].value); + if (isNaN(timestamp) == false) { + this._setStagesTime(timestamp); + } + } + + submitForm(): void { + } + +} diff --git a/src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.html b/src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.html new file mode 100644 index 0000000..22a4ab0 --- /dev/null +++ b/src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.html @@ -0,0 +1,149 @@ + + +
+ + Guild War Day {{ warInfo.day }} VS {{ warInfo.clanEnemyName }} + +
+ +
+ {{ warInfo.endTime | date: 'dd/MM/yyyy HH:mm:ss' }} +
+
+ + +
+
+
Server End Time
+
{{ warInfo.endTime | date: 'dd/MM/yyyy HH:mm:ss' }}
+
Next War Time
+
{{ warInfo.nextWarTime| date: 'dd/MM/yyyy HH:mm:ss' }}
+
Next Lock Time
+
{{ warInfo.nextLockTime | date: 'dd/MM/yyyy HH:mm:ss' }}
+
+
+
+
+ + + +
+ + {{ warInfo.clanEnemyName }} Members + +
+ +
+ {{ subtitle }} {{ warInfo.endTime | date: 'dd/MM/yyyy HH:mm:ss' }} +
+
+ + + + + + + + + + + + + @for (enemy of getEnemies(); track enemy; let index = $index) { + + + + + + + + } + +
+
+ # +
+
+
+ Name + +
+
+
+ Last Login +
+
+
+ Heroes +
+
+
+ Titans +
+
+ {{ (index+1) }} + +
+ + {{ enemy.name }} +
+
+ {{ enemy.lastLoginTime + '000' | date: 'dd/MM HH:mm' }} + + {{ enemy.heroes.power | number : '1.0' }} + + {{ enemy.titans.power | number : '1.0' }} +
+
+
+ +
+
+ + +
+ + {{ warInfo.clanEnemyName }} Heroes {{ title }} + +
+ +
+ {{ subtitle }} +
+
+ + + + + + + + + +
+
+
+ + +
+ + {{ warInfo.clanEnemyName }} Titans {{ title }} + +
+ +
+ {{ subtitle }} +
+
+ + + + + + + + + +
+
+
\ No newline at end of file diff --git a/src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.scss b/src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.spec.ts b/src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.spec.ts new file mode 100644 index 0000000..ff431a0 --- /dev/null +++ b/src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GuildwarAttackComponent } from './guildwar-attack.component'; + +describe('GuildwarAttackComponent', () => { + let component: GuildwarAttackComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [GuildwarAttackComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(GuildwarAttackComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.ts b/src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.ts new file mode 100644 index 0000000..e99ed01 --- /dev/null +++ b/src/app/components/shared/herowars-components/guildwar-attack/guildwar-attack.component.ts @@ -0,0 +1,285 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { DatePipe, DecimalPipe } from '@angular/common'; +import { MatCardModule } from '@angular/material/card'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatIconModule } from '@angular/material/icon'; + +import { FortificationCardContentComponent } from 'src/app/components/shared'; +import { + HWGuildWarEnemySlot, HWGuildWarEnemyTeam, HWGuildWarFortification, + HWGuildWarHeroTeam, HWGuildWarTitanTeam, HWGuildWarSlots, HWMember +} from 'src/app/core/models'; + +/* JSON data */ +import guildWarData from 'src/files-data/hw-guild-war.json'; // page Overview -> Statistics | page Guild War -> Guild War +import guildWarInfo from 'src/files-data/hw-guild-war-info.json'; // page Guild War -> Guild War +//import guildWarLog from 'src/files-data/hw-guild-war-log.json'; // page Guild War -> Guild War +import guildWarSlots from 'src/files-data/hw-guild-war-slots.json'; // no pages + +@Component({ + selector: 'app-guildwar-attack', + standalone: true, + imports: [ + DatePipe, DecimalPipe, + MatCardModule, MatDividerModule, MatIconModule, + FortificationCardContentComponent + ], + templateUrl: './guildwar-attack.component.html', + styleUrl: './guildwar-attack.component.scss' +}) +export class GuildwarAttackComponent implements OnInit { + private _championsByPower: HWMember[] = []; + private _enemySlots: number[] = []; + public guildEnemies: HWMember[] = []; + public guildMembers: HWMember[] = []; + public title = 'Fortifications'; + public subtitle = 'Guild War Attack'; + public now = new Date(); + public warInfo: { day: number, clanEnemyName: string, endTime: number, nextWarTime: number, nextLockTime: number } = { + day: 0, + clanEnemyName: '', + endTime: 0, + nextWarTime: 0, + nextLockTime: 0 + }; + + @Input() set members(value: HWMember[]) { + this.guildMembers = value; + } + + ngOnInit() { + this.warInfo.day = parseInt(guildWarInfo.day); + this.warInfo.clanEnemyName = guildWarInfo.enemyClan.title; + this.warInfo.endTime = (guildWarInfo.endTime * 1000); + this.warInfo.nextWarTime = (guildWarInfo.nextWarTime * 1000); + this.warInfo.nextLockTime = (guildWarInfo.nextLockTime * 1000); + this._setChampionsByPower(); + this._setEnemies(); + } + + private _getFortification(indexes: number[], type: string, name: string): HWGuildWarFortification { + const teams: HWMember[] = []; + const slots: HWGuildWarSlots = guildWarSlots.slots; + let count = 0; + indexes.forEach((data) => { + switch (type) { + case 'heroes': + teams.push(this.guildEnemies[data]); + count += this.guildEnemies[data].heroes.power; + break; + case 'titans': + teams.push(this.guildEnemies[data]); + count += this.guildEnemies[data].titans.power; + break; + default: + break; + } + }); + return { + name: name, + type: type, + count: count, + teams: teams, + positions: this._enemySlots, + slots: slots[name] + }; + } + + private _getDefense(type: string, name: string): HWGuildWarFortification { + const teams: HWMember[] = []; + const slots: HWGuildWarSlots = guildWarSlots.slots; + let count = 0; + slots[name].forEach(slot => { + let enemies: HWMember[] = []; + let team: HWMember = {} as HWMember; + enemies = this.guildEnemies.filter(enemy => parseInt(enemy.id) === this._enemySlots[slot]); + if (enemies.length) { + team = enemies[0]; + teams.push(team); + switch (type) { + case 'heroes': + count += team.heroes.power; + break; + case 'titans': + count += team.titans.power; + break; + default: + break; + } + } + }); + + return { + name: name, + type: type, + count: count, + teams: teams, + positions: this._enemySlots, + slots: slots[name] + }; + } + + private _setEnemies(): void { + const warriors: number[] = []; + for (const data of Object.entries(guildWarInfo.enemyClanTries)) { + warriors.push(parseInt(data[0])); + } + for (const data of Object.entries(guildWarInfo.enemyClanMembers)) { + const enemy: HWMember = {} as HWMember; + Object.assign(enemy, data[1]); + if (warriors.indexOf(parseInt(enemy.id)) !== -1) { + enemy.champion = true; + } else { + enemy.champion = false; + } + enemy.heroes = { power: 0, teams: []}; + enemy.titans = { power: 0, teams: []}; + + //console.log(guildWarInfo.enemySlots); + + this.guildEnemies.push(enemy); + } + + for (const data of Object.entries(guildWarInfo.enemySlots)) { + const ennemySlot: HWGuildWarEnemySlot = {} as HWGuildWarEnemySlot; + Object.assign(ennemySlot, data[1]); + //console.log(ennemySlot.slotId, ennemySlot.user.name, ennemySlot.user.id); //, ennemySlot.team["1"].power); + ennemySlot.teams = []; + let totalHeroPower = 0; + let totalTitanPower = 0; + if (ennemySlot.user !== null) { + this._enemySlots[ennemySlot.slotId] = parseInt(ennemySlot.user.id); + for (const team of Object.entries(data[1].team[0])) { + /* + ennemySlot.teams.push(enemyTeam); + console.log(enemyTeam); + */ + const enemyTeam: HWGuildWarEnemyTeam = {} as HWGuildWarEnemyTeam; + Object.assign(enemyTeam, team[1]); + switch (enemyTeam.type) { + case 'hero': + case 'pet': + totalHeroPower += enemyTeam.power; + break; + case 'titan': + totalTitanPower += enemyTeam.power; + break; + default: + break; + } + ennemySlot.teams.push(team[1]); + //console.log(team[1]); + } + //console.log(totalHeroPower, totalTitanPower, ennemySlot.teams); + + this.guildEnemies.some((item) => { + if (item.id === ennemySlot.user.id) { + if (totalHeroPower) { + item.heroes.power = totalHeroPower; + item.heroes.teams = ennemySlot.teams; + } + if (totalTitanPower) { + item.titans.power = totalTitanPower; + item.titans.teams = ennemySlot.teams; + } + return true; + } + return false; + }); + } + this.guildEnemies.sort((a, b) => ((a.heroes.power + a.titans.power) > (b.heroes.power + b.titans.power) ? -1 : 1)); // Descending + } + } + + private _setChampionsByPower(): void { + for (const [teamId, teamValues] of Object.entries(guildWarData.teams)) { + const index = this.guildMembers.findIndex(member => member.id === teamId); + let totalHeroPower = 0; + let totalTitanPower = 0; + const heroes: HWGuildWarHeroTeam[] = []; + const titans: HWGuildWarTitanTeam[] = []; + + for (const unit of Object.entries(teamValues.clanDefence_heroes.units)) { + heroes.push(unit[1]); + totalHeroPower += unit[1].power; + } + for (const unit of Object.entries(teamValues.clanDefence_titans.units)) { + titans.push(unit[1]); + totalTitanPower += unit[1].power; + } + this.guildMembers[index].heroes = { power: totalHeroPower, teams: heroes }; + this.guildMembers[index].titans = { power: totalTitanPower, teams: titans }; + } + this.guildMembers.sort((a, b) => ((a.heroes.power + a.titans.power) > (b.heroes.power + b.titans.power) ? -1 : 1)); // Descending + this._championsByPower = this.guildMembers.filter(member => member.champion === true); + } + + getEnemies(): HWMember[] { + return this.guildEnemies; + } + + getMembers(): HWMember[] { + return this.guildMembers; + } + + getLighthouse(): HWGuildWarFortification { + //const indexes: number[] = [0, 4, 8]; + //return this._getFortification(indexes, 'heroes', 'Lighthouse'); + return this._getDefense('heroes', 'Lighthouse'); + } + + getBarracks(): HWGuildWarFortification { + //const indexes: number[] = [1, 5, 6]; + //return this._getFortification(indexes, 'heroes', 'Barracks'); + return this._getDefense('heroes', 'Barracks'); + } + + getMageAcademy(): HWGuildWarFortification { + //const indexes: number[] = [2, 3, 7]; + //return this._getFortification(indexes, 'heroes', 'Mage Academy'); + return this._getDefense('heroes', 'Mage Academy'); + } + + getFoundry(): HWGuildWarFortification { + //const indexes: number[] = [9, 11, 12, 13]; + //return this._getFortification(indexes, 'heroes', 'Foundry'); + return this._getDefense('heroes', 'Foundry'); + } + + getCitadel(): HWGuildWarFortification { + //const indexes: number[] = [10, 14, 15, 16, 17, 18, 19]; + //return this._getFortification(indexes, 'heroes', 'Citadel'); + return this._getDefense('heroes', 'Citadel'); + } + + getBridge(): HWGuildWarFortification { + //const indexes: number[] = [0, 1, 2, 3]; + //return this._getFortification(indexes, 'titans', 'Bridge'); + return this._getDefense('titans', 'Bridge'); + } + + getGatesOfNature(): HWGuildWarFortification { + //const indexes: number[] = [4, 9, 14, 19]; + //return this._getFortification(indexes, 'titans', 'Gates Of Nature'); + return this._getDefense('titans', 'Gates Of Nature'); + } + + getBastionOfFire(): HWGuildWarFortification { + //const indexes: number[] = [5, 10, 15, 16]; + //return this._getFortification(indexes, 'titans', 'Bastion Of Fire'); + return this._getDefense('titans', 'Bastion Of Fire'); + } + + getBastionOfIce(): HWGuildWarFortification { + //const indexes: number[] = [6, 11, 12, 17]; + //return this._getFortification(indexes, 'titans', 'Bastion Of Ice'); + return this._getDefense('titans', 'Bastion Of Ice'); + } + + getSpringOfElements(): HWGuildWarFortification { + //const indexes: number[] = [7, 8, 13, 18]; + //return this._getFortification(indexes, 'titans', 'Spring Of Elements'); + return this._getDefense('titans', 'Spring Of Elements'); + } + +} diff --git a/src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.html b/src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.html new file mode 100644 index 0000000..22d871f --- /dev/null +++ b/src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.html @@ -0,0 +1,57 @@ + + +
+ + {{ title }} + +
+ +
+ {{ subtitle }} +
+
+ + + + + + + + + + + @for (champion of getChampionsByPower(); track champion; let index = $index) { + + + + + + } + +
+
+ # +
+
+
+ Name +
+
+
+ Power + +
+
+ {{ (index+1) }} + + {{ champion.name }} + + @if (teamType === 'heroes') { + {{ champion.heroes.power | number : '1.0' }} + } + @else { + {{ champion.titans.power | number : '1.0' }} + } +
+
+
\ No newline at end of file diff --git a/src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.scss b/src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.scss new file mode 100644 index 0000000..9c4480f --- /dev/null +++ b/src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.scss @@ -0,0 +1 @@ +/* guildwar-champions */ diff --git a/src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.spec.ts b/src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.spec.ts new file mode 100644 index 0000000..eff2a52 --- /dev/null +++ b/src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GuildwarChampionsComponent } from './guildwar-champions.component'; + +describe('GuildwarChampionsComponent', () => { + let component: GuildwarChampionsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [GuildwarChampionsComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(GuildwarChampionsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.ts b/src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.ts new file mode 100644 index 0000000..3726c47 --- /dev/null +++ b/src/app/components/shared/herowars-components/guildwar-champions/guildwar-champions.component.ts @@ -0,0 +1,58 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { DecimalPipe } from '@angular/common'; +import { MatCardModule } from '@angular/material/card'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatIconModule } from '@angular/material/icon'; + +import { HWMember } from 'src/app/core/models'; +//import { HWGuildWarFortification, HWMember } from 'src/app/core/models'; + +@Component({ + selector: 'app-guildwar-champions', + standalone: true, + imports: [ + DecimalPipe, + MatCardModule, MatDividerModule, MatIconModule + ], + templateUrl: './guildwar-champions.component.html', + styleUrl: './guildwar-champions.component.scss' +}) +export class GuildwarChampionsComponent implements OnInit { + private _championsByPower: HWMember[] = []; + public guildMembers: HWMember[] = []; + public color: string = 'primary'; + public teamType: string = ''; + public title = 'Champions'; + public subtitle = 'by power'; + + @Input() set members(value: HWMember[]) { + this.guildMembers = value; + } + + @Input() set type(value: string) { + this.teamType = value; + } + + ngOnInit() { + switch (this.teamType) { + case 'heroes': + this.color = 'navy'; + this.subtitle = 'heroes power'; + this.guildMembers.sort((a, b) => (a.heroes.power > b.heroes.power ? -1 : 1)); // Descending + this._championsByPower = this.guildMembers.filter(member => member.champion === true); + break; + case 'titans': + this.color = 'purple'; + this.subtitle = 'titans power'; + this.guildMembers.sort((a, b) => (a.titans.power > b.titans.power ? -1 : 1)); // Descending + this._championsByPower = this.guildMembers.filter(member => member.champion === true); + break; + default: + break; + } + } + + getChampionsByPower(): HWMember[] { + return this._championsByPower; + } +} diff --git a/src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.html b/src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.html new file mode 100644 index 0000000..e82a52a --- /dev/null +++ b/src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.html @@ -0,0 +1,36 @@ + + +
+ + {{ title }} + +
+ +
+ {{ subtitle }} +
+
+ + @if (teamType === 'heroes') { + + + + + + + + } + @else { + + + + + + + + } + +
+
+ Position to check +
\ No newline at end of file diff --git a/src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.scss b/src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.spec.ts b/src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.spec.ts new file mode 100644 index 0000000..f2885ed --- /dev/null +++ b/src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GuildwarDefenceComponent } from './guildwar-defence.component'; + +describe('GuildwarDefenceComponent', () => { + let component: GuildwarDefenceComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [GuildwarDefenceComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(GuildwarDefenceComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.ts b/src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.ts new file mode 100644 index 0000000..5f016ce --- /dev/null +++ b/src/app/components/shared/herowars-components/guildwar-defence/guildwar-defence.component.ts @@ -0,0 +1,191 @@ +import { Component, Input, OnInit } from '@angular/core'; +//import { DecimalPipe } from '@angular/common'; +import { MatCardModule } from '@angular/material/card'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatIconModule } from '@angular/material/icon'; + +import { FortificationCardContentComponent } from 'src/app/components/shared'; +//import { HWMember } from 'src/app/core/models'; +import { HWGuildWarFortification, HWGuildWarHeroTeam, HWGuildWarSlots, HWGuildWarTitanTeam, HWMember } from 'src/app/core/models'; + +/* JSON data */ +import guildWarData from 'src/files-data/hw-guild-war.json'; // page Overview -> Statistics | page Guild War -> Guild War +import guildWarSlots from 'src/files-data/hw-guild-war-slots.json'; // no pages + +@Component({ + selector: 'app-guildwar-defence', + standalone: true, + imports: [ + MatCardModule, MatDividerModule, MatIconModule, + FortificationCardContentComponent + ], + templateUrl: './guildwar-defence.component.html', + styleUrl: './guildwar-defence.component.scss' +}) +export class GuildwarDefenceComponent implements OnInit { + private _championsByPower: HWMember[] = []; + private _championSlots: number[] = []; + public guildMembers: HWMember[] = []; + public teamType: string = ''; + public title = 'Fortifications'; + public subtitle = 'Guild War Defence'; + + @Input() set members(value: HWMember[]) { + this.guildMembers = value; + } + + @Input() set type(value: string) { + this.teamType = value; + } + + ngOnInit() { + for (const [teamId, teamValues] of Object.entries(guildWarData.teams)) { + const index = this.guildMembers.findIndex(member => member.id === teamId); + let totalHeroPower = 0; + let totalTitanPower = 0; + const heroes: HWGuildWarHeroTeam[] = []; + const titans: HWGuildWarTitanTeam[] = []; + this.guildMembers[index].heroes = { power: totalHeroPower, teams: heroes }; + this.guildMembers[index].titans = { power: totalTitanPower, teams: titans }; + + for (const unit of Object.entries(teamValues.clanDefence_heroes.units)) { + heroes.push(unit[1]); + totalHeroPower += unit[1].power; + } + for (const unit of Object.entries(teamValues.clanDefence_titans.units)) { + titans.push(unit[1]); + totalTitanPower += unit[1].power; + } + this.guildMembers[index].heroes = { power: totalHeroPower, teams: heroes }; + this.guildMembers[index].titans = { power: totalTitanPower, teams: titans }; + } + for (const data of Object.entries(guildWarData.slots)) { + this._championSlots[parseInt(data[0])] = data[1]; + } + switch (this.teamType) { + case 'heroes': + this.title = 'Heroes Fortifications'; + this.guildMembers.sort((a, b) => (a.heroes.power > b.heroes.power ? -1 : 1)); // Descending + break; + case 'titans': + this.title = 'Titans Fortifications'; + this.guildMembers.sort((a, b) => (a.titans.power > b.titans.power ? -1 : 1)); // Descending + break; + default: + break; + } + this._championsByPower = this.guildMembers.filter(member => member.champion === true); + } + + private _getFortification(indexes: number[], type: string, name: string): HWGuildWarFortification { + const teams: HWMember[] = []; + const slots: HWGuildWarSlots = guildWarSlots.slots; + let count = 0; + indexes.forEach((data) => { + switch (type) { + case 'heroes': + //console.log(name, data, this._championsByPower[data]); + teams.push(this._championsByPower[data]); + count += this._championsByPower[data].heroes.power; + break; + case 'titans': + teams.push(this._championsByPower[data]); + count += this._championsByPower[data].titans.power; + break; + default: + break; + } + }); + return { + name: name, + type: type, + count: count, + teams: teams, + positions: this._championSlots, + slots: slots[name] + }; + } + + /* + -------------------------------- + 0 - 3 - 6 + 1 - 4 - 7 + 2 - 5 - 8 + -------------------------------- + 9 - 10 - 11 - 12 + -------------------------------- + 13 - 14 - 15 - 16 - 17 - 18 - 19 + -------------------------------- + Mage Academy 1-2-31 + Lighthouse 3-4-32 + Barracks 5-6-33 + Foundry 13-14-15-36 + Citadel 25-26-28-28-29-30-40 + */ + + getLighthouse(): HWGuildWarFortification { + const indexes: number[] = [0, 4, 8]; + return this._getFortification(indexes, 'heroes', 'Lighthouse'); + } + + getBarracks(): HWGuildWarFortification { + const indexes: number[] = [1, 5, 6]; + return this._getFortification(indexes, 'heroes', 'Barracks'); + } + + getMageAcademy(): HWGuildWarFortification { + const indexes: number[] = [2, 3, 7]; + return this._getFortification(indexes, 'heroes', 'Mage Academy'); + } + + getFoundry(): HWGuildWarFortification { + const indexes: number[] = [9, 11, 12, 13]; + return this._getFortification(indexes, 'heroes', 'Foundry'); + } + + getCitadel(): HWGuildWarFortification { + const indexes: number[] = [10, 14, 15, 16, 17, 18, 19]; + return this._getFortification(indexes, 'heroes', 'Citadel'); + } + + /* + -------------------------------- + 0 - 1 - 2 - 3 + -------------------------------- + 4 - 8 - 12 - 16 + 5 - 9 - 13 - 17 + 6 - 10 - 14 - 18 + 7 - 11 - 15 - 19 + -------------------------------- + Bridge 7-8-9-34 + Spring of Elements 10-11-12-35 + Gates of Nature 16-17-18-37 + Bastion of Fire 19-20-21-38 + Bastion of Ice 22-23-24-39 + */ + + getBridge(): HWGuildWarFortification { + const indexes: number[] = [0, 1, 2, 3]; + return this._getFortification(indexes, 'titans', 'Bridge'); + } + + getGatesOfNature(): HWGuildWarFortification { + const indexes: number[] = [4, 9, 14, 19]; + return this._getFortification(indexes, 'titans', 'Gates Of Nature'); + } + + getBastionOfFire(): HWGuildWarFortification { + const indexes: number[] = [5, 10, 15, 16]; + return this._getFortification(indexes, 'titans', 'Bastion Of Fire'); + } + + getBastionOfIce(): HWGuildWarFortification { + const indexes: number[] = [6, 11, 12, 17]; + return this._getFortification(indexes, 'titans', 'Bastion Of Ice'); + } + + getSpringOfElements(): HWGuildWarFortification { + const indexes: number[] = [7, 8, 13, 18]; + return this._getFortification(indexes, 'titans', 'Spring Of Elements'); + } +} diff --git a/src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.html b/src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.html new file mode 100644 index 0000000..fdf62ae --- /dev/null +++ b/src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.html @@ -0,0 +1,101 @@ + + +
+ + {{ title }} + +
+ +
+ {{ subtitle }} +
+
+ + + + + + + + + + + + + @for (member of getChampionsByPower(); track member; let index = $index) { + + + + + + + + } + + + + + + + + + + + + + +
+
+ # +
+
+
+ Name +
+
+
+ Avg + +
+
+
+ Heroes +
+
+
+ Titans +
+
+ {{ (index+1) }} + +
+ + {{ member.name }} +
+
+ {{ ((member.heroes.power + member.titans.power) / 2) | number : '1.0-0' }} + + {{ member.heroes.power | number : '1.0' }} + + {{ member.titans.power | number : '1.0' }} +
+ Totals + + {{ guildTotalHeroesPower | number : '1.0' }} + + {{ guildTotalTitansPower | number : '1.0' }} +
+ Averages + + {{ guildAverageHeroesPower | number : '1.0' }} + + {{ guildAverageTitansPower | number : '1.0' }} +
+
+
+
+ Champion signet + No Champion signet + Below average + Above average +
\ No newline at end of file diff --git a/src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.scss b/src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.scss new file mode 100644 index 0000000..f9db35e --- /dev/null +++ b/src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.scss @@ -0,0 +1 @@ +/* guildwar-teams */ diff --git a/src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.spec.ts b/src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.spec.ts new file mode 100644 index 0000000..89c2840 --- /dev/null +++ b/src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GuildwarTeamsComponent } from './guildwar-teams.component'; + +describe('GuildwarTeamsComponent', () => { + let component: GuildwarTeamsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [GuildwarTeamsComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(GuildwarTeamsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.ts b/src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.ts new file mode 100644 index 0000000..beb4085 --- /dev/null +++ b/src/app/components/shared/herowars-components/guildwar-teams/guildwar-teams.component.ts @@ -0,0 +1,78 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { DecimalPipe } from '@angular/common'; +import { MatCardModule } from '@angular/material/card'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatIconModule } from '@angular/material/icon'; + +import { HWGuildWarHeroTeam, HWGuildWarTitanTeam, HWMember } from 'src/app/core/models'; + +import guildWarData from 'src/files-data/hw-guild-war.json'; // page Overview -> Statistics | page Guild War -> Guild War + +@Component({ + selector: 'app-guildwar-teams', + standalone: true, + imports: [ + DecimalPipe, + MatCardModule, MatDividerModule, MatIconModule + ], + templateUrl: './guildwar-teams.component.html', + styleUrl: './guildwar-teams.component.scss' +}) +export class GuildwarTeamsComponent implements OnInit { + private _championsByPower: HWMember[] = []; + public guildMembers: HWMember[] = []; + public title = 'Members'; + public subtitle = 'guild war teams power'; + public guildAverageHeroesPower: number = 0; + public guildAverageTitansPower: number = 0; + public guildTotalHeroesPower: number = 0; + public guildTotalTitansPower: number = 0; + + @Input() set members(value: HWMember[]) { + this.guildMembers = value; + } + + ngOnInit() { + + this.guildMembers.sort((a, b) => (((a.heroes.power + a.titans.power) / 2) > ((b.heroes.power + b.titans.power) / 2) ? -1 : 1)) + .map((data) => { + /* + this.guildTotalHeroesPower += data.heroes.power; + this.guildTotalTitansPower += data.titans.power; + this.guildAverageHeroesPower = Math.floor((this.guildTotalHeroesPower / this.guildMembers.length)); + this.guildAverageTitansPower = Math.floor((this.guildTotalTitansPower / this.guildMembers.length)); + */ + this._championsByPower.push(data); + return data; + }); + + for (const [teamId, teamValues] of Object.entries(guildWarData.teams)) { + const index = this._championsByPower.findIndex(member => member.id === teamId); + let totalHeroPower = 0; + let totalTitanPower = 0; + const heroes: HWGuildWarHeroTeam[] = []; + const titans: HWGuildWarTitanTeam[] = []; + + for (const unit of Object.entries(teamValues.clanDefence_heroes.units)) { + heroes.push(unit[1]); + totalHeroPower += unit[1].power; + } + for (const unit of Object.entries(teamValues.clanDefence_titans.units)) { + titans.push(unit[1]); + totalTitanPower += unit[1].power; + } + this._championsByPower[index].heroes = { power: totalHeroPower, teams: heroes }; + this._championsByPower[index].titans = { power: totalTitanPower, teams: titans }; + this.guildTotalHeroesPower += totalHeroPower; + this.guildTotalTitansPower += totalTitanPower; + this._championsByPower[index].rewards = Math.floor((this._championsByPower[index].scoreGifts + this._championsByPower[index].warGifts)); + } + this.guildAverageHeroesPower = Math.floor((this.guildTotalHeroesPower / this._championsByPower.length)); + this.guildAverageTitansPower = Math.floor((this.guildTotalTitansPower / this._championsByPower.length)); + } + + getChampionsByPower(): HWMember[] { + return this._championsByPower; + } + +} diff --git a/src/app/components/shared/herowars-components/index.ts b/src/app/components/shared/herowars-components/index.ts new file mode 100644 index 0000000..0a58942 --- /dev/null +++ b/src/app/components/shared/herowars-components/index.ts @@ -0,0 +1,8 @@ +export * from './fortification-card-content/fortification-card-content.component'; +export * from './guild-card/guild-card.component'; +export * from './guildraids-log/guildraids-log.component'; +export * from './guildwar-attack/guildwar-attack.component'; +export * from './guildwar-champions/guildwar-champions.component'; +export * from './guildwar-defence/guildwar-defence.component'; +export * from './guildwar-teams/guildwar-teams.component'; +export * from './members-statistics/members-statistics.component'; diff --git a/src/app/components/shared/herowars-components/members-statistics/members-statistics.component.html b/src/app/components/shared/herowars-components/members-statistics/members-statistics.component.html new file mode 100644 index 0000000..478935f --- /dev/null +++ b/src/app/components/shared/herowars-components/members-statistics/members-statistics.component.html @@ -0,0 +1,270 @@ + + +
+ + {{ title }} + +
+ +
+ {{ subtitle }} +
+
+ + + + + + + + + + + + + + + + + + + + + @for (member of getMembersByName(); track member; let index = $index) { + + + + + + + + + + + + + + + + } + + + + + + + + + + + + + + + + + + + + + + + +
+
+ # +
+
+
+ Name + +
+
+
+ ID +
+
+
+ Last Login +
+
+
+ Dismissal Delay +
+
+
+ Dungeon +
+
+
+ Activity +
+
+
+ Prestige +
+
+
+ War Fights +
+
+
+ Adventures +
+
+
+ Score +
+
+
+ Name +
+
+
+ Rewards +
+
+ {{ (index+1) }} + +
+ + {{ member.name }} +
+
+ {{ member.id }} + + {{ member.lastLoginTime + '000' | date: 'dd/MM HH:mm' }} + + {{ member.inactivity.dropDelay }} + +
+
+ {{ member.stat.todayDungeonActivity | number : '1.0' }} +
+
+
+ {{ member.stat.dungeonActivitySum | number : '1.0' }} +
+
+
+
+
+ {{ member.stat.todayActivity | number : '1.0' }} +
+
+
+ {{ member.stat.activitySum | number : '1.0' }} +
+
+
+
+
+ {{ member.stat.todayPrestige | number : '1.0' }} +
+
+
+ {{ member.stat.prestigeSum | number : '1.0' }} +
+
+
+ {{ member.clanWarSum }} + + {{ member.adventureSum }} + + {{ member.score | number : '1.0' }} + +
+ {{ member.name }} +
+
+ {{ member.rewards | number : '1.0' }} +
+ Totals + +
+
+ {{ guildTodayTotal.titanite | number : '1.0' }} +
+
+
+ {{ guildSumTotal.titanite | number : '1.0' }} +
+
+
+
+
+ {{ guildTodayTotal.activity | number : '1.0' }} +
+
+
+ {{ guildSumTotal.activity | number : '1.0' }} +
+
+
+
+
+ {{ guildTodayTotal.prestige | number : '1.0' }} +
+
+
+ {{ guildSumTotal.prestige | number : '1.0' }} +
+
+
+ {{ guildSumTotal.war | number : '1.0' }} + + {{ guildSumTotal.adventure | number : '1.0' }} + + {{ guildSumTotal.score | number : '1.0' }} + + {{ guildSumTotal.rewards }} +
+ Averages + +
+
+ {{ guildTodayAverages.titanite | number : '1.0-1' }} +
+
+
+ {{ guildSumAverages.titanite | number : '1.0-1' }} +
+
+
+
+
+ {{ guildTodayAverages.activity | number : '1.0-1' }} +
+
+
+ {{ guildSumAverages.activity | number : '1.0-1' }} +
+
+
+
+
+ {{ guildTodayAverages.prestige | number : '1.0-1' }} +
+
+
+ {{ guildSumAverages.prestige | number : '1.0-1' }} +
+
+
+ {{ guildSumAverages.war | number : '1.0-1' }} + + {{ guildSumAverages.adventure | number : '1.0-1' }} + + {{ guildSumAverages.score | number : '1.0-1' }} + + {{ guildSumAverages.rewards | number : '1.0-1' }} +
+
+
+
+ Champion signet + No Champion signet + Inactivity > {{ daysToWarn }} days + Below average + Above average +
\ No newline at end of file diff --git a/src/app/components/shared/herowars-components/members-statistics/members-statistics.component.scss b/src/app/components/shared/herowars-components/members-statistics/members-statistics.component.scss new file mode 100644 index 0000000..bbeacbb --- /dev/null +++ b/src/app/components/shared/herowars-components/members-statistics/members-statistics.component.scss @@ -0,0 +1,5 @@ +/* members-statistics */ + +.hstack .value { + min-width: 56px; +} \ No newline at end of file diff --git a/src/app/components/shared/herowars-components/members-statistics/members-statistics.component.spec.ts b/src/app/components/shared/herowars-components/members-statistics/members-statistics.component.spec.ts new file mode 100644 index 0000000..a0f0dfd --- /dev/null +++ b/src/app/components/shared/herowars-components/members-statistics/members-statistics.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MembersStatisticsComponent } from './members-statistics.component'; + +describe('MembersStatisticsComponent', () => { + let component: MembersStatisticsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MembersStatisticsComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(MembersStatisticsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/shared/herowars-components/members-statistics/members-statistics.component.ts b/src/app/components/shared/herowars-components/members-statistics/members-statistics.component.ts new file mode 100644 index 0000000..1fd2afc --- /dev/null +++ b/src/app/components/shared/herowars-components/members-statistics/members-statistics.component.ts @@ -0,0 +1,159 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { DatePipe, DecimalPipe } from '@angular/common'; +import { MatCardModule } from '@angular/material/card'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatIconModule } from '@angular/material/icon'; + +import { HWActivityStat, HWGuildClan, HWGuildData, HWMember, HWMemberStat, HWWeekStat } from 'src/app/core/models/herowars'; +import { UtilitiesService } from 'src/app/core/services'; + +import guildData from 'src/files-data/hw-guild-data.json'; // page Membres +import guildStatistics from 'src/files-data/hw-guild-statistics.json'; // page Overview -> Statistics + +@Component({ + selector: 'app-members-statistics', + standalone: true, + imports: [ + DatePipe, DecimalPipe, + MatCardModule, MatDividerModule, MatIconModule + ], + templateUrl: './members-statistics.component.html', + styleUrl: './members-statistics.component.scss' +}) +export class MembersStatisticsComponent implements OnInit { + public guildMembers: HWMember[] = []; + public title = 'Members'; + public subtitle = 'statistics'; + public daysToWarn = 1; + public guildSumAverages: HWActivityStat = { activity: 0, prestige: 0, titanite: 0, war: 0, adventure: 0, gifts: 0, score: 0, scoreGifts: 0, warGifts: 0, rewards: 0 }; + public guildTodayAverages: HWActivityStat = { activity: 0, prestige: 0, titanite: 0, war: 0, adventure: 0, gifts: 0, score: 0, scoreGifts: 0, warGifts: 0, rewards: 0 }; + public guildSumTotal: HWActivityStat = { activity: 0, prestige: 0, titanite: 0, war: 0, adventure: 0, gifts: 0, score: 0, scoreGifts: 0, warGifts: 0, rewards: 0 }; + public guildTodayTotal: HWActivityStat = { activity: 0, prestige: 0, titanite: 0, war: 0, adventure: 0, gifts: 0, score: 0, scoreGifts: 0, warGifts: 0, rewards: 0 }; + public guildData: HWGuildData = {} as HWGuildData; + private _guildClan: HWGuildClan = {} as HWGuildClan; + private _membersByName: HWMember[] = []; + private _deviations: { activity: number[], prestige: number[], titanite: number[] } = { activity: [], prestige: [], titanite: [] }; + + @Input() set members(value: HWMember[]) { + this.guildMembers = value; + } + + constructor( + private _utilitiesService: UtilitiesService + ) { } + + ngOnInit() { + + const oneDayInSec = (24 * 60 * 60); + const today = new Date(); + const daysToKick = parseInt(guildData.clan.daysToKick); + this.daysToWarn = (parseInt(guildData.clan.daysToKick) / 2); + this.guildMembers.sort((a, b) => (a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1)).map((data) => { + const last = new Date((parseInt(data.lastLoginTime) * 1000)); + const exp = new Date(last.getTime() + ((daysToKick * oneDayInSec) * 1000)); + const diff = Math.floor(((exp.getTime() - today.getTime()) / 1000)); + const daysLeft = Math.floor((diff / oneDayInSec)); + let timeLeft = diff; + if (daysLeft >= 1) { + timeLeft = (diff - (daysLeft * oneDayInSec)); + } + data.inactivity = { + daysLeft: daysLeft, + timeLeft: timeLeft, + dropDelay: `${daysLeft}d, ${this._utilitiesService.secondsToDuration(timeLeft)}`, + dropDate: Math.floor((exp.getTime() / 1000)) + }; + this._membersByName.push(data); + return data; + }); + + Object.assign(this._guildClan, guildData.clan); + this.guildData.clan = this._guildClan; + this.guildData.membersStat = guildData.membersStat; + + for (const item of Object.entries(guildStatistics.stat)) { + const index = this._membersByName.findIndex(member => member.id === item[1].id); + if (index !== -1) { + this._membersByName[index].adventureSum = item[1].adventureStat.reduce((accumulator, currentValue) => accumulator + currentValue, 0); + this._membersByName[index].clanGiftsSum = item[1].clanGifts.reduce((accumulator, currentValue) => accumulator + currentValue, 0); + this._membersByName[index].clanWarSum = item[1].clanWarStat.reduce((accumulator, currentValue) => accumulator + currentValue, 0); + this.guildSumTotal.adventure += this._membersByName[index].adventureSum; + this.guildSumTotal.gifts += this._membersByName[index].clanGiftsSum; + this.guildSumTotal.war += this._membersByName[index].clanWarSum; + const stat: HWWeekStat = {} as HWWeekStat; + Object.assign(stat, item[1]); + this._membersByName[index].weekStat = stat; + } else { + console.log(item[1].id); + } + } + + for (const data of Object.entries(guildData.membersStat)) { + const stat: HWMemberStat = {} as HWMemberStat; + Object.assign(stat, data[1]); + const index = this._membersByName.findIndex(member => member.id === data[1].userId); + if (index !== -1) { + this._membersByName[index].stat = stat; + } + this._membersByName[index].score = (this._membersByName[index].stat.dungeonActivitySum + this._membersByName[index].stat.activitySum + this._membersByName[index].stat.prestigeSum); + this._membersByName[index].warGifts = (((guildData.clan.giftsCount / 2) * ((this._membersByName[index].clanWarSum * 10) / 100)) / 20); + + this.guildTodayTotal.activity += stat.todayActivity; + this.guildTodayTotal.prestige += stat.todayPrestige; + this.guildTodayTotal.titanite += stat.todayDungeonActivity; + this.guildTodayTotal.score += (this._membersByName[index].stat.todayDungeonActivity + this._membersByName[index].stat.todayActivity + this._membersByName[index].stat.todayPrestige); + this.guildSumTotal.activity += stat.activitySum; + this.guildSumTotal.prestige += stat.prestigeSum; + this.guildSumTotal.titanite += stat.dungeonActivitySum; + this.guildSumTotal.score += this._membersByName[index].score; + this.guildSumTotal.warGifts += this._membersByName[index].warGifts; + this._deviations.activity.push(stat.activitySum); + this._deviations.prestige.push(stat.prestigeSum); + this._deviations.titanite.push(stat.dungeonActivitySum); + //this.guildSumTotal.warGifts += ((this._membersByName[index].score / this.guildSumTotal.score) * (guildData.clan.giftsCount / 2)) + } + this.guildSumTotal.scoreGifts = (guildData.clan.giftsCount - Math.floor(this.guildSumTotal.warGifts)); + this.guildTodayAverages.activity = (this.guildTodayTotal.activity / this._membersByName.length); + this.guildTodayAverages.prestige = (this.guildTodayTotal.prestige / this._membersByName.length); + this.guildTodayAverages.titanite = (this.guildTodayTotal.titanite / this._membersByName.length); + this.guildTodayAverages.score = (this.guildTodayTotal.score / this._membersByName.length); + this.guildSumAverages.activity = (this.guildSumTotal.activity / this._membersByName.length); + this.guildSumAverages.prestige = (this.guildSumTotal.prestige / this._membersByName.length); + this.guildSumAverages.titanite = (this.guildSumTotal.titanite / this._membersByName.length); + this.guildSumAverages.war = (this.guildSumTotal.war / 20); + this.guildSumAverages.adventure = (this.guildSumTotal.adventure / this._membersByName.length); + this.guildSumAverages.gifts = (this.guildSumTotal.gifts / this._membersByName.length); + this.guildSumAverages.score = (this.guildSumTotal.score / this._membersByName.length); + + this._membersByName.map((data) => { + data.scoreGifts = ((data.score / this.guildSumTotal.score) * this.guildSumTotal.scoreGifts); + data.rewards = Math.floor((data.scoreGifts + data.warGifts)); + this.guildSumTotal.rewards += data.rewards; + return data; + }); + this.guildSumAverages.rewards = (this.guildSumTotal.rewards / this._membersByName.length); + } + + getMembersByName(): HWMember[] { + return this._membersByName; + } + + private _standardDeviation(array: number[]): number { + const n = array.length; + const mean = array.reduce((a, b) => a + b) / n; + return Math.sqrt(array.map(x => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n); + } + + getStandardDeviationActivity(): number { + return this._standardDeviation(this._deviations.activity); + } + + getStandardDeviationAPrestige(): number { + return this._standardDeviation(this._deviations.prestige); + } + + getStandardDeviationTitanite(): number { + return this._standardDeviation(this._deviations.titanite); + } + +} diff --git a/src/app/components/shared/index.ts b/src/app/components/shared/index.ts index 80e0a7f..cc26686 100644 --- a/src/app/components/shared/index.ts +++ b/src/app/components/shared/index.ts @@ -1,6 +1,5 @@ export * from './accordion'; export * from './dashboard-components'; -export * from './fortification-card-content/fortification-card-content.component'; export * from './helpers-chart'; export * from './helpers-jump'; export * from './herowars-components'; diff --git a/src/app/components/shared/menu-items.ts b/src/app/components/shared/menu-items.ts index efacc80..a64085d 100755 --- a/src/app/components/shared/menu-items.ts +++ b/src/app/components/shared/menu-items.ts @@ -53,7 +53,9 @@ const MENUITEMS: Menu[] = [ { parent: 'page', state: 'les-fleurs', type: 'link', name: 'Fleurs', icon: 'marijuana', desc: '' }, { parent: 'page', state: 'les-resines', type: 'link', name: 'Résines', icon: 'butter', desc: '' }, { parent: 'page', state: 'les-molecules', type: 'link', name: 'Molécules', icon: 'molecule', desc: '' }, - { state: 'herowars', type: 'link', name: 'Hero Wars', icon: 'military_tech', icontype: 'mat', desc: '' } + { state: 'herowars', type: 'menu', name: 'Hero Wars', icon: 'military_tech', icontype: 'mat', desc: '' }, + { parent: 'herowars', state: 'guildwar', type: 'link', name: 'Guild War', icon: 'military_tech', icontype: 'mat', desc: '' }, + { parent: 'herowars', state: 'guildraid', type: 'link', name: 'Guild Raid', icon: 'military_tech', icontype: 'mat', desc: '' } ]; const MENUPJUMP: Menu[] = [ diff --git a/src/app/core/models/herowars/clan-list-config.model.ts b/src/app/core/models/herowars/clan-list-config.model.ts new file mode 100644 index 0000000..1685915 --- /dev/null +++ b/src/app/core/models/herowars/clan-list-config.model.ts @@ -0,0 +1,16 @@ +export interface HWClanListConfig { + type: string; + filters: HWClanListFilters; +} + +export interface HWClanListFilters { + id?: string; + title?: string; + country?: string; + level?: string; + minLevel?: string; + ownerId?: string; + serverId?: string; + topActivity?: string; + topDungeon?: string; +} diff --git a/src/app/core/models/herowars/clan-list.model.ts b/src/app/core/models/herowars/clan-list.model.ts new file mode 100644 index 0000000..d11f036 --- /dev/null +++ b/src/app/core/models/herowars/clan-list.model.ts @@ -0,0 +1,6 @@ +import { HWClan } from './clan.model'; + +export interface HWClanList { + clans: Array; + clansCount: number; +} diff --git a/src/app/core/models/herowars/clan.model.ts b/src/app/core/models/herowars/clan.model.ts new file mode 100644 index 0000000..a0664fd --- /dev/null +++ b/src/app/core/models/herowars/clan.model.ts @@ -0,0 +1,84 @@ +import { HWMember } from './member.model'; +import { HWActivityStat, HWGuildStat, HWMemberStat } from './stat.model'; +import { PageLinks, PageMeta } from '../shared.model'; + +export interface HWGuildClan { + id: string; + ownerId: string; + level: string; + title: string; + description: string; + icon: { + flagColor1: number; + flagColor2: number; + flagShape: number; + iconColor: number; + iconShape: number; + }; + country: string; + minLevel: string; + serverId: string; + membersCount: string; + disbanding: boolean; + topActivity: string; + topDungeon: string; + roleNames: never[]; + frameId: number; + members: {[key: string]: HWMember}; + news: string; + activityPoints: number; + dungeonPoints: number; + blackList: {[key: string]: number}; + warriors: number[]; + giftsCount: number; + daysToKick: string; + league: string; + sumAverages: HWActivityStat; + sumTotal: HWActivityStat; + todayAverages: HWActivityStat; + todayTotal: HWActivityStat; +} +export interface HWGuildData { + clan: HWGuildClan; + slots: {[key: string]: number}; + membersStat: HWMemberStat[]; + stat: HWGuildStat; + serverResetTime: number; + clanWarEndSeasonTime: number; + freeClanChangeInterval: { + start: number; + end: number; + }; + giftUids: string[]; +} + +export interface HWClan { + id: string; + country: string; + description: string; + disbanding: boolean; + frameId: number; + icon: { + flagColor1: number; + flagColor2: number; + flagShape: number; + iconColor: number; + iconShape: number; + }; + level: string; + members: {[key: string]: HWMember}; + membersCount: string; + minLevel: string; + ownerId: string; + /*roleNames: never[];*/ + serverId: string; + title: string; + topActivity: string; + topDungeon: string; +} + +export interface HWClanPageData { + clan: HWClan; + _links: PageLinks; + _meta: PageMeta; +} diff --git a/src/app/core/models/herowars/fortification.model.ts b/src/app/core/models/herowars/fortification.model.ts new file mode 100644 index 0000000..b95a228 --- /dev/null +++ b/src/app/core/models/herowars/fortification.model.ts @@ -0,0 +1,10 @@ +import { HWMember } from './member.model'; + +export interface HWGuildWarFortification { + name: string; + type: string; + count: number; + teams: HWMember[]; + positions: number[]; + slots: number[]; +} \ No newline at end of file diff --git a/src/app/core/models/herowars/guildwar.model.ts b/src/app/core/models/herowars/guildwar.model.ts new file mode 100644 index 0000000..a2f8785 --- /dev/null +++ b/src/app/core/models/herowars/guildwar.model.ts @@ -0,0 +1,80 @@ + +export interface HWGuildWarHeroTeam { + id: number; + level: number; + color: number; + star: number; + power: number; +} +export interface HWGuildWarTitanTeam { + id: number; + level: number; + star: number; + element: string; + elementSpiritLevel: number; + elementSpiritStar: number; + elementSpiritSkills: { + skillId: number; + level: number; + tierScale: number; + }[]; + elementAffinityPower: number; + power: number; +} +export interface HWGuildWarEnemyTeam { + element: string; + elementSpiritLevel: number; + elementSpiritStar: number; + elementSpiritSkills: { + skillId: number; + level: number; + tierScale: number; + }[]; + elementAffinityPower: number; + state: { + isDead: boolean; + hp: number; + energy: number; + maxHp: number; + }; + id: number; + star: number; + color: number; + level: number; + power: number; + type: string; +} +export interface HWGuildWarSlots { + [key: string]: number[]; +} +export interface HWGuildWarEnemySlot { + attackerId: number; + status: string; + user: { + id: string; + name: string; + lastLoginTime: string; + serverId: string; + level: string; + clanId: string; + clanRole: string; + commander: boolean; + avatarId: string; + isChatModerator: boolean; + frameId: number; + leagueId: number; + allowPm: string; + clanTitle: string; + clanIcon: { + flagColor1: number; + flagColor2: number; + flagShape: number; + iconColor: number; + iconShape: number; + }; + }; + pointsFarmed: number; + slotId: number; + totalPoints: number; + teams: HWGuildWarEnemyTeam[]; +} diff --git a/src/app/core/models/herowars/hw.model.ts b/src/app/core/models/herowars/hw.model.ts new file mode 100644 index 0000000..6cfbb4d --- /dev/null +++ b/src/app/core/models/herowars/hw.model.ts @@ -0,0 +1,264 @@ +export interface HWMember { + id: string; + name: string; + lastLoginTime: string; + serverId: string; + level: string; + clanId: string; + clanRole: string; + commander: boolean; + avatarId: string; + isChatModerator: boolean; + frameId: number; + leagueId: number; + allowPm: string; + showProfile: boolean; + clanTitle: string; + clanIcon: { + flagColor1: number; + flagColor2: number; + flagShape: number; + iconColor: number; + iconShape: number; + }; + champion: boolean; + heroes: { + power: number; + teams: HWGuildWarHeroTeam[]; + }; + titans: { + power: number; + teams: HWGuildWarTitanTeam[]; + }; + stat: HWMemberStat; + inactivity: { + daysLeft: number, + timeLeft: number, + dropDate: number; + dropDelay: string; + } + adventureSum: number; + clanGiftsSum: number; + clanWarSum: number; + weekStat: HWWeekStat; + score: number; + scoreGifts: number; + warGifts: number; + rewards: number; + raids: HWGuildRaid[]; + raidsInfo: { + variationAvg: number; + variationSum: number; + } +} +export interface HWGuildWarHeroTeam { + id: number; + level: number; + color: number; + star: number; + power: number; +} +export interface HWGuildWarTitanTeam { + id: number; + level: number; + star: number; + element: string; + elementSpiritLevel: number; + elementSpiritStar: number; + elementSpiritSkills: { + skillId: number; + level: number; + tierScale: number; + }[]; + elementAffinityPower: number; + power: number; +} +export interface HWGuildWarFortification { + name: string; + type: string; + count: number; + teams: HWMember[]; + positions: number[]; + slots: number[]; +} +export interface HWGuildStat { + todayActivity: number; + activitySum: number; + dungeonActivitySum: number; + todayRaid: never[]; + todayItemsActivity: number; + todayDungeonActivity: number; + activityForRuneAvailable: boolean; + adventureStat: number; + clanWarStat: number; +} +export interface HWGuildClan { + id: string; + ownerId: string; + level: string; + title: string; + description: string; + icon: { + flagColor1: number; + flagColor2: number; + flagShape: number; + iconColor: number; + iconShape: number; + }; + country: string; + minLevel: string; + serverId: string; + membersCount: string; + disbanding: boolean; + topActivity: string; + topDungeon: string; + roleNames: never[]; + frameId: number; + members: {[key: string]: HWMember}; + news: string; + activityPoints: number; + dungeonPoints: number; + blackList: {[key: string]: number}; + warriors: number[]; + giftsCount: number; + daysToKick: string; + league: string; +} +export interface HWGuildData { + clan: HWGuildClan; + slots: {[key: string]: number}; + membersStat: HWMemberStat[]; + stat: HWGuildStat; + serverResetTime: number; + clanWarEndSeasonTime: number; + freeClanChangeInterval: { + start: number; + end: number; + }; + giftUids: string[]; +} +export interface HWActivityStat { + activity: number; + prestige: number; + titanite: number; + war: number; + adventure: number; + gifts: number; + score: number; + scoreGifts: number; + warGifts: number; + rewards: number; +} +export interface HWWeekStat { + activity: number[]; + dungeonActivity: number[]; + adventureStat: number[]; + clanWarStat: number[]; + prestigeStat: number[]; + clanGifts: number[]; +} +export interface HWMemberStat { + activitySum: number; + todayActivity: number; + dungeonActivitySum: number; + todayDungeonActivity: number; + raidSum: number; + wasChampion: boolean; + todayPrestige: number; + prestigeSum: number; +} +export interface HWGuildRaidAttacker { + id: number; + power: number; + type: string; +} +export interface HWGuildRaidStage { + num: number; + name: string; + maxPower: number; + duration: number; + startTime: number; + endTime: number; +} +export interface HWGuildRaid { + userId: string; + userName: string; + power: number; + variation: { + value: number; + percent: number; + color: string; + }; + tooltip: string; + startTime: string; + endTime: string; + damage: { + "1": number; + "2": number; + }; + level: string; + attackers: HWGuildRaidAttacker[]; + stage: HWGuildRaidStage; + +} +export interface HWGuildRaidAttackers { + [key: string]: HWGuildRaidAttacker; +} +export interface HWGuildWarEnemySlot { + attackerId: number; + status: string; + user: { + id: string; + name: string; + lastLoginTime: string; + serverId: string; + level: string; + clanId: string; + clanRole: string; + commander: boolean; + avatarId: string; + isChatModerator: boolean; + frameId: number; + leagueId: number; + allowPm: string; + clanTitle: string; + clanIcon: { + flagColor1: number; + flagColor2: number; + flagShape: number; + iconColor: number; + iconShape: number; + }; + }; + pointsFarmed: number; + slotId: number; + totalPoints: number; + teams: HWGuildWarEnemyTeam[]; +} + +export interface HWGuildWarEnemyTeam { + element: string; + elementSpiritLevel: number; + elementSpiritStar: number; + elementSpiritSkills: { + skillId: number; + level: number; + tierScale: number; + }[]; + elementAffinityPower: number; + state: { + isDead: boolean; + hp: number; + energy: number; + maxHp: number; + }; + id: number; + star: number; + color: number; + level: number; + power: number; + type: string; +} +export interface HWGuildWarSlots { + [key: string]: number[]; +} \ No newline at end of file diff --git a/src/app/core/models/herowars/index.ts b/src/app/core/models/herowars/index.ts new file mode 100644 index 0000000..44ae6f8 --- /dev/null +++ b/src/app/core/models/herowars/index.ts @@ -0,0 +1,9 @@ +export * from './clan-list-config.model'; +export * from './clan-list.model'; +export * from './clan.model'; +export * from './fortification.model'; +export * from './guildwar.model'; +//export * from './hw.model'; +export * from './member.model'; +export * from './raid.model'; +export * from './stat.model'; diff --git a/src/app/core/models/herowars/member.model.ts b/src/app/core/models/herowars/member.model.ts new file mode 100644 index 0000000..ceaa7e8 --- /dev/null +++ b/src/app/core/models/herowars/member.model.ts @@ -0,0 +1,57 @@ +import { HWGuildRaid } from './raid.model'; +import { HWMemberStat, HWWeekStat } from './stat.model'; +import { HWGuildWarHeroTeam, HWGuildWarTitanTeam } from './guildwar.model'; + +export interface HWMember { + id: string; + allowPm: string; + avatarId: string; + clanIcon: { + flagColor1: number; + flagColor2: number; + flagShape: number; + iconColor: number; + iconShape: number; + }; + clanId: string; + clanRole: string; + clanTitle: string; + commander: boolean; + frameId: number; + isChatModerator: boolean; + lastLoginTime: string; + leagueId: number; + level: string; + name: string; + serverId: string; + showProfile: boolean; + champion: boolean; + heroes: { + power: number; + teams: HWGuildWarHeroTeam[]; + }; + titans: { + power: number; + teams: HWGuildWarTitanTeam[]; + }; + stat: HWMemberStat; + inactivity: { + daysLeft: number, + timeLeft: number, + dropDate: number; + dropDelay: string; + } + adventureSum: number; + clanGiftsSum: number; + clanWarSum: number; + weekStat: HWWeekStat; + score: number; + scoreGifts: number; + warGifts: number; + rewards: number; + raids: HWGuildRaid[]; + raidsInfo: { + variationAvg: number; + variationSum: number; + } +} \ No newline at end of file diff --git a/src/app/core/models/herowars/raid.model.ts b/src/app/core/models/herowars/raid.model.ts new file mode 100644 index 0000000..47db532 --- /dev/null +++ b/src/app/core/models/herowars/raid.model.ts @@ -0,0 +1,38 @@ + +export interface HWGuildRaidAttacker { + id: number; + power: number; + type: string; +} +export interface HWGuildRaidStage { + num: number; + name: string; + maxPower: number; + duration: number; + startTime: number; + endTime: number; +} +export interface HWGuildRaid { + userId: string; + userName: string; + power: number; + variation: { + value: number; + percent: number; + color: string; + }; + tooltip: string; + startTime: string; + endTime: string; + damage: { + "1": number; + "2": number; + }; + level: string; + attackers: HWGuildRaidAttacker[]; + stage: HWGuildRaidStage; + +} +export interface HWGuildRaidAttackers { + [key: string]: HWGuildRaidAttacker; +} diff --git a/src/app/core/models/herowars/stat.model.ts b/src/app/core/models/herowars/stat.model.ts new file mode 100644 index 0000000..0edce2a --- /dev/null +++ b/src/app/core/models/herowars/stat.model.ts @@ -0,0 +1,42 @@ + +export interface HWGuildStat { + todayActivity: number; + activitySum: number; + dungeonActivitySum: number; + todayRaid: never[]; + todayItemsActivity: number; + todayDungeonActivity: number; + activityForRuneAvailable: boolean; + adventureStat: number; + clanWarStat: number; +} +export interface HWActivityStat { + activity: number; + prestige: number; + titanite: number; + war: number; + adventure: number; + gifts: number; + score: number; + scoreGifts: number; + warGifts: number; + rewards: number; +} +export interface HWWeekStat { + activity: number[]; + dungeonActivity: number[]; + adventureStat: number[]; + clanWarStat: number[]; + prestigeStat: number[]; + clanGifts: number[]; +} +export interface HWMemberStat { + activitySum: number; + todayActivity: number; + dungeonActivitySum: number; + todayDungeonActivity: number; + raidSum: number; + wasChampion: boolean; + todayPrestige: number; + prestigeSum: number; +} \ No newline at end of file diff --git a/src/app/core/models/index.ts b/src/app/core/models/index.ts index 88db527..f8b7a3a 100644 --- a/src/app/core/models/index.ts +++ b/src/app/core/models/index.ts @@ -13,7 +13,7 @@ export * from './category.model'; export * from './chart.model'; export * from './dropzone.model'; export * from './errors.model'; -export * from './hw.model'; +export * from './herowars/'; export * from './jump.model'; export * from './jump-list.model'; export * from './jump-list-config.model'; diff --git a/src/app/core/services/hwclan.service.ts b/src/app/core/services/hwclan.service.ts new file mode 100644 index 0000000..be47305 --- /dev/null +++ b/src/app/core/services/hwclan.service.ts @@ -0,0 +1,60 @@ +import { Injectable } from '@angular/core'; +import { HttpParams } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; + +import { ApiService } from './api.service'; +import { + HWClan, HWClanList, HWClanListConfig, HWClanListFilters, HWClanPageData +} from 'src/app/core/models'; + +@Injectable({ providedIn: 'root' }) +export class HWClanService { + constructor( + private apiService: ApiService + ) { } + + query(config: HWClanListConfig): Observable { + // Convert any filters over to Angular's URLSearchParams + const params: HWClanListFilters = {} as HWClanListFilters; + Object.assign(params, config.filters); + return this.apiService + .get( + '/clans', + new HttpParams({ fromObject: <{ + [param: string]: string | number | boolean | readonly (string | number | boolean)[]; + }>params }) + ); + } + + get(id: string): Observable { + return this.apiService.get(`/clans/${id}`); + } + + getAll(): Observable> { + return this.apiService.get('/clans').pipe(map(data => data.clans)); + } + + create(clan: HWClan): Observable { + return this.apiService.post('/clans/', { clan: clan }).pipe(map(data => data.clan)); + } + + update(clan: HWClan): Observable { + return this.apiService.put(`/clans/${clan.id}`, { clan: clan }).pipe(map(data => data.clan)); + } + + destroy(id: string): Observable { + return this.apiService.delete(`/clans/${id}`).pipe(map(data => data.deleted)); + } + + save(clan: HWClan): Observable { + // If we're updating an existing clan + if (clan.id) { + return this.apiService.put(`/clans/${clan.id}`, { clan: clan }).pipe(map(data => data.clan)); + // Otherwise, create a new clan + } else { + return this.apiService.post('/clans/', { clan: clan }).pipe(map(data => data.clan)); + } + } + +} diff --git a/src/app/core/services/hwmember.service.ts b/src/app/core/services/hwmember.service.ts new file mode 100644 index 0000000..be47305 --- /dev/null +++ b/src/app/core/services/hwmember.service.ts @@ -0,0 +1,60 @@ +import { Injectable } from '@angular/core'; +import { HttpParams } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; + +import { ApiService } from './api.service'; +import { + HWClan, HWClanList, HWClanListConfig, HWClanListFilters, HWClanPageData +} from 'src/app/core/models'; + +@Injectable({ providedIn: 'root' }) +export class HWClanService { + constructor( + private apiService: ApiService + ) { } + + query(config: HWClanListConfig): Observable { + // Convert any filters over to Angular's URLSearchParams + const params: HWClanListFilters = {} as HWClanListFilters; + Object.assign(params, config.filters); + return this.apiService + .get( + '/clans', + new HttpParams({ fromObject: <{ + [param: string]: string | number | boolean | readonly (string | number | boolean)[]; + }>params }) + ); + } + + get(id: string): Observable { + return this.apiService.get(`/clans/${id}`); + } + + getAll(): Observable> { + return this.apiService.get('/clans').pipe(map(data => data.clans)); + } + + create(clan: HWClan): Observable { + return this.apiService.post('/clans/', { clan: clan }).pipe(map(data => data.clan)); + } + + update(clan: HWClan): Observable { + return this.apiService.put(`/clans/${clan.id}`, { clan: clan }).pipe(map(data => data.clan)); + } + + destroy(id: string): Observable { + return this.apiService.delete(`/clans/${id}`).pipe(map(data => data.deleted)); + } + + save(clan: HWClan): Observable { + // If we're updating an existing clan + if (clan.id) { + return this.apiService.put(`/clans/${clan.id}`, { clan: clan }).pipe(map(data => data.clan)); + // Otherwise, create a new clan + } else { + return this.apiService.post('/clans/', { clan: clan }).pipe(map(data => data.clan)); + } + } + +} diff --git a/src/app/routes/auth.routes.ts b/src/app/routes/auth.routes.ts index f986d1a..6a074a6 100644 --- a/src/app/routes/auth.routes.ts +++ b/src/app/routes/auth.routes.ts @@ -2,7 +2,8 @@ import { Routes } from '@angular/router'; import { AeronefsComponent, CalculatorComponent, CanopiesComponent, CredentialsComponent, - DashboardComponent, DemoComponent, DropzonesComponent, HerowarsComponent, JumpComponent, JumpsComponent, + HerowarsComponent, HerowarsGuildraidComponent, HerowarsGuildwarComponent, + DashboardComponent, DemoComponent, DropzonesComponent, JumpComponent, JumpsComponent, LogbookComponent, PageComponent, PagesComponent, ProductComponent, ProductsComponent, ProfileComponent, QcmComponent, SettingsComponent } from 'src/app/components'; import { authGuard, adminGuard } from 'src/app/core/guards'; @@ -62,6 +63,16 @@ export const AUTH_ROUTES: Routes = [ component: HerowarsComponent, canActivate: [ authGuard ] }, + { + path: 'herowars/guildwar', + component: HerowarsGuildwarComponent, + canActivate: [ authGuard ] + }, + { + path: 'herowars/guildraid', + component: HerowarsGuildraidComponent, + canActivate: [ authGuard ] + }, { path: 'jumps', component: JumpsComponent, diff --git a/src/styles/_palettes.scss b/src/styles/_palettes.scss index fb1efdb..b35af69 100644 --- a/src/styles/_palettes.scss +++ b/src/styles/_palettes.scss @@ -580,6 +580,40 @@ $md-custom-pink: ( A700 : #000000, ) ); + +$md-custom-jinza: ( + 50 : #ffecef, + 100 : #ffd0d4, + 200 : #f3a09d, + 300 : #eb7a77, + 400 : #f65e54, + 500 : #fa5039, + 600 : #ed4739, + 700 : #da3d33, + 800 : #cd372c, + 900 : #be2c20, + A100 : #fdf1f1, + A200 : #fbe4e4, + A400 : #f7cac9, + A700 : #f1a19f, + contrast: ( + 50 : #000000, + 100 : #000000, + 200 : #000000, + 300 : #000000, + 400 : #000000, + 500 : #000000, + 600 : #000000, + 700 : #ffffff, + 800 : #ffffff, + 900 : #ffffff, + A100 : #000000, + A200 : #000000, + A400 : #000000, + A700 : #000000, + ) +); + $md-custom-red: ( 50: #ffebee, 100: #ffcdd2, diff --git a/src/styles/app.scss b/src/styles/app.scss index 8bd7c06..0287bb9 100755 --- a/src/styles/app.scss +++ b/src/styles/app.scss @@ -259,6 +259,9 @@ dl.dl-horizontal { .text-error { color: $error !important; } +.text-muted { + color: $muted !important; +} /**************************** * Extra Background Colors *