Fix: various bug fix
This commit is contained in:
@@ -1,23 +1,52 @@
|
||||
package stages
|
||||
|
||||
import (
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"gitea.konchin.com/ytshih/inp2025/types"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
type BaseModel struct {
|
||||
queue *[]*tea.Program
|
||||
stack []types.Program
|
||||
client *resty.Client
|
||||
|
||||
// after login
|
||||
loginCount int
|
||||
}
|
||||
|
||||
func NewBaseModel(
|
||||
queue *[]*tea.Program,
|
||||
endpoint string,
|
||||
) *BaseModel {
|
||||
return &BaseModel{
|
||||
queue: queue,
|
||||
stack: []types.Program{},
|
||||
client: resty.New().
|
||||
SetBaseURL(endpoint).
|
||||
SetDisableWarn(true),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *BaseModel) Size() int {
|
||||
return len(m.stack)
|
||||
}
|
||||
|
||||
func (m *BaseModel) Pop() types.Program {
|
||||
stack := m.stack[:]
|
||||
var ret types.Program
|
||||
ret, stack = stack[len(stack)-1], stack[:len(stack)-1]
|
||||
m.stack = stack
|
||||
return ret
|
||||
}
|
||||
|
||||
func (m *BaseModel) Push(program types.Program) error {
|
||||
stack := m.stack[:]
|
||||
for len(stack) > 0 && stack[len(stack)-1].Stage > program.Stage {
|
||||
var p types.Program
|
||||
p, stack = stack[len(stack)-1], stack[:len(stack)-1]
|
||||
|
||||
if err := p.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
stack = append(stack, program)
|
||||
m.stack = stack
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,9 +5,11 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"gitea.konchin.com/ytshih/inp2025/models"
|
||||
"gitea.konchin.com/ytshih/inp2025/handlers/auth"
|
||||
"gitea.konchin.com/ytshih/inp2025/types"
|
||||
"github.com/charmbracelet/bubbles/textinput"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type landingOperationType int
|
||||
@@ -73,14 +75,18 @@ type postLoginMsg struct{}
|
||||
|
||||
func (m *LandingModel) postLogin() tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
resp, err := m.BaseModel.client.R().
|
||||
var res auth.PostLoginOutput
|
||||
resp, err := m.client.R().
|
||||
SetResult(&res).
|
||||
ForceContentType("application/json").
|
||||
SetBasicAuth(m.username.Value(), m.password.Value()).
|
||||
Post("/auth/login")
|
||||
if err == nil {
|
||||
switch resp.StatusCode() {
|
||||
case http.StatusOK:
|
||||
m.BaseModel.client.SetBasicAuth(
|
||||
m.client.SetBasicAuth(
|
||||
m.username.Value(), m.password.Value())
|
||||
m.loginCount = res.LoginCount
|
||||
m.info = "login success.\n"
|
||||
m.err = nil
|
||||
case http.StatusUnauthorized:
|
||||
@@ -101,8 +107,8 @@ type postRegisterMsg struct{}
|
||||
|
||||
func (m *LandingModel) postRegister() tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
resp, err := m.BaseModel.client.R().
|
||||
SetBody(models.User{
|
||||
resp, err := m.client.R().
|
||||
SetBody(auth.PostRegisterInput{
|
||||
Username: m.username.Value(),
|
||||
Password: m.password.Value(),
|
||||
}).
|
||||
@@ -193,8 +199,22 @@ func (m *LandingModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
}
|
||||
case postLoginMsg:
|
||||
if m.err == nil {
|
||||
*m.queue = append(*m.queue,
|
||||
tea.NewProgram(NewLobbyModel(m.BaseModel)))
|
||||
m.Push(types.Program{
|
||||
Run: func() error {
|
||||
m.client.SetBaseURL(viper.GetString("auth-endpoint"))
|
||||
_, err := m.client.R().
|
||||
Post("/auth/logout")
|
||||
return err
|
||||
},
|
||||
Stage: types.StageLanding,
|
||||
})
|
||||
|
||||
program := tea.NewProgram(NewLobbyModel(m.BaseModel))
|
||||
m.Push(types.Program{
|
||||
Run: func() error { _, err := program.Run(); return err },
|
||||
Stage: types.StageLobby,
|
||||
})
|
||||
|
||||
return m, tea.Quit
|
||||
} else {
|
||||
m.reset()
|
||||
|
||||
@@ -172,6 +172,7 @@ func (m *LobbyModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
case "ctrl+c":
|
||||
m.shutdown()
|
||||
return m, tea.Quit
|
||||
}
|
||||
}
|
||||
@@ -207,10 +208,25 @@ func (m *LobbyModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
case serverSendReplyMsg:
|
||||
if m.err == nil {
|
||||
m.shutdown()
|
||||
|
||||
m.client.SetBaseURL("http://" + m.remote)
|
||||
shutdown := workflows.WordleServer(m.listener)
|
||||
*m.queue = append(*m.queue,
|
||||
tea.NewProgram(NewWordleClientModel(m.BaseModel, shutdown)))
|
||||
m.Push(types.Program{
|
||||
Run: func() error { shutdown(); return nil },
|
||||
Stage: types.StageGaming,
|
||||
})
|
||||
|
||||
m.Push(types.Program{
|
||||
Run: func() error { m.client.R().Post("/api/end"); return nil },
|
||||
Stage: types.StageGaming,
|
||||
})
|
||||
|
||||
p := tea.NewProgram(NewWordleClientModel(m.BaseModel))
|
||||
m.Push(types.Program{
|
||||
Run: func() error { _, err := p.Run(); return err },
|
||||
Stage: types.StageGaming,
|
||||
})
|
||||
|
||||
return m, tea.Quit
|
||||
} else {
|
||||
m.op = lobbyOperationServerWaiting
|
||||
@@ -229,17 +245,29 @@ func (m *LobbyModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
m.cursor = (m.cursor + 1) % n
|
||||
}
|
||||
case "enter":
|
||||
m.remote = m.endpoints[m.cursor]
|
||||
cmds = append(cmds, m.clientJoin())
|
||||
if n := len(m.endpoints); n > 0 && m.cursor < n {
|
||||
m.remote = m.endpoints[m.cursor]
|
||||
cmds = append(cmds, m.clientJoin())
|
||||
}
|
||||
}
|
||||
case clientScanMsg:
|
||||
cmds = append(cmds, m.clientScan())
|
||||
case clientJoinMsg:
|
||||
if m.err == nil && m.remote != "" {
|
||||
m.shutdown()
|
||||
|
||||
m.client.SetBaseURL("http://" + m.remote)
|
||||
*m.BaseModel.queue = append(*m.BaseModel.queue,
|
||||
tea.NewProgram(NewWordleClientModel(m.BaseModel, func() {})))
|
||||
m.Push(types.Program{
|
||||
Run: func() error { m.client.R().Post("/api/end"); return nil },
|
||||
Stage: types.StageGaming,
|
||||
})
|
||||
|
||||
p := tea.NewProgram(NewWordleClientModel(m.BaseModel))
|
||||
m.Push(types.Program{
|
||||
Run: func() error { _, err := p.Run(); return err },
|
||||
Stage: types.StageGaming,
|
||||
})
|
||||
|
||||
return m, tea.Quit
|
||||
}
|
||||
}
|
||||
@@ -251,13 +279,16 @@ func (m *LobbyModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
func (m *LobbyModel) View() string {
|
||||
var b strings.Builder
|
||||
|
||||
fmt.Fprintf(&b, "Login as '%s' for '%d' times\n",
|
||||
m.client.UserInfo.Username, m.loginCount)
|
||||
|
||||
switch m.op {
|
||||
case lobbyOperationChoose:
|
||||
b.WriteString("Choose Role\n(S)erver / (C)lient\n")
|
||||
case lobbyOperationServerWaiting:
|
||||
b.WriteString("Wait for user to join...\n")
|
||||
case lobbyOperationServerChoose:
|
||||
fmt.Fprintf(&b, "Receive Join Request by '%s'\nAccept (Y)/N\n",
|
||||
fmt.Fprintf(&b, "Receive Join Request by '%s'\nAccept (Y) / (n)\n",
|
||||
m.remoteUser)
|
||||
case lobbyOperationClientScannning:
|
||||
b.WriteString("Scanning server...\nChoose one to join\n")
|
||||
|
||||
@@ -22,9 +22,8 @@ const (
|
||||
|
||||
type WordleClientModel struct {
|
||||
*BaseModel
|
||||
conn *websocket.Conn
|
||||
state types.WordleState
|
||||
shutdown types.ShutdownFunc
|
||||
conn *websocket.Conn
|
||||
state types.WordleState
|
||||
|
||||
input textinput.Model
|
||||
err error
|
||||
@@ -32,7 +31,6 @@ type WordleClientModel struct {
|
||||
|
||||
func NewWordleClientModel(
|
||||
base *BaseModel,
|
||||
shutdown types.ShutdownFunc,
|
||||
) *WordleClientModel {
|
||||
input := textinput.New()
|
||||
input.Focus()
|
||||
@@ -41,7 +39,6 @@ func NewWordleClientModel(
|
||||
return &WordleClientModel{
|
||||
BaseModel: base,
|
||||
input: input,
|
||||
shutdown: shutdown,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,14 +115,15 @@ func (m *WordleClientModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg.String() {
|
||||
case "ctrl+c":
|
||||
m.conn.Close()
|
||||
m.shutdown()
|
||||
return m, tea.Quit
|
||||
case "enter":
|
||||
if m.state.GameEnd {
|
||||
m.conn.Close()
|
||||
m.shutdown()
|
||||
*m.queue = append(*m.queue,
|
||||
tea.NewProgram(NewLobbyModel(m.BaseModel)))
|
||||
p := tea.NewProgram(NewLobbyModel(m.BaseModel))
|
||||
m.Push(types.Program{
|
||||
Run: func() error { _, err := p.Run(); return err },
|
||||
Stage: types.StageLobby,
|
||||
})
|
||||
return m, tea.Quit
|
||||
}
|
||||
if len(m.input.Value()) == types.GUESS_WORD_LENGTH {
|
||||
|
||||
Reference in New Issue
Block a user