192 lines
5.0 KiB
Go
192 lines
5.0 KiB
Go
|
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 <pokemon_name>")
|
||
|
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)
|
||
|
}
|
||
|
}
|