src to pkg, impl lobby.Closed

main
Bel LaPointe 2025-02-12 16:48:58 -07:00
parent 1f6b79aa3b
commit e35ddef4b7
18 changed files with 117 additions and 21 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
**/*.sw* **/*.sw*
/src/state/fsm/template /src/state/fsm/template
/pkg/state/fsm/template

View File

@ -3,7 +3,7 @@ package db_test
import ( import (
"context" "context"
"database/sql" "database/sql"
"gitea/price-is-wrong/src/lib/db" "gitea/price-is-wrong/pkg/lib/db"
"testing" "testing"
) )

21
pkg/lib/db/new.go Normal file
View File

@ -0,0 +1,21 @@
package db
import (
"context"
"database/sql"
_ "github.com/glebarez/sqlite"
)
func New(ctx context.Context, driver, conn string) (*sql.DB, error) {
db, err := sql.Open(driver, conn)
if err != nil {
return nil, err
}
if err := db.PingContext(ctx); err != nil {
return nil, err
}
return db, nil
}

View File

@ -2,11 +2,10 @@ package lib
import ( import (
"context" "context"
"database/sql"
"path" "path"
"testing" "testing"
"gitea/price-is-wrong/src/lib/db" "gitea/price-is-wrong/pkg/lib/db"
_ "github.com/glebarez/sqlite" _ "github.com/glebarez/sqlite"
) )
@ -15,7 +14,7 @@ func NewTestCtx(t *testing.T) context.Context {
d := t.TempDir() d := t.TempDir()
p := path.Join(d, "db.db") p := path.Join(d, "db.db")
t.Logf("test db at %s", p) t.Logf("test db at %s", p)
b, err := sql.Open("sqlite", p) b, err := db.New(context.Background(), "sqlite", p)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -2,8 +2,8 @@ package lib_test
import ( import (
"context" "context"
"gitea/price-is-wrong/src/lib" "gitea/price-is-wrong/pkg/lib"
"gitea/price-is-wrong/src/lib/db" "gitea/price-is-wrong/pkg/lib/db"
"sync" "sync"
"testing" "testing"
) )

View File

@ -2,8 +2,8 @@ package lobby
import ( import (
"context" "context"
"gitea/price-is-wrong/src/lib/db" "gitea/price-is-wrong/pkg/lib/db"
lobby "gitea/price-is-wrong/src/state/lobby/internal" lobby "gitea/price-is-wrong/pkg/state/lobby/internal"
"slices" "slices"
) )
@ -15,6 +15,10 @@ func (l *Lobby) Leave(ctx context.Context, id int) error {
return l.upsertEvent(ctx, &lobby.PlayerLeave{ID: id}) return l.upsertEvent(ctx, &lobby.PlayerLeave{ID: id})
} }
func (l *Lobby) Close(ctx context.Context) error {
return l.upsertEvent(ctx, &lobby.Close{})
}
func (l *Lobby) upsertEvent(ctx context.Context, e lobby.Event) error { func (l *Lobby) upsertEvent(ctx context.Context, e lobby.Event) error {
if err := upsertEvent(ctx, l.id, e); err != nil { if err := upsertEvent(ctx, l.id, e); err != nil {
return err return err

60
pkg/state/lobby/events.go Normal file
View File

@ -0,0 +1,60 @@
package lobby
import (
"context"
"gitea/price-is-wrong/pkg/lib/db"
lobby "gitea/price-is-wrong/pkg/state/lobby/internal"
"slices"
)
func (l *Lobby) Join(ctx context.Context, id int) error {
return l.upsertEvent(ctx, &lobby.PlayerJoin{ID: id})
}
func (l *Lobby) Leave(ctx context.Context, id int) error {
return l.upsertEvent(ctx, &lobby.PlayerLeave{ID: id})
}
func (l *Lobby) Close(ctx context.Context) error {
return l.upsertEvent(ctx, &lobby.Close{})
}
func (l *Lobby) upsertEvent(ctx context.Context, e lobby.Event) error {
if err := upsertEvent(ctx, l.id, e); err != nil {
return err
}
l2, err := openID(ctx, l.id)
if err != nil {
return err
}
*l = *l2
return nil
}
func upsertEvent(ctx context.Context, lobbyID int, e lobby.Event) error {
b, err := lobby.MarshalEvent(e)
if err != nil {
return err
}
_, err = db.From(ctx).ExecContext(ctx, `
INSERT INTO lobby_events (lobby_id, payload) VALUES (?, ?)
`, lobbyID, b)
return err
}
func (l *Lobby) apply(e lobby.Event) error {
switch e := e.(type) {
case *lobby.PlayerJoin:
if !slices.Contains(l.Players, e.ID) {
l.Players = append(l.Players, e.ID)
}
case *lobby.PlayerLeave:
l.Players = slices.DeleteFunc(l.Players, func(id int) bool { return id == e.ID })
case *lobby.Close:
l.Closed = true
}
return nil
}

View File

@ -2,7 +2,7 @@ package lobby
import ( import (
"fmt" "fmt"
"gitea/price-is-wrong/src/lib/event" "gitea/price-is-wrong/pkg/lib/event"
) )
type Event interface{} type Event interface{}
@ -15,10 +15,14 @@ type PlayerLeave struct {
ID int ID int
} }
type Close struct {
}
func ParseEvent(b []byte) (Event, error) { func ParseEvent(b []byte) (Event, error) {
typesToPointers := map[string]any{ typesToPointers := map[string]any{
"*lobby.PlayerJoin": &PlayerJoin{}, "*lobby.PlayerJoin": &PlayerJoin{},
"*lobby.PlayerLeave": &PlayerLeave{}, "*lobby.PlayerLeave": &PlayerLeave{},
"*lobby.Close": &Close{},
} }
t, err := event.Parse(b, typesToPointers) t, err := event.Parse(b, typesToPointers)
return typesToPointers[t], err return typesToPointers[t], err

View File

@ -2,7 +2,7 @@ package lobby_test
import ( import (
"fmt" "fmt"
lobby "gitea/price-is-wrong/src/state/lobby/internal" lobby "gitea/price-is-wrong/pkg/state/lobby/internal"
"testing" "testing"
) )

View File

@ -1,8 +1,8 @@
package lobby_test package lobby_test
import ( import (
"gitea/price-is-wrong/src/lib" "gitea/price-is-wrong/pkg/lib"
"gitea/price-is-wrong/src/state/lobby" "gitea/price-is-wrong/pkg/state/lobby"
"testing" "testing"
) )
@ -44,4 +44,10 @@ func TestOpen(t *testing.T) {
} else if len(l.Players) != 2 { } else if len(l.Players) != 2 {
t.Errorf("second join yielded wrong players: %+v", l.Players) t.Errorf("second join yielded wrong players: %+v", l.Players)
} }
if err := l.Close(ctx); err != nil {
t.Fatal(err)
} else if !l.Closed {
t.Error(l.Closed)
}
} }

View File

@ -4,13 +4,14 @@ import (
"context" "context"
"database/sql" "database/sql"
"fmt" "fmt"
"gitea/price-is-wrong/src/lib/db" "gitea/price-is-wrong/pkg/lib/db"
lobby "gitea/price-is-wrong/src/state/lobby/internal" lobby "gitea/price-is-wrong/pkg/state/lobby/internal"
) )
type Lobby struct { type Lobby struct {
id int id int
Players []int Players []int
Closed bool
} }
func Open(ctx context.Context, name string) (*Lobby, error) { func Open(ctx context.Context, name string) (*Lobby, error) {

View File

@ -2,8 +2,8 @@ package priceiswrong
import ( import (
"context" "context"
"gitea/price-is-wrong/src/lib/db" "gitea/price-is-wrong/pkg/lib/db"
priceiswrong "gitea/price-is-wrong/src/state/priceiswrong/internal" priceiswrong "gitea/price-is-wrong/pkg/state/priceiswrong/internal"
"html" "html"
"math/rand" "math/rand"
) )

View File

@ -2,7 +2,7 @@ package priceiswrong
import ( import (
"fmt" "fmt"
"gitea/price-is-wrong/src/lib/event" "gitea/price-is-wrong/pkg/lib/event"
) )
type Event interface{} type Event interface{}

View File

@ -4,8 +4,8 @@ import (
"context" "context"
"database/sql" "database/sql"
"fmt" "fmt"
"gitea/price-is-wrong/src/lib/db" "gitea/price-is-wrong/pkg/lib/db"
priceiswrong "gitea/price-is-wrong/src/state/priceiswrong/internal" priceiswrong "gitea/price-is-wrong/pkg/state/priceiswrong/internal"
) )
type PriceIsWrong struct { type PriceIsWrong struct {

View File

@ -1,8 +1,8 @@
package priceiswrong_test package priceiswrong_test
import ( import (
"gitea/price-is-wrong/src/lib" "gitea/price-is-wrong/pkg/lib"
"gitea/price-is-wrong/src/state/priceiswrong" "gitea/price-is-wrong/pkg/state/priceiswrong"
"testing" "testing"
) )