Pokédex Pro

A WPF-based Pokédex app demonstrating API integration

C# • WPF • XAML • API Fetch

C# Development

  • Built a Pokédex desktop application using WPF (C#)
  • Integrated the PokéAPI to dynamically fetch and display Pokémon data, including stats, types, and sprites.
  • Implemented stat calculation logic using base stats, EVs, IVs, level, and nature multipliers for accurate in-game results.
  • Added input validation and error handling for user-provided EVs, IVs, and level values.
  • Developed type mapping and nature modifiers for enhanced gameplay accuracy and data clarity.
  • Organized code into separate layers for UI, logic, and data parsing to ensure maintainability and scalability.
                                        
public async Task Fetch(string endpoint, CancellationToken cancellationToken = default) where T : class
{          
    try
    {
        HttpResponseMessage response = await _client.GetAsync(endpoint, cancellationToken);
        if (response.StatusCode == HttpStatusCode.NotFound)
            return null;

        response.EnsureSuccessStatusCode();
        string jsonResponse = await response.Content.ReadAsStringAsync(cancellationToken);
        return JsonSerializer.Deserialize(jsonResponse);
    }
    catch (HttpRequestException ex)
    {
        Console.Error.WriteLine($"HTTP fetching error: {ex.Message}");
        return null;
    }
    catch (JsonException ex)
    {
        Console.Error.WriteLine($"JSON parsing error: {ex.Message}");
        return null;
    }
}
                                        
                                    
                                        
 public record Pokemon(
    [property: JsonPropertyName("abilities")] IReadOnlyList Abilities,
    [property: JsonPropertyName("base_experience")] long BaseExperience,
    [property: JsonPropertyName("forms")] IReadOnlyList Forms,
    [property: JsonPropertyName("game_indices")] IReadOnlyList GameIndices,
    [property: JsonPropertyName("height")] long Height,
    [property: JsonPropertyName("held_items")] IReadOnlyList HeldItems,
    [property: JsonPropertyName("id")] long Id,
    [property: JsonPropertyName("is_default")] bool IsDefault,
    [property: JsonPropertyName("location_area_encounters")] Uri LocationAreaEncounters,
    [property: JsonPropertyName("moves")] IReadOnlyList Moves,
    [property: JsonPropertyName("name")] string Name,
    [property: JsonPropertyName("order")] long Order,
    [property: JsonPropertyName("species")] Species Species,
    [property: JsonPropertyName("sprites")] Sprites Sprites,
    [property: JsonPropertyName("stats")] IReadOnlyList Stats,
    [property: JsonPropertyName("types")] IReadOnlyList Types,
    [property: JsonPropertyName("weight")] long Weight
);
                                        
                                    
                                
                            

                            
                                        
public static BaseStats GetBaseStats(Pokemon pokemon)
{
    ArgumentNullException.ThrowIfNull(pokemon);

    if (pokemon.Stats is null || pokemon.Stats.Count == 0)
        throw new InvalidOperationException("There are no valid stat entries");

    Dictionary dict = pokemon.Stats.ToDictionary(s => s.StatValue.Name, s => (int)s.BaseStat, StringComparer.OrdinalIgnoreCase);

    int Get(string key) => dict.TryGetValue(key, out var v) ? v : throw new KeyNotFoundException($"stat entry '{key}' in '{pokemon.Name}' was not found.");

    return new BaseStats(
        HP: Get("hp"),
        Attack: Get("attack"),
        Defense: Get("defense"),
        SpAttack: Get("special-attack"),
        SpDefense: Get("special-defense"),
        Speed: Get("speed")
    );
}
                                        
                                    

Get in Touch

Contact Me