Files
boot-dev-pokedex/main.go
2025-03-10 22:36:41 +02:00

235 lines
5.0 KiB
Go

package main
import (
"bufio"
"errors"
"fmt"
"github.com/rdarius/boot-dev-pokedex/pokeapi"
"math/rand"
"os"
"strings"
"time"
)
type config struct {
pokeapiClient pokeapi.Client
nextLocationsURL *string
prevLocationsURL *string
caughtPokemon map[string]pokeapi.Pokemon
}
type cliCommand struct {
name string
description string
callback func(*config, ...string) error
}
var commands map[string]cliCommand
func main() {
pokeClient := pokeapi.NewClient(5*time.Second, time.Minute*5)
cfg := &config{
caughtPokemon: map[string]pokeapi.Pokemon{},
pokeapiClient: pokeClient,
}
commands = map[string]cliCommand{
"exit": {
name: "exit",
description: "Exit the Pokedex",
callback: commandExit,
},
"explore": {
name: "explore <location_name>",
description: "Explore a location",
callback: commandExplore,
},
"help": {
name: "help",
description: "Display a help message",
callback: printHelpMessage,
},
"map": {
name: "map",
description: "Get the next page of locations",
callback: commandMapf,
},
"mapb": {
name: "mapb",
description: "Get the previous page of locations",
callback: commandMapb,
},
"catch": {
name: "catch <pokemon_name>",
description: "Attempt to catch a pokemon",
callback: commandCatch,
},
"inspect": {
name: "inspect <pokemon_name>",
description: "View details about a caught Pokemon",
callback: commandInspect,
},
"pokedex": {
name: "pokedex",
description: "View list of pokemons caught",
callback: commandPokedex,
},
}
for {
// read user input
input := bufio.NewScanner(os.Stdin)
fmt.Print("Pokedex > ")
for input.Scan() {
word := input.Text()
cleanedWord := cleanInput(word)
command := cleanedWord[0]
var args []string
if len(cleanedWord) > 1 {
args = cleanedWord[1:]
}
cmd, ok := commands[command]
if ok {
err := cmd.callback(cfg, args...)
if err != nil {
fmt.Println(err)
}
} else {
fmt.Println("Unknown command")
}
fmt.Print("Pokedex > ")
}
}
}
func commandExit(*config, ...string) error {
fmt.Println("Closing the Pokedex... Goodbye!")
os.Exit(0)
return nil
}
func cleanInput(text string) []string {
output := strings.ToLower(text)
words := strings.Fields(output)
return words
}
func printHelpMessage(*config, ...string) error {
fmt.Print("Welcome to the Pokedex!\nUsage:\n\n")
for _, v := range commands {
fmt.Printf("%s: %s\n", v.name, v.description)
}
return nil
}
func commandMapf(cfg *config, _ ...string) error {
locationsResp, err := cfg.pokeapiClient.ListLocations(cfg.nextLocationsURL)
if err != nil {
return err
}
cfg.nextLocationsURL = locationsResp.Next
cfg.prevLocationsURL = locationsResp.Previous
for _, loc := range locationsResp.Results {
fmt.Println(loc.Name)
}
return nil
}
func commandMapb(cfg *config, _ ...string) error {
if cfg.prevLocationsURL == nil {
return errors.New("you're on the first page")
}
locationResp, err := cfg.pokeapiClient.ListLocations(cfg.prevLocationsURL)
if err != nil {
return err
}
cfg.nextLocationsURL = locationResp.Next
cfg.prevLocationsURL = locationResp.Previous
for _, loc := range locationResp.Results {
fmt.Println(loc.Name)
}
return nil
}
func commandExplore(cfg *config, args ...string) error {
if len(args) != 1 {
return errors.New("you must provide a location name")
}
name := args[0]
location, err := cfg.pokeapiClient.GetLocation(name)
if err != nil {
return err
}
fmt.Printf("Exploring %s...\n", location.Name)
fmt.Println("Found Pokemon: ")
for _, enc := range location.PokemonEncounters {
fmt.Printf(" - %s\n", enc.Pokemon.Name)
}
return nil
}
func commandCatch(cfg *config, args ...string) error {
if len(args) != 1 {
return errors.New("you must provide a pokemon name")
}
name := args[0]
pokemon, err := cfg.pokeapiClient.GetPokemon(name)
if err != nil {
return err
}
res := rand.Intn(pokemon.BaseExperience)
fmt.Printf("Throwing a Pokeball at %s...\n", pokemon.Name)
if res > 40 {
fmt.Printf("%s escaped!\n", pokemon.Name)
return nil
}
fmt.Printf("%s was caught!\n", pokemon.Name)
cfg.caughtPokemon[pokemon.Name] = pokemon
return nil
}
func commandInspect(cfg *config, args ...string) error {
if len(args) != 1 {
return errors.New("you must provide a pokemon name")
}
name := args[0]
pokemon, ok := cfg.caughtPokemon[name]
if !ok {
return errors.New("you have not caught that pokemon")
}
fmt.Println("Name:", pokemon.Name)
fmt.Println("Height:", pokemon.Height)
fmt.Println("Weight:", pokemon.Weight)
fmt.Println("Stats:")
for _, stat := range pokemon.Stats {
fmt.Printf(" -%s: %v\n", stat.Stat.Name, stat.BaseStat)
}
fmt.Println("Types:")
for _, typeInfo := range pokemon.Types {
fmt.Println(" -", typeInfo.Type.Name)
}
return nil
}
func commandPokedex(cfg *config, _ ...string) error {
for name := range cfg.caughtPokemon {
fmt.Println(cfg.caughtPokemon[name].Name)
}
return nil
}