diff --git a/character.go b/character.go index 13e2413..576c100 100644 --- a/character.go +++ b/character.go @@ -11,11 +11,19 @@ func (c Character) String() string { return c.Name } +// AffinityRelation holds precomputed affinity values for a pair or trio. type AffinityRelation struct { - IDA int `json:"chara_a"` - IDB int `json:"chara_b"` - IDC int `json:"chara_c,omitzero"` - Affinity int `json:"affinity"` + IDA CharacterID `json:"chara_a"` + IDB CharacterID `json:"chara_b"` + IDC CharacterID `json:"chara_c,omitzero"` + Affinity int `json:"affinity"` +} + +// AffinityDetail holds a single affinity entry. +type AffinityDetail struct { + CharaID CharacterID `json:"chara_id"` + Relation uint16 `json:"relation"` + Affinity uint16 `json:"affinity"` } // Conversation describes a lobby conversation. diff --git a/cmd/horsebot/main.go b/cmd/horsebot/main.go index 926a588..396a89d 100644 --- a/cmd/horsebot/main.go +++ b/cmd/horsebot/main.go @@ -129,6 +129,7 @@ func main() { mux.Handle("GET /", httpmiddle.Compress(5)(http.FileServerFS(os.DirFS(public)))) } mux.Handle("GET /api/global/affinity", httpmiddle.Compress(5)(dataroute(ctx, db, mdb.AffinitySummary))) + mux.Handle("GET /api/global/affinity-detail", httpmiddle.Compress(5)(dataroute(ctx, db, mdb.AffinityDetail))) mux.Handle("GET /api/global/character", httpmiddle.Compress(5)(dataroute(ctx, db, mdb.Characters))) mux.Handle("GET /api/global/conversation", httpmiddle.Compress(5)(dataroute(ctx, db, mdb.Conversations))) mux.Handle("GET /api/global/race", httpmiddle.Compress(5)(dataroute(ctx, db, mdb.Races))) diff --git a/mdb/character.go b/mdb/character.go index 10a3cca..8459572 100644 --- a/mdb/character.go +++ b/mdb/character.go @@ -15,6 +15,8 @@ var ( characterSQL string //go:embed sql/affinity.sql affinitySQL string + //go:embed sql/affinity-detail.sql + affinityDetailSQL string //go:embed sql/uma.sql umaSQL string //go:embed sql/conversation.sql @@ -35,14 +37,25 @@ func Characters(ctx context.Context, db *sqlitex.Pool) ([]horse.Character, error func AffinitySummary(ctx context.Context, db *sqlitex.Pool) ([]horse.AffinityRelation, error) { return load(ctx, db, nil, affinitySQL, func(s *sqlite.Stmt) horse.AffinityRelation { return horse.AffinityRelation{ - IDA: s.ColumnInt(0), - IDB: s.ColumnInt(1), - IDC: s.ColumnInt(2), + IDA: horse.CharacterID(s.ColumnInt(0)), + IDB: horse.CharacterID(s.ColumnInt(1)), + IDC: horse.CharacterID(s.ColumnInt(2)), Affinity: s.ColumnInt(3), } }) } +// AffinityDetail gets all individual affinity group entries. +func AffinityDetail(ctx context.Context, db *sqlitex.Pool) ([]horse.AffinityDetail, error) { + return load(ctx, db, nil, affinityDetailSQL, func(s *sqlite.Stmt) horse.AffinityDetail { + return horse.AffinityDetail{ + CharaID: horse.CharacterID(s.ColumnInt(0)), + Relation: uint16(s.ColumnInt(1)), + Affinity: uint16(s.ColumnInt(2)), + } + }) +} + // Umas retrieves all trainable Uma variants. func Umas(ctx context.Context, db *sqlitex.Pool) ([]horse.Uma, error) { return load(ctx, db, make([]horse.Uma, 0, 128), umaSQL, func(s *sqlite.Stmt) horse.Uma { diff --git a/mdb/character_test.go b/mdb/character_test.go index 8340032..806604a 100644 --- a/mdb/character_test.go +++ b/mdb/character_test.go @@ -44,6 +44,107 @@ func TestAffinitySummary(t *testing.T) { } } +func TestAffinityDetail(t *testing.T) { + db := testdb(t.Context(), "file:TestAffinityDetail?mode=memory&cache=shared", characterSQL) + got, err := mdb.AffinityDetail(t.Context(), db) + if err != nil { + t.Error(err) + } + want := []horse.AffinityDetail{ + {CharaID: 1001, Relation: 103, Affinity: 2}, + {CharaID: 1001, Relation: 202, Affinity: 2}, + {CharaID: 1001, Relation: 301, Affinity: 2}, + {CharaID: 1001, Relation: 401, Affinity: 2}, + {CharaID: 1001, Relation: 502, Affinity: 2}, + {CharaID: 1001, Relation: 510, Affinity: 2}, + {CharaID: 1001, Relation: 2001, Affinity: 1}, + {CharaID: 1001, Relation: 2102, Affinity: 1}, + {CharaID: 1001, Relation: 2301, Affinity: 1}, + {CharaID: 1001, Relation: 2406, Affinity: 1}, + {CharaID: 1001, Relation: 2506, Affinity: 1}, + {CharaID: 1001, Relation: 2510, Affinity: 1}, + {CharaID: 1001, Relation: 2516, Affinity: 1}, + {CharaID: 1001, Relation: 2519, Affinity: 1}, + {CharaID: 1001, Relation: 2601, Affinity: 1}, + {CharaID: 1001, Relation: 2603, Affinity: 1}, + {CharaID: 1001, Relation: 2811, Affinity: 1}, + {CharaID: 1001, Relation: 2903, Affinity: 7}, + {CharaID: 1001, Relation: 3003, Affinity: 7}, + {CharaID: 1001, Relation: 3004, Affinity: 7}, + {CharaID: 1001, Relation: 3101, Affinity: 7}, + {CharaID: 1001, Relation: 3205, Affinity: 1}, + {CharaID: 1001, Relation: 7003, Affinity: 1}, + {CharaID: 1001, Relation: 7004, Affinity: 1}, + {CharaID: 1001, Relation: 7005, Affinity: 1}, + {CharaID: 1001, Relation: 7006, Affinity: 1}, + {CharaID: 1001, Relation: 7007, Affinity: 1}, + {CharaID: 1001, Relation: 8001, Affinity: 1}, + {CharaID: 1001, Relation: 8002, Affinity: 1}, + {CharaID: 1001, Relation: 8003, Affinity: 1}, + {CharaID: 1001, Relation: 8004, Affinity: 1}, + {CharaID: 1001, Relation: 8005, Affinity: 1}, + {CharaID: 1001, Relation: 8006, Affinity: 1}, + {CharaID: 1001, Relation: 8007, Affinity: 1}, + {CharaID: 1001, Relation: 8008, Affinity: 1}, + {CharaID: 1001, Relation: 8009, Affinity: 1}, + {CharaID: 1001, Relation: 8010, Affinity: 1}, + {CharaID: 1001, Relation: 8011, Affinity: 1}, + {CharaID: 1001, Relation: 8012, Affinity: 1}, + {CharaID: 1001, Relation: 8013, Affinity: 1}, + {CharaID: 1001, Relation: 8014, Affinity: 1}, + {CharaID: 1001, Relation: 8015, Affinity: 1}, + {CharaID: 1001, Relation: 8016, Affinity: 1}, + {CharaID: 1001, Relation: 8443, Affinity: 1}, + {CharaID: 1001, Relation: 8479, Affinity: 1}, + {CharaID: 1001, Relation: 8511, Affinity: 1}, + {CharaID: 1001, Relation: 8536, Affinity: 1}, + {CharaID: 1001, Relation: 8640, Affinity: 1}, + {CharaID: 1002, Relation: 104, Affinity: 2}, + {CharaID: 1002, Relation: 202, Affinity: 2}, + {CharaID: 1002, Relation: 301, Affinity: 2}, + {CharaID: 1002, Relation: 402, Affinity: 2}, + {CharaID: 1002, Relation: 2001, Affinity: 1}, + {CharaID: 1002, Relation: 2406, Affinity: 1}, + {CharaID: 1002, Relation: 2512, Affinity: 1}, + {CharaID: 1002, Relation: 2601, Affinity: 1}, + {CharaID: 1002, Relation: 2603, Affinity: 1}, + {CharaID: 1002, Relation: 2810, Affinity: 1}, + {CharaID: 1002, Relation: 2901, Affinity: 7}, + {CharaID: 1002, Relation: 3003, Affinity: 7}, + {CharaID: 1002, Relation: 3101, Affinity: 7}, + {CharaID: 1002, Relation: 3205, Affinity: 1}, + {CharaID: 1002, Relation: 7000, Affinity: 1}, + {CharaID: 1002, Relation: 7001, Affinity: 1}, + {CharaID: 1002, Relation: 7002, Affinity: 1}, + {CharaID: 1002, Relation: 7013, Affinity: 1}, + {CharaID: 1002, Relation: 7015, Affinity: 1}, + {CharaID: 1002, Relation: 8017, Affinity: 1}, + {CharaID: 1002, Relation: 8018, Affinity: 1}, + {CharaID: 1002, Relation: 8019, Affinity: 1}, + {CharaID: 1002, Relation: 8020, Affinity: 1}, + {CharaID: 1002, Relation: 8021, Affinity: 1}, + {CharaID: 1002, Relation: 8022, Affinity: 1}, + {CharaID: 1002, Relation: 8023, Affinity: 1}, + {CharaID: 1002, Relation: 8024, Affinity: 1}, + {CharaID: 1002, Relation: 8025, Affinity: 1}, + {CharaID: 1002, Relation: 8026, Affinity: 1}, + {CharaID: 1002, Relation: 8027, Affinity: 1}, + {CharaID: 1002, Relation: 8028, Affinity: 1}, + {CharaID: 1002, Relation: 8029, Affinity: 1}, + {CharaID: 1002, Relation: 8030, Affinity: 1}, + {CharaID: 1002, Relation: 8031, Affinity: 1}, + {CharaID: 1002, Relation: 8032, Affinity: 1}, + {CharaID: 1002, Relation: 8444, Affinity: 1}, + {CharaID: 1002, Relation: 8480, Affinity: 1}, + {CharaID: 1002, Relation: 8512, Affinity: 1}, + {CharaID: 1002, Relation: 8537, Affinity: 1}, + {CharaID: 1002, Relation: 8641, Affinity: 1}, + } + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("wrong affinity details (+got/-want):\n%s", diff) + } +} + func TestUmas(t *testing.T) { db := testdb(t.Context(), "file:TestUmas?mode=memory&cache=shared", characterSQL) got, err := mdb.Umas(t.Context(), db) diff --git a/mdb/sql/affinity-detail.sql b/mdb/sql/affinity-detail.sql new file mode 100644 index 0000000..5efeb52 --- /dev/null +++ b/mdb/sql/affinity-detail.sql @@ -0,0 +1,7 @@ +SELECT + m.chara_id, + m.relation_type, + r.relation_point +FROM succession_relation_member m + JOIN succession_relation r ON m.relation_type = r.relation_type +ORDER BY m.chara_id, m.relation_type