package main import ( "encoding/json" "fmt" "io" "math" "net/http" "os" "sort" "strings" "golang.org/x/text/cases" "golang.org/x/text/language" ) type Pokemon struct { Name string `json:"name"` Weight int `json:"weight"` Types []Type `json:"types"` Sprites Sprites `json:"sprites"` } type Type struct { TypeDetails TypeDetails `json:"type"` } type TypeDetails struct { Name string `json:"name"` URL string `json:"url"` } type DamageRelations struct { DoubleDamageFrom []TypeDetails `json:"double_damage_from"` HalfDamageFrom []TypeDetails `json:"half_damage_from"` NoDamageFrom []TypeDetails `json:"no_damage_from"` DoubleDamageTo []TypeDetails `json:"double_damage_to"` HalfDamageTo []TypeDetails `json:"half_damage_to"` NoDamageTo []TypeDetails `json:"no_damage_to"` } type Sprites struct { BackDefault string `json:"back_default"` BackFemale *string `json:"back_female"` BackShiny string `json:"back_shiny"` BackShinyFemale *string `json:"back_shiny_female"` FrontDefault string `json:"front_default"` FrontFemale *string `json:"front_female"` FrontShiny string `json:"front_shiny"` FrontShinyFemale *string `json:"front_shiny_female"` } func getPokemonData(pokemonName string) (*Pokemon, error) { url := fmt.Sprintf("https://pokeapi.co/api/v2/pokemon/%s", strings.ToLower(pokemonName)) resp, err := http.Get(url) if err != nil { return nil, fmt.Errorf("failed to fetch Pokémon data: %w", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("HTTP error: %s", resp.Status) } body, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("failed to read response body: %w", err) } var pokemon Pokemon if err := json.Unmarshal(body, &pokemon); err != nil { return nil, fmt.Errorf("failed to parse Pokémon data: %w", err) } return &pokemon, nil } func getTypeDamageRelations(typeURL string) (*DamageRelations, error) { resp, err := http.Get(typeURL) if err != nil { return nil, fmt.Errorf("failed to fetch type damage relations: %w", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("HTTP error: %s", resp.Status) } body, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("failed to read response body: %w", err) } var damageRelations struct { DamageRelations DamageRelations `json:"damage_relations"` } if err := json.Unmarshal(body, &damageRelations); err != nil { return nil, fmt.Errorf("failed to parse damage relations: %w", err) } return &damageRelations.DamageRelations, nil } func calculateCombinedWeaknesses(types []Type) map[string]float64 { typeEffects := make(map[string]float64) for _, pokeType := range types { typeName := pokeType.TypeDetails.Name typeURL := pokeType.TypeDetails.URL damageRelations, err := getTypeDamageRelations(typeURL) if err != nil { fmt.Printf("Error fetching damage relations for type %s: %v\n", typeName, err) continue } for _, dmgType := range damageRelations.DoubleDamageFrom { typeEffects[dmgType.Name] += 1 } for _, dmgType := range damageRelations.HalfDamageFrom { typeEffects[dmgType.Name] -= 0.5 } for _, dmgType := range damageRelations.NoDamageFrom { typeEffects[dmgType.Name] = 0 } } combinedWeaknesses := make(map[string]float64) for typeName, multiplier := range typeEffects { combinedWeaknesses[typeName] = math.Pow(2, multiplier) } return combinedWeaknesses } func main() { if len(os.Args) != 2 { fmt.Println("Usage: go run pokecli.go ") os.Exit(1) } pokemonName := os.Args[1] pokemon, err := getPokemonData(pokemonName) if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } fmt.Printf("Name: %s\n", cases.Title(language.Und).String(pokemon.Name)) fmt.Printf("Weight: %d\n", pokemon.Weight) fmt.Println("\nTypes:") for _, pokeType := range pokemon.Types { typeName := pokeType.TypeDetails.Name typeURL := pokeType.TypeDetails.URL fmt.Printf(" - %s\n", cases.Title(language.Und).String(typeName)) damageRelations, err := getTypeDamageRelations(typeURL) if err != nil { fmt.Printf("Error fetching damage relations for type %s: %v\n", typeName, err) continue } if len(damageRelations.DoubleDamageTo) > 0 { for _, dmgType := range damageRelations.DoubleDamageTo { fmt.Printf(" * %s\n", cases.Title(language.English).String(dmgType.Name)) } } } combinedWeaknesses := calculateCombinedWeaknesses(pokemon.Types) fmt.Println("\nWeaknesses:") type Weakness struct { TypeName string Multiplier float64 } var weaknesses []Weakness for typeName, multiplier := range combinedWeaknesses { if multiplier > 1 { weaknesses = append(weaknesses, Weakness{TypeName: typeName, Multiplier: multiplier}) } } sort.Slice(weaknesses, func(i, j int) bool { return weaknesses[i].Multiplier > weaknesses[j].Multiplier }) for _, weakness := range weaknesses { fmt.Printf(" - %s: %.1fx\n", cases.Title(language.English).String(weakness.TypeName), weakness.Multiplier) } }