A command-line REPL (Read-Eval-Print Loop) application for exploring the Pokemon world using the PokeAPI.
- Interactive REPL: Command-line interface for exploring Pokemon locations
- Command History: Use up/down arrow keys to cycle through previous commands
- Location Navigation: Browse through 20 location areas at a time
- Pagination: Navigate forward and backward through location pages
- Location Exploration: Discover which Pokemon can be found in specific areas
- Pokemon Catching: Catch Pokemon with difficulty-based success rates
- Pokemon Collection: Build your Pokedex by catching Pokemon
- Pokemon Inspection: View detailed stats, types, and attributes of caught Pokemon
- Intelligent Caching: Reduces API load and improves response times dramatically
- Command Arguments: Support for parameterized commands (e.g.,
explore <location>,catch <pokemon>) - Clean Architecture: Well-organized code with internal packages for separation of concerns
# Clone the repository
git clone https://github.com/remuscazacu/pokedexcli.git
cd pokedexcli
# Build the application
go build
# Run the application
./pokedexcli| Command | Description |
|---|---|
help |
Displays a help message with all available commands |
exit |
Exit the Pokedex |
map |
Displays the names of 20 location areas (next page) |
mapb |
Displays the previous 20 location areas (previous page) |
explore <location_area> |
Displays the Pokemon found in a specific location area |
catch <pokemon> |
Attempt to catch a Pokemon (catch rate based on difficulty) |
inspect <pokemon> |
View details about a caught Pokemon |
pokedex |
List all caught Pokemon |
Pokedex > help
Welcome to the Pokedex!
Usage:
help: Displays a help message
exit: Exit the Pokedex
map: Displays the names of 20 location areas
mapb: Displays the previous 20 location areas
explore <location_area>: Displays the Pokemon found in a location area
catch <pokemon>: Attempt to catch a Pokemon
inspect <pokemon>: View details about a caught Pokemon
pokedex: List all caught Pokemon
Pokedex > map
canalave-city-area
eterna-city-area
pastoria-city-area
sunyshore-city-area
sinnoh-pokemon-league-area
oreburgh-mine-1f
oreburgh-mine-b1f
valley-windworks-area
eterna-forest-area
fuego-ironworks-area
mt-coronet-1f-route-207
mt-coronet-2f
mt-coronet-3f
mt-coronet-exterior-snowfall
mt-coronet-exterior-blizzard
mt-coronet-4f
mt-coronet-4f-small-room
mt-coronet-5f
mt-coronet-6f
mt-coronet-1f-from-exterior
Pokedex > map
mt-coronet-1f-route-216
mt-coronet-1f-route-211
mt-coronet-b1f
great-marsh-area-1
great-marsh-area-2
great-marsh-area-3
great-marsh-area-4
great-marsh-area-5
great-marsh-area-6
solaceon-ruins-2f
solaceon-ruins-1f
solaceon-ruins-b1f-a
solaceon-ruins-b1f-b
solaceon-ruins-b1f-c
solaceon-ruins-b2f-a
solaceon-ruins-b2f-b
solaceon-ruins-b2f-c
solaceon-ruins-b3f-a
solaceon-ruins-b3f-b
solaceon-ruins-b3f-c
Pokedex > mapb
canalave-city-area
eterna-city-area
pastoria-city-area
sunyshore-city-area
sinnoh-pokemon-league-area
oreburgh-mine-1f
oreburgh-mine-b1f
valley-windworks-area
eterna-forest-area
fuego-ironworks-area
mt-coronet-1f-route-207
mt-coronet-2f
mt-coronet-3f
mt-coronet-exterior-snowfall
mt-coronet-exterior-blizzard
mt-coronet-4f
mt-coronet-4f-small-room
mt-coronet-5f
mt-coronet-6f
mt-coronet-1f-from-exterior
Pokedex > explore pastoria-city-area
Exploring pastoria-city-area...
Found Pokemon:
- tentacool
- tentacruel
- magikarp
- gyarados
- remoraid
- octillery
- wingull
- pelipper
- shellos
- gastrodon
Pokedex > catch pikachu
Throwing a Pokeball at pikachu...
pikachu was caught!
You may now inspect it with the inspect command.
Pokedex > catch magikarp
Throwing a Pokeball at magikarp...
magikarp was caught!
You may now inspect it with the inspect command.
Pokedex > catch blissey
Throwing a Pokeball at blissey...
blissey escaped!
Pokedex > inspect pikachu
Name: pikachu
Height: 4
Weight: 60
Stats:
-hp: 35
-attack: 55
-defense: 40
-special-attack: 50
-special-defense: 50
-speed: 90
Types:
- electric
Pokedex > pokedex
Your Pokedex:
- pikachu
- magikarp
Pokedex > exit
Closing the Pokedex... Goodbye!
pokedexcli/
├── main.go # Application entry point
├── repl.go # REPL implementation and commands
├── internal/
│ ├── pokeapi/ # PokeAPI client package
│ │ ├── pokeapi.go # HTTP client with caching
│ │ └── pokeapi_test.go # API client tests
│ └── pokecache/ # Caching package
│ ├── pokecache.go # Thread-safe cache implementation
│ └── pokecache_test.go # Cache tests
├── main_test.go # Main function tests
└── repl_test.go # REPL and command tests
Thread-safe caching system with automatic cleanup.
Key Components:
Cachestruct: Holds cached entries with mutex protectioncacheEntrystruct: Stores creation timestamp and raw dataNewCache(interval time.Duration): Creates cache with configurable TTLAdd(key string, val []byte): Stores data in cacheGet(key string) ([]byte, bool): Retrieves cached data- Background reaper: Automatically removes expired entries
Features:
- Thread-safe using
sync.RWMutex - Automatic expiration via background goroutine
- Configurable time-to-live (TTL)
- Efficient read/write locking
PokeAPI HTTP client with integrated caching.
Key Components:
Clientstruct: Manages API interactions with cacheNewClient(cache *pokecache.Cache): Creates API clientGetLocationAreas(url *string): Fetches location areas list with cachingGetLocationArea(name string): Fetches specific location area details with cachingGetPokemon(name string): Fetches specific Pokemon data with cachingLocationAreasResponse: JSON response structure for location listsLocationAreaResponse: JSON response structure for location details with Pokemon encountersPokemonResponse: JSON response structure for Pokemon data (stats, types, base experience, etc.)
Caching Strategy:
- Check cache using URL as key
- On cache hit: Return cached data immediately
- On cache miss: Fetch from API, store in cache, return data
The caching system provides dramatic performance improvements by storing API responses in memory:
- Cache Key: Full URL endpoint (e.g.,
https://pokeapi.co/api/v2/location-area/) - Cache Check: Before making HTTP request, checks if URL exists in cache
- Cache Hit: Returns cached JSON data (unmarshals and returns)
- Cache Miss: Makes HTTP request, stores raw response body in cache
- Automatic Cleanup: Background goroutine removes entries older than 5 minutes
Default cache TTL: 5 minutes
The cache can be configured by modifying the duration in repl.go:
cache := pokecache.NewCache(5 * time.Minute)Real-world performance measurements:
| Request Type | Response Time | Improvement |
|---|---|---|
| Cache Miss (network) | ~113ms | Baseline |
| Cache Hit (memory) | ~53µs | 2,128x faster |
- Reduced API Load: Minimizes requests to PokeAPI
- Faster Response Times: Cached requests return in microseconds
- Transparent Operation: Commands don't need caching awareness
- Automatic Expiration: Old entries cleaned up automatically
- Thread-Safe: Handles concurrent access properly
The catch system uses a difficulty-based algorithm that makes it harder to catch stronger Pokemon:
- Base Experience Factor: Each Pokemon has a
base_experiencevalue from the PokeAPI - Catch Threshold Calculation:
catchThreshold = maxBaseExp (600) - pokemon.BaseExperience - Minimum Threshold: Even the strongest Pokemon have at least a 50/600 (~8%) catch chance
- Random Check: A random number (0-600) is generated - if it's less than the threshold, the Pokemon is caught
Real-world catch rates based on testing:
| Pokemon | Base Experience | Approximate Catch Rate |
|---|---|---|
| Magikarp | 40 | ~93% (very easy) |
| Pikachu | 112 | ~80% (easy) |
| Blissey | 608 | ~8% (very hard) |
- Low base experience Pokemon (like Magikarp, Caterpie) are very easy to catch
- Medium base experience Pokemon (like Pikachu, Charmander) are moderately easy
- High base experience Pokemon (like Blissey, Tyranitar) require many attempts
# Run all tests
go test ./...
# Run tests with verbose output
go test -v ./...
# Run tests with coverage
go test -cover ./...
# Generate coverage report
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out✓ Main package: 94.0% coverage
✓ internal/pokeapi: 78.3% coverage
✓ internal/pokecache: 100.0% coverage
- Unit Tests: Individual function and method testing
- Integration Tests: Command and API interaction testing
- Caching Tests: Cache hit/miss verification
- Concurrency Tests: Thread-safety validation
- Define command function with signature:
func commandName(cfg *config) error - Register in
getCommands()map - Add help text to
commandHelp() - Write tests in
repl_test.go
func commandExample(cfg *config) error {
fmt.Println("Example command executed!")
return nil
}
// Register in getCommands()
"example": {
name: "example",
description: "Example command",
callback: commandExample,
}- Language: Go 1.x
- API: PokeAPI v2
- CLI Library: github.com/chzyer/readline for command history and line editing
- Concurrency: Goroutines for background cache cleanup
- Thread Safety: sync.RWMutex for concurrent access
- Command Pattern: Command registry for extensibility
- Repository Pattern: API client abstraction
- Cache-Aside Pattern: Load on cache miss
- REPL Pattern: Interactive command-line interface
- Clean architecture with separation of concerns
- Internal packages for API and caching logic
- Comprehensive test coverage (>90%)
- Thread-safe concurrent operations
- Error handling throughout
Contributions are welcome! Please ensure:
- All tests pass:
go test ./... - Code is properly formatted:
go fmt ./... - New features include tests
- Documentation is updated
This project is for educational purposes.
- PokeAPI for providing the Pokemon data API
- The Go community for excellent documentation and tools