diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1e67ba..5135306 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ on: - main env: - VERSION_NUMBER: 'v1.6.0' + VERSION_NUMBER: 'v1.6.1' DOCKERHUB_REGISTRY_NAME: 'digitalghostdev/poke-cli' AWS_REGION: 'us-west-2' diff --git a/.goreleaser.yml b/.goreleaser.yml index 46cfe4d..380e571 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -14,7 +14,7 @@ builds: - windows - darwin ldflags: - - -s -w -X main.version=v1.6.0 + - -s -w -X main.version=v1.6.1 archives: - formats: [ 'zip' ] @@ -39,15 +39,15 @@ changelog: homebrew_casks: - name: poke-cli + description: "A hybrid CLI/TUI tool written in Go for viewing Pokémon data from the terminal!" + homepage: "https://docs.poke-cli.com/" + license: MIT conflicts: - formula: poke-cli repository: owner: digitalghost-dev name: homebrew-tap token: "{{.Env.GITHUB_TOKEN}}" - homepage: "https://docs.poke-cli.com/" - description: "A hybrid CLI/TUI tool written in Go for viewing Pokémon data from the terminal!" - license: "Apache License 2.0" hooks: post: install: | @@ -55,21 +55,12 @@ homebrew_casks: system_command "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "#{staged_path}/poke-cli"] end -winget: +scoops: - name: poke-cli - publisher: digitalghost-dev - license: MIT + description: "A hybrid CLI/TUI tool written in Go for viewing Pokémon data from the terminal!" homepage: "https://docs.poke-cli.com/" - short_description: "Pokémon CLI/TUI terminal tool." + license: MIT repository: owner: digitalghost-dev - name: winget-pkgs - token: "{{.Env.GITHUB_TOKEN}}" - branch: "poke-cli-{{.Version}}" - pull_request: - enabled: true - base: - owner: microsoft - name: winget-pkgs - branch: master - description: "A hybrid CLI/TUI tool written in Go for viewing Pokémon data from the terminal!" \ No newline at end of file + name: scoop-bucket + token: "{{ .Env.GITHUB_TOKEN }}" diff --git a/Dockerfile b/Dockerfile index 9ea0df2..c86729c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ RUN go mod download COPY . . -RUN go build -ldflags "-X main.version=v1.6.0" -o poke-cli . +RUN go build -ldflags "-X main.version=v1.6.1" -o poke-cli . # build 2 FROM --platform=$BUILDPLATFORM alpine:3.22 diff --git a/README.md b/README.md index 0ea351b..65e11bf 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ pokemon-logo

Pokémon CLI

