Skip to content

Commit f2306c8

Browse files
authored
Merge pull request #352 from vkedwardli/fix/battle-results-and-round-data
Resolve 0:0 battle results and individual player data overwriting
2 parents 6dc570f + 9e28cc6 commit f2306c8

4 files changed

Lines changed: 165 additions & 37 deletions

File tree

gdxsv/db.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,11 @@ type DB interface {
274274
// SetReplayURLBulk updates battle_record to set replay_url.
275275
SetReplayURLBulk(battleCodes, urls, disks []string) error
276276

277-
// SaveBattleRoundData updates battle_record to set used_ms_mask, used_ms_list, round_win.
278-
SaveBattleRoundData(battleCode string, usedMsMask int, usedMsList string, roundWin string) error
277+
// SaveBattleRoundWin updates battle_record to set round_win for all participants.
278+
SaveBattleRoundWin(battleCode string, roundWin string) error
279+
280+
// SaveUserUsedMs updates battle_record to set used_ms_mask and used_ms_list for a specific user.
281+
SaveUserUsedMs(battleCode string, userID string, usedMsMask int, usedMsList string) error
279282

280283
// ResetDailyBattleCount clears daily battle count of all users.
281284
ResetDailyBattleCount() (err error)

gdxsv/db_sqlite.go

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,19 @@ func (db SQLiteDB) Migrate() error {
275275
_ = tx.Rollback()
276276
return errors.Wrap(err, "2021-06 INSERT failed")
277277
}
278+
} else if err.Error() == "table battle_record has no column named result" {
279+
// NOTE: A column removed. battle_record.result
280+
var validColumns []string
281+
for _, col := range columns {
282+
if col != "result" {
283+
validColumns = append(validColumns, col)
284+
}
285+
}
286+
_, err = tx.Exec(`INSERT INTO ` + table + `(` + strings.Join(validColumns, ",") + `) SELECT ` + strings.Join(validColumns, ",") + ` FROM ` + tmp)
287+
if err != nil {
288+
_ = tx.Rollback()
289+
return errors.Wrap(err, "2026-02 result removal INSERT failed")
290+
}
278291
} else {
279292
_ = tx.Rollback()
280293
return errors.Wrap(err, "INSERT failed")
@@ -549,15 +562,24 @@ WHERE
549562
return err
550563
}
551564

552-
func (db SQLiteDB) SaveBattleRoundData(battleCode string, usedMsMask int, usedMsList string, roundWin string) error {
565+
func (db SQLiteDB) SaveBattleRoundWin(battleCode string, roundWin string) error {
553566
_, err := db.Exec(`
554567
UPDATE battle_record
555568
SET
556-
used_ms_mask = ?,
557-
used_ms_list = ?,
558569
round_win = ?
559570
WHERE
560-
battle_code = ?`, usedMsMask, usedMsList, roundWin, battleCode)
571+
battle_code = ?`, roundWin, battleCode)
572+
return err
573+
}
574+
575+
func (db SQLiteDB) SaveUserUsedMs(battleCode string, userID string, usedMsMask int, usedMsList string) error {
576+
_, err := db.Exec(`
577+
UPDATE battle_record
578+
SET
579+
used_ms_mask = ?,
580+
used_ms_list = ?
581+
WHERE
582+
battle_code = ? AND user_id = ?`, usedMsMask, usedMsList, battleCode, userID)
561583
return err
562584
}
563585

@@ -933,6 +955,32 @@ GROUP BY battle_code ORDER BY created `+order, q)
933955
continue
934956
}
935957

