generate is coo
parent
f6736b8461
commit
7450ba86b6
|
|
@ -1 +1,2 @@
|
||||||
**/*.sw*
|
**/*.sw*
|
||||||
|
/src/state/fsm/template
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"gitea/price-is-wrong/src/lib/db"
|
||||||
|
template "gitea/price-is-wrong/src/state/fsm/template/internal"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t *Template) TODO(ctx context.Context, id int) error {
|
||||||
|
return io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Template) upsertEvent(ctx context.Context, e template.Event) error {
|
||||||
|
if err := upsertEvent(ctx, p.id, e); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p2, err := openID(ctx, p.id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*p = *p2
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func upsertEvent(ctx context.Context, templateID int, e template.Event) error {
|
||||||
|
b, err := template.MarshalEvent(e)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = db.From(ctx).ExecContext(ctx, `
|
||||||
|
INSERT INTO template_events (template_id, payload) VALUES (?, ?)
|
||||||
|
`, templateID, b)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Template) apply(e template.Event) error {
|
||||||
|
switch e := e.(type) {
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"gitea/price-is-wrong/src/lib/event"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Event interface{}
|
||||||
|
|
||||||
|
func ParseEvent(b []byte) (Event, error) {
|
||||||
|
typesToPointers := map[string]any{
|
||||||
|
"*any": &b,
|
||||||
|
}
|
||||||
|
t, err := event.Parse(b, typesToPointers)
|
||||||
|
return typesToPointers[t], err
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalEvent(e Event) ([]byte, error) {
|
||||||
|
return event.Serialize(fmt.Sprintf("%T", e), e)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
package template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"gitea/price-is-wrong/src/lib/db"
|
||||||
|
template "gitea/price-is-wrong/src/state/fsm/template/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Template struct {
|
||||||
|
id int
|
||||||
|
Host int
|
||||||
|
Contestants Player
|
||||||
|
}
|
||||||
|
|
||||||
|
type Player struct {
|
||||||
|
ID int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Open(ctx context.Context, name string) (*Template, error) {
|
||||||
|
if err := initialize(ctx); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to initialize template: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if result, err := open(ctx, name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if result == nil {
|
||||||
|
if err := create(ctx, name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mustOpen(ctx, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustOpen(ctx context.Context, name string) (*Template, error) {
|
||||||
|
result, err := open(ctx, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if result == nil {
|
||||||
|
return nil, fmt.Errorf("no template found with name %s", name)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func open(ctx context.Context, name string) (*Template, error) {
|
||||||
|
row := db.From(ctx).QueryRow(`SELECT id FROM templates WHERE name=?`, name)
|
||||||
|
if err := row.Err(); err != nil {
|
||||||
|
return nil, fmt.Errorf("no template found with name %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
var id sql.NullInt32
|
||||||
|
if err := row.Scan(&id); err == sql.ErrNoRows || !id.Valid {
|
||||||
|
return nil, nil
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to scan id from templates: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return openID(ctx, int(id.Int32))
|
||||||
|
}
|
||||||
|
|
||||||
|
func openID(ctx context.Context, id int) (*Template, error) {
|
||||||
|
rows, err := db.From(ctx).QueryContext(ctx, `
|
||||||
|
SELECT payload
|
||||||
|
FROM template_events
|
||||||
|
WHERE template_events.template_id=?
|
||||||
|
ORDER BY id
|
||||||
|
`, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to query event payloads for id %d: %w", id, err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
result := Template{id: id}
|
||||||
|
for rows.Next() {
|
||||||
|
var b []byte
|
||||||
|
if err := rows.Scan(&b); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to scan event: %w", err)
|
||||||
|
}
|
||||||
|
event, err := template.ParseEvent(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse event: %w", err)
|
||||||
|
}
|
||||||
|
if err := result.apply(event); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to apply event %s: %w", b, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &result, rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func create(ctx context.Context, name string) error {
|
||||||
|
_, err := db.From(ctx).ExecContext(ctx, `
|
||||||
|
INSERT INTO templates (name) VALUES (?)
|
||||||
|
`, name)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func initialize(ctx context.Context) error {
|
||||||
|
_, err := db.From(ctx).ExecContext(ctx, `
|
||||||
|
CREATE TABLE IF NOT EXISTS templates (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT
|
||||||
|
);
|
||||||
|
CREATE TABLE IF NOT EXISTS template_events (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
template_id NUMBER,
|
||||||
|
payload TEXT,
|
||||||
|
FOREIGN KEY (template_id) REFERENCES templates (id)
|
||||||
|
);
|
||||||
|
`)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
package fsm
|
||||||
|
|
||||||
|
//go:generate cp -r ./.template ./template
|
||||||
Loading…
Reference in New Issue