Skip to content

Commit

Permalink
adding damage chart (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
digitalghost-dev committed Nov 3, 2024
1 parent 0cf60fc commit fd85061
Showing 1 changed file with 108 additions and 57 deletions.
165 changes: 108 additions & 57 deletions cmd/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/charmbracelet/bubbles/table"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/x/term"
"github.com/digitalghost-dev/poke-cli/connections"
"golang.org/x/text/cases"
"golang.org/x/text/language"
Expand All @@ -26,8 +27,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case tea.KeyMsg:
switch msg.String() {
case "q", "ctrl+c":
// Fully quiting the program while
// the table is in selection mode
// Quit the program when in selection mode
m.selectedOption = "quit"
return m, tea.Quit
case "enter":
Expand All @@ -51,30 +51,108 @@ func (m model) View() string {
return "Select a type! Hit 'Q' or 'CTRL-C' to quit.\n" + typesTableBorder.Render(m.table.View()) + "\n"
}

// Creating a separate function that handles all the logic for building the table.
func tableGeneration(endpoint string) table.Model {
columns := []table.Column{
{Title: "Type", Width: 16},
// Helper function to get color for a given type name from colorMap
func getTypeColor(typeName string) string {
color := colorMap[typeName]

return color
}

// Function to display type details after a type is selected
func displayTypeDetails(typesName string, endpoint string) {

// Setting up variables to style the list
var columnWidth = 13
var subtle = lipgloss.AdaptiveColor{Light: "#D9DCCF", Dark: "#383838"}
var list = lipgloss.NewStyle().Border(lipgloss.NormalBorder(), false, true, false, false).BorderForeground(subtle).MarginRight(2).Height(8).Width(columnWidth + 1)
var listHeader = lipgloss.NewStyle().BorderStyle(lipgloss.NormalBorder()).BorderBottom(true).BorderForeground(subtle).MarginRight(2).Render
var listItem = lipgloss.NewStyle().Render
var docStyle = lipgloss.NewStyle().Padding(1, 1, 1, 1)

baseURL := "https://pokeapi.co/api/v2/"
typesStruct, typeName, _ := connections.TypesApiCall(endpoint, typesName, baseURL)

// Format selected type
selectedType := cases.Title(language.English).String(typeName)
coloredType := lipgloss.NewStyle().Foreground(lipgloss.Color(getTypeColor(typeName))).Render(selectedType)

fmt.Printf("You selected the %s type.\nNumber of Pokémon with type: %d\n", coloredType, len(typesStruct.Pokemon))
fmt.Println("----------")
fmt.Println(styleBold.Render("Damage Chart:"))

physicalWidth, _, _ := term.GetSize(uintptr(int(os.Stdout.Fd())))
doc := strings.Builder{}

// Helper function to build list items
buildListItems := func(items []struct{ Name, URL string }) string {
var itemList []string
for _, item := range items {
color := getTypeColor(item.Name)
coloredStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(color))
coloredItem := coloredStyle.Render(cases.Title(language.English).String(item.Name))
itemList = append(itemList, listItem(coloredItem))
}
return lipgloss.JoinVertical(lipgloss.Left, itemList...)
}

// Render lists based on Damage Relations
lists := lipgloss.JoinHorizontal(lipgloss.Top,
list.Render(
lipgloss.JoinVertical(lipgloss.Left,
listHeader("Weakness"),
buildListItems([]struct{ Name, URL string }(typesStruct.DamageRelations.DoubleDamageFrom)),
),
),
list.Width(columnWidth).Render(
lipgloss.JoinVertical(lipgloss.Left,
listHeader("x2 Damage"),
buildListItems([]struct{ Name, URL string }(typesStruct.DamageRelations.DoubleDamageTo)),
),
),
list.Width(columnWidth).Render(
lipgloss.JoinVertical(lipgloss.Left,
listHeader("Resists"),
buildListItems([]struct{ Name, URL string }(typesStruct.DamageRelations.HalfDamageFrom)),
),
),
list.Width(columnWidth).Render(
lipgloss.JoinVertical(lipgloss.Left,
listHeader("x0.5 Damage"),
buildListItems([]struct{ Name, URL string }(typesStruct.DamageRelations.HalfDamageTo)),
),
),
list.Width(columnWidth).Render(
lipgloss.JoinVertical(lipgloss.Left,
listHeader("Immune"),
buildListItems([]struct{ Name, URL string }(typesStruct.DamageRelations.NoDamageFrom)),
),
),
list.Width(columnWidth).Render(
lipgloss.JoinVertical(lipgloss.Left,
listHeader("x0 Damage"),
buildListItems([]struct{ Name, URL string }(typesStruct.DamageRelations.NoDamageTo)),
),
),
)

// Append lists to document
doc.WriteString(lipgloss.JoinHorizontal(lipgloss.Top, lists))

if physicalWidth > 0 {
docStyle = docStyle.MaxWidth(physicalWidth)
}

// Print the rendered document
fmt.Println(docStyle.Render(doc.String()))
}

// Function that generates and handles the type selection table
func tableGeneration(endpoint string) table.Model {
columns := []table.Column{{Title: "Type", Width: 16}}
rows := []table.Row{
{"Normal"},
{"Fire"},
{"Water"},
{"Electric"},
{"Grass"},
{"Ice"},
{"Fighting"},
{"Poison"},
{"Ground"},
{"Flying"},
{"Psychic"},
{"Bug"},
{"Rock"},
{"Ghost"},
{"Dragon"},
{"Steel"},
{"Fairy"},
{"Normal"}, {"Fire"}, {"Water"}, {"Electric"}, {"Grass"}, {"Ice"},
{"Fighting"}, {"Poison"}, {"Ground"}, {"Flying"}, {"Psychic"}, {"Bug"},
{"Rock"}, {"Ghost"}, {"Dragon"}, {"Steel"}, {"Fairy"},
}

t := table.New(
Expand All @@ -85,15 +163,8 @@ func tableGeneration(endpoint string) table.Model {
)

s := table.DefaultStyles()
s.Header = s.Header.
BorderStyle(lipgloss.NormalBorder()).
BorderForeground(lipgloss.Color("#FFCC00")).
BorderBottom(true).
Bold(false)
s.Selected = s.Selected.
Foreground(lipgloss.Color("#000")).
Background(lipgloss.Color("#FFCC00")).
Bold(false)
s.Header = s.Header.BorderStyle(lipgloss.NormalBorder()).BorderForeground(lipgloss.Color("#FFCC00")).BorderBottom(true)
s.Selected = s.Selected.Foreground(lipgloss.Color("#000")).Background(lipgloss.Color("#FFCC00"))
t.SetStyles(s)

m := model{table: t}
Expand All @@ -103,40 +174,22 @@ func tableGeneration(endpoint string) table.Model {
os.Exit(1)
}

// Type assert to model and access the selected option
// Access the selected option from the model
finalModel, ok := programModel.(model)
if !ok {
fmt.Println("Error: could not retrieve final model")
os.Exit(1)
}

// Check if the user quit the program by pressing 'Q' or 'CTRL-C'
if finalModel.selectedOption == "quit" {
// Return early to prevent further execution
return t
if finalModel.selectedOption != "quit" {
typesName := strings.ToLower(finalModel.selectedOption)
displayTypeDetails(typesName, endpoint) // Call function to display type details
}

// Proceed with the API call only if a type was selected
typesName := strings.ToLower(finalModel.selectedOption)

baseURL := "https://pokeapi.co/api/v2/"
typeResponse, typeName, _ := connections.TypesApiCall(endpoint, typesName, baseURL)

selectedType := cases.Title(language.English).String(typeName)

pokemonCount := len(typeResponse.Pokemon)

// Picking the type's color from the colorMap map in cmd/styles.go:
coloredStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(colorMap[typeName]))
coloredType := coloredStyle.Render(selectedType)

fmt.Printf("You selected Type: %s\nNumber of Pokémon with type: %d\n", coloredType, pokemonCount)
return t
}

func TypesCommand() {
styleBold = lipgloss.NewStyle().Bold(true)
styleItalic = lipgloss.NewStyle().Italic(true)

flag.Usage = func() {
helpMessage := helpBorder.Render(
Expand All @@ -153,13 +206,11 @@ func TypesCommand() {

flag.Parse()

err := ValidateTypesArgs(os.Args)
if err != nil {
if err := ValidateTypesArgs(os.Args); err != nil {
fmt.Println(err.Error())
os.Exit(1)
}

endpoint := strings.ToLower(os.Args[1])[0:4]

tableGeneration(endpoint)
}

0 comments on commit fd85061

Please sign in to comment.