diff --git a/gui/draw.go b/gui/draw.go index cca63a1..388ad17 100644 --- a/gui/draw.go +++ b/gui/draw.go @@ -2,19 +2,17 @@ package gui import ( "fmt" + "math/rand" "strings" + "time" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) -var hotPinkText = lipgloss.NewStyle().Foreground(lipgloss.Color("#FF06B7")) -var frontText = lipgloss.NewStyle().Foreground(lipgloss.Color("#268bd2")) -var backText = lipgloss.NewStyle().Foreground(lipgloss.Color("#6c71c4")) - -func (m *model) nextCard() { - m.drawSeen = false -} +var hotPinkTextStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#FF06B7")) +var frontTextStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#268bd2")) +var backTextStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#6c71c4")) func (m *model) updateDraw(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { @@ -27,16 +25,18 @@ func (m *model) updateDraw(msg tea.Msg) (tea.Model, tea.Cmd) { m.drawSeen = true case "2": // Correct if m.drawSeen { - // TODO + m.drawSeen = false + m.drawRandomCard() } case "3": // Incorrect if m.drawSeen { - // TODO: + m.drawSeen = false + m.drawRandomCard() } case "4": // Skip if !m.drawSeen { - // CAN SKIP - // TODO: + m.drawSeen = false + m.drawRandomCard() } case "ctrl+c", "q": @@ -45,10 +45,14 @@ func (m *model) updateDraw(msg tea.Msg) (tea.Model, tea.Cmd) { m.switchMode(Select) } } - return m, nil + return m, tea.Tick(time.Second, func(_ time.Time) tea.Msg { + return nil + }) } func (m *model) viewDraw() string { + card := m.selectedCard() + // Button Text viewText := "1: View" correctText := "2: Correct" @@ -56,17 +60,21 @@ func (m *model) viewDraw() string { skipText := "4: Skip" // Buttons default - viewOption := fmt.Sprintf("[%s]", hotPinkText.Width(7).Render(viewText)) + viewOption := fmt.Sprintf("[%s]", hotPinkTextStyle.Width(7).Render(viewText)) correctOption := fmt.Sprintf(strings.Repeat(" ", len(correctText)+2)) incorrectOption := fmt.Sprintf(strings.Repeat(" ", len(incorrectText)+2)) skipOption := fmt.Sprintf(strings.Repeat(" ", len(skipText)+2)) // Button text filling + frontText := frontTextStyle.Width(len(card.Front)).Render(card.Front) + backText := "" + if m.drawSeen { - correctOption = fmt.Sprintf("[%s]", hotPinkText.Width(10).Render(correctText)) - incorrectOption = fmt.Sprintf("[%s]", hotPinkText.Width(12).Render(incorrectText)) + backText = backTextStyle.Width(len(card.Back)).Render(card.Back) + correctOption = fmt.Sprintf("[%s]", hotPinkTextStyle.Width(10).Render(correctText)) + incorrectOption = fmt.Sprintf("[%s]", hotPinkTextStyle.Width(12).Render(incorrectText)) } else { - skipOption = fmt.Sprintf("[%s]", hotPinkText.Width(7).Render(skipText)) + skipOption = fmt.Sprintf("[%s]", hotPinkTextStyle.Width(7).Render(skipText)) } selectedMap := fmt.Sprintf("%v", m.selected) @@ -74,8 +82,8 @@ func (m *model) viewDraw() string { // Return a template return template(`Draw Mode ({numSelected} cards, {selectedCardIndexes}): -{cardList} -{selectedMap} +{frontTextStyle} +{backTextStyle} {viewOption} {correctOption} {incorrectOption} {skipOption} @@ -85,11 +93,13 @@ Press [q] to quit. "{numSelected}", fmt.Sprintf("%d", len(m.selected)), "{selectedCardIndexes}", fmt.Sprintf("%v", m.selectedCardIndexes()), "{cardList}", m.cardListToString(), - "{selectedMap}", fmt.Sprintf("%s", frontText.Width(len(selectedMap)).Render(selectedMap)), + "{selectedMap}", fmt.Sprintf("%s", frontTextStyle.Width(len(selectedMap)).Render(selectedMap)), "{viewOption}", viewOption, "{correctOption}", correctOption, "{incorrectOption}", incorrectOption, "{skipOption}", skipOption, + "{frontTextStyle}", frontText, + "{backTextStyle}", backText, ) } @@ -103,3 +113,24 @@ func (m *model) cardListToString() string { } return s } + +func (m *model) drawRandomCard() { + if len(m.selectedCardIndexes()) == 1 { + // Can't draw a next card, just return same card. + return + } + rand.Seed(time.Now().Unix()) // initialize global pseudo random generator + indexes := m.selectedCardIndexes() + nextId := m.drawCardId + + // Randomize until the next card is not the same card + for { + randomIndex := indexes[rand.Intn(len(indexes))] + nextId = m.deck[randomIndex].Id + if m.drawCardId != nextId { + break + } + } + + m.drawCardId = nextId +} diff --git a/gui/model.go b/gui/model.go index 531a3d2..cd89607 100644 --- a/gui/model.go +++ b/gui/model.go @@ -5,6 +5,7 @@ import ( "github.com/charmbracelet/bubbles/list" "github.com/charmbracelet/bubbles/textinput" "reflect" + "sort" ) type model struct { @@ -17,21 +18,37 @@ type model struct { createInputs []textinput.Model // Inputs for front and back, is an array because we change position by an index createdInputIndex int // holds an index for which input is active editing in create mode - drawSeen bool - drawCardIndex int + drawSeen bool + drawCardId string mode Mode err error } +/// returns an int slice of the selected card indexes, sorted func (m *model) selectedCardIndexes() []int { var keys []int for _, key := range reflect.ValueOf(m.selected).MapKeys() { keys = append(keys, int(key.Int())) } + sort.Ints(keys) return keys } +/// Returns a card with matching drawCardId +func (m *model) selectedCard() models.Card { + for _, card := range m.deck { + if card.Id == m.drawCardId { + return card + } + } + return models.Card{ + Front: "ERROR", + Back: "ERROR", + Id: "-1", + } +} + func initialModel() model { front := textinput.New() front.Placeholder = "Front..." @@ -45,9 +62,22 @@ func initialModel() model { back.Width = 80 deck := []models.Card{ - models.NewCard("Hello (JP)", "Konnichi wa"), - models.NewCard("Hello (SP)", "Hola"), - models.NewCard("Hello (DE)", "Guten Tag"), + models.NewCard("Oui, je parle français.", "Yes, I speak French."), + models.NewCard("Non, je ne parle pas français.", "No, I don’t speak French."), + models.NewCard("Merci beaucoup.", "Thank you very much."), + models.NewCard("Je mange le pain.", "I eat the bread."), + models.NewCard("Tu manges la salade.", "You seat the salad."), + models.NewCard("Vous mangez la pizza.", "You eat the pizza."), + models.NewCard("Le garçon chante.", "The boy sings."), + models.NewCard("La fille nage.", "The girl swims."), + models.NewCard("Les enfants chantent.", "The children sing."), + models.NewCard("Un garçon écrit.", "A boy writes."), + models.NewCard("Une fille dort.", "A girl sleeps."), + models.NewCard("Des enfant étudient.", "Some kids study."), + models.NewCard("Je le/la mange.", "I eat it."), + models.NewCard("Je les mange.", "I eat them."), + models.NewCard("Marc et Sylvie.", "Marc and Sylvie."), + models.NewCard("Il aime Sylvie mais il est trop timide.", "He likes Sylvie but he’s ),too shy."), } var items []list.Item diff --git a/gui/select.go b/gui/select.go index 84d19ea..6a9f857 100644 --- a/gui/select.go +++ b/gui/select.go @@ -52,7 +52,7 @@ func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list } } - fmt.Fprint(w, fn(str)) + _, _ = fmt.Fprint(w, fn(str)) // ignore error } func (m *model) updateSelect(msg tea.Msg) (tea.Model, tea.Cmd) { @@ -81,7 +81,11 @@ func (m *model) updateSelect(msg tea.Msg) (tea.Model, tea.Cmd) { // MODES case "d": - m.switchMode(Draw) + // Only draw if at least one card + if len(m.selected) > 0 { + m.drawRandomCard() + m.switchMode(Draw) + } case "c": m.switchMode(Create) @@ -91,7 +95,6 @@ func (m *model) updateSelect(msg tea.Msg) (tea.Model, tea.Cmd) { card, ok := m.selectList.SelectedItem().(models.Card) if ok { idx := SliceIndex(len(m.deck), func(i int) bool { return m.deck[i].Id == card.Id }) - fmt.Printf("%d IS THE CARD: %s", idx, card.Front) if _, ok := m.selected[idx]; ok { delete(m.selected, idx) m.deck[idx].Selected = false