Skip to content

Commit

Permalink
feat: custom deck (#86)
Browse files Browse the repository at this point in the history
* chore: cleanup

* feat: smart calculate vote color in deck

* feat: Priority deck

* fix: allow passing text to Add action

* feat: add decks to state

* feat: renderCardFlags
  • Loading branch information
igor-sirotin authored Sep 1, 2024
1 parent da1571b commit e9951fb
Show file tree
Hide file tree
Showing 16 changed files with 81 additions and 63 deletions.
10 changes: 0 additions & 10 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,11 @@ func SetupLogger() {
}

func createLogFile() string {
//executableFilePath, err := os.Executable()
//if err != nil {
// panic(err)
//}

//s.configDirs.QueryFolderContainsFile(playerFileName).Path)

name := fmt.Sprintf("waku-pp-%s.log", time.Now().UTC().Format(time.RFC3339))
name = strings.Replace(name, ":", "-", -1)
//executableDir := filepath.Dir(executableFilePath)

configDirs := configdir.New(VendorName, ApplicationName)
folders := configDirs.QueryFolders(configdir.Global)
path := filepath.Join(folders[0].Path, logsDirectory, name)
//err = folders[0].WriteFile(path, []byte(playerUUID))

if err := os.MkdirAll(filepath.Dir(path), 0770); err != nil {
panic(err)
Expand Down
2 changes: 1 addition & 1 deletion internal/view/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func runAddAction(m *model, args []string) tea.Cmd {
err := errors.New("empty issue")
return messages.NewErrorMessage(err)
}
return commands.AddIssue(m.game, args[0])()
return commands.AddIssue(m.game, strings.Join(args, " "))()
}
}

Expand Down
1 change: 0 additions & 1 deletion internal/view/commands/actions.go

This file was deleted.

27 changes: 18 additions & 9 deletions internal/view/components/deckview/deckview.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,12 @@ func (m Model) View() string {
for i, value := range m.deck {
card := renderCard(
value,
m.voteCursor.Match(i),
m.finishCursor.Match(i),
value == m.myVote,
m.deck,
renderCardFlags{
voteCursor: m.voteCursor.Match(i),
finishCursor: m.finishCursor.Match(i),
voted: value == m.myVote,
},
)
cards = append(cards, card, " ") // Add a space between cards
}
Expand Down Expand Up @@ -120,27 +123,33 @@ func (m *Model) FinishCursor() int {
return m.finishCursor.Position()
}

func renderCard(value protocol.VoteValue, voteCursor bool, finishCursor bool, voted bool) string {
type renderCardFlags struct {
voteCursor bool
finishCursor bool
voted bool
}

func renderCard(value protocol.VoteValue, deck protocol.Deck, flags renderCardFlags) string {
card := table.New().
Border(lipgloss.RoundedBorder()).
BorderStyle(*cardBorderStyle(voted, finishCursor)).
BorderStyle(*cardBorderStyle(flags.voted, flags.finishCursor)).
StyleFunc(func(row, col int) lipgloss.Style {
return *voteview.VoteStyle(value)
return *voteview.VoteStyle(value, deck)
}).
Rows([]string{string(value)}).
String()

var column []string
column = []string{}

if !voted {
if !flags.voted {
column = append(column, "")
}

column = append(column, card)

if voteCursor {
if voted {
if flags.voteCursor {
if flags.voted {
column = append(column, "")
}
column = append(column, " ^")
Expand Down
8 changes: 7 additions & 1 deletion internal/view/components/deckview/deckview_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ type Suite struct {
}

func (s *Suite) TestRenderCard() {
deck := protocol.Deck{"1", "2", "3", "4"}

testCases := []struct {
value protocol.VoteValue
cursor bool
Expand All @@ -35,7 +37,11 @@ func (s *Suite) TestRenderCard() {
}

for _, tc := range testCases {
result := renderCard(tc.value, tc.cursor, false, tc.voted)
result := renderCard(tc.value, deck, renderCardFlags{
voteCursor: tc.cursor,
finishCursor: false,
voted: tc.voted},
)
s.Require().Equal(tc.expected, result)
}
}
Expand Down
5 changes: 4 additions & 1 deletion internal/view/components/hintview/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var (

type Model struct {
hint *protocol.Hint
deck protocol.Deck
}

func New() Model {
Expand All @@ -42,6 +43,8 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
if issue != nil {
m.hint = issue.Hint
}

m.deck = msg.State.Deck
}

return m, nil
Expand All @@ -53,7 +56,7 @@ func (m Model) View() string {
}

return lipgloss.JoinVertical(lipgloss.Top,
headerStyle.Render("Recommended:")+""+voteview.Render(m.hint.Value),
headerStyle.Render("Recommended:")+""+voteview.Render(m.hint.Value, m.deck),
headerStyle.Render("Acceptable:")+" "+renderAcceptanceIcon(m.hint.Acceptable),
headerStyle.Render(">")+" "+textStyle.Render(m.hint.Description),
)
Expand Down
4 changes: 3 additions & 1 deletion internal/view/components/issuesview/issues_view.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ var (
type Model struct {
issues protocol.IssuesList
activeIssue protocol.IssueID
deck protocol.Deck
commandMode bool
isDealer bool
focused bool
Expand Down Expand Up @@ -55,6 +56,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
} else {
m.issues = msg.State.Issues
m.activeIssue = msg.State.ActiveIssue
m.deck = msg.State.Deck
}
m.cursor.SetRange(0, len(m.issues)-1)
m.updateCursorFocus()
Expand Down Expand Up @@ -85,7 +87,7 @@ func (m Model) View() string {
result := " - "
if issue.Result != nil {
vote := fmt.Sprintf("%2s", string(*issue.Result))
result = voteview.VoteStyle(*issue.Result).Render(vote)
result = voteview.VoteStyle(*issue.Result, m.deck).Render(vote)
} else if issue.ID == activeIssue {
result = fmt.Sprintf(" %2s ", m.spinner.View())
}
Expand Down
1 change: 1 addition & 0 deletions internal/view/components/playervoteview/playerVoteView.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
}

m.voteView.SetValue(vote.Value)
m.voteView.SetDeck(state.Deck)
m.voteView.Show()
}

Expand Down
31 changes: 20 additions & 11 deletions internal/view/components/voteview/voteview.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package voteview

import (
"strconv"

"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
Expand All @@ -18,7 +16,7 @@ var (
NoVoteStyle = CommonVoteStyle.Copy().Foreground(lipgloss.Color("#444444"))
ReadyVoteStyle = CommonVoteStyle.Copy().Foreground(lipgloss.Color("#5fd700"))
LightVoteStyle = CommonVoteStyle.Copy().Foreground(lipgloss.Color("#00B0FF"))
MediumVoteStyle = CommonVoteStyle.Copy().Foreground(lipgloss.Color("#ffd787"))
MediumVoteStyle = CommonVoteStyle.Copy().Foreground(lipgloss.Color("#FFD787"))
DangerVoteStyle = CommonVoteStyle.Copy().Foreground(lipgloss.Color("#FF6D00")) // ff005f
)

Expand All @@ -34,6 +32,7 @@ const (

type Model struct {
value protocol.VoteValue
deck protocol.Deck
style *lipgloss.Style
state VoteValueState

Expand Down Expand Up @@ -99,6 +98,10 @@ func (m *Model) SetValue(value protocol.VoteValue) {
m.value = value
}

func (m *Model) SetDeck(deck protocol.Deck) {
m.deck = deck
}

func (m *Model) Reset() {
m.state = voteValueDefault
m.value = ""
Expand All @@ -107,7 +110,7 @@ func (m *Model) Reset() {

func (m *Model) Show() {
m.state = voteValueDefault
m.style = VoteStyle(m.value)
m.style = VoteStyle(m.value, m.deck)
}

func (m *Model) Hide() {
Expand All @@ -130,20 +133,26 @@ func (m *Model) Clear() {
m.style = &CommonVoteStyle
}

func VoteStyle(vote protocol.VoteValue) *lipgloss.Style {
voteNumber, err := strconv.Atoi(string(vote))
if err != nil {
func VoteStyle(vote protocol.VoteValue, deck protocol.Deck) *lipgloss.Style {
if vote == protocol.UncertaintyCard {
return &CommonVoteStyle
}
if voteNumber >= 13 {
index := deck.Index(vote)
if index < 0 {
return &CommonVoteStyle
}

deckLength := float32(len(deck))

if index >= int(deckLength*0.8) {
return &DangerVoteStyle
}
if voteNumber >= 5 {
if index >= int(deckLength*0.4) {
return &MediumVoteStyle
}
return &LightVoteStyle
}

func Render(vote protocol.VoteValue) string {
return VoteStyle(vote).Render(string(vote))
func Render(vote protocol.VoteValue, deck protocol.Deck) string {
return VoteStyle(vote, deck).Render(string(vote))
}
18 changes: 10 additions & 8 deletions pkg/game/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ type configuration struct {
AutoRevealDelay time.Duration
}

var defaultConfig = configuration{
PlayerName: "",
EnableSymmetricEncryption: true,
OnlineMessagePeriod: 5 * time.Second,
StateMessagePeriod: 30 * time.Second,
PublishStateLoopEnabled: true,
AutoRevealEnabled: true,
AutoRevealDelay: 1 * time.Second,
func defaultConfig() configuration {
return configuration{
PlayerName: "",
EnableSymmetricEncryption: true,
OnlineMessagePeriod: 5 * time.Second,
StateMessagePeriod: 30 * time.Second,
PublishStateLoopEnabled: true,
AutoRevealEnabled: true,
AutoRevealDelay: 1 * time.Second,
}
}
11 changes: 7 additions & 4 deletions pkg/game/decks.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ import (
"golang.org/x/exp/maps"
)

var fibonacciDeck = protocol.Deck{"1", "2", "3", "5", "8", "13", "21", "?"}

const Fibonacci = "fibonacci"
const (
DefaultDeck = FibonacciDeck
FibonacciDeck = "fibonacci"
PriorityDeck = "priority"
)

//var TShirtDeck = []protocol.VoteResult{
// "XS", "S", "M", "L", "XL", "XXL",
//}

var decks = map[string]protocol.Deck{
Fibonacci: fibonacciDeck,
FibonacciDeck: {"1", "2", "3", "5", "8", "13", "21", "?"},
PriorityDeck: {"4", "3", "2", "1", "0", "?"},
}

func GetDeck(deckName string) (protocol.Deck, bool) {
Expand Down
5 changes: 1 addition & 4 deletions pkg/game/features.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package game

type FeatureFlags struct {
EnableDeckSelection bool
}

func defaultFeatureFlags() FeatureFlags {
return FeatureFlags{
EnableDeckSelection: false,
}
return FeatureFlags{}
}

type codeControlFlags struct {
Expand Down
10 changes: 2 additions & 8 deletions pkg/game/game.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func NewGame(opts []Option) *Game {
game := &Game{
exitRoom: nil,
messages: make(chan []byte, 42),
config: defaultConfig,
config: defaultConfig(),
features: defaultFeatureFlags(),
codeControls: defaultCodeControlFlags(),
initialized: false,
Expand Down Expand Up @@ -476,7 +476,7 @@ func (g *Game) CreateNewRoom() (*protocol.Room, *protocol.State, error) {
return nil, nil, errors.Wrap(err, "failed to create a new room")
}

deckName := Fibonacci // FIXME: Remove hardcoded deck
deckName := DefaultDeck
deck, deckFound := GetDeck(deckName)
if !deckFound {
return nil, nil, errors.Wrap(err, fmt.Sprintf("unknown deck '%s'", deckName))
Expand Down Expand Up @@ -526,9 +526,6 @@ func (g *Game) JoinRoom(roomID protocol.RoomID, state *protocol.State) error {
g.roomID = roomID
g.state = state
g.stateTimestamp = 0
if g.isDealer {
g.state.Deck, _ = GetDeck(Fibonacci) // FIXME: remove hardcoded deck
}

g.resetMyVote()

Expand Down Expand Up @@ -657,9 +654,6 @@ func (g *Game) hiddenCurrentState() *protocol.State {
}

func (g *Game) SetDeck(deck protocol.Deck) error {
if !g.features.EnableDeckSelection {
return errors.New("deck selection is disabled")
}
if !g.isDealer {
return errors.New("only dealer can set deck")
}
Expand Down
5 changes: 4 additions & 1 deletion pkg/game/game_handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ func (g *Game) handleStateMessage(payload []byte) {
}

g.state = &message.State
g.state.Deck, _ = GetDeck(Fibonacci) // FIXME: remove hardcoded deck
if g.state.Deck == nil {
// Fallback to FibonacciDeck deck, it was default before 1.2.0
g.state.Deck, _ = GetDeck(FibonacciDeck)
}
g.notifyChangedState(false)
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/game/game_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (s *Suite) TestStateSize() {
}

votes := make(map[protocol.PlayerID]protocol.VoteResult, playersCount)
deck, deckFound := GetDeck(Fibonacci)
deck, deckFound := GetDeck(FibonacciDeck)
s.Require().True(deckFound)

state.Deck = deck
Expand Down
4 changes: 2 additions & 2 deletions pkg/protocol/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ type State struct {
Issues IssuesList `json:"issues"`
ActiveIssue IssueID `json:"activeIssue"`
VotesRevealed bool `json:"votesRevealed"`
Timestamp int64 `json:"-"` // TODO: Fix conflict with Message.Timestamp. Change type to time.Time.
Deck Deck `json:"-"`
Timestamp int64 `json:"-"` // TODO: Fix conflict with Message.Timestamp. Change type to time.Time.
Deck Deck `json:"deck"` // NOTE: This field is experimental and not supported by web client
}

type VoteState string
Expand Down

0 comments on commit e9951fb

Please sign in to comment.