Browse Source

- Updates to work with the new strucutre

pull/1/head
Dan 1 year ago
parent
commit
81c8488a37
  1. 41
      src/app/core/models/plan.model.ts
  2. 10
      src/app/core/services/plan.service.ts
  3. 58
      src/app/core/services/pokemon.service.ts
  4. 8
      src/app/features/plan/plan-game/plan-game.component.ts
  5. 137
      src/app/features/plan/plan-pokemon/plan-pokemon.component.ts
  6. 4
      src/app/features/plan/plan.component.ts

41
src/app/core/models/plan.model.ts

@ -1,29 +1,14 @@
export interface GamePlan {
game_name: string;
game_id: number;
pokemon: PlanPokemon[];
}
export interface PlanPokemon {
pfic: string;
name: string;
form_name?: string;
catch_count: number;
evolve_to: EvolutionTarget[];
breed_for: BreedingTarget[];
}
export interface EvolutionTarget {
pfic: string;
name: string;
form_name?: string;
method: string;
count: number;
}
export interface BreedingTarget {
pfic: string;
name: string;
form_name?: string;
count: number;
}
game_name: string;
pokemon: Record<string, PokemonFamilyEntry>;
}
export interface PokemonFamilyEntry {
representative: string;
catch_count: number;
evolve_to: string[];
breed_for: string[];
Any?: number;
Male?: number;
Female?: number;
}

10
src/app/core/services/plan.service.ts

@ -30,8 +30,10 @@ export class PlanService {
}
private recalculateAffectedGames(pfic: string) {
return
// This would need to check all games for the affected Pokemon
// and update their totals accordingly
/*
this.getPlan().pipe(take(1)).subscribe(games => {
games.forEach(game => {
const affectedPokemon = game.pokemon.find(p =>
@ -47,10 +49,16 @@ export class PlanService {
}
});
});
*/
}
private calculateGameTotal(game: GamePlan): number {
return game.pokemon.reduce((total, pokemon) => total + pokemon.catch_count, 0);
var sum = 0;
for(const family in game.pokemon)
{
sum += game.pokemon[family].catch_count;
}
return sum
}
}

58
src/app/core/services/pokemon.service.ts

