Added more functionality to the Pokedex; WIP - add more testing and refactor
This commit is contained in:
		
							parent
							
								
									f0b303c0c0
								
							
						
					
					
						commit
						f6e8038cdc
					
				
							
								
								
									
										63
									
								
								command_catch.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								command_catch.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
	"net/http"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
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 == "" {
 | 
			
		||||
		baseUrl = "https://pokeapi.co/api/v2/pokemon/" + *a
 | 
			
		||||
	}
 | 
			
		||||
	// 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
 | 
			
		||||
}
 | 
			
		||||
@ -3,10 +3,9 @@ package main
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"k3gtpi.jumpingcrab.com/go-learning/pokedexcli/internal/pokecache"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func commandExit(p *PokedexConfig, c *pokecache.Cache) error {
 | 
			
		||||
func commandExit(p *PokedexConfig, a *string) error {
 | 
			
		||||
	fmt.Println("Closing the Pokedex... Goodbye!")
 | 
			
		||||
	os.Exit(0)
 | 
			
		||||
	return nil
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										43
									
								
								command_explore.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								command_explore.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/http"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
@ -2,14 +2,12 @@ package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"k3gtpi.jumpingcrab.com/go-learning/pokedexcli/internal/pokecache"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func commandHelp(p *PokedexConfig, c *pokecache.Cache) error {
 | 
			
		||||
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.Printf("%s			%s\n", v.name, v.description)
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Println()
 | 
			
		||||
	return nil
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										45
									
								
								command_inspect.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								command_inspect.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/yaml.v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type PokemonInspectOutput struct {
 | 
			
		||||
	Name   string
 | 
			
		||||
	Height int
 | 
			
		||||
	Weight int
 | 
			
		||||
	Stats  map[string]int
 | 
			
		||||
	Types  []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
@ -1,25 +1,23 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"k3gtpi.jumpingcrab.com/go-learning/pokedexcli/internal/pokecache"
 | 
			
		||||
	"net/http"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func commandMap(p *PokedexConfig, c *pokecache.Cache) error {
 | 
			
		||||
func commandMap(p *PokedexConfig, a *string) error {
 | 
			
		||||
	var baseUrl string
 | 
			
		||||
	if p.Next == nil {
 | 
			
		||||
	if p.LocationData.Next == nil {
 | 
			
		||||
		baseUrl = "https://pokeapi.co/api/v2/location-area/"
 | 
			
		||||
	} else {
 | 
			
		||||
		baseUrl = *p.Next
 | 
			
		||||
		baseUrl = *p.LocationData.Next
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var body []byte
 | 
			
		||||
	// Check if respones is available in cache
 | 
			
		||||
	if resp, exists := c.Get(baseUrl); exists {
 | 
			
		||||
	if resp, exists := p.Cache.Get(baseUrl); exists {
 | 
			
		||||
		body = resp
 | 
			
		||||
	} else {
 | 
			
		||||
		client := &http.Client{}
 | 
			
		||||
@ -37,13 +35,13 @@ func commandMap(p *PokedexConfig, c *pokecache.Cache) error {
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return fmt.Errorf("could not read request body! Err: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
		c.Add(baseUrl, body)
 | 
			
		||||
		p.Cache.Add(baseUrl, body)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := json.Unmarshal(body, &p); err != nil {
 | 
			
		||||
	if err := json.Unmarshal(body, &p.LocationData); err != nil {
 | 
			
		||||
		return fmt.Errorf("could not unmarshal response! Err: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	for _, location := range p.Results {
 | 
			
		||||
	for _, location := range p.LocationData.Locations {
 | 
			
		||||
		fmt.Println(location["name"])
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
 | 
			
		||||
@ -1,23 +1,22 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"k3gtpi.jumpingcrab.com/go-learning/pokedexcli/internal/pokecache"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func commandMapb(p *PokedexConfig, c *pokecache.Cache) error {
 | 
			
		||||
func commandMapb(p *PokedexConfig, a *string) error {
 | 
			
		||||
	var baseUrl string
 | 
			
		||||
	if p.Previous == nil {
 | 
			
		||||
	if p.LocationData.Previous == nil {
 | 
			
		||||
		fmt.Println("you're on the first page")
 | 
			
		||||
		return nil
 | 
			
		||||
	} else {
 | 
			
		||||
		baseUrl = *p.Previous
 | 
			
		||||
		baseUrl = *p.LocationData.Previous
 | 
			
		||||
	}
 | 
			
		||||
	var body []byte
 | 
			
		||||
	if resp, exists := c.Get(baseUrl); exists {
 | 
			
		||||
	if resp, exists := p.Cache.Get(baseUrl); exists {
 | 
			
		||||
		body = resp
 | 
			
		||||
	} else {
 | 
			
		||||
		client := &http.Client{}
 | 
			
		||||
@ -36,12 +35,12 @@ func commandMapb(p *PokedexConfig, c *pokecache.Cache) error {
 | 
			
		||||
			return fmt.Errorf("could not read request body! Err: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		c.Add(baseUrl, body)
 | 
			
		||||
		p.Cache.Add(baseUrl, body)
 | 
			
		||||
	}
 | 
			
		||||
	if err := json.Unmarshal(body, &p); err != nil {
 | 
			
		||||
	if err := json.Unmarshal(body, &p.LocationData); err != nil {
 | 
			
		||||
		return fmt.Errorf("could not unmarshal response! Err: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	for _, location := range p.Results {
 | 
			
		||||
	for _, location := range p.LocationData.Locations {
 | 
			
		||||
		fmt.Println(location["name"])
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								command_pokedex.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								command_pokedex.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							@ -1,3 +1,5 @@
 | 
			
		||||
module k3gtpi.jumpingcrab.com/go-learning/pokedexcli
 | 
			
		||||
 | 
			
		||||
go 1.24.5
 | 
			
		||||
 | 
			
		||||
require gopkg.in/yaml.v2 v2.4.0
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 | 
			
		||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 | 
			
		||||
@ -1,25 +1,25 @@
 | 
			
		||||
package pokecache
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"time"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type cacheEntry struct {
 | 
			
		||||
	createdAt	time.Time
 | 
			
		||||
	val			[]byte
 | 
			
		||||
	createdAt time.Time
 | 
			
		||||
	val       []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Cache struct {
 | 
			
		||||
	PokeCache	map[string]cacheEntry
 | 
			
		||||
	Interval	time.Duration
 | 
			
		||||
	Mu			sync.Mutex
 | 
			
		||||
	PokeCache map[string]cacheEntry
 | 
			
		||||
	Interval  time.Duration
 | 
			
		||||
	Mu        sync.Mutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Cache) Add(key string, val []byte) {
 | 
			
		||||
	newEntry := cacheEntry{
 | 
			
		||||
		createdAt: 	time.Now(),
 | 
			
		||||
		val:		val,
 | 
			
		||||
		createdAt: time.Now(),
 | 
			
		||||
		val:       val,
 | 
			
		||||
	}
 | 
			
		||||
	c.Mu.Lock()
 | 
			
		||||
	defer c.Mu.Unlock()
 | 
			
		||||
@ -45,7 +45,7 @@ func (c *Cache) reapLoop() {
 | 
			
		||||
		c.Mu.Lock()
 | 
			
		||||
		for k, v := range c.PokeCache {
 | 
			
		||||
			if time.Since(v.createdAt) > c.Interval {
 | 
			
		||||
				delete(c.PokeCache,  k)
 | 
			
		||||
				delete(c.PokeCache, k)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		c.Mu.Unlock()
 | 
			
		||||
@ -55,11 +55,9 @@ func (c *Cache) reapLoop() {
 | 
			
		||||
func NewCache(interval time.Duration) *Cache {
 | 
			
		||||
	newCache := Cache{
 | 
			
		||||
		PokeCache: map[string]cacheEntry{},
 | 
			
		||||
		Interval: interval,
 | 
			
		||||
		Mu: sync.Mutex{},
 | 
			
		||||
		Interval:  interval,
 | 
			
		||||
		Mu:        sync.Mutex{},
 | 
			
		||||
	}
 | 
			
		||||
	go newCache.reapLoop()
 | 
			
		||||
	return &newCache
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,11 @@
 | 
			
		||||
package pokecache
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func TestAddGet(t *testing.T) {
 | 
			
		||||
	const interval = 5 * time.Second
 | 
			
		||||
	cases := []struct {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										130
									
								
								repl.go
									
									
									
									
									
								
							
							
						
						
									
										130
									
								
								repl.go
									
									
									
									
									
								
							@ -1,41 +1,89 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"k3gtpi.jumpingcrab.com/go-learning/pokedexcli/internal/pokecache"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"k3gtpi.jumpingcrab.com/go-learning/pokedexcli/internal/pokecache"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type cliCommand struct {
 | 
			
		||||
	name		string
 | 
			
		||||
	description	string
 | 
			
		||||
	callback	func(*PokedexConfig, *pokecache.Cache) error
 | 
			
		||||
	name        string
 | 
			
		||||
	description string
 | 
			
		||||
	callback    func(*PokedexConfig, *string) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PokedexLocationData struct {
 | 
			
		||||
	Next      *string             `json:"next"`
 | 
			
		||||
	Previous  *string             `json:"previous"`
 | 
			
		||||
	Locations []map[string]string `json:"results"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PokemonSummary struct {
 | 
			
		||||
	Name    string `json:"name"`
 | 
			
		||||
	DataUrl string `json:"url"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PokemonStat struct {
 | 
			
		||||
	Name string `json:"name"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PokemonStats struct {
 | 
			
		||||
	BaseStat int         `json:"base_stat"`
 | 
			
		||||
	PokeStat PokemonStat `json:"stat"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PokemonTypeEntry struct {
 | 
			
		||||
	Name string `json:"name"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PokemonTypes struct {
 | 
			
		||||
	PokeType PokemonTypeEntry `json:"type"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PokemonDetails struct {
 | 
			
		||||
	Name           string         `json:"name"`
 | 
			
		||||
	BaseExperience int            `json:"base_experience"`
 | 
			
		||||
	Weight         int            `json:"weight"`
 | 
			
		||||
	Height         int            `json:"height"`
 | 
			
		||||
	PokeStats      []PokemonStats `json:"stats"`
 | 
			
		||||
	PokeTypes      []PokemonTypes `json:"types"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PokemonEncounterData struct {
 | 
			
		||||
	PokemonSummary PokemonSummary `json:"pokemon"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PokedexLocalPokemons struct {
 | 
			
		||||
	LocationName      string                 `json:"name"`
 | 
			
		||||
	PokemonEncounters []PokemonEncounterData `json:"pokemon_encounters"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PokedexConfig struct {
 | 
			
		||||
	Next		*string
 | 
			
		||||
	Previous	*string
 | 
			
		||||
	Results		[]map[string]string
 | 
			
		||||
	Cache         *pokecache.Cache
 | 
			
		||||
	LocationData  PokedexLocationData
 | 
			
		||||
	LocalPokemons PokedexLocalPokemons
 | 
			
		||||
	CaughtPokemon []PokemonDetails
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var supportedCommands map[string]cliCommand
 | 
			
		||||
 | 
			
		||||
func startRepl() {
 | 
			
		||||
	reader := bufio.NewScanner(os.Stdin)
 | 
			
		||||
	fmt.Println("Welcome to the Pokedex!")
 | 
			
		||||
	pokedexConfig := PokedexConfig{}
 | 
			
		||||
	cache := pokecache.NewCache(5 * time.Second)
 | 
			
		||||
	pokedexConfig.Cache = pokecache.NewCache(5 * time.Second)
 | 
			
		||||
	for {
 | 
			
		||||
		// Print prompt
 | 
			
		||||
		fmt.Printf("Pokedex > ")
 | 
			
		||||
		reader.Scan()
 | 
			
		||||
 | 
			
		||||
		words := cleanInput(reader.Text())
 | 
			
		||||
		if len(words) == 0 {
 | 
			
		||||
			continue
 | 
			
		||||
		} else if len(words) > 2 {
 | 
			
		||||
			fmt.Printf("Commands can only take one argument!")
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		commandName := words[0]
 | 
			
		||||
@ -45,8 +93,14 @@ func startRepl() {
 | 
			
		||||
			fmt.Println("Unknown command.")
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if err := command.callback(&pokedexConfig, cache); err != nil {
 | 
			
		||||
			fmt.Printf("Encountered error running command: %v\nErr: %v", command.name, err)
 | 
			
		||||
 | 
			
		||||
		arg := ""
 | 
			
		||||
		if len(words) == 2 {
 | 
			
		||||
			arg = words[1]
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := command.callback(&pokedexConfig, &arg); err != nil {
 | 
			
		||||
			fmt.Printf("Encountered error running command: %v\nErr: %v\n\n", command.name, err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -61,27 +115,47 @@ func cleanInput(text string) []string {
 | 
			
		||||
	return words
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getCommands() map[string]cliCommand{
 | 
			
		||||
func getCommands() map[string]cliCommand {
 | 
			
		||||
	return map[string]cliCommand{
 | 
			
		||||
		"help": {
 | 
			
		||||
			name:			"help",
 | 
			
		||||
			description:	"Prints this help menu.",
 | 
			
		||||
			callback:		commandHelp,
 | 
			
		||||
			name:        "help",
 | 
			
		||||
			description: "Prints this help menu.",
 | 
			
		||||
			callback:    commandHelp,
 | 
			
		||||
		},
 | 
			
		||||
		"exit": {
 | 
			
		||||
			name:			"exit",
 | 
			
		||||
			description:	"Exits the Pokedex",
 | 
			
		||||
			callback:		commandExit,
 | 
			
		||||
			name:        "exit",
 | 
			
		||||
			description: "Exits the Pokedex",
 | 
			
		||||
			callback:    commandExit,
 | 
			
		||||
		},
 | 
			
		||||
		"map": {
 | 
			
		||||
			name:			"map",
 | 
			
		||||
			description:	"Print Pokemon world locations.",
 | 
			
		||||
			callback:		commandMap,
 | 
			
		||||
			name:        "map",
 | 
			
		||||
			description: "Print Pokemon world locations.",
 | 
			
		||||
			callback:    commandMap,
 | 
			
		||||
		},
 | 
			
		||||
		"mapb": {
 | 
			
		||||
			name:			"mapb",
 | 
			
		||||
			description:	"Print previoud Pokemon locationsi.",
 | 
			
		||||
			callback:		commandMapb,
 | 
			
		||||
			name:        "mapb",
 | 
			
		||||
			description: "Print previous Pokemon locations.",
 | 
			
		||||
			callback:    commandMapb,
 | 
			
		||||
		},
 | 
			
		||||
		"explore": {
 | 
			
		||||
			name:        "explore",
 | 
			
		||||
			description: "Print Pokemon found in specified area. Requires AREA_NAME argument.",
 | 
			
		||||
			callback:    commandExplore,
 | 
			
		||||
		},
 | 
			
		||||
		"catch": {
 | 
			
		||||
			name:        "catch",
 | 
			
		||||
			description: "Attempt to catch a Pokemon present in current area. Requires POKEMON_NAME argument.",
 | 
			
		||||
			callback:    commandCatch,
 | 
			
		||||
		},
 | 
			
		||||
		"inspect": {
 | 
			
		||||
			name:        "inspect",
 | 
			
		||||
			description: "Inspect a caught Pokemon. Requires POKEMON_NAME argument.",
 | 
			
		||||
			callback:    commandInspect,
 | 
			
		||||
		},
 | 
			
		||||
		"pokedex": {
 | 
			
		||||
			name:        "pokedex",
 | 
			
		||||
			description: "Inspect the Pokedex contents.",
 | 
			
		||||
			callback:    commandPokedex,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								repl_test.go
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								repl_test.go
									
									
									
									
									
								
							@ -1,26 +1,26 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestCleanInput(t * testing.T) {
 | 
			
		||||
func TestCleanInput(t *testing.T) {
 | 
			
		||||
	cases := []struct {
 | 
			
		||||
		input		string
 | 
			
		||||
		expected	[]string
 | 
			
		||||
		input    string
 | 
			
		||||
		expected []string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			input: 		" hello world ",
 | 
			
		||||
			expected: 	[]string{"hello", "world"},
 | 
			
		||||
			input:    " hello world ",
 | 
			
		||||
			expected: []string{"hello", "world"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			input:		"Charmander Bulbasaur PIKACHU",
 | 
			
		||||
			expected:	[]string{"charmander", "bulbasaur", "pikachu"},
 | 
			
		||||
			input:    "Charmander Bulbasaur PIKACHU",
 | 
			
		||||
			expected: []string{"charmander", "bulbasaur", "pikachu"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			input:		"",
 | 
			
		||||
			expected:	[]string{},
 | 
			
		||||
			input:    "",
 | 
			
		||||
			expected: []string{},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	successCount := 0
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user