package main import ( "encoding/json" "fmt" "io" "math/rand" "net/http" "os" "gopkg.in/yaml.v2" ) type PokemonInspectOutput struct { Name string Height int Weight int Stats map[string]int Types []string } func commandHelp(p *PokedexConfig, a *string) error { fmt.Print("Pokedex CLI - available commands:\n\n") for _, v := range getCommands() { fmt.Printf("%s %s\n", v.name, v.description) } fmt.Println() return nil } func commandExit(p *PokedexConfig, a *string) error { fmt.Println("Closing the Pokedex... Goodbye!") os.Exit(0) return nil } func commandMap(p *PokedexConfig, a *string) error { var baseUrl string if p.LocationData.Next == nil { baseUrl = "https://pokeapi.co/api/v2/location-area/" } else { baseUrl = *p.LocationData.Next } var body []byte if resp, exists := p.Cache.Get(baseUrl); exists { body = resp } else { client := &http.Client{} resp, err := client.Get(baseUrl) if err != nil { return fmt.Errorf("could not make request to Pokedex API! Err: %w", err) } body, err = io.ReadAll(resp.Body) defer resp.Body.Close() if resp.StatusCode > 299 { return fmt.Errorf("request returned non-200 code! Code: %v Body: %v", resp.StatusCode, body) } if err != nil { return fmt.Errorf("could not read request body! Err: %w", err) } p.Cache.Add(baseUrl, body) } if err := json.Unmarshal(body, &p.LocationData); err != nil { return fmt.Errorf("could not unmarshal response! Err: %w", err) } for _, location := range p.LocationData.Locations { fmt.Println(location["name"]) } return nil } func commandMapb(p *PokedexConfig, a *string) error { var baseUrl string if p.LocationData.Previous == nil { fmt.Println("you're on the first page") return nil } else { baseUrl = *p.LocationData.Previous } var body []byte if resp, exists := p.Cache.Get(baseUrl); exists { body = resp } else { client := &http.Client{} resp, err := client.Get(baseUrl) if err != nil { return fmt.Errorf("could not make request to Pokedex API! Err: %w", err) } body, err = io.ReadAll(resp.Body) defer resp.Body.Close() if resp.StatusCode > 299 { return fmt.Errorf("request returned non-200 code! Code: %v Body: %v", resp.StatusCode, body) } if err != nil { return fmt.Errorf("could not read request body! Err: %w", err) } p.Cache.Add(baseUrl, body) } if err := json.Unmarshal(body, &p.LocationData); err != nil { return fmt.Errorf("could not unmarshal response! Err: %w", err) } for _, location := range p.LocationData.Locations { fmt.Println(location["name"]) } return nil } func commandExplore(p *PokedexConfig, a *string) error { if *a == "" { return fmt.Errorf("you need to specify an area to explore") } baseUrl := "https://pokeapi.co/api/v2/location-area/" + *a + "/" body, exists := p.Cache.Get(baseUrl) if !exists { client := http.Client{} resp, err := client.Get(baseUrl) if err != nil { return fmt.Errorf("could not make request to Pokedex API! Err: %w", err) } body, err = io.ReadAll(resp.Body) defer resp.Body.Close() if resp.StatusCode > 299 { return fmt.Errorf("request returned non-200 code! Code: %v Body: %v", resp.StatusCode, body) } if err != nil { return fmt.Errorf("could not read request body! Err: %w", err) } p.Cache.Add(baseUrl, body) } if err := json.Unmarshal(body, &p.LocalPokemons); err != nil { return fmt.Errorf("could not unmarshal response! Err: %w", err) } for _, pokemon := range p.LocalPokemons.PokemonEncounters { fmt.Println(pokemon.PokemonSummary.Name) } return nil } func commandCatch(p *PokedexConfig, a *string) error { if *a == "" { return fmt.Errorf("you need to specify a Pokemon to catch") } var pokemonName string var baseUrl string for _, encounter := range p.LocalPokemons.PokemonEncounters { if encounter.PokemonSummary.Name == *a { pokemonName = *a baseUrl = encounter.PokemonSummary.DataUrl } } if pokemonName != *a { fmt.Println("this pokemon is not present in the current area") return nil } body, exists := p.Cache.Get(baseUrl) if !exists { client := http.Client{} resp, err := client.Get(baseUrl) if err != nil { return fmt.Errorf("could not make request to Pokedex API! Err: %w", err) } body, err = io.ReadAll(resp.Body) defer resp.Body.Close() if resp.StatusCode > 299 { return fmt.Errorf("request returned non-200 code! Code: %v Body: %v", resp.StatusCode, body) } if err != nil { return fmt.Errorf("could not read request body! Err: %w", err) } p.Cache.Add(baseUrl, body) } var pokemon PokemonDetails if err := json.Unmarshal(body, &pokemon); err != nil { return fmt.Errorf("could not unmarshal Pokemon data! err: %w", err) } fmt.Printf("Throwing a Pokeball at %s...\n", *a) catchSuccess := rand.Intn(pokemon.BaseExperience) if 2*catchSuccess >= pokemon.BaseExperience { fmt.Printf("%s was caught!\n", pokemon.Name) p.CaughtPokemon = append(p.CaughtPokemon, pokemon) return nil } fmt.Printf("%s escaped!\n", *a) return nil } func commandPokedex(p *PokedexConfig, a *string) error { if len(p.CaughtPokemon) == 0 { fmt.Println("Your Pokedex is empty.") return nil } fmt.Println("Your Pokedex:") for _, pokemon := range p.CaughtPokemon { fmt.Println(" - ", pokemon.Name) } return nil } func commandInspect(p *PokedexConfig, a *string) error { found := false for _, pokemon := range p.CaughtPokemon { if pokemon.Name == *a { found = true stats := map[string]int{} types := []string{} for _, pokeStat := range pokemon.PokeStats { stats[pokeStat.PokeStat.Name] = pokeStat.BaseStat } for _, pokeType := range pokemon.PokeTypes { types = append(types, pokeType.PokeType.Name) } pokemonInspectOutput := PokemonInspectOutput{ Name: pokemon.Name, Height: pokemon.Height, Weight: pokemon.Weight, Stats: stats, Types: types, } data, _ := yaml.Marshal(pokemonInspectOutput) fmt.Println(string(data)) } } if !found { fmt.Println("you have not caught that pokemon") } return nil }