generated from templates/go-generic
checkpoint: updated main
This commit is contained in:
parent
70faf8366a
commit
b6088bfd88
1 changed files with 103 additions and 94 deletions
159
main.go
159
main.go
|
@ -2,14 +2,13 @@ package main
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"maps"
|
||||
"net/http"
|
||||
"os"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/pokedex/internal/pokeclient"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -27,40 +26,22 @@ var state State
|
|||
type command struct {
|
||||
name string
|
||||
description string
|
||||
callback func() error
|
||||
callback callbackFunc
|
||||
}
|
||||
|
||||
type callbackFunc func() error
|
||||
|
||||
func main() {
|
||||
run()
|
||||
}
|
||||
|
||||
func run() {
|
||||
fmt.Print("pokedex > ")
|
||||
client := pokeclient.NewClient(
|
||||
5*time.Minute,
|
||||
10*time.Second,
|
||||
)
|
||||
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
|
||||
for scanner.Scan() {
|
||||
command := scanner.Text()
|
||||
|
||||
cmdMap := getCommandMap()
|
||||
if _, ok := cmdMap[command]; !ok {
|
||||
fmt.Println("ERROR: Unrecognised command.")
|
||||
|
||||
fmt.Print("\npokedex > ")
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if err := cmdMap[command].callback(); err != nil {
|
||||
fmt.Printf("ERROR: %v.\n", err)
|
||||
}
|
||||
|
||||
fmt.Print("pokedex > ")
|
||||
}
|
||||
}
|
||||
|
||||
func getCommandMap() map[string]command {
|
||||
return map[string]command{
|
||||
commandMap := map[string]command{
|
||||
"exit": {
|
||||
name: "exit",
|
||||
description: "Exit the Pokedex",
|
||||
|
@ -69,41 +50,81 @@ func getCommandMap() map[string]command {
|
|||
"help": {
|
||||
name: "help",
|
||||
description: "Displays a help message",
|
||||
callback: commandHelp,
|
||||
callback: nil,
|
||||
},
|
||||
"map": {
|
||||
name: "map",
|
||||
description: "Displays the next 20 locations in the Pokemon world",
|
||||
callback: commandMap,
|
||||
callback: commandMap(client),
|
||||
},
|
||||
"mapb": {
|
||||
name: "map back",
|
||||
description: "Displays the previous 20 locations in the Pokemon world",
|
||||
callback: commandMapB,
|
||||
callback: commandMapB(client),
|
||||
},
|
||||
}
|
||||
|
||||
summaries := summaryMap(commandMap)
|
||||
|
||||
commandMap["help"] = command{
|
||||
name: "help",
|
||||
description: "Displays a help message",
|
||||
callback: commandHelp(summaries),
|
||||
}
|
||||
|
||||
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 > ")
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if err := commandMap[command].callback(); err != nil {
|
||||
fmt.Printf("ERROR: %v.\n", err)
|
||||
}
|
||||
|
||||
fmt.Print("pokedex > ")
|
||||
}
|
||||
}
|
||||
|
||||
func commandHelp() error {
|
||||
cmdMap := getCommandMap()
|
||||
|
||||
func commandHelp(summaries map[string]string) callbackFunc {
|
||||
return func() error {
|
||||
keys := []string{}
|
||||
|
||||
for key := range maps.All(cmdMap) {
|
||||
for key := range maps.All(summaries) {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
||||
slices.Sort(keys)
|
||||
|
||||
fmt.Printf("\nWelcome to the Pokedex!\nUsage:\n")
|
||||
fmt.Printf("\nCommands:\n")
|
||||
|
||||
for _, key := range slices.All(keys) {
|
||||
fmt.Printf("\n%s: %s", key, cmdMap[key].description)
|
||||
fmt.Printf("\n%s: %s", key, summaries[key])
|
||||
}
|
||||
|
||||
fmt.Println("\n")
|
||||
fmt.Printf("\n\n")
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func commandExit() error {
|
||||
|
@ -112,63 +133,51 @@ func commandExit() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func commandMap() error {
|
||||
func commandMap(client *pokeclient.Client) callbackFunc {
|
||||
return func() error {
|
||||
url := state.Next
|
||||
if url == nil {
|
||||
url = new(string)
|
||||
*url = baseURL + locationAreaEndpoint
|
||||
}
|
||||
|
||||
return printMap(*url)
|
||||
return printResourceList(client, *url)
|
||||
}
|
||||
}
|
||||
|
||||
func commandMapB() error {
|
||||
func commandMapB(client *pokeclient.Client) callbackFunc {
|
||||
return func() error {
|
||||
url := state.Previous
|
||||
if url == nil {
|
||||
return fmt.Errorf("no previous locations available")
|
||||
}
|
||||
|
||||
return printMap(*url)
|
||||
return printResourceList(client, *url)
|
||||
}
|
||||
}
|
||||
|
||||
func printMap(url string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
func printResourceList(client *pokeclient.Client, url string) error {
|
||||
list, err := client.GetNamedAPIResourceList(url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating the HTTP request: %w", err)
|
||||
return fmt.Errorf("unable to get the list of resources: %w", err)
|
||||
}
|
||||
|
||||
client := http.Client{}
|
||||
state.Next = list.Next
|
||||
state.Previous = list.Previous
|
||||
|
||||
resp, err := client.Do(request)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting the response from the server: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= 400 {
|
||||
return fmt.Errorf(
|
||||
"received a bad status from %s: (%d) %s",
|
||||
url,
|
||||
resp.StatusCode,
|
||||
resp.Status,
|
||||
)
|
||||
}
|
||||
|
||||
var result NamedAPIResourceList
|
||||
|
||||
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||
return fmt.Errorf("unable to decode the JSON response: %w", err)
|
||||
}
|
||||
|
||||
state.Next = result.Next
|
||||
state.Previous = result.Previous
|
||||
|
||||
for _, location := range slices.All(result.Results) {
|
||||
for _, location := range slices.All(list.Results) {
|
||||
fmt.Println(location.Name)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func summaryMap(commandMap map[string]command) map[string]string {
|
||||
summaries := make(map[string]string)
|
||||
|
||||
for key, value := range maps.All(commandMap) {
|
||||
summaries[key] = value.description
|
||||
}
|
||||
|
||||
return summaries
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue