pokedex/main.go

184 lines
3.3 KiB
Go
Raw Normal View History

2024-08-28 12:36:14 +01:00
package main
import (
"bufio"
2024-08-28 12:36:14 +01:00
"fmt"
"maps"
2024-08-28 12:36:14 +01:00
"os"
"slices"
"time"
2024-09-19 11:34:51 +01:00
"codeflow.dananglin.me.uk/apollo/pokedex/internal/pokeclient"
2024-08-28 12:36:14 +01:00
)
const (
baseURL string = "https://pokeapi.co/api/v2"
locationAreaEndpoint string = "/location-area"
2024-08-28 12:36:14 +01:00
)
type State struct {
Previous *string
Next *string
}
var state State
type command struct {
name string
description string
2024-09-19 11:34:51 +01:00
callback callbackFunc
}
2024-09-19 11:34:51 +01:00
type callbackFunc func() error
2024-08-28 12:36:14 +01:00
func main() {
run()
}
func run() {
2024-09-19 11:34:51 +01:00
client := pokeclient.NewClient(
5*time.Minute,
10*time.Second,
)
2024-09-19 11:34:51 +01:00
commandMap := map[string]command{
"exit": {
name: "exit",
description: "Exit the Pokedex",
callback: commandExit,
},
"help": {
name: "help",
description: "Displays a help message",
2024-09-19 11:34:51 +01:00
callback: nil,
},
"map": {
name: "map",
description: "Displays the next 20 locations in the Pokemon world",
2024-09-19 11:34:51 +01:00
callback: commandMap(client),
},
"mapb": {
name: "map back",
description: "Displays the previous 20 locations in the Pokemon world",
2024-09-19 11:34:51 +01:00
callback: commandMapB(client),
},
}
2024-09-19 11:34:51 +01:00
summaries := summaryMap(commandMap)
2024-09-19 11:34:51 +01:00
commandMap["help"] = command{
name: "help",
description: "Displays a help message",
callback: commandHelp(summaries),
}
2024-09-19 11:34:51 +01:00
fmt.Printf("\nWelcome to the Pokedex!\n")
fmt.Print("\npokedex > ")
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
command := scanner.Text()
cmd, ok := commandMap[command]
if !ok {
fmt.Println("ERROR: Unrecognised command.")
fmt.Print("\npokedex > ")
continue
}
if cmd.callback == nil {
fmt.Println("ERROR: This command is defined but does not have a callback function.")
fmt.Print("\npokedex > ")
2024-09-19 11:34:51 +01:00
continue
}
2024-09-19 11:34:51 +01:00
if err := commandMap[command].callback(); err != nil {
fmt.Printf("ERROR: %v.\n", err)
}
fmt.Print("pokedex > ")
}
2024-09-19 11:34:51 +01:00
}
2024-09-19 11:34:51 +01:00
func commandHelp(summaries map[string]string) callbackFunc {
return func() error {
keys := []string{}
2024-09-19 11:34:51 +01:00
for key := range maps.All(summaries) {
keys = append(keys, key)
}
slices.Sort(keys)
fmt.Printf("\nCommands:\n")
for _, key := range slices.All(keys) {
fmt.Printf("\n%s: %s", key, summaries[key])
}
fmt.Printf("\n\n")
return nil
}
}
func commandExit() error {
os.Exit(0)
return nil
}
2024-09-19 11:34:51 +01:00
func commandMap(client *pokeclient.Client) callbackFunc {
return func() error {
url := state.Next
if url == nil {
url = new(string)
*url = baseURL + locationAreaEndpoint
}
2024-09-19 11:34:51 +01:00
return printResourceList(client, *url)
}
}
2024-09-19 11:34:51 +01:00
func commandMapB(client *pokeclient.Client) callbackFunc {
return func() error {
url := state.Previous
if url == nil {
return fmt.Errorf("no previous locations available")
}
2024-09-19 11:34:51 +01:00
return printResourceList(client, *url)
}
2024-09-19 11:34:51 +01:00
}
2024-09-19 11:34:51 +01:00
func printResourceList(client *pokeclient.Client, url string) error {
list, err := client.GetNamedAPIResourceList(url)
if err != nil {
2024-09-19 11:34:51 +01:00
return fmt.Errorf("unable to get the list of resources: %w", err)
}
2024-09-19 11:34:51 +01:00
state.Next = list.Next
state.Previous = list.Previous
2024-09-19 11:34:51 +01:00
for _, location := range slices.All(list.Results) {
fmt.Println(location.Name)
}
2024-09-19 11:34:51 +01:00
return nil
}
func summaryMap(commandMap map[string]command) map[string]string {
summaries := make(map[string]string)
2024-09-19 11:34:51 +01:00
for key, value := range maps.All(commandMap) {
summaries[key] = value.description
}
2024-09-19 11:34:51 +01:00
return summaries
2024-08-28 12:36:14 +01:00
}