version-label - docker-image-size + docker-image-size ci-status-badge
@@ -30,7 +30,7 @@ View future plans in the [Roadmap](#roadmap) section. ## Installation * [Homebrew](#homebrew) -* [Winget](#winget) +* [Scoop](#scoop) * [Linux Packages](#linux-packages) * [Docker Image](#docker-image) * [Binary](#binary) @@ -42,19 +42,24 @@ View future plans in the [Roadmap](#roadmap) section. ```bash brew install --cask digitalghost-dev/tap/poke-cli ```` -2. Verify install: +2. Verify installation: ```bash poke-cli -v ``` -### Winget -1. Install the package: +### Scoop +1. Add the bucket: ```powershell - winget install poke-cli + scoop bucket add digitalghost https://github.com/digitalghost-dev/scoop-bucket.git ``` -2. Verify install: - ```bash +2. Install poke-cli: + ```powershell + scoop install poke-cli + ``` + +3. Verify installation: + ```powershell poke-cli -v ``` @@ -86,11 +91,11 @@ Cloudsmith is a fully cloud-based service that lets you easily create, store, an 3. Choose how to interact with the container: * Run a single command and exit: ```bash - docker run --rm -it digitalghostdev/poke-cli:v1.6.0 [subcommand] flag] + docker run --rm -it digitalghostdev/poke-cli:v1.6.1 [subcommand] flag] ``` * Enter the container and use its shell: ```bash - docker run --rm -it --name poke-cli --entrypoint /bin/sh digitalghostdev/poke-cli:v1.6.0 -c "cd /app && exec sh" + docker run --rm -it --name poke-cli --entrypoint /bin/sh digitalghostdev/poke-cli:v1.6.1 -c "cd /app && exec sh" # placed into the /app directory, run the program with './poke-cli' # example: ./poke-cli ability swift-swim ``` diff --git a/card_data/infrastructure/aws/rds/provider.tf b/card_data/infrastructure/aws/rds/provider.tf index eee0069..56b4453 100755 --- a/card_data/infrastructure/aws/rds/provider.tf +++ b/card_data/infrastructure/aws/rds/provider.tf @@ -1,12 +1,20 @@ provider "aws" { - profile = "terraform-user" - region = "us-west-2" + region = "us-west-2" } terraform { - required_providers { - aws = { - version = "~> 6.7.0" - } + cloud { + organization = "digitalghost-dev" + + workspaces { + project = "poke-cli" + name = "poke-cli" + } } -} + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 6.7.0" + } + } +} \ No newline at end of file diff --git a/card_data/pipelines/definitions.py b/card_data/pipelines/definitions.py new file mode 100644 index 0000000..6941003 --- /dev/null +++ b/card_data/pipelines/definitions.py @@ -0,0 +1,7 @@ +from pathlib import Path +from dagster import definitions, load_from_defs_folder + + +@definitions +def defs(): + return load_from_defs_folder(project_root=Path(__file__).parent.parent) \ No newline at end of file diff --git a/card_data/pipelines/defs/extract/extract_data.py b/card_data/pipelines/defs/extract/extract_data.py new file mode 100644 index 0000000..f8c9e94 --- /dev/null +++ b/card_data/pipelines/defs/extract/extract_data.py @@ -0,0 +1,177 @@ +import time +import json + +import dagster as dg +import polars as pl + +from pydantic import BaseModel, HttpUrl, ValidationError +from typing import Optional +from termcolor import colored + +import requests + +class Series(BaseModel): + id: str + name: str + logo: Optional[HttpUrl] = None + + +class Set(BaseModel): + series_id: str + set_id: str + set_name: str + official_card_count: int | None + total_card_count: int | None + logo: Optional[str] = None + symbol: Optional[str] = None + + +@dg.asset(kinds={"API", "Polars", "Pydantic"}) +def extract_series_data() -> pl.DataFrame: + url: str = "https://api.tcgdex.net/v2/en/series" + data = requests.get(url).json() + + # Pydantic validation + try: + validated: list[Series] = [Series(**item) for item in data] + print( + colored(" ✓", "green"), "Pydantic validation passed for all series entries." + ) + except ValidationError as e: + print(colored(" ✖", "red"), "Pydantic validation failed.") + print(e) + raise + + filtered = [s.model_dump(mode="json") for s in validated if s.id in ["swsh", "sv"]] + return pl.DataFrame(filtered) + + +@dg.asset(kinds={"API", "Polars", "Pydantic"}) +def extract_set_data() -> pl.DataFrame: + url_list = [ + "https://api.tcgdex.net/v2/en/series/swsh", + "https://api.tcgdex.net/v2/en/series/sv" + ] + + flat: list[dict] = [] + + for url in url_list: + data = requests.get(url).json() + series_id = data.get("id") + + for s in data.get("sets", []): + entry = { + "series_id": series_id, + "set_id": s.get("id"), + "set_name": s.get("name"), + "official_card_count": s.get("cardCount", {}).get("official"), + "total_card_count": s.get("cardCount", {}).get("total"), + "logo": s.get("logo"), + "symbol": s.get("symbol") + } + flat.append(entry) + + # Pydantic validation + try: + validated: list[Set] = [Set(**item) for item in flat] + print( + colored(" ✓", "green"), + "Pydantic validation passed for all set entries." + ) + except ValidationError as e: + print(colored(" ✖", "red"), "Pydantic validation failed.") + print(e) + raise + + return pl.DataFrame([s.model_dump(mode="json") for s in validated]) + + +@dg.asset(kinds={"API"}) +def extract_card_url_from_set() -> list: + urls = [ + "https://api.tcgdex.net/v2/en/sets/sv01", + "https://api.tcgdex.net/v2/en/sets/sv02", + ] + + all_card_urls = [] # Initialize empty list to collect all URLs + + for url in urls: + try: + r = requests.get(url) + r.raise_for_status() + + data = r.json()["cards"] + + set_card_urls = [f"https://api.tcgdex.net/v2/en/cards/{card['id']}" for card in data] + all_card_urls.extend(set_card_urls) # Add all URLs from this set + + time.sleep(0.1) + + except requests.RequestException as e: + print(f"Failed to fetch set {url}: {e}") + + return all_card_urls + + +@dg.asset(deps=[extract_card_url_from_set], kinds={"API"}) +def extract_card_info() -> list: + card_url_list = extract_card_url_from_set() + cards_list = [] + + for url in card_url_list: + try: + r = requests.get(url) + r.raise_for_status() + data = r.json() + cards_list.append(data) + time.sleep(0.1) + except requests.RequestException as e: + print(f"Failed to fetch {url}: {e}") + + return cards_list + + +@dg.asset(deps=[extract_card_info], kinds={"Polars"}) +def create_card_dataframe() -> pl.DataFrame: + cards_list = extract_card_info() + + all_flat_cards = [] + + for card in cards_list: + flat = {} + + # Copy top-level scalar values + scalar_keys = ['category', 'hp', 'id', 'illustrator', 'image', 'localId', + 'name', 'rarity', 'regulationMark', 'retreat', 'stage'] + for key in scalar_keys: + flat[key] = card.get(key) + + # Flatten nested dicts with prefixes + for key, value in card.get("legal", {}).items(): + flat[f"legal_{key}"] = value + + for key, value in card.get("set", {}).items(): + if isinstance(value, dict): + for sub_key, sub_val in value.items(): + flat[f"set_{key}_{sub_key}"] = sub_val + else: + flat[f"set_{key}"] = value + + # Flatten types (list of strings) + flat["types"] = ", ".join(card.get("types", [])) + + flat["attacks_json"] = json.dumps(card.get("attacks", []), ensure_ascii=False) + + attacks = card.get("attacks", []) + for i, atk in enumerate(attacks): + prefix = f"attack_{i+1}" + flat[f"{prefix}_name"] = atk.get("name") + flat[f"{prefix}_damage"] = atk.get("damage") + flat[f"{prefix}_effect"] = atk.get("effect") + flat[f"{prefix}_cost"] = ", ".join(atk.get("cost", [])) + + all_flat_cards.append(flat) + + df = pl.DataFrame(all_flat_cards) + + return df diff --git a/cmd/pokemon/pokemon.go b/cmd/pokemon/pokemon.go index 0dece62..061e480 100644 --- a/cmd/pokemon/pokemon.go +++ b/cmd/pokemon/pokemon.go @@ -75,22 +75,26 @@ func PokemonCommand() (string, error) { output.WriteString(err.Error()) return output.String(), err } - capitalizedString := cases.Title(language.English).String(strings.ReplaceAll(pokemonName, "-", " ")) - // Weight calculation - weightKilograms := float64(pokemonStruct.Weight) / 10 - weightPounds := float64(weightKilograms) * 2.20462 + pokemonSpeciesStruct, err := connections.PokemonSpeciesApiCall("pokemon-species", pokemonName, connections.APIURL) + if err != nil { + output.WriteString(err.Error()) + return output.String(), err + } + + capitalizedString := cases.Title(language.English).String(strings.ReplaceAll(pokemonName, "-", " ")) - // Height calculation - heightMeters := float64(pokemonStruct.Height) / 10 - heightFeet := heightMeters * 3.28084 - feet := int(heightFeet) - inches := int(math.Round((heightFeet - float64(feet)) * 12)) // Use math.Round to avoid truncation + entry := func(w io.Writer) { + for _, entry := range pokemonSpeciesStruct.FlavorTextEntries { + if entry.Language.Name == "en" && (entry.Version.Name == "x" || entry.Version.Name == "shield" || entry.Version.Name == "scarlet") { + flavorText := strings.ReplaceAll(entry.FlavorText, "\n", " ") + flavorText = strings.Join(strings.Fields(flavorText), " ") - // Adjust for rounding to 12 inches (carry over to the next foot) - if inches == 12 { - feet++ - inches = 0 + wrapped := utils.WrapText(flavorText, 60) + fmt.Fprintln(w, wrapped) + return + } + } } typing := func(w io.Writer) { @@ -117,15 +121,55 @@ func PokemonCommand() (string, error) { fmt.Fprintln(w, joinedTypes) } - var typeOutput bytes.Buffer + metrics := func(w io.Writer) { + // Weight calculation + weightKilograms := float64(pokemonStruct.Weight) / 10 + weightPounds := float64(weightKilograms) * 2.20462 + + // Height calculation + heightMeters := float64(pokemonStruct.Height) / 10 + heightFeet := heightMeters * 3.28084 + feet := int(heightFeet) + inches := int(math.Round((heightFeet - float64(feet)) * 12)) // Use math.Round to avoid truncation + + // Adjust for rounding to 12 inches (carry over to the next foot) + if inches == 12 { + feet++ + inches = 0 + } + + fmt.Fprintf(w, "\n%s National Pokédex #: %d\n%s Weight: %.1fkg (%.1f lbs)\n%s Height: %.1fm (%d′%02d″)\n", + styling.ColoredBullet, pokemonStruct.ID, + styling.ColoredBullet, weightKilograms, weightPounds, + styling.ColoredBullet, heightMeters, feet, inches) + } + + species := func(w io.Writer) { + if pokemonSpeciesStruct.EvolvesFromSpecies.Name != "" { + evolvesFrom := pokemonSpeciesStruct.EvolvesFromSpecies.Name + + capitalizedPokemonName := cases.Title(language.English).String(strings.ReplaceAll(evolvesFrom, "-", " ")) + fmt.Fprintf(w, "%s %s %s", styling.ColoredBullet, "Evolves from:", capitalizedPokemonName) + } else { + fmt.Fprintf(w, "%s %s", styling.ColoredBullet, "Basic Pokémon") + } + } + + var ( + entryOutput bytes.Buffer + typeOutput bytes.Buffer + metricsOutput bytes.Buffer + speciesOutput bytes.Buffer + ) + + entry(&entryOutput) typing(&typeOutput) + metrics(&metricsOutput) + species(&speciesOutput) output.WriteString(fmt.Sprintf( - "Your selected Pokémon: %s\n%s\n%s National Pokédex #: %d\n%s Weight: %.1fkg (%.1f lbs)\n%s Height: %.1fm (%d′%02d″)\n", - capitalizedString, typeOutput.String(), - styling.ColoredBullet, pokemonStruct.ID, - styling.ColoredBullet, weightKilograms, weightPounds, - styling.ColoredBullet, heightMeters, feet, inches, + "Your selected Pokémon: %s\n%s%s%s%s\n", + capitalizedString, entryOutput.String(), typeOutput.String(), metricsOutput.String(), speciesOutput.String(), )) if *imageFlag != "" || *shortImageFlag != "" { @@ -142,38 +186,22 @@ func PokemonCommand() (string, error) { } } - if *abilitiesFlag || *shortAbilitiesFlag { - if err := flags.AbilitiesFlag(&output, endpoint, pokemonName); err != nil { - output.WriteString(fmt.Sprintf("error parsing flags: %v\n", err)) - return "", fmt.Errorf("error parsing flags: %w", err) - } - } - - if *defenseFlag || *shortDefenseFlag { - if err := flags.DefenseFlag(&output, endpoint, pokemonName); err != nil { - output.WriteString(fmt.Sprintf("error parsing flags: %v\n", err)) - return "", fmt.Errorf("error parsing flags: %w", err) - } - } - - if *moveFlag || *shortMoveFlag { - if err := flags.MovesFlag(&output, endpoint, pokemonName); err != nil { - output.WriteString(fmt.Sprintf("error parsing flags: %v\n", err)) - return "", fmt.Errorf("error parsing flags: %w", err) - } + flagChecks := []struct { + condition bool + flagFunc func(io.Writer, string, string) error + }{ + {*abilitiesFlag || *shortAbilitiesFlag, flags.AbilitiesFlag}, + {*defenseFlag || *shortDefenseFlag, flags.DefenseFlag}, + {*moveFlag || *shortMoveFlag, flags.MovesFlag}, + {*typesFlag || *shortTypesFlag, flags.TypesFlag}, + {*statsFlag || *shortStatsFlag, flags.StatsFlag}, } - if *typesFlag || *shortTypesFlag { - if err := flags.TypesFlag(&output, endpoint, pokemonName); err != nil { - output.WriteString(fmt.Sprintf("error parsing flags: %v\n", err)) - return "", fmt.Errorf("error parsing flags: %w", err) - } - } - - if *statsFlag || *shortStatsFlag { - if err := flags.StatsFlag(&output, endpoint, pokemonName); err != nil { - output.WriteString(fmt.Sprintf("error parsing flags: %v\n", err)) - return "", fmt.Errorf("error parsing flags: %w", err) + for _, check := range flagChecks { + if check.condition { + if err := check.flagFunc(&output, endpoint, pokemonName); err != nil { + return utils.HandleFlagError(&output, err) + } } } diff --git a/cmd/utils/output.go b/cmd/utils/output.go index e942329..e658261 100644 --- a/cmd/utils/output.go +++ b/cmd/utils/output.go @@ -3,6 +3,7 @@ package utils import ( "fmt" "os" + "strings" ) // HandleCommandOutput takes a function that returns (string, error) and wraps it in a no-argument @@ -19,3 +20,37 @@ func HandleCommandOutput(fn func() (string, error)) func() int { return 0 } } + +func HandleFlagError(output *strings.Builder, err error) (string, error) { + fmt.Fprintf(output, "error parsing flags: %v\n", err) + return "", fmt.Errorf("error parsing flags: %w", err) +} + +func WrapText(text string, width int) string { + words := strings.Fields(text) + if len(words) == 0 { + return text + } + + var result strings.Builder + lineLength := 0 + + for _, word := range words { + wordLen := len(word) + + if lineLength > 0 && lineLength+1+wordLen > width { + result.WriteString("\n") + lineLength = 0 + } + + if lineLength > 0 { + result.WriteString(" ") + lineLength++ + } + + result.WriteString(word) + lineLength += wordLen + } + + return result.String() +} diff --git a/cmd/utils/output_test.go b/cmd/utils/output_test.go index 2454850..cc2c865 100644 --- a/cmd/utils/output_test.go +++ b/cmd/utils/output_test.go @@ -4,6 +4,7 @@ import ( "errors" "io" "os" + "strings" "testing" ) @@ -53,3 +54,85 @@ func TestHandleCommandOutput_Error(t *testing.T) { t.Errorf("expected 'something failed\\n', got %q", output) } } + +func TestHandleFlagError_WithError(t *testing.T) { + var b strings.Builder + msg, err := HandleFlagError(&b, errors.New("bad flag")) + + if got := b.String(); got != "error parsing flags: bad flag\n" { + t.Fatalf("builder content mismatch: got %q", got) + } + if msg != "" { + t.Fatalf("expected empty message, got %q", msg) + } + if err == nil { + t.Fatalf("expected non-nil error") + } + if err.Error() != "error parsing flags: bad flag" { + t.Fatalf("unexpected error message: %q", err.Error()) + } +} + +func TestHandleFlagError_NilError(t *testing.T) { + var b strings.Builder + msg, err := HandleFlagError(&b, nil) + + if got := b.String(); got != "error parsing flags: \n" { + t.Fatalf("builder content mismatch for nil error: got %q", got) + } + if msg != "" { + t.Fatalf("expected empty message, got %q", msg) + } + if err == nil { + t.Fatalf("expected non-nil error when wrapping nil") + } + // Document current behavior of fmt.Errorf with %w and nil + if err.Error() != "error parsing flags: %!w()" { + t.Fatalf("unexpected error message for nil wrap: %q", err.Error()) + } +} + +func TestWrapText_EmptyString(t *testing.T) { + if got := WrapText("", 10); got != "" { + t.Fatalf("expected empty string, got %q", got) + } +} + +func TestWrapText_OnlySpaces(t *testing.T) { + if got := WrapText(" ", 10); got != " " { + t.Fatalf("expected to preserve spaces, got %q", got) + } +} + +func TestWrapText_NoWrap(t *testing.T) { + if got := WrapText("hello world", 20); got != "hello world" { + t.Fatalf("expected 'hello world', got %q", got) + } +} + +func TestWrapText_CollapseSpaces(t *testing.T) { + if got := WrapText("hello world", 20); got != "hello world" { + t.Fatalf("expected collapsed spaces, got %q", got) + } +} + +func TestWrapText_WrapAtWidth(t *testing.T) { + if got := WrapText("hello world", 10); got != "hello\nworld" { + t.Fatalf("expected wrap at width, got %q", got) + } +} + +func TestWrapText_LongWord(t *testing.T) { + in := "supercalifragilisticexpialidocious" + if got := WrapText(in, 10); got != in { + t.Fatalf("expected long word unchanged, got %q", got) + } +} + +func TestWrapText_MultipleLines(t *testing.T) { + in := "one two three four five" + expected := "one two\nthree\nfour\nfive" + if got := WrapText(in, 7); got != expected { + t.Fatalf("expected %q, got %q", expected, got) + } +} diff --git a/connections/connection.go b/connections/connection.go index 9d0f1a4..ac6e839 100644 --- a/connections/connection.go +++ b/connections/connection.go @@ -5,11 +5,12 @@ import ( "errors" "flag" "fmt" - "github.com/digitalghost-dev/poke-cli/structs" - "github.com/digitalghost-dev/poke-cli/styling" "io" "net/http" "net/url" + + "github.com/digitalghost-dev/poke-cli/structs" + "github.com/digitalghost-dev/poke-cli/styling" ) const APIURL = "https://pokeapi.co/api/v2/" @@ -120,6 +121,24 @@ func PokemonApiCall(endpoint string, pokemonName string, baseURL string) (struct return pokemonStruct, pokemonStruct.Name, nil } +// PokemonSpeciesApiCall function for calling the pokemon endpoint of the pokeAPI +func PokemonSpeciesApiCall(endpoint string, pokemonSpeciesName string, baseURL string) (structs.PokemonSpeciesJSONStruct, error) { + fullURL := baseURL + endpoint + "/" + pokemonSpeciesName + + var pokemonSpeciesStruct structs.PokemonSpeciesJSONStruct + err := ApiCallSetup(fullURL, &pokemonSpeciesStruct, false) + + if err != nil { + errMessage := styling.ErrorBorder.Render( + styling.ErrorColor.Render("✖ Error!"), + "\nPokémon not found.\n\u2022 Perhaps a typo?\n\u2022 Missing a hyphen instead of a space?", + ) + return structs.PokemonSpeciesJSONStruct{}, fmt.Errorf("%s", errMessage) + } + + return pokemonSpeciesStruct, nil +} + // TypesApiCall function for calling the type endpoint of the pokeAPI func TypesApiCall(endpoint string, typesName string, baseURL string) (structs.TypesJSONStruct, string, int) { fullURL := baseURL + endpoint + "/" + typesName diff --git a/connections/connection_test.go b/connections/connection_test.go index dc4b186..29f1e70 100644 --- a/connections/connection_test.go +++ b/connections/connection_test.go @@ -2,12 +2,13 @@ package connections import ( "encoding/json" - "github.com/digitalghost-dev/poke-cli/structs" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "net/http" "net/http/httptest" "testing" + + "github.com/digitalghost-dev/poke-cli/structs" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // TestApiCallSetup - Test for the ApiCallSetup function @@ -239,3 +240,41 @@ func TestTypesApiCall(t *testing.T) { assert.Equal(t, "electric", name) assert.Equal(t, 13, id) } + +func TestPokemonSpeciesApiCall(t *testing.T) { + // Successful API call returns expected species data + t.Run("Successful API call returns expected species", func(t *testing.T) { + expectedSpecies := structs.PokemonSpeciesJSONStruct{ + Name: "flareon", + } + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + err := json.NewEncoder(w).Encode(expectedSpecies) + assert.NoError(t, err, "Expected no error for encoding response") + })) + defer ts.Close() + + species, err := PokemonSpeciesApiCall("/pokemon-species", "flareon", ts.URL) + + require.NoError(t, err, "Expected no error on successful API call") + assert.Equal(t, expectedSpecies, species, "Expected species struct does not match") + }) + + // Failed API call returns styled error + t.Run("Failed API call returns styled error", func(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Simulate API failure (e.g., 404 Not Found) + http.Error(w, "Not Found", http.StatusNotFound) + })) + defer ts.Close() + + species, err := PokemonSpeciesApiCall("/pokemon-species", "non-existent-species", ts.URL) + + require.Error(t, err, "Expected an error for invalid species") + assert.Equal(t, structs.PokemonSpeciesJSONStruct{}, species, "Expected empty species struct on error") + + assert.Contains(t, err.Error(), "Pokémon not found", "Expected 'Pokémon not found' in error message") + assert.Contains(t, err.Error(), "Perhaps a typo?", "Expected helpful suggestion in error message") + }) +} diff --git a/flags/pokemonflagset.go b/flags/pokemonflagset.go index 51c93dc..cac01af 100644 --- a/flags/pokemonflagset.go +++ b/flags/pokemonflagset.go @@ -330,18 +330,17 @@ func ImageFlag(w io.Writer, endpoint string, pokemonName string, size string) er } // Anonymous function to transform the image to a string - // ToString generates an ASCII representation of the image with color ToString := func(width int, height int, img image.Image) string { // Resize the image to the specified width, preserving aspect ratio img = imaging.Resize(img, width, height, imaging.NearestNeighbor) b := img.Bounds() - imageWidth := b.Max.X - 2 // Adjust width to exclude margins - h := b.Max.Y - 4 // Adjust height to exclude margins + + imageWidth := b.Max.X + h := b.Max.Y str := strings.Builder{} - // Loop through the image pixels, two rows at a time - for heightCounter := 2; heightCounter < h; heightCounter += 2 { - for x := 1; x < imageWidth; x++ { + for heightCounter := 0; heightCounter < h-1; heightCounter += 2 { + for x := 0; x < imageWidth; x++ { // Get the color of the current and next row's pixels c1, _ := styling.MakeColor(img.At(x, heightCounter)) color1 := lipgloss.Color(c1.Hex()) diff --git a/nfpm.yaml b/nfpm.yaml index 76d0671..d7cf5d6 100644 --- a/nfpm.yaml +++ b/nfpm.yaml @@ -1,7 +1,7 @@ name: "poke-cli" arch: "arm64" platform: "linux" -version: "v1.6.0" +version: "v1.6.1" section: "default" version_schema: semver maintainer: "Christian S" diff --git a/structs/structs.go b/structs/structs.go index 6cb083c..14fdaf1 100644 --- a/structs/structs.go +++ b/structs/structs.go @@ -143,6 +143,26 @@ type PokemonJSONStruct struct { } `json:"stats"` } +// PokemonSpeciesJSONStruct pokemon-species endpoint from API +type PokemonSpeciesJSONStruct struct { + Name string `json:"name"` + EvolvesFromSpecies struct { + Name string `json:"name"` + URL string `json:"url"` + } `json:"evolves_from_species"` + FlavorTextEntries []struct { + FlavorText string `json:"flavor_text"` + Language struct { + Name string `json:"name"` + URL string `json:"url"` + } `json:"language"` + Version struct { + Name string `json:"name"` + URL string `json:"url"` + } `json:"version"` + } `json:"flavor_text_entries"` +} + // TypesJSONStruct type endpoint from API type TypesJSONStruct struct { Name string `json:"name"` diff --git a/testdata/main_latest_flag.golden b/testdata/main_latest_flag.golden index b4cf72d..59c536f 100644 --- a/testdata/main_latest_flag.golden +++ b/testdata/main_latest_flag.golden @@ -1,6 +1,6 @@ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ ┃ ┃ Latest available version: ┃ -┃ • v1.5.2 ┃ +┃ • v1.6.0 ┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ diff --git a/testdata/pokemon_abilities.golden b/testdata/pokemon_abilities.golden index 797379d..e0d27a1 100644 --- a/testdata/pokemon_abilities.golden +++ b/testdata/pokemon_abilities.golden @@ -1,10 +1,13 @@ Your selected Pokémon: Metagross +With four linked brains, it’s more intelligent than a +supercomputer, and it uses calculations to analyze foes. Steel Psychic • National Pokédex #: 376 • Weight: 550.0kg (1212.5 lbs) • Height: 1.6m (5′03″) +• Evolves from: Metang ───────── Abilities Ability 1: Clear Body diff --git a/testdata/pokemon_defense.golden b/testdata/pokemon_defense.golden index ecbdc92..3564883 100644 --- a/testdata/pokemon_defense.golden +++ b/testdata/pokemon_defense.golden @@ -1,10 +1,13 @@ Your selected Pokémon: Dragapult +Apparently the Dreepy inside Dragapult’s horns eagerly +look forward to being launched out at Mach speeds. Dragon Ghost • National Pokédex #: 887 • Weight: 50.0kg (110.2 lbs) • Height: 3.0m (9′10″) +• Evolves from: Drakloak ───────────── Type Defenses Immune: Fighting, Normal diff --git a/testdata/pokemon_defense_ability_immunities.golden b/testdata/pokemon_defense_ability_immunities.golden index 2cf19a0..1617e68 100644 --- a/testdata/pokemon_defense_ability_immunities.golden +++ b/testdata/pokemon_defense_ability_immunities.golden @@ -1,10 +1,13 @@ Your selected Pokémon: Gastrodon +When its natural enemy attacks, it oozes purple fluid and +escapes. Water Ground • National Pokédex #: 423 • Weight: 29.9kg (65.9 lbs) • Height: 0.9m (2′11″) +• Evolves from: Shellos ───────────── Type Defenses Immune: Electric diff --git a/testdata/pokemon_image.golden b/testdata/pokemon_image.golden index a42575f..192501f 100644 --- a/testdata/pokemon_image.golden +++ b/testdata/pokemon_image.golden @@ -1,51 +1,58 @@ Your selected Pokémon: Skeledirge +The fiery bird changes shape when Skeledirge sings. Rumor +has it that the bird was born when the fireball on +Skeledirge’s head gained a soul. Fire Ghost • National Pokédex #: 911 • Weight: 326.5kg (719.8 lbs) • Height: 1.6m (5′03″) +• Evolves from: Crocalor ───── Image -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ diff --git a/testdata/pokemon_image_flag_non-valid_size.golden b/testdata/pokemon_image_flag_non-valid_size.golden index e2a70b2..4f24d0f 100644 --- a/testdata/pokemon_image_flag_non-valid_size.golden +++ b/testdata/pokemon_image_flag_non-valid_size.golden @@ -1,10 +1,13 @@ Your selected Pokémon: Floatzel +It floats using its well-developed flotation sac. It assists +in the rescues of drowning people. Water • National Pokédex #: 419 • Weight: 33.5kg (73.9 lbs) • Height: 1.1m (3′07″) +• Evolves from: Buizel ───── Image ╭───────────────────────────╮ diff --git a/testdata/pokemon_moves.golden b/testdata/pokemon_moves.golden index 25441c1..1388551 100644 --- a/testdata/pokemon_moves.golden +++ b/testdata/pokemon_moves.golden @@ -1,28 +1,35 @@ Your selected Pokémon: Greninja +It creates throwing stars out of compressed water. When it +spins them and throws them at high speed, these stars can +split metal in two. + + Water Dark + • National Pokédex #: 658 • Weight: 40.0kg (88.2 lbs) -• Height: 4.9m (4′11″) +• Height: 1.5m (4′11″) +• Evolves from: Frogadier ─────────────── Learnable Moves -┌──────────────────┬────────┬──────────┬────────┬─────┐ -│Name │Level │Type │Accuracy│Power│ -├──────────────────┼────────┼──────────┼────────┼─────┤ -│Water Shuriken │0 │Water │100 │15 │ -│Pound │1 │Normal │100 │40 │ -│Growl │1 │Normal │100 │0 │ -│Water Gun │1 │Water │100 │40 │ -│Quick Attack │1 │Normal │100 │40 │ -│Night Slash │1 │Dark │100 │70 │ -│Role Play │1 │Psychic │0 │0 │ -│Haze │1 │Ice │0 │0 │ -│Lick │10 │Ghost │100 │30 │ -│Water Pulse │14 │Water │100 │60 │ -│Smokescreen │19 │Normal │100 │0 │ -│Shadow Sneak │23 │Ghost │100 │40 │ -│Spikes │28 │Ground │0 │0 │ -│Aerial Ace │33 │Flying │0 │60 │ -│Substitute │42 │Normal │0 │0 │ -│Extrasensory │49 │Psychic │100 │80 │ -│Double Team │56 │Normal │0 │0 │ -│Hydro Pump │68 │Water │80 │110 │ -└──────────────────┴────────┴──────────┴────────┴─────┘ +┌──────────────────┬────────┬──────────┬──────────┬────────┐ +│Name │Level │Type │Accuracy │Power │ +├──────────────────┼────────┼──────────┼──────────┼────────┤ +│Water Shuriken │0 │Water │100 │15 │ +│Role Play │1 │Psychic │0 │0 │ +│Pound │1 │Normal │100 │40 │ +│Water Gun │1 │Water │100 │40 │ +│Quick Attack │1 │Normal │100 │40 │ +│Night Slash │1 │Dark │100 │70 │ +│Growl │1 │Normal │100 │0 │ +│Haze │1 │Ice │0 │0 │ +│Lick │10 │Ghost │100 │30 │ +│Water Pulse │14 │Water │100 │60 │ +│Smokescreen │19 │Normal │100 │0 │ +│Shadow Sneak │23 │Ghost │100 │40 │ +│Spikes │28 │Ground │0 │0 │ +│Aerial Ace │33 │Flying │0 │60 │ +│Substitute │42 │Normal │0 │0 │ +│Extrasensory │49 │Psychic │100 │80 │ +│Double Team │56 │Normal │0 │0 │ +│Hydro Pump │68 │Water │80 │110 │ +└──────────────────┴────────┴──────────┴──────────┴────────┘ diff --git a/testdata/pokemon_no_flags_dual_type.golden b/testdata/pokemon_no_flags_dual_type.golden index 4c00755..078f0eb 100644 --- a/testdata/pokemon_no_flags_dual_type.golden +++ b/testdata/pokemon_no_flags_dual_type.golden @@ -1,7 +1,10 @@ Your selected Pokémon: Victini +This Pokémon brings victory. It is said that Trainers with +Victini always win, regardless of the type of encounter. Psychic Fire • National Pokédex #: 494 • Weight: 4.0kg (8.8 lbs) • Height: 0.4m (1′04″) +• Basic Pokémon diff --git a/testdata/pokemon_stats.golden b/testdata/pokemon_stats.golden index 255d44c..86d40dd 100644 --- a/testdata/pokemon_stats.golden +++ b/testdata/pokemon_stats.golden @@ -1,10 +1,13 @@ Your selected Pokémon: Toxicroak +It has a poison sac at its throat. When it croaks, the +stored poison is churned for greater potency. Poison Fighting • National Pokédex #: 454 • Weight: 44.4kg (97.9 lbs) • Height: 1.3m (4′03″) +• Evolves from: Croagunk ────────── Base Stats HP ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 83 diff --git a/testdata/pokemon_types.golden b/testdata/pokemon_types.golden deleted file mode 100644 index 52306ce..0000000 --- a/testdata/pokemon_types.golden +++ /dev/null @@ -1,8 +0,0 @@ -Your selected Pokémon: Armarouge -• National Pokédex #: 936 -• Weight: 85.0kg (187.4 lbs) -• Height: 4.9m (4′11″) -────── -Typing -Type 1: Fire -Type 2: Psychic