diff --git a/README.md b/README.md new file mode 100644 index 0000000..a862d53 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# GOKEDEX +A blazing fast pokedex cli written in go diff --git a/command_catch.go b/command_catch.go new file mode 100644 index 0000000..82dcbf8 --- /dev/null +++ b/command_catch.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "math/rand" +) + +func commandCatch(cfg *config, pokemonName string) error { + pokemon, err := cfg.pokeClient.PokemonInfo(&pokemonName) + if err != nil { + return err + } + fmt.Printf("Throwing a Pokeball at %s...\n", pokemonName) + baseExp := pokemon.BaseExp + catchRate := 500 - baseExp + catchRoll := rand.Intn(500) + if catchRoll <= catchRate { + (*cfg.pokeDex)[pokemonName] = pokemon + fmt.Println(pokemonName, "was caught!") + } else { + fmt.Println(pokemonName, "escaped!") + } + + return nil +} diff --git a/command_exit.go b/command_exit.go index f2df532..2be2786 100644 --- a/command_exit.go +++ b/command_exit.go @@ -5,7 +5,7 @@ import ( "os" ) -func commandExit(cfg *config) error { +func commandExit(cfg *config, arg string) error { fmt.Println("Closing the Pokedex... Goodbye!") os.Exit(0) return nil diff --git a/command_explore.go b/command_explore.go new file mode 100644 index 0000000..f2d67b3 --- /dev/null +++ b/command_explore.go @@ -0,0 +1,20 @@ +package main + +import ( + "fmt" +) + +func commandExplore(cfg *config, areaName string) error { + encounters, err := cfg.pokeClient.ListEncounters(&areaName) + if err != nil { + return err + } + + fmt.Printf("Exploring %s...\n", encounters.Name) + fmt.Println("Found Pokemon:") + for _, p := range encounters.Encounters { + fmt.Printf(" - %s\n", p.Pokemon.Name) + } + + return nil +} diff --git a/command_help.go b/command_help.go index ed990e0..ee49dbb 100644 --- a/command_help.go +++ b/command_help.go @@ -2,13 +2,13 @@ package main import "fmt" -func commandHelp(cfg *config) error { +func commandHelp(cfg *config, arg string) error { fmt.Println() fmt.Println("Welcome to the Pokedex!") fmt.Println("Usage:") fmt.Println() for _, c := range getCommands() { - fmt.Printf("\t%v\t\t%v\n", c.name, c.description) + fmt.Printf(" %v\t\t\t%v\n", c.name, c.description) } fmt.Println() return nil diff --git a/command_inspect.go b/command_inspect.go new file mode 100644 index 0000000..785d4fb --- /dev/null +++ b/command_inspect.go @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "fmt" +) + +func commandInspect(cfg *config, pokemonName string) error { + pokemon, ok := (*cfg.pokeDex)[pokemonName] + if !ok { + return errors.New("you havent caught that pokemon yet") + } + fmt.Println("") + fmt.Printf(" Name: %v\n", pokemon.Name) + fmt.Printf(" Height: %v\n", pokemon.Height) + fmt.Printf(" Weight: %v\n", pokemon.Weight) + fmt.Println(" Stats:") + for _, stat := range pokemon.Stats { + fmt.Printf(" -%v: %v\n", stat.Stat.Name, stat.BaseStat) + } + fmt.Println(" Types:") + for _, t := range pokemon.Types { + fmt.Printf(" - %v\n", t.Type.Name) + } + fmt.Println("") + + return nil +} diff --git a/command_map.go b/command_map.go index 315027e..c341d63 100644 --- a/command_map.go +++ b/command_map.go @@ -5,7 +5,7 @@ import ( "fmt" ) -func commandMap(cfg *config) error { +func commandMap(cfg *config, arg string) error { // if cfg.nextLocationsURL == nil { // return errors.New("you're on the last page") // } @@ -25,7 +25,7 @@ func commandMap(cfg *config) error { return nil } -func commandMapb(cfg *config) error { +func commandMapb(cfg *config, arg string) error { if cfg.prevLocationsURL == nil { return errors.New("you're on the first page") } diff --git a/command_pokedex.go b/command_pokedex.go new file mode 100644 index 0000000..3564fb6 --- /dev/null +++ b/command_pokedex.go @@ -0,0 +1,18 @@ +package main + +import ( + "errors" + "fmt" +) + +func commandPokedex(cfg *config, arg string) error { + if len(*cfg.pokeDex) == 0 { + return errors.New("you haven't caught any pokemon") + } + + fmt.Println(" Your Pokedex:") + for k := range *cfg.pokeDex { + fmt.Printf(" - %v\n", k) + } + return nil +} diff --git a/gokedex b/gokedex index 8a1f909..1df6961 100755 Binary files a/gokedex and b/gokedex differ diff --git a/internal/pokeapi/encounter_list.go b/internal/pokeapi/encounter_list.go new file mode 100644 index 0000000..d11a292 --- /dev/null +++ b/internal/pokeapi/encounter_list.go @@ -0,0 +1,80 @@ +package pokeapi + +import ( + "bytes" + "encoding/json" + "errors" + "io" + "net/http" +) + +func (c *Client) ListEncounters(areaName *string) (RespShallowLocationExplore, error) { + if areaName == nil { + return RespShallowLocationExplore{}, errors.New("invalid location for exploration") + } + + url := "https://pokeapi.co/api/v2/location-area/" + *areaName + data, ok := c.cache.Get(url) + if !ok { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return RespShallowLocationExplore{}, err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return RespShallowLocationExplore{}, err + } + defer resp.Body.Close() + + data, err = io.ReadAll(resp.Body) + if err != nil { + return RespShallowLocationExplore{}, err + } + c.cache.Add(url, data) + } + + var encounterResp RespShallowLocationExplore + + decoder := json.NewDecoder(bytes.NewReader(data)) + if err := decoder.Decode(&encounterResp); err != nil { + return RespShallowLocationExplore{}, err + } + + return encounterResp, nil +} + +func (c *Client) PokemonInfo(pokemon *string) (Pokemon, error) { + if pokemon == nil { + return Pokemon{}, errors.New("please enter the pokemon name") + } + url := "https://pokeapi.co/api/v2/pokemon/" + *pokemon + data, ok := c.cache.Get(url) + if !ok { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return Pokemon{}, err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return Pokemon{}, err + } + defer resp.Body.Close() + + data, err = io.ReadAll(resp.Body) + if err != nil { + return Pokemon{}, err + } + c.cache.Add(url, data) + } + + var pokemonResp Pokemon + + decoder := json.NewDecoder(bytes.NewReader(data)) + if err := decoder.Decode(&pokemonResp); err != nil { + return Pokemon{}, err + } + + return pokemonResp, nil +} diff --git a/internal/pokeapi/types_pokemons.go b/internal/pokeapi/types_pokemons.go index a1fefeb..102c50b 100644 --- a/internal/pokeapi/types_pokemons.go +++ b/internal/pokeapi/types_pokemons.go @@ -8,5 +8,51 @@ type RespShallowLocationExplore struct { Name string `json:"name"` URL string `json:"url"` } `json:"pokemon"` - } + } `json:"pokemon_encounters"` +} + +type Pokemon struct { + Abilities []struct { + Ability struct { + Name string `json:"name"` + URL string `json:"url"` + } `json:"ability"` + IsHidden bool `json:"is_hidden"` + Slot int `json:"slot"` + } `json:"abilities"` + BaseExp int `json:"base_experience"` + Cires struct { + Latest string `json:"latest"` + Legacy string `json:"legacy"` + } `json:"cires"` + Forms []struct { + Name string `json:"name"` + URL string `json:"url"` + } `json:"forms"` + Height int `json:"height"` + Id int `json:"id"` + Moves []struct { + Move struct { + Name string `json:"name"` + URL string `json:"url"` + } `json:"move"` + } `json:"moves"` + Name string `json:"name"` + Order int `json:"order"` + Stats []struct { + BaseStat int `json:"base_stat"` + Effort int `json:"effort"` + Stat struct { + Name string `json:"name"` + URL string `json:"url"` + } `json:"stat"` + } `json:"stats"` + Types []struct { + Slot int `json:"slot"` + Type struct { + Name string `json:"name"` + URL string `json:"url"` + } `json:"type"` + } `json:"types"` + Weight int `json:"weight"` } diff --git a/main.go b/main.go index c19495d..0eae45c 100644 --- a/main.go +++ b/main.go @@ -10,8 +10,10 @@ const prompt = "Pokedex > " func main() { pokeClient := pokeapi.NewClient(5*time.Second, 5*time.Minute) + catchedPokemon := map[string]pokeapi.Pokemon{} cfg := &config{ pokeClient: pokeClient, + pokeDex: &catchedPokemon, } startRepl(cfg) } diff --git a/repl.go b/repl.go index 4d7f809..4c005ff 100644 --- a/repl.go +++ b/repl.go @@ -31,6 +31,26 @@ func getCommands() map[string]cliCommand { description: "Displays the names of the previous 20 locations", callback: commandMapb, }, + "explore": { + name: "explore ", + description: "Displays the pokemon found in an area", + callback: commandExplore, + }, + "catch": { + name: "catch ", + description: "Attempt to catch a pokemon", + callback: commandCatch, + }, + "inspect": { + name: "inspect ", + description: "Displays info of a catched pokemon", + callback: commandInspect, + }, + "pokedex": { + name: "pokedex", + description: "Displays your caught pokemon", + callback: commandPokedex, + }, } } @@ -46,10 +66,15 @@ func startRepl(cfg *config) { } inputCommand := words[0] + commandArg := "" + if len(words) > 1 { + commandArg = words[1] + } + command, exists := getCommands()[inputCommand] if exists { - err := command.callback(cfg) + err := command.callback(cfg, commandArg) if err != nil { fmt.Printf("%v error: %v\n", command.name, err.Error()) } @@ -65,11 +90,12 @@ func startRepl(cfg *config) { type cliCommand struct { name string description string - callback func(*config) error + callback func(*config, string) error } type config struct { pokeClient pokeapi.Client + pokeDex *map[string]pokeapi.Pokemon nextLocationsURL *string prevLocationsURL *string }