@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { concatMap, map, Observable, pipe, shareReplay, tap } from 'rxjs';
import { catchError, concatMap, map, Observable, pipe, shareReplay, tap } from 'rxjs';
import { Pokemon, PokemonEncounter } from '../models/pokemon.model';
import { environment } from '../../../environments/environment.development';
import { comparePfics } from '../utils/pfic-utils';
@ -165,9 +165,56 @@ export class PokemonService {
return this.caughtPokemon.has(pfic);
}
getPokemonFromPFIC(pfic:string): Pokemon {
return this.pokemonFormMap.get(pfic) as Pokemon
getPokemonFromPFIC(pfic: string): Observable<Pokemon | null> {
// Check the cache for the PFIC
const cachedPokemon = this.pokemonFormMap.get(pfic);
if (cachedPokemon) {
// Return the cached Pokémon as an Observable
return new Observable((observer) => {
observer.next(cachedPokemon);
observer.complete();
});
}
// If not in cache, fetch from the server
return this.http.get<any>(`${this.apiUrl}/pokemon/${pfic}/details`).pipe(
map(data => {
const pkmn = {
PFIC: data.pfic,
Name: data.data.name,
Form: data.data.form_name,
NationalDex: data.data.national_dex,
Generation: data.data.generation,
StorableInHome: data.data.storable_in_home,
IsBabyForm: data.data.is_baby_form,
Encounters: data.data.encounters || [],
MarkIcon: "",
MarkName: data.data.mark,
Image: "",
IsDefault: data.data.is_default || false,
IsGenderRelevant: data.data.gender_relevant,
IsCaught: this.caughtPokemon.has(data.pfic)
} as Pokemon;
pkmn.MarkIcon = this.getMarkImgName(pkmn.MarkName)
pkmn.Image = this.getPokemonImageUrl(pkmn)
return pkmn;
}),
tap((pokemon) => {
// Cache the result for future requests
this.pokemonFormMap.set(pfic, pokemon);
}),
map((pokemon) => pokemon), // Map the server response directly to the output
shareReplay(1), // Cache the HTTP result for future subscribers
catchError((error): Observable<Pokemon | null> => {
console.error(`Error fetching Pokémon with PFIC ${pfic}:`, error);
return new Observable((observer) => {
observer.next(null);
observer.complete();
});
})
);
}
updateCaughtStatus(pfic: string, caught: boolean) {
if (caught) {
@ -177,7 +224,10 @@ export class PokemonService {
}
}
getPokemonImageUrl(data: Pokemon): string {
getPokemonImageUrl(data: Pokemon | null): string {
if (data === null) {
return "";
}
if (data.IsGenderRelevant) {
return `/assets/images/pokemon/${data.PFIC}.png`;
}

8
src/app/features/plan/plan-game/plan-game.component.ts

@ -73,7 +73,13 @@ export class PlanGameComponent {
@Output() gameSelect = new EventEmitter<GamePlan>();
getTotalCatchCount(): number {
return this.game.pokemon.reduce((sum, pokemon) => sum + pokemon.catch_count, 0);
var sum = 0;
for(const family in this.game.pokemon)
{
sum += this.game.pokemon[family].catch_count;
}
return sum
//return this.game.pokemon.values().reduce((sum, pokemon) => sum + pokemon.catch_count, 0);
}
getGameBoxArt(): string {

137
src/app/features/plan/plan-pokemon/plan-pokemon.component.ts

@ -1,12 +1,13 @@
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { Component, Input, Output, EventEmitter, ChangeDetectorRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatIconModule } from '@angular/material/icon';
import { MatChipsModule } from '@angular/material/chips';
import { MatTooltipModule } from '@angular/material/tooltip';
import { PlanPokemon } from '../../../core/models/plan.model';
import { PokemonFamilyEntry } from '../../../core/models/plan.model';
import { LazyImgDirective } from '../../../shared/directives/lazy-img.directive';
import { PokemonService } from '../../../core/services/pokemon.service';
import { Pokemon } from '../../../core/models/pokemon.model';
// Define an interface for the status update event
interface PokemonStatusEvent {
@ -35,58 +36,58 @@ interface PokemonStatusEvent {
<div class="pokemon-header">
<img
lazyImg
[src]="pokemonService.getPokemonImageUrl(pokemonService.getPokemonFromPFIC(pokemon.pfic))"
[alt]="pokemon.name"
[src]="pokemonService.getPokemonImageUrl(this.representative_pokemon)"
[alt]="this.representative_pokemon?.Name"
class="pokemon-thumbnail"
[class.grayscale]="pokemon.catch_count === 0"
[class.grayscale]="pokemon_family.catch_count === 0"
>
<div class="pokemon-info">
<div class="pokemon-name">
{{ pokemon.name }}
<span *ngIf="pokemon.form_name" class="form-name">
({{ pokemon.form_name }})
{{ this.representative_pokemon?.Name }}
<span *ngIf="this.representative_pokemon?.Form" class="form-name">
({{ this.representative_pokemon?.Form }})
</span>
</div>
<div class="catch-info">
<img
src="/assets/images/pokeball_color.png"
[class.grayscale]="pokemon.catch_count === 0"
[class.grayscale]="pokemon_family.catch_count === 0"
class="pokeball-icon"
[matTooltip]="'Need: ' + pokemon.catch_count"
[matTooltip]="'Need: ' + pokemon_family.catch_count"
>
<span class="catch-count">{{ pokemon.catch_count }}</span>
<span class="catch-count">{{ pokemon_family.catch_count }}</span>
</div>
</div>
</div>
</mat-expansion-panel-header>
<div class="targets-grid" *ngIf="hasTargets">
<ng-container *ngIf="pokemon.evolve_to.length > 0">
<ng-container *ngIf="evolve_to.length > 0">
<div class="target-section">
<h4>Evolution Targets</h4>
<div class="target-cards">
<div
*ngFor="let target of pokemon.evolve_to"
*ngFor="let target of evolve_to"
class="target-card"
[class.completed]="isTargetCompleted(target.pfic)"
[class.completed]="isTargetCompleted(target.PFIC)"
>
<img
lazyImg
[src]="pokemonService.getPokemonImageUrl(pokemonService.getPokemonFromPFIC(target.pfic))"
[alt]="target.name"
[src]="pokemonService.getPokemonImageUrl(target)"
[alt]="target.Name"
class="target-image"
[class.grayscale]="isTargetCompleted(target.pfic)"
[class.grayscale]="isTargetCompleted(target.PFIC)"
>
<div class="target-details">
<div class="target-name">
{{ target.name }}
<span *ngIf="target.form_name">({{ target.form_name }})</span>
{{ target.Name }}
<span *ngIf="target.Form">({{ target.Form }})</span>
</div>
<mat-chip-listbox>
<mat-chip>{{ target.method }}</mat-chip>
<mat-chip color="primary" selected>Need: {{ target.count }}</mat-chip>
<mat-chip>Method _PLACEDHOLDER_</mat-chip>
<mat-chip color="primary" selected>Need: {{ 1 }}</mat-chip>
</mat-chip-listbox>
</div>
</div>
@ -94,30 +95,30 @@ interface PokemonStatusEvent {
</div>
</ng-container>
<ng-container *ngIf="pokemon.breed_for.length > 0">
<ng-container *ngIf="pokemon_family.breed_for.length > 0">
<div class="target-section">
<h4>Breeding Targets</h4>
<div class="target-cards">
<div
*ngFor="let target of pokemon.breed_for"
*ngFor="let target of breed_for"
class="target-card"
[class.completed]="isTargetCompleted(target.pfic)"
[class.completed]="isTargetCompleted(target.PFIC)"
>
<img
lazyImg
[src]="pokemonService.getPokemonImageUrl(pokemonService.getPokemonFromPFIC(target.pfic))"
[alt]="target.name"
[src]="pokemonService.getPokemonImageUrl(target)"
[alt]="target.Name"
class="target-image"
[class.grayscale]="isTargetCompleted(target.pfic)"
[class.grayscale]="isTargetCompleted(target.PFIC)"
>
<div class="target-details">
<div class="target-name">
{{ target.name }}
<span *ngIf="target.form_name">({{ target.form_name }})</span>
{{ target.Name }}
<span *ngIf="target.Form">({{ target.Form }})</span>
</div>
<mat-chip-listbox>
<mat-chip>Breed</mat-chip>
<mat-chip color="primary" selected>Need: {{ target.count }}</mat-chip>
<mat-chip color="primary" selected>Need: {{ 1 }}</mat-chip>
</mat-chip-listbox>
</div>
</div>
@ -252,13 +253,61 @@ interface PokemonStatusEvent {
`]
})
export class PlanPokemonComponent {
@Input() pokemon!: PlanPokemon;
@Input() pokemon_family!: PokemonFamilyEntry;
@Output() statusUpdate = new EventEmitter<PokemonStatusEvent>();
constructor(public pokemonService: PokemonService) {}
representative_pokemon: Pokemon | null = null;
evolve_to: Pokemon[] = [];
breed_for: Pokemon[] = [];
constructor(
public pokemonService: PokemonService,
private cdr: ChangeDetectorRef
) {}
ngOnInit() {
this.pokemonService.getPokemonFromPFIC(this.pokemon_family.representative).subscribe({
next: (pokemon) => {
this.representative_pokemon = pokemon
},
error: (error) => {
console.error('Error loading Pokemon:', error);
this.cdr.markForCheck();
}
});
for(const target of this.pokemon_family.evolve_to) {
this.pokemonService.getPokemonFromPFIC(target).subscribe({
next: (pokemon) => {
if(pokemon) {
this.evolve_to.push(pokemon)
}
},
error: (error) => {
console.error('Error loading Pokemon:', error);
this.cdr.markForCheck();
}
});
}
for(const target of this.pokemon_family.breed_for) {
this.pokemonService.getPokemonFromPFIC(target).subscribe({
next: (pokemon) => {
if(pokemon) {
this.breed_for.push(pokemon)
}
},
error: (error) => {
console.error('Error loading Pokemon:', error);
this.cdr.markForCheck();
}
});
}
}
get hasTargets(): boolean {
return this.pokemon.evolve_to.length > 0 || this.pokemon.breed_for.length > 0;
return this.pokemon_family.evolve_to.length > 0 || this.pokemon_family.breed_for.length > 0;
}
isTargetCompleted(pfic: string): boolean {
@ -271,14 +320,14 @@ export class PlanPokemonComponent {
let evolveCount = 0;
// Calculate breeding needs
if (this.pokemon.breed_for.length > 0) {
if (this.pokemon_family.breed_for.length > 0) {
breedCount = 1; // We only need one for breeding, regardless of how many we breed
}
// Calculate evolution needs
this.pokemon.evolve_to.forEach(target => {
if (!this.isTargetCompleted(target.pfic)) {
evolveCount += target.count;
this.pokemon_family.evolve_to.forEach(target => {
if (!this.isTargetCompleted(target)) {
evolveCount += 1;
}
});
@ -287,23 +336,27 @@ export class PlanPokemonComponent {
updateCatchCount() {
const newCount = this.calculateTotalNeeded();
if (newCount !== this.pokemon.catch_count) {
this.pokemon.catch_count = newCount;
if (newCount !== this.pokemon_family.catch_count) {
this.pokemon_family.catch_count = newCount;
if (newCount === 0) {
// Emit event to move to completed section
this.statusUpdate.emit({
pfic: this.pokemon.pfic,
pfic: this.pokemon_family.representative,
caught: true,
completed: true
});
} else if (newCount > 0 && this.pokemon.catch_count === 0) {
} else if (newCount > 0 && this.pokemon_family.catch_count === 0) {
// Emit event to move back to active section
this.statusUpdate.emit({
pfic: this.pokemon.pfic,
pfic: this.pokemon_family.representative,
caught: false,
completed: false
});
}
}
}
getRepresentativePokemon() {
return this.pokemonService.getPokemonFromPFIC(this.pokemon_family.representative)
}
}

4
src/app/features/plan/plan.component.ts

@ -36,8 +36,8 @@ import { PlanPokemonComponent } from "./plan-pokemon/plan-pokemon.component";
<h2>{{ selectedGame.game_name }} - Pokémon to Catch</h2>
<div class="pokemon-list">
<app-plan-pokemon
*ngFor="let pokemon of selectedGame.pokemon"
[pokemon]="pokemon"
*ngFor="let pokemon of selectedGame.pokemon | keyvalue"
[pokemon_family]="pokemon.value"
(statusUpdate)="onPokemonStatusUpdate($event)"
></app-plan-pokemon>
</div>

Loading…
Cancel
Save