package main import ( "context" _ "embed" "fmt" "zombiezen.com/go/sqlite/sqlitex" ) //go:embed character.sql var characterSQL string //go:embed character.affinity2.sql var characterAffinity2SQL string //go:embed character.affinity3.sql var characterAffinity3SQL string //go:embed skill-group.sql var skillGroupSQL string type ( Character struct{} SkillGroup struct{} ) type NamedID[T any] struct { // Disallow conversions between NamedID types. _ [0]*T ID int Name string // For internal use, the index of the identity, when it's needed. // We don't show this in public API, but it lets us use vectors for lookups. Index int } func Characters(ctx context.Context, db *sqlitex.Pool) ([]NamedID[Character], error) { conn, err := db.Take(ctx) defer db.Put(conn) if err != nil { return nil, fmt.Errorf("couldn't get connection for characters: %w", err) } stmt, _, err := conn.PrepareTransient(characterSQL) if err != nil { return nil, fmt.Errorf("couldn't prepare statement for characters: %w", err) } defer stmt.Finalize() var r []NamedID[Character] for { ok, err := stmt.Step() if err != nil { return nil, fmt.Errorf("error stepping characters: %w", err) } if !ok { break } c := NamedID[Character]{ ID: stmt.ColumnInt(0), Name: stmt.ColumnText(1), Index: stmt.ColumnInt(2), } r = append(r, c) } return r, nil } type AffinityRelation struct { IDA int NameA string IDB int NameB string IDC int NameC string Affinity int } func CharacterPairs(ctx context.Context, db *sqlitex.Pool) ([]AffinityRelation, error) { conn, err := db.Take(ctx) defer db.Put(conn) if err != nil { return nil, fmt.Errorf("couldn't get connection for character pairs: %w", err) } stmt, _, err := conn.PrepareTransient(characterAffinity2SQL) if err != nil { return nil, fmt.Errorf("couldn't prepare statement for character pairs: %w", err) } defer stmt.Finalize() var r []AffinityRelation for { ok, err := stmt.Step() if err != nil { return nil, fmt.Errorf("error stepping character pairs: %w", err) } if !ok { break } p := AffinityRelation{ IDA: stmt.ColumnInt(0), NameA: stmt.ColumnText(1), IDB: stmt.ColumnInt(2), NameB: stmt.ColumnText(3), Affinity: stmt.ColumnInt(4), } r = append(r, p) } return r, nil } func CharacterTrios(ctx context.Context, db *sqlitex.Pool) ([]AffinityRelation, error) { conn, err := db.Take(ctx) defer db.Put(conn) if err != nil { return nil, fmt.Errorf("couldn't get connection for character trios: %w", err) } stmt, _, err := conn.PrepareTransient(characterAffinity3SQL) if err != nil { return nil, fmt.Errorf("couldn't prepare statement for character trios: %w", err) } defer stmt.Finalize() var r []AffinityRelation for { ok, err := stmt.Step() if err != nil { return nil, fmt.Errorf("error stepping character trios: %w", err) } if !ok { break } p := AffinityRelation{ IDA: stmt.ColumnInt(0), NameA: stmt.ColumnText(1), IDB: stmt.ColumnInt(2), NameB: stmt.ColumnText(3), IDC: stmt.ColumnInt(4), NameC: stmt.ColumnText(5), Affinity: stmt.ColumnInt(6), } r = append(r, p) } return r, nil } func SkillGroups(ctx context.Context, db *sqlitex.Pool) ([]NamedID[SkillGroup], error) { conn, err := db.Take(ctx) defer db.Put(conn) if err != nil { return nil, fmt.Errorf("couldn't get connection for skill groups: %w", err) } stmt, _, err := conn.PrepareTransient(skillGroupSQL) if err != nil { return nil, fmt.Errorf("couldn't prepare statement for skill groups: %w", err) } defer stmt.Finalize() var r []NamedID[SkillGroup] for { ok, err := stmt.Step() if err != nil { return nil, fmt.Errorf("error stepping skill groups: %w", err) } if !ok { break } g := NamedID[SkillGroup]{ ID: stmt.ColumnInt(0), Name: stmt.ColumnText(1), } r = append(r, g) } return r, nil }