...

Source file src/go.formulabun.club/replays/store/client.go

Documentation: go.formulabun.club/replays/store

     1  package store
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  
     7  	_ "github.com/go-sql-driver/mysql"
     8  
     9  	"go.formulabun.club/srb2kart/lump/replay"
    10  )
    11  
    12  type columnScanner interface {
    13  	Scan(dest ...any) error
    14  }
    15  
    16  func ConvertToStoreData(replay replay.ReplayRaw) (r Replay, files []ReplayFile, err error) {
    17  	if len(replay.PlayerEntries) != 1 {
    18  		err = fmt.Errorf("Replay file doesn't contain exactly 1 player, it contains %v", len(replay.PlayerEntries))
    19  		return
    20  	}
    21  	player := replay.PlayerEntries[0]
    22  	r = Replay{
    23  		GameMap: replay.GameMap,
    24  		Time:    replay.Time,
    25  		BestLap: replay.Lap,
    26  		Speed:   player.Speed,
    27  		Weight:  player.Weight,
    28  	}
    29  	copy(r.PlayerName[:], player.Name[:16])
    30  	copy(r.PlayerSkin[:], player.Skin[:16])
    31  	copy(r.PlayerColor[:], player.Color[:16])
    32  
    33  	files = make([]ReplayFile, len(replay.WadEntries))
    34  	for i, file := range replay.WadEntries {
    35  		files[i].FileName = file.FileName
    36  		copy(files[i].FileCheckSum[:16], file.WadMd5[:])
    37  	}
    38  
    39  	return r, files, nil
    40  }
    41  
    42  func (db *Client) InsertReplayRaw(replay replay.ReplayRaw) (id int64, err error) {
    43  	r, files, err := ConvertToStoreData(replay)
    44  	if err != nil {
    45  		return 0, err
    46  	}
    47  	return db.InsertReplayInfo(r, files)
    48  }
    49  
    50  func (db *Client) InsertReplayInfo(replay Replay, files []ReplayFile) (id int64, err error) {
    51  	t, err := db.Begin()
    52  	defer t.Commit()
    53  	if err != nil {
    54  		return
    55  	}
    56  
    57  	res, err := t.Exec(
    58  		`
    59  INSERT INTO replays
    60  (GameMap, Time, BestLap, PlayerName, PlayerSkin, PlayerColor, Speed, Weight)
    61  VALUE
    62  (?, ?, ?, ?, ?, ?, ?, ?)
    63  `,
    64  		replay.GameMap, replay.Time, replay.BestLap, fmt.Sprintf("%s", replay.PlayerName), fmt.Sprintf("%s", replay.PlayerSkin), fmt.Sprintf("%s", replay.PlayerColor), replay.Speed, replay.Weight)
    65  	if err != nil {
    66  		t.Rollback()
    67  		return
    68  	}
    69  
    70  	id, err = res.LastInsertId()
    71  
    72  	for _, file := range files {
    73  		checksum := hex.EncodeToString(file.FileCheckSum[:])
    74  		_, err = t.Exec(
    75  			`
    76  INSERT INTO replayfiles
    77  (ReplayID, FileName, FileCheckSum)
    78  VALUE
    79  (?, ?, ?)
    80  `,
    81  			id, file.FileName, checksum)
    82  		if err != nil {
    83  			t.Rollback()
    84  			return
    85  		}
    86  
    87  	}
    88  
    89  	return
    90  }
    91  
    92  func scanRow(row columnScanner) (Replay, error) {
    93  	var result Replay
    94  	var name, skin, color string
    95  	err := row.Scan(&result.ReplayID, &result.GameMap, &result.Time, &result.BestLap, &name, &skin, &color, &result.Speed, &result.Weight)
    96  
    97  	copy(result.PlayerName[:], name)
    98  	copy(result.PlayerSkin[:], skin)
    99  	copy(result.PlayerColor[:], color)
   100  
   101  	return result, err
   102  }
   103  
   104  func (db *Client) GetReplayById(id int64) (result Replay, err error) {
   105  	row := db.QueryRow(
   106  		`
   107  SELECT ReplayID, GameMap, Time, BestLap, PlayerName, PlayerSkin, PlayerColor, Speed, Weight from replays 
   108  WHERE ReplayId = ?
   109  `, id)
   110  	return scanRow(row)
   111  }
   112  
   113  func (db *Client) FindReplay(r Replay) ([]Replay, error) {
   114  	var where = "WHERE GameMap %s ? AND Time %s ? AND BestLap %s ? AND Speed %s ? AND Weight %s ?"
   115  	var cMap, cTime, cLap, cSpeed, cWeight string
   116  	if r.GameMap == 0 {
   117  		cMap = ">"
   118  	} else {
   119  		cMap = "="
   120  	}
   121  	if r.Time == 0 {
   122  		cTime = ">"
   123  	} else {
   124  		cTime = "<="
   125  	}
   126  	if r.BestLap == 0 {
   127  		cLap = ">"
   128  	} else {
   129  		cLap = "<="
   130  	}
   131  	if r.Speed == 0 {
   132  		cSpeed = ">"
   133  	} else {
   134  		cSpeed = "="
   135  	}
   136  	if r.Weight == 0 {
   137  		cWeight = ">"
   138  	} else {
   139  		cWeight = "="
   140  	}
   141  
   142  	where = fmt.Sprintf(where, cMap, cTime, cLap, cSpeed, cWeight)
   143  	rows, err := db.Query(
   144  		fmt.Sprintf(`SELECT ReplayID, GameMap, min(Time), BestLap, PlayerName, PlayerSkin, Playercolor, Speed, weight FROM replays
   145      %s
   146      GROUP BY PlayerName
   147      ORDER BY Time ASC`, where),
   148  		r.GameMap, r.Time, r.BestLap, r.Speed, r.Weight)
   149  
   150  	var result = []Replay{}
   151  	if err != nil {
   152  		return result, err
   153  	}
   154  
   155  	for rows.Next() {
   156  		item, err := scanRow(rows)
   157  		if err != nil {
   158  			return result, err
   159  		}
   160  		result = append(result, item)
   161  	}
   162  	return result, err
   163  
   164  }
   165  

View as plain text