958+
// Calculate wins from winList first
959+
for i := 0; i < n; i++ {
960+
team, _ := strconv.Atoi(teamList[i])
961+
win, _ := strconv.Atoi(winList[i])
962+
if team == TeamRenpo && replay.RenpoWin < win {
963+
replay.RenpoWin = win
964+
}
965+
if team == TeamZeon && replay.ZeonWin < win {
966+
replay.ZeonWin = win
967+
}
968+
}
969+
970+
// If winList was all 0, try to use RoundWin ("1,2,1" etc)
971+
if replay.RenpoWin == 0 && replay.ZeonWin == 0 && r.RoundWin != "" {
972+
rounds := strings.Split(r.RoundWin, ",")
973+
for _, roundWinStr := range rounds {
974+
winTeam, _ := strconv.Atoi(roundWinStr)
975+
switch winTeam {
976+
case TeamRenpo:
977+
replay.RenpoWin++
978+
case TeamZeon:
979+
replay.ZeonWin++
980+
}
981+
}
982+
}
983+
936984
for i := 0; i < n; i++ {
937985
team, err := strconv.Atoi(teamList[i])
938986
if err != nil {
@@ -944,20 +992,6 @@ GROUP BY battle_code ORDER BY created `+order, q)
944992
return nil, err
945993
}
946994

947-
if team == TeamRenpo && replay.RenpoWin == 0 {
948-
replay.RenpoWin, err = strconv.Atoi(winList[i])
949-
if err != nil {
950-
return nil, err
951-
}
952-
}
953-
954-
if team == TeamZeon && replay.ZeonWin == 0 {
955-
replay.ZeonWin, err = strconv.Atoi(winList[i])
956-
if err != nil {
957-
return nil, err
958-
}
959-
}
960-
961995
usedMsList := ""
962996
if i < len(usedMsListList) {
963997
usedMsList = usedMsListList[i]

gdxsv/lbs_handler.go

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1752,24 +1752,31 @@ var _ = register(lbsP2PMatchingReport, func(p *LbsPeer, m *LbsMessage) {
17521752
return records[i].Pos < records[j].Pos
17531753
})
17541754

1755-
for posIdx, rec := range records {
1756-
var usedMsMask int
1757-
var usedMsParts []string
1758-
for _, rd := range report.RoundData {
1759-
msID := 0
1760-
if posIdx < len(rd.UsedMs) {
1761-
msID = int(rd.UsedMs[posIdx])
1762-
}
1763-
usedMsParts = append(usedMsParts, strconv.Itoa(msID))
1764-
if msID > 0 {
1765-
usedMsMask |= 1 << msID
1766-
}
1755+
if len(roundWin) > 0 {
1756+
err := getDB().SaveBattleRoundWin(report.BattleCode, roundWin)
1757+
if err != nil {
1758+
p.logger.Warn("SaveBattleRoundWin", zap.Error(err))
17671759
}
1768-
usedMsList := strings.Join(usedMsParts, ",")
17691760

1770-
err := getDB().SaveBattleRoundData(rec.BattleCode, usedMsMask, usedMsList, roundWin)
1771-
if err != nil {
1772-
p.logger.Warn("SaveBattleRoundData", zap.Error(err), zap.String("user_id", rec.UserID))
1761+
for posIdx, rec := range records {
1762+
var usedMsMask int
1763+
var usedMsParts []string
1764+
for _, rd := range report.RoundData {
1765+
msID := 0
1766+
if posIdx < len(rd.UsedMs) {
1767+
msID = int(rd.UsedMs[posIdx])
1768+
}
1769+
usedMsParts = append(usedMsParts, strconv.Itoa(msID))
1770+
if msID > 0 {
1771+
usedMsMask |= 1 << msID
1772+
}
1773+
}
1774+
usedMsList := strings.Join(usedMsParts, ",")
1775+
1776+
err := getDB().SaveUserUsedMs(rec.BattleCode, rec.UserID, usedMsMask, usedMsList)
1777+
if err != nil {
1778+
p.logger.Warn("SaveUserUsedMs", zap.Error(err), zap.String("user_id", rec.UserID))
1779+
}
17731780
}
17741781
}
17751782
p.logger.Info("SaveBattleRoundData done",

gdxsv/lbs_handler_test.go

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
package main
22

3-
import "testing"
3+
import (
4+
"bytes"
5+
"compress/zlib"
6+
"testing"
7+
"time"
8+
9+
pb "gdxsv/gdxsv/proto"
10+
11+
"google.golang.org/protobuf/proto"
12+
)
413

514
func Test_isOldFlycastVersion(t *testing.T) {
615
type args struct {
@@ -61,3 +70,78 @@ func Test_isOldFlycastVersion(t *testing.T) {
6170
}
6271
requiredFlycastVersion = backup
6372
}
73+
74+
func TestLbs_P2PMatchingReport(t *testing.T) {
75+
lbs := NewLbs()
76+
defer lbs.Quit()
77+
go lbs.eventLoop()
78+
79+
user1, cancel1 := prepareLoggedInUser(t, lbs, PlatformConsole, GameDiskDC2, DBUser{
80+
UserID: "U1",
81+
Name: "N1",
82+
})
83+
defer cancel1()
84+
85+
battleCode := "testreport"
86+
// Setup 2 players in database
87+
for i, uid := range []string{"U1", "U2"} {
88+
must(t, getDB().AddBattleRecord(&BattleRecord{
89+
BattleCode: battleCode,
90+
UserID: uid,
91+
Pos: i + 1,
92+
Players: 2,
93+
Team: i + 1,
94+
ReplayURL: "http://example.com/replay",
95+
}))
96+
}
97+
98+
report := &pb.P2PMatchingReport{
99+
BattleCode: battleCode,
100+
CloseReason: "game_end",
101+
PlayerCount: 2,
102+
RoundData: []*pb.BattleLogRound{
103+
{WinTeam: 1, UsedMs: []int32{10, 20}}, // U1 used MS 10, U2 used MS 20
104+
{WinTeam: 1, UsedMs: []int32{11, 21}},
105+
},
106+
}
107+
108+
bin, _ := proto.Marshal(report)
109+
var buf bytes.Buffer
110+
zw := zlib.NewWriter(&buf)
111+
_, err := zw.Write(bin)
112+
must(t, err)
113+
zw.Close()
114+
115+
user1.MustWriteMessage(&LbsMessage{
116+
Command: lbsP2PMatchingReport,
117+
BodySize: uint16(buf.Len()),
118+
Body: buf.Bytes(),
119+
})
120+
121+
// Wait for processing
122+
time.Sleep(100 * time.Millisecond)
123+
124+
// Verify database
125+
for _, uid := range []string{"U1", "U2"} {
126+
rec, err := getDB().GetBattleRecordUser(battleCode, uid)
127+
must(t, err)
128+
assertEq(t, "1,1", rec.RoundWin)
129+
if uid == "U1" {
130+
assertEq(t, "10,11", rec.UsedMsList)
131+
assertEq(t, (1<<10)|(1<<11), rec.UsedMsMask)
132+
} else {
133+
assertEq(t, "20,21", rec.UsedMsList)
134+
assertEq(t, (1<<20)|(1<<21), rec.UsedMsMask)
135+
}
136+
}
137+
138+
// Verify FindReplay uses RoundWin for scoring
139+
q := NewFindReplayQuery()
140+
q.BattleCode = battleCode
141+
replays, err := getDB().FindReplay(q)
142+
must(t, err)
143+
assertEq(t, 1, len(replays))
144+
assertEq(t, 2, replays[0].RenpoWin) // 2 rounds won by team 1
145+
assertEq(t, 0, replays[0].ZeonWin)
146+
}
147+

0 commit comments

Comments
 (0)