feat(herowars): migrate JSON static imports to HttpClient assets

Replace all TypeScript JSON imports with an HWDataService that loads
6 data files from /assets/files-data/ via HttpClient with shareReplay(1).
Update all 9 consumer components to subscribe asynchronously. Remove
unused qcm-bpa.json import and dead methods from QcmComponent.
Add ADR 0013 documenting the decision.
This commit is contained in:
2026-04-26 23:46:35 +02:00
parent 86c075db10
commit fa00719a3e
23 changed files with 89071 additions and 551 deletions
@@ -17,9 +17,6 @@ import { ClanViewModel, MembersViewModel } from '@viewmodels/herowars';
import { HWClanService, HWMemberService, UtilitiesService } from '@services';
import { MAX_CLAN_MEMBERS } from '@constants';
import guildData from '@data/hw-guild-data.json'; // page Membres
import guildStatistics from '@data/hw-guild-statistics.json'; // page Overview -> Statistics
@Component({
selector: 'app-herowars-guildwar',
imports: [
@@ -93,29 +90,35 @@ export class HerowarsGuildwarComponent implements OnInit {
}
loadClan(): void {
this._guildClan = this._clanService.loadClan();
this.clanViewModel = new ClanViewModel(this._guildClan);
this.clanLoaded = true;
this._clanService.loadClan().subscribe((clan) => {
this._guildClan = clan;
this.clanViewModel = new ClanViewModel(this._guildClan);
this.clanLoaded = true;
});
}
loadData(): void {
this._guildClan = this._clanService.loadClan();
this._guildMembers = this._memberService.loadMembers(this._guildClan);
this._guildClan = this._clanService.loadClanStats(this._guildClan, this._guildMembers);
this.daysToWarn = parseInt(this._guildClan.daysToKick) / 2;
this.clanViewModel = new ClanViewModel(this._guildClan);
this.clanLoaded = true;
this.membersViewModel = new MembersViewModel(this._guildMembers);
this.membersLoaded = true;
console.log(this._guildClan);
console.log(this._guildMembers);
this._clanService.loadClan().subscribe((clan) => {
this._guildClan = clan;
this._memberService.loadMembers(this._guildClan).subscribe((members) => {
this._guildMembers = members;
this._guildClan = this._clanService.loadClanStats(this._guildClan, this._guildMembers);
this.daysToWarn = parseInt(this._guildClan.daysToKick) / 2;
this.clanViewModel = new ClanViewModel(this._guildClan);
this.clanLoaded = true;
this.membersViewModel = new MembersViewModel(this._guildMembers);
this.membersLoaded = true;
});
});
}
loadMembers(): void {
this._guildMembers = this._memberService.loadMembers(this._guildClan);
this.membersViewModel = new MembersViewModel(this._guildMembers);
this._guildClan = this._clanService.loadClanStats(this._guildClan, this._guildMembers);
this.membersLoaded = true;
this._memberService.loadMembers(this._guildClan).subscribe((members) => {
this._guildMembers = members;
this.membersViewModel = new MembersViewModel(this._guildMembers);
this._guildClan = this._clanService.loadClanStats(this._guildClan, this._guildMembers);
this.membersLoaded = true;
});
}
getMembers(): HWMember[] {
@@ -124,11 +127,9 @@ export class HerowarsGuildwarComponent implements OnInit {
syncClan(): void {
console.log(this._guildClan);
console.log(guildData);
}
syncMembers(): void {
console.log(this._guildMembers);
console.log(guildStatistics);
}
}
@@ -1,29 +1,32 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideAnimations } from '@angular/platform-browser/animations';
import { provideNativeDateAdapter } from '@angular/material/core';
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { HerowarsComponent } from './herowars.component';
describe('HerowarsComponent', () => {
let component: HerowarsComponent;
let fixture: ComponentFixture<HerowarsComponent>;
let component: HerowarsComponent;
let fixture: ComponentFixture<HerowarsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HerowarsComponent],
providers: [
provideAnimations(),
provideNativeDateAdapter(),
],
})
.compileComponents();
fixture = TestBed.createComponent(HerowarsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HerowarsComponent],
providers: [
provideAnimations(),
provideNativeDateAdapter(),
provideHttpClient(),
provideHttpClientTesting(),
],
}).compileComponents();
it('should create', () => {
expect(component).toBeTruthy();
});
fixture = TestBed.createComponent(HerowarsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -18,10 +18,7 @@ import {
MembersStatisticsComponent,
} from '@components/shared';
import { Errors, HWMember } from '@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
import { HWDataService } from '@services';
@Component({
selector: 'app-herowars',
@@ -51,6 +48,7 @@ import guildData from 'src/files-data/hw-guild-data.json'; // page Membres
})
export class HerowarsComponent implements OnInit {
private _titleService = inject(Title);
private _dataService = inject(HWDataService);
public title = 'HeroWars GM Tools';
public description = 'Tools in working progress.';
@@ -60,23 +58,20 @@ export class HerowarsComponent implements OnInit {
private _guildMembers: HWMember[] = [];
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;
this._titleService.setTitle(this.title);
this._dataService.guildData$.subscribe({
next: (guildData) => {
for (const data of Object.entries(guildData.clan.members)) {
const member: HWMember = {} as HWMember;
Object.assign(member, data[1]);
member.champion = guildData.clan.warriors.indexOf(parseInt(member.id)) !== -1;
member.heroes = { power: 0, teams: [] };
member.titans = { power: 0, teams: [] };
this._guildMembers.push(member);
}
member.heroes = { power: 0, teams: [] };
member.titans = { power: 0, teams: [] };
this._guildMembers.push(member);
}
} catch (error) {
console.error(error);
}
},
error: (err) => console.error(err),
});
}
getMembers(): HWMember[] {
-50
View File
@@ -18,7 +18,6 @@ import { MenuItems } from '@components/shared';
import { ListErrorsComponent } from '@components/shared';
import { Errors, Qcm, QcmCategory, QcmQuestion, QcmQuestionState, User } from '@models';
import { QcmService, UserService } from '@services';
import data from 'src/qcm-bpa.json';
@Component({
selector: 'app-qcm',
@@ -174,55 +173,6 @@ export class QcmComponent implements OnInit, OnDestroy {
console.log('onSubmit');
}
private _importChoices() {
try {
data.categories.forEach((category) => {
category.questions.forEach((question) => {
this._qcmService
.saveChoices(question)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({
next: (question) => {
console.log('question : ', question);
//console.log(`Le saut n°${jump.numero} a été ajouté !`, 'OK');
},
error: (err) => {
console.log('err : ', err);
//console.log(`Le saut n'a pas été ajouté !`, 'Error', err);
this.errors = err;
},
});
});
});
} catch (error) {
console.error(error);
}
}
private _importQuestions() {
try {
data.categories.forEach((category) => {
//Object.assign(this.jump, category);
this._qcmService
.saveQuestions(category)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({
next: (category) => {
console.log('category : ', category);
//console.log(`Le saut n°${jump.numero} a été ajouté !`, 'OK');
},
error: (err) => {
console.log('err : ', err);
//console.log(`Le saut n'a pas été ajouté !`, 'Error', err);
this.errors = err;
},
});
});
} catch (error) {
console.error(error);
}
}
private _resetErrors(): void {
this.errors = { errors: {} };
}
@@ -1,23 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { GuildCardComponent } from './guild-card.component';
describe('GuildCardComponent', () => {
let component: GuildCardComponent;
let fixture: ComponentFixture<GuildCardComponent>;
let component: GuildCardComponent;
let fixture: ComponentFixture<GuildCardComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [GuildCardComponent]
})
.compileComponents();
fixture = TestBed.createComponent(GuildCardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [GuildCardComponent],
providers: [provideHttpClient(), provideHttpClientTesting()],
}).compileComponents();
it('should create', () => {
expect(component).toBeTruthy();
});
fixture = TestBed.createComponent(GuildCardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,12 +1,11 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } 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 '@models';
import guildData from 'src/files-data/hw-guild-data.json'; // page Membres
import { HWDataService } from '@services';
@Component({
selector: 'app-guild-card',
@@ -15,18 +14,34 @@ import guildData from 'src/files-data/hw-guild-data.json'; // page Membres
styleUrl: './guild-card.component.scss',
})
export class GuildCardComponent implements OnInit {
public guildData: HWGuildData = {} as HWGuildData;
private _dataService = inject(HWDataService);
public guildData: HWGuildData = {
clan: { warriors: [] as number[] } as unknown as HWGuildClan,
stat: {} as HWGuildStat,
slots: {},
membersStat: [],
serverResetTime: 0,
clanWarEndSeasonTime: 0,
freeClanChangeInterval: { start: 0, end: 0 },
giftUids: [],
};
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;
this._dataService.guildData$.subscribe({
next: (data) => {
Object.assign(this._guildClan, data.clan);
this.guildData.clan = this._guildClan;
Object.assign(this._guildStat, data.stat);
this.guildData.stat = this._guildStat;
this.guildData.serverResetTime = data.serverResetTime;
this.guildData.clanWarEndSeasonTime = data.clanWarEndSeasonTime;
this.guildData.freeClanChangeInterval = data.freeClanChangeInterval;
this.guildData.giftUids = data.giftUids;
},
error: (err) => console.error(err),
});
}
}
@@ -13,8 +13,7 @@ import { MatStepperIntl, MatStepperModule } from '@angular/material/stepper';
import { MatTooltipModule } from '@angular/material/tooltip';
import { HWGuildRaid, HWGuildRaidAttacker, HWGuildRaidAttackers, HWGuildRaidStage, HWMember } from '@models';
import guildRaids from 'src/files-data/hw-guild-raids.json'; // page Asgard -> Guild Raid -> Log
import { HWDataService } from '@services';
@Injectable()
export class StepperIntl extends MatStepperIntl {
@@ -49,6 +48,7 @@ export class StepperIntl extends MatStepperIntl {
})
export class GuildraidsLogComponent implements OnInit {
private fb = inject(FormBuilder);
private _dataService = inject(HWDataService);
public now: Date;
public raidsForm: FormGroup;
@@ -107,100 +107,82 @@ export class GuildraidsLogComponent implements OnInit {
ngOnInit() {
this.guildMembers.map((data) => {
data.raids = [];
data.raidsInfo = {
variationAvg: 0,
variationSum: 0,
};
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';
this._dataService.guildRaids$.subscribe({
next: (guildRaids) => {
for (const member of Object.entries(guildRaids)) {
const index = this.guildMembers.findIndex((item) => item.id === member[0]);
const memberRaids: HWGuildRaid[] = [];
if (index !== -1) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
for (const data of Object.entries(member[1] as Record<string, any>)) {
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);
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, percent, color };
raid.tooltip = Math.floor(raid.variation.value / 1000) + 'k';
memberRaids.push(raid);
this._guildRaids.push(raid);
}
value = raid.power - raid.stage.maxPower;
this.guildMembers[index].raids = memberRaids;
const varSum = memberRaids.reduce((acc, cur) => acc + cur.variation.percent, 0);
this.guildMembers[index].raidsInfo = {
variationAvg: varSum / memberRaids.length,
variationSum: varSum,
};
}
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;
});*/
this._guildRaids.sort((a, b) => (a.startTime < b.startTime ? -1 : 1));
this.guildMembers.sort((a, b) => (a.raidsInfo.variationAvg > b.raidsInfo.variationAvg ? -1 : 1));
},
error: (err) => console.error(err),
});
}
public getMembers(): HWMember[] {
@@ -1,23 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { GuildwarAttackComponent } from './guildwar-attack.component';
describe('GuildwarAttackComponent', () => {
let component: GuildwarAttackComponent;
let fixture: ComponentFixture<GuildwarAttackComponent>;
let component: GuildwarAttackComponent;
let fixture: ComponentFixture<GuildwarAttackComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [GuildwarAttackComponent]
})
.compileComponents();
fixture = TestBed.createComponent(GuildwarAttackComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [GuildwarAttackComponent],
providers: [provideHttpClient(), provideHttpClientTesting()],
}).compileComponents();
it('should create', () => {
expect(component).toBeTruthy();
});
fixture = TestBed.createComponent(GuildwarAttackComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, inject } from '@angular/core';
import { DatePipe, DecimalPipe } from '@angular/common';
import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider';
@@ -14,12 +14,8 @@ import {
HWGuildWarSlots,
HWMember,
} from '@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
import { HWDataService } from '@services';
import { combineLatest } from 'rxjs';
@Component({
selector: 'app-guildwar-attack',
@@ -28,8 +24,10 @@ import guildWarSlots from 'src/files-data/hw-guild-war-slots.json'; // no pages
styleUrl: './guildwar-attack.component.scss',
})
export class GuildwarAttackComponent implements OnInit {
private _dataService = inject(HWDataService);
private _championsByPower: HWMember[] = [];
private _enemySlots: number[] = [];
private _slots: HWGuildWarSlots = {};
public guildEnemies: HWMember[] = [];
public guildMembers: HWMember[] = [];
public title = 'Fortifications';
@@ -49,18 +47,29 @@ export class GuildwarAttackComponent implements OnInit {
}
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();
combineLatest([
this._dataService.guildWarData$,
this._dataService.guildWarInfo$,
this._dataService.guildWarSlots$,
]).subscribe({
next: ([guildWarData, guildWarInfo, guildWarSlotsData]) => {
this._slots = guildWarSlotsData.slots;
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(guildWarData);
this._setEnemies(guildWarInfo);
},
error: (err) => console.error(err),
});
}
private _getFortification(indexes: number[], type: string, name: string): HWGuildWarFortification {
const teams: HWMember[] = [];
const slots: HWGuildWarSlots = guildWarSlots.slots;
const slots: HWGuildWarSlots = this._slots;
if (!slots[name]) return { name, type, count: 0, teams: [], positions: this._enemySlots, slots: [] };
let count = 0;
indexes.forEach((data) => {
switch (type) {
@@ -88,7 +97,8 @@ export class GuildwarAttackComponent implements OnInit {
private _getDefense(type: string, name: string): HWGuildWarFortification {
const teams: HWMember[] = [];
const slots: HWGuildWarSlots = guildWarSlots.slots;
const slots: HWGuildWarSlots = this._slots;
if (!slots[name]) return { name, type, count: 0, teams: [], positions: this._enemySlots, slots: [] };
let count = 0;
slots[name].forEach((slot) => {
let enemies: HWMember[] = [];
@@ -120,12 +130,15 @@ export class GuildwarAttackComponent implements OnInit {
};
}
private _setEnemies(): void {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _setEnemies(guildWarInfo: any): void {
const warriors: number[] = [];
for (const data of Object.entries(guildWarInfo.enemyClanTries)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
for (const data of Object.entries(guildWarInfo.enemyClanTries as Record<string, any>)) {
warriors.push(parseInt(data[0]));
}
for (const data of Object.entries(guildWarInfo.enemyClanMembers)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
for (const data of Object.entries(guildWarInfo.enemyClanMembers as Record<string, any>)) {
const enemy: HWMember = {} as HWMember;
Object.assign(enemy, data[1]);
if (warriors.indexOf(parseInt(enemy.id)) !== -1) {
@@ -141,16 +154,17 @@ export class GuildwarAttackComponent implements OnInit {
this.guildEnemies.push(enemy);
}
for (const data of Object.entries(guildWarInfo.enemySlots)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
for (const data of Object.entries(guildWarInfo.enemySlots as Record<string, any>)) {
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])) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
for (const team of Object.entries(data[1].team[0] as Record<string, any>)) {
/*
ennemySlot.teams.push(enemyTeam);
console.log(enemyTeam);
@@ -194,8 +208,10 @@ export class GuildwarAttackComponent implements OnInit {
}
}
private _setChampionsByPower(): void {
for (const [teamId, teamValues] of Object.entries(guildWarData.teams)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _setChampionsByPower(guildWarData: any): void {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
for (const [teamId, teamValues] of Object.entries(guildWarData.teams as Record<string, any>)) {
const index = this.guildMembers.findIndex((member) => member.id === teamId);
if (index === -1) continue;
let totalHeroPower = 0;
@@ -203,11 +219,15 @@ export class GuildwarAttackComponent implements OnInit {
const heroes: HWGuildWarHeroTeam[] = [];
const titans: HWGuildWarTitanTeam[] = [];
for (const unit of Object.entries(teamValues.clanDefence_heroes.units)) {
for (const unit of Object.entries(
teamValues.clanDefence_heroes.units as Record<string, HWGuildWarHeroTeam>,
)) {
heroes.push(unit[1]);
totalHeroPower += unit[1].power;
}
for (const unit of Object.entries(teamValues.clanDefence_titans.units)) {
for (const unit of Object.entries(
teamValues.clanDefence_titans.units as Record<string, HWGuildWarTitanTeam>,
)) {
titans.push(unit[1]);
totalTitanPower += unit[1].power;
}
@@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, inject } from '@angular/core';
//import { DecimalPipe } from '@angular/common';
import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider';
@@ -7,10 +7,8 @@ import { MatIconModule } from '@angular/material/icon';
import { FortificationCardContentComponent } from '../fortification-card-content/fortification-card-content.component';
//import { HWMember } from '@models';
import { HWGuildWarFortification, HWGuildWarHeroTeam, HWGuildWarSlots, HWGuildWarTitanTeam, HWMember } from '@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
import { HWDataService } from '@services';
import { combineLatest } from 'rxjs';
@Component({
selector: 'app-guildwar-defence',
@@ -19,8 +17,10 @@ import guildWarSlots from 'src/files-data/hw-guild-war-slots.json'; // no pages
styleUrl: './guildwar-defence.component.scss',
})
export class GuildwarDefenceComponent implements OnInit {
private _dataService = inject(HWDataService);
private _championsByPower: HWMember[] = [];
private _championSlots: number[] = [];
private _slots: HWGuildWarSlots = {};
public guildMembers: HWMember[] = [];
public teamType: string = '';
public title = 'Fortifications';
@@ -35,48 +35,58 @@ export class GuildwarDefenceComponent implements OnInit {
}
ngOnInit() {
for (const [teamId, teamValues] of Object.entries(guildWarData.teams)) {
const index = this.guildMembers.findIndex((member) => member.id === teamId);
if (index === -1) continue;
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);
combineLatest([this._dataService.guildWarData$, this._dataService.guildWarSlots$]).subscribe({
next: ([guildWarData, guildWarSlotsData]) => {
this._slots = guildWarSlotsData.slots;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
for (const [teamId, teamValues] of Object.entries(guildWarData.teams as Record<string, any>)) {
const index = this.guildMembers.findIndex((member) => member.id === teamId);
if (index === -1) continue;
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 as Record<string, HWGuildWarHeroTeam>,
)) {
heroes.push(unit[1]);
totalHeroPower += unit[1].power;
}
for (const unit of Object.entries(
teamValues.clanDefence_titans.units as Record<string, HWGuildWarTitanTeam>,
)) {
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 as Record<string, number>)) {
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));
break;
case 'titans':
this.title = 'Titans Fortifications';
this.guildMembers.sort((a, b) => (a.titans.power > b.titans.power ? -1 : 1));
break;
default:
break;
}
this._championsByPower = this.guildMembers.filter((member) => member.champion === true);
},
error: (err) => console.error(err),
});
}
private _getFortification(indexes: number[], type: string, name: string): HWGuildWarFortification {
const teams: HWMember[] = [];
const slots: HWGuildWarSlots = guildWarSlots.slots;
const slots: HWGuildWarSlots = this._slots;
let count = 0;
indexes.forEach((data) => {
const member = this._championsByPower[data];
@@ -1,12 +1,11 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, inject } 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 '@models';
import guildWarData from 'src/files-data/hw-guild-war.json'; // page Overview -> Statistics | page Guild War -> Guild War
import { HWDataService } from '@services';
@Component({
selector: 'app-guildwar-teams',
@@ -15,6 +14,7 @@ import guildWarData from 'src/files-data/hw-guild-war.json'; // page Overview ->
styleUrl: './guildwar-teams.component.scss',
})
export class GuildwarTeamsComponent implements OnInit {
private _dataService = inject(HWDataService);
private _championsByPower: HWMember[] = [];
public guildMembers: HWMember[] = [];
public title = 'Members';
@@ -32,42 +32,45 @@ export class GuildwarTeamsComponent implements OnInit {
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);
if (index === -1) continue;
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);
this._dataService.guildWarData$.subscribe({
next: (guildWarData) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
for (const [teamId, teamValues] of Object.entries(guildWarData.teams as Record<string, any>)) {
const index = this._championsByPower.findIndex((member) => member.id === teamId);
if (index === -1) continue;
let totalHeroPower = 0;
let totalTitanPower = 0;
const heroes: HWGuildWarHeroTeam[] = [];
const titans: HWGuildWarTitanTeam[] = [];
for (const unit of Object.entries(
teamValues.clanDefence_heroes.units as Record<string, HWGuildWarHeroTeam>,
)) {
heroes.push(unit[1]);
totalHeroPower += unit[1].power;
}
for (const unit of Object.entries(
teamValues.clanDefence_titans.units as Record<string, HWGuildWarTitanTeam>,
)) {
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);
},
error: (err) => console.error(err),
});
}
getChampionsByPower(): HWMember[] {
@@ -1,14 +1,12 @@
import { Component, Input, OnInit, inject } from '@angular/core';
import { combineLatest } from 'rxjs';
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 '@models/herowars';
import { UtilitiesService } from '@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
import { HWDataService, UtilitiesService } from '@services';
@Component({
selector: 'app-members-statistics',
@@ -18,6 +16,7 @@ import guildStatistics from 'src/files-data/hw-guild-statistics.json'; // page O
})
export class MembersStatisticsComponent implements OnInit {
private _utilitiesService = inject(UtilitiesService);
private _dataService = inject(HWDataService);
public guildMembers: HWMember[] = [];
public title = 'Members';
@@ -85,114 +84,105 @@ export class MembersStatisticsComponent implements OnInit {
}
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;
combineLatest([this._dataService.guildData$, this._dataService.guildStatistics$]).subscribe({
next: ([guildData, guildStatistics]) => {
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,
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(
(acc: number, cur: number) => acc + cur,
0,
);
this._membersByName[index].clanGiftsSum = item[1].clanGifts.reduce(
(acc: number, cur: number) => acc + cur,
0,
);
this._membersByName[index].clanWarSum = item[1].clanWarStat.reduce(
(acc: number, cur: number) => acc + cur,
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;
}
}
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;
} else {
continue;
}
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;
for (const data of Object.entries(guildData.membersStat)) {
const stat: HWMemberStat = {} as HWMemberStat;
Object.assign(stat, data[1]);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const index = this._membersByName.findIndex((member) => member.id === (data[1] as any).userId);
if (index === -1) continue;
this._membersByName[index].stat = stat;
this._membersByName[index].score = stat.dungeonActivitySum + stat.activitySum + 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 += stat.todayDungeonActivity + stat.todayActivity + 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.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;
},
error: (err) => console.error(err),
});
this.guildSumAverages.rewards = this.guildSumTotal.rewards / this._membersByName.length;
}
getMembersByName(): HWMember[] {
@@ -14,12 +14,12 @@ import {
HWGuildClan,
HWMember,
} from '@models';
import guildData from 'src/files-data/hw-guild-data.json'; // page Membres
import { HWDataService } from './hw-data.service';
@Injectable({ providedIn: 'root' })
export class HWClanService {
private apiService = inject(ApiService);
private _dataService = inject(HWDataService);
private _apiDomain = '/herowars';
@@ -87,15 +87,18 @@ export class HWClanService {
}
}
loadClan(): HWGuildClan {
const guildClan: HWGuildClan = {} as HWGuildClan;
Object.assign(guildClan, guildData.clan);
guildClan.sumAverages = this._resetActivity();
guildClan.sumTotal = this._resetActivity();
guildClan.todayAverages = this._resetActivity();
guildClan.todayTotal = this._resetActivity();
return guildClan;
loadClan(): Observable<HWGuildClan> {
return this._dataService.guildData$.pipe(
map((guildData) => {
const guildClan: HWGuildClan = {} as HWGuildClan;
Object.assign(guildClan, guildData.clan);
guildClan.sumAverages = this._resetActivity();
guildClan.sumTotal = this._resetActivity();
guildClan.todayAverages = this._resetActivity();
guildClan.todayTotal = this._resetActivity();
return guildClan;
}),
);
}
loadClanStats(clan: HWGuildClan, members: HWMember[]): HWGuildClan {
@@ -0,0 +1,44 @@
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { shareReplay } from 'rxjs/operators';
import { HWGuildData, HWGuildWarSlots, HWWeekStat } from '@models';
export interface HWGuildStatistics {
stat: (HWWeekStat & { id: string })[];
}
@Injectable({ providedIn: 'root' })
export class HWDataService {
private _http = inject(HttpClient);
readonly guildData$: Observable<HWGuildData> = this._http
.get<HWGuildData>('/assets/files-data/hw-guild-data.json')
.pipe(shareReplay(1));
readonly guildStatistics$: Observable<HWGuildStatistics> = this._http
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.get<HWGuildStatistics>('/assets/files-data/hw-guild-statistics.json')
.pipe(shareReplay(1));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
readonly guildRaids$: Observable<Record<string, Record<string, any>>> = this._http
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.get<Record<string, Record<string, any>>>('/assets/files-data/hw-guild-raids.json')
.pipe(shareReplay(1));
/* eslint-disable @typescript-eslint/no-explicit-any */
readonly guildWarData$: Observable<any> = this._http
.get<any>('/assets/files-data/hw-guild-war.json')
.pipe(shareReplay(1));
readonly guildWarInfo$: Observable<any> = this._http
.get<any>('/assets/files-data/hw-guild-war-info.json')
.pipe(shareReplay(1));
/* eslint-enable @typescript-eslint/no-explicit-any */
readonly guildWarSlots$: Observable<{ slots: HWGuildWarSlots }> = this._http
.get<{ slots: HWGuildWarSlots }>('/assets/files-data/hw-guild-war-slots.json')
.pipe(shareReplay(1));
}
@@ -1,6 +1,6 @@
import { Injectable, inject } from '@angular/core';
import { HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { combineLatest, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiService, UtilitiesService } from '@services';
@@ -14,13 +14,12 @@ import {
HWMemberPageData,
HWMemberStat,
} from '@models';
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
import { HWDataService } from './hw-data.service';
@Injectable({ providedIn: 'root' })
export class HWMemberService {
private _apiService = inject(ApiService);
private _utilitiesService = inject(UtilitiesService);
private _dataService = inject(HWDataService);
private _apiDomain = '/herowars';
@@ -76,83 +75,79 @@ export class HWMemberService {
}
}
loadMembers(clan: HWGuildClan): HWMember[] {
const guildMembers: HWMember[] = [];
const now = new Date();
const oneDayInSec = 24 * 60 * 60;
const daysToKick = parseInt(guildData.clan.daysToKick);
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: [] };
guildMembers.push(member);
}
guildMembers.map((data: HWMember) => {
const last = new Date(parseInt(data.lastLoginTime) * 1000);
const exp = new Date(last.getTime() + daysToKick * oneDayInSec * 1000);
const diff = Math.floor((exp.getTime() - 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) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
const { userId, ...memberStatWithoutUserId } = guildData.membersStat[index] as any;
Object.assign(data.stat, memberStatWithoutUserId);
}
index = guildStatistics.stat.findIndex((stat) => stat.id === data.id);
if (index !== -1) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
const { id, ...weekStatSource } = guildStatistics.stat[index] as any;
const stat: HWWeekStat = {} as HWWeekStat;
Object.assign(stat, weekStatSource);
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,
);
} else {
data.weekStat = {} as HWWeekStat;
data.adventureSum = 0;
data.clanGiftsSum = 0;
data.clanWarSum = 0;
}
data.score = data.stat.dungeonActivitySum + data.stat.activitySum + data.stat.prestigeSum;
data.warGifts = ((clan.giftsCount / 2) * ((data.clanWarSum * 10) / 100)) / 20;
data.scoreGifts = 0;
data.rewards = 0;
return data;
});
return guildMembers;
loadMembers(clan: HWGuildClan): Observable<HWMember[]> {
return combineLatest([this._dataService.guildData$, this._dataService.guildStatistics$]).pipe(
map(([guildData, guildStatistics]) => {
const guildMembers: HWMember[] = [];
const now = new Date();
const oneDayInSec = 24 * 60 * 60;
const daysToKick = parseInt(guildData.clan.daysToKick);
for (const data of Object.entries(guildData.clan.members)) {
const member: HWMember = {} as HWMember;
Object.assign(member, data[1]);
member.champion = guildData.clan.warriors.indexOf(parseInt(member.id)) !== -1;
member.heroes = { power: 0, teams: [] };
member.titans = { power: 0, teams: [] };
guildMembers.push(member);
}
guildMembers.map((data: HWMember) => {
const last = new Date(parseInt(data.lastLoginTime) * 1000);
const exp = new Date(last.getTime() + daysToKick * oneDayInSec * 1000);
const diff = Math.floor((exp.getTime() - 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;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let index = guildData.membersStat.findIndex((stat) => (stat as any).userId === data.id);
if (index !== -1) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
const { userId, ...memberStatWithoutUserId } = guildData.membersStat[index] as any;
Object.assign(data.stat, memberStatWithoutUserId);
}
index = guildStatistics.stat.findIndex((stat) => stat.id === data.id);
if (index !== -1) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
const { id, ...weekStatSource } = guildStatistics.stat[index] as any;
const stat: HWWeekStat = {} as HWWeekStat;
Object.assign(stat, weekStatSource);
data.weekStat = stat;
data.adventureSum = guildStatistics.stat[index].adventureStat.reduce(
(acc: number, cur: number) => acc + cur,
0,
);
data.clanGiftsSum = guildStatistics.stat[index].clanGifts.reduce(
(acc: number, cur: number) => acc + cur,
0,
);
data.clanWarSum = guildStatistics.stat[index].clanWarStat.reduce(
(acc: number, cur: number) => acc + cur,
0,
);
} else {
data.weekStat = {} as HWWeekStat;
data.adventureSum = 0;
data.clanGiftsSum = 0;
data.clanWarSum = 0;
}
data.score = data.stat.dungeonActivitySum + data.stat.activitySum + data.stat.prestigeSum;
data.warGifts = ((clan.giftsCount / 2) * ((data.clanWarSum * 10) / 100)) / 20;
data.scoreGifts = 0;
data.rewards = 0;
return data;
});
return guildMembers;
}),
);
}
}
+2 -2
View File
@@ -1,3 +1,3 @@
export * from './hw-clan.service';
export * from './hw-member.service';
export * from './hw-data.service';
export * from './hw-member.service';