From 90d621c19583c7c2affb4290cc4c0d65957f5813 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 1 Jun 2026 20:23:05 +0200 Subject: [PATCH] feat: Rename game to soundtrack throughout codebase - Database migration: rename game table to soundtrack - Rename game_name to soundtrack_name, game_id to soundtrack_id - Update all SQL queries in soundtrack.sql, song.sql, song_list.sql, statistics.sql - Regenerate sqlc code (soundtrack.sql.go, song.sql.go, etc.) - Update backend: music.go, sync.go, statistics.go - Update server: musicHandler.go, syncHandler.go, routes.go - Update frontend: hello.go - Keep URL paths as /games for backward compatibility Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe --- cmd/web/hello.go | 2 +- internal/backend/music.go | 52 ++-- internal/backend/statistics.go | 74 ++--- internal/backend/sync.go | 92 +++--- .../000005_rename_game_to_soundtrack.down.sql | 33 +++ .../000005_rename_game_to_soundtrack.up.sql | 33 +++ internal/db/queries/game.sql | 49 ---- internal/db/queries/song.sql | 12 +- internal/db/queries/song_list.sql | 2 +- internal/db/queries/soundtrack.sql | 49 ++++ internal/db/queries/statistics.sql | 114 ++++---- internal/db/repository/game.sql.go | 246 ---------------- internal/db/repository/models.go | 48 ++-- internal/db/repository/song.sql.go | 50 ++-- internal/db/repository/song_list.sql.go | 18 +- internal/db/repository/soundtrack.sql.go | 246 ++++++++++++++++ internal/db/repository/statistics.sql.go | 262 +++++++++--------- internal/server/musicHandler.go | 20 +- internal/server/routes.go | 18 +- internal/server/syncHandler.go | 34 +-- 20 files changed, 760 insertions(+), 694 deletions(-) create mode 100644 internal/db/migrations/000005_rename_game_to_soundtrack.down.sql create mode 100644 internal/db/migrations/000005_rename_game_to_soundtrack.up.sql delete mode 100644 internal/db/queries/game.sql create mode 100644 internal/db/queries/soundtrack.sql delete mode 100644 internal/db/repository/game.sql.go create mode 100644 internal/db/repository/soundtrack.sql.go diff --git a/cmd/web/hello.go b/cmd/web/hello.go index 5445720..87feded 100644 --- a/cmd/web/hello.go +++ b/cmd/web/hello.go @@ -30,7 +30,7 @@ func FindGameWebHandler(w http.ResponseWriter, r *http.Request) { func search(searchText string) { games_added = nil - games := backend.GetAllGames() + games := backend.GetAllSoundtracks() for _, game := range games { if is_match_exact(searchText, game) { add_game(game) diff --git a/internal/backend/music.go b/internal/backend/music.go index c9717b4..359ec52 100644 --- a/internal/backend/music.go +++ b/internal/backend/music.go @@ -22,7 +22,7 @@ type SongInfo struct { var currentSong = -1 -var gamesNew []repository.Game +var gamesNew []repository.Soundtrack var songQueNew []repository.Song @@ -37,10 +37,10 @@ func initRepo() { } } -func getAllGames() []repository.Game { +func getAllGames() []repository.Soundtrack { if len(gamesNew) == 0 { initRepo() - gamesNew, _ = BackendRepo().FindAllGames(BackendCtx()) + gamesNew, _ = BackendRepo().FindAllSoundtracks(BackendCtx()) } return gamesNew @@ -59,7 +59,7 @@ func Reset() { songQueNew = nil currentSong = -1 initRepo() - gamesNew, _ = BackendRepo().FindAllGames(BackendCtx()) + gamesNew, _ = BackendRepo().FindAllSoundtracks(BackendCtx()) } func AddLatestToQue() { @@ -77,8 +77,8 @@ func AddLatestPlayed() { currentSongData := songQueNew[currentSong] initRepo() - BackendRepo().AddGamePlayed(BackendCtx(), currentSongData.GameID) - BackendRepo().AddSongPlayed(BackendCtx(), repository.AddSongPlayedParams{GameID: currentSongData.GameID, SongName: currentSongData.SongName}) + BackendRepo().AddSoundtrackPlayed(BackendCtx(), currentSongData.SoundtrackID) + BackendRepo().AddSongPlayed(BackendCtx(), repository.AddSongPlayedParams{SoundtrackID: currentSongData.SoundtrackID, SongName: currentSongData.SongName}) } func SetPlayed(songNumber int) { @@ -87,8 +87,8 @@ func SetPlayed(songNumber int) { } songData := songQueNew[songNumber] initRepo() - BackendRepo().AddGamePlayed(BackendCtx(), songData.GameID) - BackendRepo().AddSongPlayed(BackendCtx(), repository.AddSongPlayedParams{GameID: songData.GameID, SongName: songData.SongName}) + BackendRepo().AddSoundtrackPlayed(BackendCtx(), songData.SoundtrackID) + BackendRepo().AddSongPlayed(BackendCtx(), repository.AddSongPlayedParams{SoundtrackID: songData.SoundtrackID, SongName: songData.SongName}) } func GetRandomSong() string { @@ -105,7 +105,7 @@ func GetRandomSong() string { func GetRandomSongLowChance() string { getAllGames() - var listOfGames []repository.Game + var listOfGames []repository.Soundtrack var averagePlayed = getAveragePlayed() @@ -131,7 +131,7 @@ func GetRandomSongClassic() string { var listOfAllSongs []repository.Song for _, game := range gamesNew { - songList, _ := BackendRepo().FindSongsFromGame(BackendCtx(), game.ID) + songList, _ := BackendRepo().FindSongsFromSoundtrack(BackendCtx(), game.ID) listOfAllSongs = append(listOfAllSongs, songList...) } @@ -139,13 +139,13 @@ func GetRandomSongClassic() string { var song repository.Song for !songFound { song = listOfAllSongs[rand.Intn(len(listOfAllSongs))] - gameData, err := BackendRepo().GetGameById(BackendCtx(), song.GameID) + gameData, err := BackendRepo().GetSoundtrackById(BackendCtx(), song.SoundtrackID) if err != nil { BackendRepo().RemoveBrokenSong(BackendCtx(), song.Path) logging.GetLogger().Warn("Song not found, removed from database", zap.String("song", song.SongName), - zap.String("game", gameData.GameName), + zap.String("game", gameData.SoundtrackName), zap.String("filename", *song.FileName)) continue } @@ -157,7 +157,7 @@ func GetRandomSongClassic() string { BackendRepo().RemoveBrokenSong(BackendCtx(), song.Path) logging.GetLogger().Warn("Song not found, removed from database", zap.String("song", song.SongName), - zap.String("game", gameData.GameName), + zap.String("game", gameData.SoundtrackName), zap.String("filename", *song.FileName)) } else { songFound = true @@ -180,7 +180,7 @@ func GetSongInfo() SongInfo { currentGameData := getCurrentGame(currentSongData) return SongInfo{ - Game: currentGameData.GameName, + Game: currentGameData.SoundtrackName, GamePlayed: currentGameData.TimesPlayed, Song: currentSongData.SongName, SongPlayed: currentSongData.TimesPlayed, @@ -195,7 +195,7 @@ func GetPlayedSongs() []SongInfo { for i, song := range songQueNew { gameData := getCurrentGame(song) songList = append(songList, SongInfo{ - Game: gameData.GameName, + Game: gameData.SoundtrackName, GamePlayed: gameData.TimesPlayed, Song: song.SongName, SongPlayed: song.TimesPlayed, @@ -217,22 +217,22 @@ func GetSong(song string) string { return songData.Path } -func GetAllGames() []string { +func GetAllSoundtracks() []string { getAllGames() var jsonArray []string for _, game := range gamesNew { - jsonArray = append(jsonArray, game.GameName) + jsonArray = append(jsonArray, game.SoundtrackName) } return jsonArray } -func GetAllGamesRandom() []string { +func GetAllSoundtracksRandom() []string { getAllGames() var jsonArray []string for _, game := range gamesNew { - jsonArray = append(jsonArray, game.GameName) + jsonArray = append(jsonArray, game.SoundtrackName) } rand.Shuffle(len(jsonArray), func(i, j int) { jsonArray[i], jsonArray[j] = jsonArray[j], jsonArray[i] }) return jsonArray @@ -266,12 +266,12 @@ func GetPreviousSong() string { } } -func getSongFromList(games []repository.Game) repository.Song { +func getSongFromList(games []repository.Soundtrack) repository.Song { songFound := false var song repository.Song for !songFound { game := getRandomGame(games) - songs, _ := BackendRepo().FindSongsFromGame(BackendCtx(), game.ID) + songs, _ := BackendRepo().FindSongsFromSoundtrack(BackendCtx(), game.ID) if len(songs) == 0 { continue } @@ -285,7 +285,7 @@ func getSongFromList(games []repository.Game) repository.Song { BackendRepo().RemoveBrokenSong(BackendCtx(), song.Path) logging.GetLogger().Warn("Song not found, removed from database", zap.String("song", song.SongName), - zap.String("game", game.GameName), + zap.String("game", game.SoundtrackName), zap.Any("filename", song.FileName)) } else { songFound = true @@ -299,13 +299,13 @@ func getSongFromList(games []repository.Game) repository.Song { return song } -func getCurrentGame(currentSongData repository.Song) repository.Game { +func getCurrentGame(currentSongData repository.Song) repository.Soundtrack { for _, game := range gamesNew { - if game.ID == currentSongData.GameID { + if game.ID == currentSongData.SoundtrackID { return game } } - return repository.Game{} + return repository.Soundtrack{} } func getAveragePlayed() int32 { @@ -317,6 +317,6 @@ func getAveragePlayed() int32 { return sum / int32(len(gamesNew)) } -func getRandomGame(listOfGames []repository.Game) repository.Game { +func getRandomGame(listOfGames []repository.Soundtrack) repository.Soundtrack { return listOfGames[rand.Intn(len(listOfGames))] } diff --git a/internal/backend/statistics.go b/internal/backend/statistics.go index 23fa4e6..e6fccb3 100644 --- a/internal/backend/statistics.go +++ b/internal/backend/statistics.go @@ -11,17 +11,17 @@ import ( // GameWithSongs represents a game with its songs for statistics type GameWithSongs struct { - GameID int32 `json:"game_id"` - GameName string `json:"game_name"` - GamePlayed int32 `json:"game_played"` - GameLastPlayed *time.Time `json:"game_last_played,omitempty"` + SoundtrackID int32 `json:"game_id"` + SoundtrackName string `json:"game_name"` + SoundtrackPlayed int32 `json:"game_played"` + SoundtrackLastPlayed *time.Time `json:"game_last_played,omitempty"` Songs []SongInfoForStats `json:"songs"` } // SongInfoForStats represents a song with game info for statistics type SongInfoForStats struct { - GameID int32 `json:"game_id"` - GameName string `json:"game_name"` + SoundtrackID int32 `json:"game_id"` + SoundtrackName string `json:"game_name"` SongName string `json:"song_name"` Path string `json:"path"` TimesPlayed int32 `json:"times_played"` @@ -72,10 +72,10 @@ func (h *StatisticsHandler) GetMostPlayedGamesWithSongs(limit int32) ([]GameWith } } result = append(result, GameWithSongs{ - GameID: row.GameID, - GameName: row.GameName, - GamePlayed: row.GamePlayed, - GameLastPlayed: row.GameLastPlayed, + SoundtrackID: row.SoundtrackID, + SoundtrackName: row.SoundtrackName, + SoundtrackPlayed: row.SoundtrackPlayed, + SoundtrackLastPlayed: row.SoundtrackLastPlayed, Songs: songs, }) } @@ -101,10 +101,10 @@ func (h *StatisticsHandler) GetLeastPlayedGamesWithSongs(limit int32) ([]GameWit } } result = append(result, GameWithSongs{ - GameID: row.GameID, - GameName: row.GameName, - GamePlayed: row.GamePlayed, - GameLastPlayed: row.GameLastPlayed, + SoundtrackID: row.SoundtrackID, + SoundtrackName: row.SoundtrackName, + SoundtrackPlayed: row.SoundtrackPlayed, + SoundtrackLastPlayed: row.SoundtrackLastPlayed, Songs: songs, }) } @@ -124,8 +124,8 @@ func (h *StatisticsHandler) GetMostPlayedSongsWithGame(limit int32) ([]SongInfoF var result []SongInfoForStats for _, row := range rows { result = append(result, SongInfoForStats{ - GameID: row.GameID, - GameName: row.GameName, + SoundtrackID: row.SoundtrackID, + SoundtrackName: row.SoundtrackName, SongName: row.SongName, Path: row.Path, TimesPlayed: row.TimesPlayed, @@ -148,8 +148,8 @@ func (h *StatisticsHandler) GetLeastPlayedSongsWithGame(limit int32) ([]SongInfo var result []SongInfoForStats for _, row := range rows { result = append(result, SongInfoForStats{ - GameID: row.GameID, - GameName: row.GameName, + SoundtrackID: row.SoundtrackID, + SoundtrackName: row.SoundtrackName, SongName: row.SongName, Path: row.Path, TimesPlayed: row.TimesPlayed, @@ -178,10 +178,10 @@ func (h *StatisticsHandler) GetNeverPlayedGames() ([]GameWithSongs, error) { } } result = append(result, GameWithSongs{ - GameID: row.GameID, - GameName: row.GameName, - GamePlayed: row.GamePlayed, - GameLastPlayed: nil, + SoundtrackID: row.SoundtrackID, + SoundtrackName: row.SoundtrackName, + SoundtrackPlayed: row.SoundtrackPlayed, + SoundtrackLastPlayed: nil, Songs: songs, }) } @@ -207,10 +207,10 @@ func (h *StatisticsHandler) GetLastPlayedGames(limit int32) ([]GameWithSongs, er } } result = append(result, GameWithSongs{ - GameID: row.GameID, - GameName: row.GameName, - GamePlayed: row.GamePlayed, - GameLastPlayed: row.GameLastPlayed, + SoundtrackID: row.SoundtrackID, + SoundtrackName: row.SoundtrackName, + SoundtrackPlayed: row.SoundtrackPlayed, + SoundtrackLastPlayed: row.SoundtrackLastPlayed, Songs: songs, }) } @@ -236,10 +236,10 @@ func (h *StatisticsHandler) GetOldestPlayedGames(limit int32) ([]GameWithSongs, } } result = append(result, GameWithSongs{ - GameID: row.GameID, - GameName: row.GameName, - GamePlayed: row.GamePlayed, - GameLastPlayed: row.GameLastPlayed, + SoundtrackID: row.SoundtrackID, + SoundtrackName: row.SoundtrackName, + SoundtrackPlayed: row.SoundtrackPlayed, + SoundtrackLastPlayed: row.SoundtrackLastPlayed, Songs: songs, }) } @@ -257,13 +257,13 @@ func (h *StatisticsHandler) GetStatisticsSummary() (*StatisticsSummary, error) { } return &StatisticsSummary{ - TotalGames: int64(row.TotalGames), - PlayedGames: int64(row.PlayedGames), - NeverPlayedGames: int64(row.NeverPlayedGames), - TotalGamePlays: int64(row.TotalGamePlays), - AvgGamePlays: float64(row.AvgGamePlays), - MaxGamePlays: int64(row.MaxGamePlays), - MinGamePlays: int64(row.MinGamePlays), + TotalGames: int64(row.TotalSoundtracks), + PlayedGames: int64(row.PlayedSoundtracks), + NeverPlayedGames: int64(row.NeverPlayedSoundtracks), + TotalGamePlays: int64(row.TotalSoundtrackPlays), + AvgGamePlays: float64(row.AvgSoundtrackPlays), + MaxGamePlays: int64(row.MaxSoundtrackPlays), + MinGamePlays: int64(row.MinSoundtrackPlays), }, nil } diff --git a/internal/backend/sync.go b/internal/backend/sync.go index 42d7621..7aae292 100644 --- a/internal/backend/sync.go +++ b/internal/backend/sync.go @@ -30,9 +30,9 @@ var start time.Time var totalTime time.Duration var timeSpent time.Duration -var allGames []repository.Game -var gamesBeforeSync []repository.Game -var gamesAfterSync []repository.Game +var allGames []repository.Soundtrack +var gamesBeforeSync []repository.Soundtrack +var gamesAfterSync []repository.Soundtrack var gamesAdded []string var gamesReAdded []string var gamesChangedTitle map[string]string @@ -80,7 +80,7 @@ func (gs GameStatus) String() string { func ResetDB() { repo.ClearSongs(BackendCtx()) - repo.ClearGames(BackendCtx()) + repo.ClearSoundtracks(BackendCtx()) } func SyncProgress() ProgressResponse { @@ -124,13 +124,13 @@ func SyncResult() SyncResponse { for _, beforeGame := range gamesBeforeSync { var found = false for _, afterGame := range gamesAfterSync { - if beforeGame.GameName == afterGame.GameName { + if beforeGame.SoundtrackName == afterGame.SoundtrackName { found = true break } } if !found { - gamesRemovedTemp = append(gamesRemovedTemp, beforeGame.GameName) + gamesRemovedTemp = append(gamesRemovedTemp, beforeGame.SoundtrackName) } } @@ -169,12 +169,12 @@ func SyncResult() SyncResponse { } } -func SyncGamesNewFull() { +func SyncSoundtracksNewFull() { syncGamesNew(true) Reset() } -func SyncGamesNewOnlyChanges() { +func SyncSoundtracksNewOnlyChanges() { syncGamesNew(false) Reset() } @@ -205,14 +205,14 @@ func syncGamesNew(full bool) { catchedErrors = nil brokenSongs = nil - gamesBeforeSync, err = repo.FindAllGames(BackendCtx()) - handleError("FindAllGames Before", err, "") + gamesBeforeSync, err = repo.FindAllSoundtracks(BackendCtx()) + handleError("FindAllSoundtracks Before", err, "") logging.GetLogger().Info("Starting sync", zap.Int("games_before", len(gamesBeforeSync))) - allGames, err = repo.GetAllGamesIncludingDeleted(BackendCtx()) - handleError("GetAllGamesIncludingDeleted", err, "") - err = repo.SetGameDeletionDate(BackendCtx()) - handleError("SetGameDeletionDate", err, "") + allGames, err = repo.GetAllSoundtracksIncludingDeleted(BackendCtx()) + handleError("GetAllSoundtracksIncludingDeleted", err, "") + err = repo.SetSoundtrackDeletionDate(BackendCtx()) + handleError("SetSoundtrackDeletionDate", err, "") directories, err := os.ReadDir(musicPath) if err != nil { @@ -236,8 +236,8 @@ func syncGamesNew(full bool) { syncWg.Wait() checkBrokenSongsNew() - gamesAfterSync, err = repo.FindAllGames(BackendCtx()) - handleError("FindAllGames After", err, "") + gamesAfterSync, err = repo.FindAllSoundtracks(BackendCtx()) + handleError("FindAllSoundtracks After", err, "") finished := time.Now() totalTime = finished.Sub(start) @@ -288,28 +288,28 @@ func syncGameNew(file os.DirEntry, foldersToSkip []string, baseDir string, full dirHash := getHashForDir(gameDir) var status GameStatus = NewGame - var oldGame repository.Game + var oldGame repository.Soundtrack var id int32 = -1 //fmt.Printf("Games before: %d\n", len(gamesBeforeSync)) for _, currentGame := range allGames { oldGame = currentGame - //fmt.Printf("%s | %s\n", oldGame.GameName, oldGame.Hash) - if oldGame.GameName == file.Name() && oldGame.Hash == dirHash { + //fmt.Printf("%s | %s\n", oldGame.SoundtrackName, oldGame.Hash) + if oldGame.SoundtrackName == file.Name() && oldGame.Hash == dirHash { status = NotChanged id = oldGame.ID //fmt.Printf("Game not changed\n") break - } else if oldGame.GameName == file.Name() && oldGame.Hash != dirHash { + } else if oldGame.SoundtrackName == file.Name() && oldGame.Hash != dirHash { status = GameChanged id = oldGame.ID //fmt.Printf("Game changed\n") break - } else if oldGame.GameName != file.Name() && oldGame.Hash == dirHash { + } else if oldGame.SoundtrackName != file.Name() && oldGame.Hash == dirHash { status = TitleChanged id = oldGame.ID - //fmt.Printf("GameName changed\n") + //fmt.Printf("SoundtrackName changed\n") break } } @@ -335,8 +335,8 @@ func syncGameNew(file os.DirEntry, foldersToSkip []string, baseDir string, full break } } - err = repo.InsertGameWithExistingId(BackendCtx(), repository.InsertGameWithExistingIdParams{ID: id, GameName: file.Name(), Path: gameDir, Hash: dirHash}) - handleError("InsertGameWithExistingId", err, "") + err = repo.InsertSoundtrackWithExistingId(BackendCtx(), repository.InsertSoundtrackWithExistingIdParams{ID: id, SoundtrackName: file.Name(), Path: gameDir, Hash: dirHash}) + handleError("InsertSoundtrackWithExistingId", err, "") if err != nil { logging.GetLogger().Debug("Game already exists, removing old ID file", zap.Int32("id", id), @@ -369,24 +369,24 @@ func syncGameNew(file os.DirEntry, foldersToSkip []string, baseDir string, full zap.String("game", file.Name()), zap.String("hash", dirHash), zap.String("status", status.String())) - err = repo.UpdateGameHash(BackendCtx(), repository.UpdateGameHashParams{Hash: dirHash, ID: id}) - handleError("UpdateGameHash", err, "") + err = repo.UpdateSoundtrackHash(BackendCtx(), repository.UpdateSoundtrackHashParams{Hash: dirHash, ID: id}) + handleError("UpdateSoundtrackHash", err, "") gamesChangedContent = append(gamesChangedContent, file.Name()) newCheckSongs(entries, gameDir, id) case TitleChanged: logging.GetLogger().Debug("Game title changed", zap.Int32("id", id), - zap.String("oldName", oldGame.GameName), + zap.String("oldName", oldGame.SoundtrackName), zap.String("newName", file.Name()), zap.String("hash", dirHash), zap.String("status", status.String())) - err = repo.UpdateGameName(BackendCtx(), repository.UpdateGameNameParams{Name: file.Name(), Path: gameDir, ID: id}) - handleError("UpdateGameName", err, "") + err = repo.UpdateSoundtrackName(BackendCtx(), repository.UpdateSoundtrackNameParams{Name: file.Name(), Path: gameDir, ID: id}) + handleError("UpdateSoundtrackName", err, "") newCheckSongs(entries, gameDir, id) if gamesChangedTitle == nil { gamesChangedTitle = make(map[string]string) } - gamesChangedTitle[oldGame.GameName] = file.Name() + gamesChangedTitle[oldGame.SoundtrackName] = file.Name() case NotChanged: var found bool = false for _, beforeGame := range gamesBeforeSync { @@ -415,8 +415,8 @@ func syncGameNew(file os.DirEntry, foldersToSkip []string, baseDir string, full zap.String("game", file.Name()), zap.String("hash", dirHash), zap.String("status", status.String())) - err = repo.RemoveDeletionDate(BackendCtx(), id) - handleError("RemoveDeletionDate", err, "") + err = repo.RemoveSoundtrackDeletionDate(BackendCtx(), id) + handleError("RemoveSoundtrackDeletionDate", err, "") } foldersSynced++ logging.GetLogger().Debug("Sync progress", @@ -427,14 +427,14 @@ func syncGameNew(file os.DirEntry, foldersToSkip []string, baseDir string, full func insertGameNew(name string, path string, hash string) int32 { var duplicateError = errors.New("ERROR: duplicate key value violates unique") - id, err := repo.InsertGame(BackendCtx(), repository.InsertGameParams{GameName: name, Path: path, Hash: hash}) - handleError("InsertGame", err, "") + id, err := repo.InsertSoundtrack(BackendCtx(), repository.InsertSoundtrackParams{SoundtrackName: name, Path: path, Hash: hash}) + handleError("InsertSoundtrack", err, "") if err != nil { logging.GetLogger().Warn("ID collision detected, resetting sequence") if strings.HasPrefix(err.Error(), duplicateError.Error()) { logging.GetLogger().Debug("Resetting game ID sequence") - _, err = repo.ResetGameIdSeq(BackendCtx()) - handleError("ResetGameIdSeq", err, "") + _, err = repo.ResetSoundtrackIdSeq(BackendCtx()) + handleError("ResetSoundtrackIdSeq", err, "") id = insertGameNew(name, path, hash) } } @@ -478,7 +478,7 @@ func newCheckSong(entry os.DirEntry, gameDir string, id int32) bool { songName, _ := strings.CutSuffix(fileName, ".mp3") song, err := repo.GetSongWithHash(BackendCtx(), songHash) - handleError("GetSongWithHash", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s", id, path, entry.Name(), songHash)) + handleError("GetSongWithHash", err, fmt.Sprintf("SoundtrackID: %d | Path: %s | SongName: %s | SongHash: %s", id, path, entry.Name(), songHash)) if err == nil { if song.SongName == songName && song.Path == path { return false @@ -491,31 +491,31 @@ func newCheckSong(entry os.DirEntry, gameDir string, id int32) bool { zap.String("song_hash", songHash)) count, err := repo.CheckSongWithHash(BackendCtx(), songHash) - handleError("CheckSongWithHash", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s\n", id, path, entry.Name(), songHash)) + handleError("CheckSongWithHash", err, fmt.Sprintf("SoundtrackID: %d | Path: %s | SongName: %s | SongHash: %s\n", id, path, entry.Name(), songHash)) if err != nil { count2, err := repo.CheckSong(BackendCtx(), path) - handleError("CheckSong", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s\n", id, path, entry.Name(), songHash)) + handleError("CheckSong", err, fmt.Sprintf("SoundtrackID: %d | Path: %s | SongName: %s | SongHash: %s\n", id, path, entry.Name(), songHash)) if count2 > 0 { err = repo.AddHashToSong(BackendCtx(), repository.AddHashToSongParams{Hash: songHash, Path: path}) - handleError("AddHashToSong", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s", id, path, entry.Name(), songHash)) + handleError("AddHashToSong", err, fmt.Sprintf("SoundtrackID: %d | Path: %s | SongName: %s | SongHash: %s", id, path, entry.Name(), songHash)) count, err = repo.CheckSongWithHash(BackendCtx(), songHash) - handleError("CheckSongWithHash 2", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s", id, path, entry.Name(), songHash)) + handleError("CheckSongWithHash 2", err, fmt.Sprintf("SoundtrackID: %d | Path: %s | SongName: %s | SongHash: %s", id, path, entry.Name(), songHash)) } } //count, _ := repo.CheckSong(ctx, path) if count > 0 { err = repo.UpdateSong(BackendCtx(), repository.UpdateSongParams{SongName: songName, FileName: &fileName, Path: path, Hash: songHash}) - handleError("UpdateSong", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s", id, path, entry.Name(), songHash)) + handleError("UpdateSong", err, fmt.Sprintf("SoundtrackID: %d | Path: %s | SongName: %s | SongHash: %s", id, path, entry.Name(), songHash)) } else { count2, err := repo.CheckSong(BackendCtx(), path) - handleError("CheckSong", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s", id, path, entry.Name(), songHash)) + handleError("CheckSong", err, fmt.Sprintf("SoundtrackID: %d | Path: %s | SongName: %s | SongHash: %s", id, path, entry.Name(), songHash)) if count2 > 0 { err = repo.AddHashToSong(BackendCtx(), repository.AddHashToSongParams{Hash: songHash, Path: path}) - handleError("AddHashToSong", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s", id, path, entry.Name(), songHash)) + handleError("AddHashToSong", err, fmt.Sprintf("SoundtrackID: %d | Path: %s | SongName: %s | SongHash: %s", id, path, entry.Name(), songHash)) } else { - err = repo.AddSong(BackendCtx(), repository.AddSongParams{GameID: id, SongName: songName, Path: path, FileName: &fileName, Hash: songHash}) - handleError("AddSong", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s", id, path, entry.Name(), songHash)) + err = repo.AddSong(BackendCtx(), repository.AddSongParams{SoundtrackID: id, SongName: songName, Path: path, FileName: &fileName, Hash: songHash}) + handleError("AddSong", err, fmt.Sprintf("SoundtrackID: %d | Path: %s | SongName: %s | SongHash: %s", id, path, entry.Name(), songHash)) } } diff --git a/internal/db/migrations/000005_rename_game_to_soundtrack.down.sql b/internal/db/migrations/000005_rename_game_to_soundtrack.down.sql new file mode 100644 index 0000000..f0236de --- /dev/null +++ b/internal/db/migrations/000005_rename_game_to_soundtrack.down.sql @@ -0,0 +1,33 @@ +-- Revert: Rename soundtrack table back to game +ALTER TABLE soundtrack RENAME TO game; + +-- Revert primary key sequence +ALTER SEQUENCE soundtrack_id_seq RENAME TO game_id_seq; + +-- Revert columns in game table +ALTER TABLE game RENAME COLUMN soundtrack_name TO game_name; + +-- Revert song table: rename soundtrack_id back to game_id +ALTER TABLE song RENAME COLUMN soundtrack_id TO game_id; + +-- Revert song primary key +ALTER TABLE song DROP CONSTRAINT IF EXISTS song_pkey; +ALTER TABLE song ADD PRIMARY KEY (game_id, path); +ALTER TABLE song RENAME CONSTRAINT song_pkey_soundtrack TO song_pkey; + +-- Revert song_list table references +ALTER TABLE song_list RENAME COLUMN soundtrack_name TO game_name; + +-- Revert foreign key constraint +ALTER TABLE song DROP CONSTRAINT IF EXISTS song_soundtrack_id_fkey; +ALTER TABLE song ADD CONSTRAINT song_game_id_fkey + FOREIGN KEY (game_id) REFERENCES game(id); + +-- Revert indexes +ALTER INDEX IF EXISTS idx_soundtrack_deleted RENAME TO idx_game_deleted; +ALTER INDEX IF EXISTS idx_soundtrack_hash RENAME TO idx_game_hash; +ALTER INDEX IF EXISTS idx_soundtrack_path RENAME TO idx_game_path; +ALTER INDEX IF EXISTS idx_soundtrack_name RENAME TO idx_game_name; +ALTER INDEX IF EXISTS idx_song_soundtrack_id RENAME TO idx_song_game_id; +ALTER INDEX IF EXISTS idx_song_soundtrack_id_song_name RENAME TO idx_song_game_id_song_name; +ALTER INDEX IF EXISTS song_list_soundtrack_name_idx RENAME TO song_list_game_name_idx; diff --git a/internal/db/migrations/000005_rename_game_to_soundtrack.up.sql b/internal/db/migrations/000005_rename_game_to_soundtrack.up.sql new file mode 100644 index 0000000..3bf03aa --- /dev/null +++ b/internal/db/migrations/000005_rename_game_to_soundtrack.up.sql @@ -0,0 +1,33 @@ +-- Rename game table to soundtrack +ALTER TABLE game RENAME TO soundtrack; + +-- Rename primary key sequence +ALTER SEQUENCE game_id_seq RENAME TO soundtrack_id_seq; + +-- Rename columns in soundtrack table +ALTER TABLE soundtrack RENAME COLUMN game_name TO soundtrack_name; + +-- Update song table: rename game_id to soundtrack_id +ALTER TABLE song RENAME COLUMN game_id TO soundtrack_id; + +-- Update song primary key +ALTER TABLE song DROP CONSTRAINT IF EXISTS song_pkey; +ALTER TABLE song ADD PRIMARY KEY (soundtrack_id, path); +ALTER TABLE song RENAME CONSTRAINT song_pkey TO song_pkey_soundtrack; + +-- Update song_list table references +ALTER TABLE song_list RENAME COLUMN game_name TO soundtrack_name; + +-- Rename foreign key constraint +ALTER TABLE song DROP CONSTRAINT IF EXISTS song_game_id_fkey; +ALTER TABLE song ADD CONSTRAINT song_soundtrack_id_fkey + FOREIGN KEY (soundtrack_id) REFERENCES soundtrack(id); + +-- Rename indexes +ALTER INDEX IF EXISTS idx_game_deleted RENAME TO idx_soundtrack_deleted; +ALTER INDEX IF EXISTS idx_game_hash RENAME TO idx_soundtrack_hash; +ALTER INDEX IF EXISTS idx_game_path RENAME TO idx_soundtrack_path; +ALTER INDEX IF EXISTS idx_game_name RENAME TO idx_soundtrack_name; +ALTER INDEX IF EXISTS idx_song_game_id RENAME TO idx_song_soundtrack_id; +ALTER INDEX IF EXISTS idx_song_game_id_song_name RENAME TO idx_song_soundtrack_id_song_name; +ALTER INDEX IF EXISTS song_list_game_name_idx RENAME TO song_list_soundtrack_name_idx; diff --git a/internal/db/queries/game.sql b/internal/db/queries/game.sql deleted file mode 100644 index ba02059..0000000 --- a/internal/db/queries/game.sql +++ /dev/null @@ -1,49 +0,0 @@ --- name: ResetGameIdSeq :one -SELECT setval('game_id_seq', (SELECT MAX(id) FROM game)+1); - --- name: GetGameNameById :one -SELECT game_name FROM game WHERE id = $1; - --- name: GetGameById :one -SELECT * -FROM game -WHERE id = $1 -AND deleted IS NULL; - --- name: SetGameDeletionDate :exec -UPDATE game SET deleted=now() WHERE deleted IS NULL; - --- name: ClearGames :exec -DELETE FROM game; - --- name: UpdateGameName :exec -UPDATE game SET game_name=sqlc.arg(name), path=sqlc.arg(path), last_changed=now() WHERE id=sqlc.arg(id); - --- name: UpdateGameHash :exec -UPDATE game SET hash=sqlc.arg(hash), last_changed=now() WHERE id=sqlc.arg(id); - --- name: RemoveDeletionDate :exec -UPDATE game SET deleted=NULL WHERE id=$1; - --- name: GetIdByGameName :one -SELECT id FROM game WHERE game_name = $1; - --- name: InsertGame :one -INSERT INTO game (game_name, path, hash, added) VALUES ($1, $2, $3, now()) returning id; - --- name: InsertGameWithExistingId :exec -INSERT INTO game (id, game_name, path, hash, added) VALUES ($1, $2, $3, $4, now()); - --- name: FindAllGames :many -SELECT * -FROM game -WHERE deleted IS NULL -ORDER BY game_name; - --- name: GetAllGamesIncludingDeleted :many -SELECT * -FROM game -ORDER BY game_name; - --- name: AddGamePlayed :exec -UPDATE game SET times_played = times_played + 1, last_played = now() WHERE id = $1; diff --git a/internal/db/queries/song.sql b/internal/db/queries/song.sql index 788470f..98928ab 100644 --- a/internal/db/queries/song.sql +++ b/internal/db/queries/song.sql @@ -1,11 +1,11 @@ -- name: ClearSongs :exec DELETE FROM song; --- name: ClearSongsByGameId :exec -DELETE FROM song WHERE game_id = $1; +-- name: ClearSongsBySoundtrackId :exec +DELETE FROM song WHERE soundtrack_id = $1; -- name: AddSong :exec -INSERT INTO song(game_id, song_name, path, file_name, hash) VALUES ($1, $2, $3, $4, $5); +INSERT INTO song(soundtrack_id, song_name, path, file_name, hash) VALUES ($1, $2, $3, $4, $5); -- name: CheckSong :one SELECT COUNT(*) FROM song WHERE path = $1; @@ -22,14 +22,14 @@ UPDATE song SET song_name=$1, file_name=$2, path=$3 where hash=$4; -- name: AddHashToSong :exec UPDATE song SET hash=$1 where path=$2; --- name: FindSongsFromGame :many +-- name: FindSongsFromSoundtrack :many SELECT * FROM song -WHERE game_id = $1; +WHERE soundtrack_id = $1; -- name: AddSongPlayed :exec UPDATE song SET times_played = times_played + 1 -WHERE game_id = $1 AND song_name = $2; +WHERE soundtrack_id = $1 AND song_name = $2; -- name: FetchAllSongs :many SELECT * FROM song; diff --git a/internal/db/queries/song_list.sql b/internal/db/queries/song_list.sql index 1ddc294..d4c0193 100644 --- a/internal/db/queries/song_list.sql +++ b/internal/db/queries/song_list.sql @@ -1,5 +1,5 @@ -- name: InsertSongInList :exec -INSERT INTO song_list (match_date, match_id, song_no, game_name, song_name) +INSERT INTO song_list (match_date, match_id, song_no, soundtrack_name, song_name) VALUES ($1, $2, $3, $4, $5); -- name: GetSongList :many diff --git a/internal/db/queries/soundtrack.sql b/internal/db/queries/soundtrack.sql new file mode 100644 index 0000000..1de82d5 --- /dev/null +++ b/internal/db/queries/soundtrack.sql @@ -0,0 +1,49 @@ +-- name: ResetSoundtrackIdSeq :one +SELECT setval('soundtrack_id_seq', (SELECT MAX(id) FROM soundtrack)+1); + +-- name: GetSoundtrackNameById :one +SELECT soundtrack_name FROM soundtrack WHERE id = $1; + +-- name: GetSoundtrackById :one +SELECT * +FROM soundtrack +WHERE id = $1 +AND deleted IS NULL; + +-- name: SetSoundtrackDeletionDate :exec +UPDATE soundtrack SET deleted=now() WHERE deleted IS NULL; + +-- name: ClearSoundtracks :exec +DELETE FROM soundtrack; + +-- name: UpdateSoundtrackName :exec +UPDATE soundtrack SET soundtrack_name=sqlc.arg(name), path=sqlc.arg(path), last_changed=now() WHERE id=sqlc.arg(id); + +-- name: UpdateSoundtrackHash :exec +UPDATE soundtrack SET hash=sqlc.arg(hash), last_changed=now() WHERE id=sqlc.arg(id); + +-- name: RemoveSoundtrackDeletionDate :exec +UPDATE soundtrack SET deleted=NULL WHERE id=$1; + +-- name: GetIdBySoundtrackName :one +SELECT id FROM soundtrack WHERE soundtrack_name = $1; + +-- name: InsertSoundtrack :one +INSERT INTO soundtrack (soundtrack_name, path, hash, added) VALUES ($1, $2, $3, now()) returning id; + +-- name: InsertSoundtrackWithExistingId :exec +INSERT INTO soundtrack (id, soundtrack_name, path, hash, added) VALUES ($1, $2, $3, $4, now()); + +-- name: FindAllSoundtracks :many +SELECT * +FROM soundtrack +WHERE deleted IS NULL +ORDER BY soundtrack_name; + +-- name: GetAllSoundtracksIncludingDeleted :many +SELECT * +FROM soundtrack +ORDER BY soundtrack_name; + +-- name: AddSoundtrackPlayed :exec +UPDATE soundtrack SET times_played = times_played + 1, last_played = now() WHERE id = $1; diff --git a/internal/db/queries/statistics.sql b/internal/db/queries/statistics.sql index 1dd7674..5d67f78 100644 --- a/internal/db/queries/statistics.sql +++ b/internal/db/queries/statistics.sql @@ -1,10 +1,10 @@ --- Most played games with their songs +-- Most played soundtracks with their songs -- name: GetMostPlayedGamesWithSongs :many SELECT - g.id as game_id, - g.game_name, - g.times_played as game_played, - g.last_played as game_last_played, + g.id as soundtrack_id, + g.soundtrack_name, + g.times_played as soundtrack_played, + g.last_played as soundtrack_last_played, json_agg( json_build_object( 'song_name', s.song_name, @@ -13,20 +13,20 @@ SELECT 'file_name', s.file_name ) ) as songs -FROM game g -LEFT JOIN song s ON g.id = s.game_id +FROM soundtrack g +LEFT JOIN song s ON g.id = s.soundtrack_id WHERE g.deleted IS NULL -GROUP BY g.id, g.game_name, g.times_played, g.last_played -ORDER BY g.times_played DESC, g.game_name +GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played +ORDER BY g.times_played DESC, g.soundtrack_name LIMIT $1; --- Least played games with their songs +-- Least played soundtracks with their songs -- name: GetLeastPlayedGamesWithSongs :many SELECT - g.id as game_id, - g.game_name, - g.times_played as game_played, - g.last_played as game_last_played, + g.id as soundtrack_id, + g.soundtrack_name, + g.times_played as soundtrack_played, + g.last_played as soundtrack_last_played, json_agg( json_build_object( 'song_name', s.song_name, @@ -35,39 +35,39 @@ SELECT 'file_name', s.file_name ) ) as songs -FROM game g -LEFT JOIN song s ON g.id = s.game_id +FROM soundtrack g +LEFT JOIN song s ON g.id = s.soundtrack_id WHERE g.deleted IS NULL -GROUP BY g.id, g.game_name, g.times_played, g.last_played -ORDER BY g.times_played ASC, g.game_name +GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played +ORDER BY g.times_played ASC, g.soundtrack_name LIMIT $1; --- Most played songs with their game info +-- Most played songs with their soundtrack info -- name: GetMostPlayedSongsWithGame :many SELECT - s.game_id as game_id, - g.game_name, + s.soundtrack_id as soundtrack_id, + g.soundtrack_name, s.song_name, s.path, s.times_played, s.file_name FROM song s -JOIN game g ON s.game_id = g.id +JOIN soundtrack g ON s.soundtrack_id = g.id WHERE g.deleted IS NULL ORDER BY s.times_played DESC, s.song_name LIMIT $1; --- Least played songs with their game info +-- Least played songs with their soundtrack info -- name: GetLeastPlayedSongsWithGame :many SELECT - s.game_id as game_id, - g.game_name, + s.soundtrack_id as soundtrack_id, + g.soundtrack_name, s.song_name, s.path, s.times_played, s.file_name FROM song s -JOIN game g ON s.game_id = g.id +JOIN soundtrack g ON s.soundtrack_id = g.id WHERE g.deleted IS NULL ORDER BY s.times_played ASC, s.song_name LIMIT $1; @@ -75,9 +75,9 @@ LIMIT $1; -- Games that have never been played (times_played = 0) -- name: GetNeverPlayedGames :many SELECT - g.id as game_id, - g.game_name, - g.times_played as game_played, + g.id as soundtrack_id, + g.soundtrack_name, + g.times_played as soundtrack_played, g.added, json_agg( json_build_object( @@ -86,19 +86,19 @@ SELECT 'times_played', s.times_played ) ) as songs -FROM game g -LEFT JOIN song s ON g.id = s.game_id +FROM soundtrack g +LEFT JOIN song s ON g.id = s.soundtrack_id WHERE g.deleted IS NULL AND g.times_played = 0 -GROUP BY g.id, g.game_name, g.times_played, g.added -ORDER BY g.game_name; +GROUP BY g.id, g.soundtrack_name, g.times_played, g.added +ORDER BY g.soundtrack_name; --- Last played games (most recently played) +-- Last played soundtracks (most recently played) -- name: GetLastPlayedGames :many SELECT - g.id as game_id, - g.game_name, - g.times_played as game_played, - g.last_played as game_last_played, + g.id as soundtrack_id, + g.soundtrack_name, + g.times_played as soundtrack_played, + g.last_played as soundtrack_last_played, json_agg( json_build_object( 'song_name', s.song_name, @@ -106,20 +106,20 @@ SELECT 'times_played', s.times_played ) ) as songs -FROM game g -LEFT JOIN song s ON g.id = s.game_id +FROM soundtrack g +LEFT JOIN song s ON g.id = s.soundtrack_id WHERE g.deleted IS NULL AND g.last_played IS NOT NULL -GROUP BY g.id, g.game_name, g.times_played, g.last_played +GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played ORDER BY g.last_played DESC LIMIT $1; --- Oldest played games (least recently played, but has been played at least once) +-- Oldest played soundtracks (least recently played, but has been played at least once) -- name: GetOldestPlayedGames :many SELECT - g.id as game_id, - g.game_name, - g.times_played as game_played, - g.last_played as game_last_played, + g.id as soundtrack_id, + g.soundtrack_name, + g.times_played as soundtrack_played, + g.last_played as soundtrack_last_played, json_agg( json_build_object( 'song_name', s.song_name, @@ -127,22 +127,22 @@ SELECT 'times_played', s.times_played ) ) as songs -FROM game g -LEFT JOIN song s ON g.id = s.game_id +FROM soundtrack g +LEFT JOIN song s ON g.id = s.soundtrack_id WHERE g.deleted IS NULL AND g.last_played IS NOT NULL -GROUP BY g.id, g.game_name, g.times_played, g.last_played +GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played ORDER BY g.last_played ASC LIMIT $1; -- Get statistics summary -- name: GetStatisticsSummary :one SELECT - COUNT(*) as total_games, - SUM(CASE WHEN times_played > 0 THEN 1 ELSE 0 END) as played_games, - SUM(CASE WHEN times_played = 0 THEN 1 ELSE 0 END) as never_played_games, - COALESCE(SUM(times_played), 0)::bigint as total_game_plays, - COALESCE(AVG(times_played), 0)::float as avg_game_plays, - COALESCE(MAX(times_played), 0)::bigint as max_game_plays, - COALESCE(MIN(times_played), 0)::bigint as min_game_plays -FROM game + COUNT(*) as total_soundtracks, + SUM(CASE WHEN times_played > 0 THEN 1 ELSE 0 END) as played_soundtracks, + SUM(CASE WHEN times_played = 0 THEN 1 ELSE 0 END) as never_played_soundtracks, + COALESCE(SUM(times_played), 0)::bigint as total_soundtrack_plays, + COALESCE(AVG(times_played), 0)::float as avg_soundtrack_plays, + COALESCE(MAX(times_played), 0)::bigint as max_soundtrack_plays, + COALESCE(MIN(times_played), 0)::bigint as min_soundtrack_plays +FROM soundtrack WHERE deleted IS NULL; diff --git a/internal/db/repository/game.sql.go b/internal/db/repository/game.sql.go deleted file mode 100644 index aaed7f3..0000000 --- a/internal/db/repository/game.sql.go +++ /dev/null @@ -1,246 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.31.1 -// source: game.sql - -package repository - -import ( - "context" -) - -const addGamePlayed = `-- name: AddGamePlayed :exec -UPDATE game SET times_played = times_played + 1, last_played = now() WHERE id = $1 -` - -func (q *Queries) AddGamePlayed(ctx context.Context, id int32) error { - _, err := q.db.Exec(ctx, addGamePlayed, id) - return err -} - -const clearGames = `-- name: ClearGames :exec -DELETE FROM game -` - -func (q *Queries) ClearGames(ctx context.Context) error { - _, err := q.db.Exec(ctx, clearGames) - return err -} - -const findAllGames = `-- name: FindAllGames :many -SELECT id, game_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash -FROM game -WHERE deleted IS NULL -ORDER BY game_name -` - -func (q *Queries) FindAllGames(ctx context.Context) ([]Game, error) { - rows, err := q.db.Query(ctx, findAllGames) - if err != nil { - return nil, err - } - defer rows.Close() - var items []Game - for rows.Next() { - var i Game - if err := rows.Scan( - &i.ID, - &i.GameName, - &i.Added, - &i.Deleted, - &i.LastChanged, - &i.Path, - &i.TimesPlayed, - &i.LastPlayed, - &i.NumberOfSongs, - &i.Hash, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getAllGamesIncludingDeleted = `-- name: GetAllGamesIncludingDeleted :many -SELECT id, game_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash -FROM game -ORDER BY game_name -` - -func (q *Queries) GetAllGamesIncludingDeleted(ctx context.Context) ([]Game, error) { - rows, err := q.db.Query(ctx, getAllGamesIncludingDeleted) - if err != nil { - return nil, err - } - defer rows.Close() - var items []Game - for rows.Next() { - var i Game - if err := rows.Scan( - &i.ID, - &i.GameName, - &i.Added, - &i.Deleted, - &i.LastChanged, - &i.Path, - &i.TimesPlayed, - &i.LastPlayed, - &i.NumberOfSongs, - &i.Hash, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getGameById = `-- name: GetGameById :one -SELECT id, game_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash -FROM game -WHERE id = $1 -AND deleted IS NULL -` - -func (q *Queries) GetGameById(ctx context.Context, id int32) (Game, error) { - row := q.db.QueryRow(ctx, getGameById, id) - var i Game - err := row.Scan( - &i.ID, - &i.GameName, - &i.Added, - &i.Deleted, - &i.LastChanged, - &i.Path, - &i.TimesPlayed, - &i.LastPlayed, - &i.NumberOfSongs, - &i.Hash, - ) - return i, err -} - -const getGameNameById = `-- name: GetGameNameById :one -SELECT game_name FROM game WHERE id = $1 -` - -func (q *Queries) GetGameNameById(ctx context.Context, id int32) (string, error) { - row := q.db.QueryRow(ctx, getGameNameById, id) - var game_name string - err := row.Scan(&game_name) - return game_name, err -} - -const getIdByGameName = `-- name: GetIdByGameName :one -SELECT id FROM game WHERE game_name = $1 -` - -func (q *Queries) GetIdByGameName(ctx context.Context, gameName string) (int32, error) { - row := q.db.QueryRow(ctx, getIdByGameName, gameName) - var id int32 - err := row.Scan(&id) - return id, err -} - -const insertGame = `-- name: InsertGame :one -INSERT INTO game (game_name, path, hash, added) VALUES ($1, $2, $3, now()) returning id -` - -type InsertGameParams struct { - GameName string `json:"game_name"` - Path string `json:"path"` - Hash string `json:"hash"` -} - -func (q *Queries) InsertGame(ctx context.Context, arg InsertGameParams) (int32, error) { - row := q.db.QueryRow(ctx, insertGame, arg.GameName, arg.Path, arg.Hash) - var id int32 - err := row.Scan(&id) - return id, err -} - -const insertGameWithExistingId = `-- name: InsertGameWithExistingId :exec -INSERT INTO game (id, game_name, path, hash, added) VALUES ($1, $2, $3, $4, now()) -` - -type InsertGameWithExistingIdParams struct { - ID int32 `json:"id"` - GameName string `json:"game_name"` - Path string `json:"path"` - Hash string `json:"hash"` -} - -func (q *Queries) InsertGameWithExistingId(ctx context.Context, arg InsertGameWithExistingIdParams) error { - _, err := q.db.Exec(ctx, insertGameWithExistingId, - arg.ID, - arg.GameName, - arg.Path, - arg.Hash, - ) - return err -} - -const removeDeletionDate = `-- name: RemoveDeletionDate :exec -UPDATE game SET deleted=NULL WHERE id=$1 -` - -func (q *Queries) RemoveDeletionDate(ctx context.Context, id int32) error { - _, err := q.db.Exec(ctx, removeDeletionDate, id) - return err -} - -const resetGameIdSeq = `-- name: ResetGameIdSeq :one -SELECT setval('game_id_seq', (SELECT MAX(id) FROM game)+1) -` - -func (q *Queries) ResetGameIdSeq(ctx context.Context) (int64, error) { - row := q.db.QueryRow(ctx, resetGameIdSeq) - var setval int64 - err := row.Scan(&setval) - return setval, err -} - -const setGameDeletionDate = `-- name: SetGameDeletionDate :exec -UPDATE game SET deleted=now() WHERE deleted IS NULL -` - -func (q *Queries) SetGameDeletionDate(ctx context.Context) error { - _, err := q.db.Exec(ctx, setGameDeletionDate) - return err -} - -const updateGameHash = `-- name: UpdateGameHash :exec -UPDATE game SET hash=$1, last_changed=now() WHERE id=$2 -` - -type UpdateGameHashParams struct { - Hash string `json:"hash"` - ID int32 `json:"id"` -} - -func (q *Queries) UpdateGameHash(ctx context.Context, arg UpdateGameHashParams) error { - _, err := q.db.Exec(ctx, updateGameHash, arg.Hash, arg.ID) - return err -} - -const updateGameName = `-- name: UpdateGameName :exec -UPDATE game SET game_name=$1, path=$2, last_changed=now() WHERE id=$3 -` - -type UpdateGameNameParams struct { - Name string `json:"name"` - Path string `json:"path"` - ID int32 `json:"id"` -} - -func (q *Queries) UpdateGameName(ctx context.Context, arg UpdateGameNameParams) error { - _, err := q.db.Exec(ctx, updateGameName, arg.Name, arg.Path, arg.ID) - return err -} diff --git a/internal/db/repository/models.go b/internal/db/repository/models.go index aed7c47..9e2cff2 100644 --- a/internal/db/repository/models.go +++ b/internal/db/repository/models.go @@ -10,19 +10,6 @@ import ( "github.com/jackc/pgx/v5/pgtype" ) -type Game struct { - ID int32 `json:"id"` - GameName string `json:"game_name"` - Added time.Time `json:"added"` - Deleted *time.Time `json:"deleted"` - LastChanged *time.Time `json:"last_changed"` - Path string `json:"path"` - TimesPlayed int32 `json:"times_played"` - LastPlayed *time.Time `json:"last_played"` - NumberOfSongs int32 `json:"number_of_songs"` - Hash string `json:"hash"` -} - type Session struct { Token string `json:"token"` IpAddress string `json:"ip_address"` @@ -33,20 +20,33 @@ type Session struct { } type Song struct { - GameID int32 `json:"game_id"` - SongName string `json:"song_name"` - Path string `json:"path"` - TimesPlayed int32 `json:"times_played"` - Hash string `json:"hash"` - FileName *string `json:"file_name"` + SoundtrackID int32 `json:"soundtrack_id"` + SongName string `json:"song_name"` + Path string `json:"path"` + TimesPlayed int32 `json:"times_played"` + Hash string `json:"hash"` + FileName *string `json:"file_name"` } type SongList struct { - MatchDate time.Time `json:"match_date"` - MatchID int32 `json:"match_id"` - SongNo int32 `json:"song_no"` - GameName *string `json:"game_name"` - SongName *string `json:"song_name"` + MatchDate time.Time `json:"match_date"` + MatchID int32 `json:"match_id"` + SongNo int32 `json:"song_no"` + SoundtrackName *string `json:"soundtrack_name"` + SongName *string `json:"song_name"` +} + +type Soundtrack struct { + ID int32 `json:"id"` + SoundtrackName string `json:"soundtrack_name"` + Added time.Time `json:"added"` + Deleted *time.Time `json:"deleted"` + LastChanged *time.Time `json:"last_changed"` + Path string `json:"path"` + TimesPlayed int32 `json:"times_played"` + LastPlayed *time.Time `json:"last_played"` + NumberOfSongs int32 `json:"number_of_songs"` + Hash string `json:"hash"` } type Vgmq struct { diff --git a/internal/db/repository/song.sql.go b/internal/db/repository/song.sql.go index 28b60c5..12025fd 100644 --- a/internal/db/repository/song.sql.go +++ b/internal/db/repository/song.sql.go @@ -24,20 +24,20 @@ func (q *Queries) AddHashToSong(ctx context.Context, arg AddHashToSongParams) er } const addSong = `-- name: AddSong :exec -INSERT INTO song(game_id, song_name, path, file_name, hash) VALUES ($1, $2, $3, $4, $5) +INSERT INTO song(soundtrack_id, song_name, path, file_name, hash) VALUES ($1, $2, $3, $4, $5) ` type AddSongParams struct { - GameID int32 `json:"game_id"` - SongName string `json:"song_name"` - Path string `json:"path"` - FileName *string `json:"file_name"` - Hash string `json:"hash"` + SoundtrackID int32 `json:"soundtrack_id"` + SongName string `json:"song_name"` + Path string `json:"path"` + FileName *string `json:"file_name"` + Hash string `json:"hash"` } func (q *Queries) AddSong(ctx context.Context, arg AddSongParams) error { _, err := q.db.Exec(ctx, addSong, - arg.GameID, + arg.SoundtrackID, arg.SongName, arg.Path, arg.FileName, @@ -48,16 +48,16 @@ func (q *Queries) AddSong(ctx context.Context, arg AddSongParams) error { const addSongPlayed = `-- name: AddSongPlayed :exec UPDATE song SET times_played = times_played + 1 -WHERE game_id = $1 AND song_name = $2 +WHERE soundtrack_id = $1 AND song_name = $2 ` type AddSongPlayedParams struct { - GameID int32 `json:"game_id"` - SongName string `json:"song_name"` + SoundtrackID int32 `json:"soundtrack_id"` + SongName string `json:"song_name"` } func (q *Queries) AddSongPlayed(ctx context.Context, arg AddSongPlayedParams) error { - _, err := q.db.Exec(ctx, addSongPlayed, arg.GameID, arg.SongName) + _, err := q.db.Exec(ctx, addSongPlayed, arg.SoundtrackID, arg.SongName) return err } @@ -92,17 +92,17 @@ func (q *Queries) ClearSongs(ctx context.Context) error { return err } -const clearSongsByGameId = `-- name: ClearSongsByGameId :exec -DELETE FROM song WHERE game_id = $1 +const clearSongsBySoundtrackId = `-- name: ClearSongsBySoundtrackId :exec +DELETE FROM song WHERE soundtrack_id = $1 ` -func (q *Queries) ClearSongsByGameId(ctx context.Context, gameID int32) error { - _, err := q.db.Exec(ctx, clearSongsByGameId, gameID) +func (q *Queries) ClearSongsBySoundtrackId(ctx context.Context, soundtrackID int32) error { + _, err := q.db.Exec(ctx, clearSongsBySoundtrackId, soundtrackID) return err } const fetchAllSongs = `-- name: FetchAllSongs :many -SELECT game_id, song_name, path, times_played, hash, file_name FROM song +SELECT soundtrack_id, song_name, path, times_played, hash, file_name FROM song ` func (q *Queries) FetchAllSongs(ctx context.Context) ([]Song, error) { @@ -115,7 +115,7 @@ func (q *Queries) FetchAllSongs(ctx context.Context) ([]Song, error) { for rows.Next() { var i Song if err := rows.Scan( - &i.GameID, + &i.SoundtrackID, &i.SongName, &i.Path, &i.TimesPlayed, @@ -132,14 +132,14 @@ func (q *Queries) FetchAllSongs(ctx context.Context) ([]Song, error) { return items, nil } -const findSongsFromGame = `-- name: FindSongsFromGame :many -SELECT game_id, song_name, path, times_played, hash, file_name +const findSongsFromSoundtrack = `-- name: FindSongsFromSoundtrack :many +SELECT soundtrack_id, song_name, path, times_played, hash, file_name FROM song -WHERE game_id = $1 +WHERE soundtrack_id = $1 ` -func (q *Queries) FindSongsFromGame(ctx context.Context, gameID int32) ([]Song, error) { - rows, err := q.db.Query(ctx, findSongsFromGame, gameID) +func (q *Queries) FindSongsFromSoundtrack(ctx context.Context, soundtrackID int32) ([]Song, error) { + rows, err := q.db.Query(ctx, findSongsFromSoundtrack, soundtrackID) if err != nil { return nil, err } @@ -148,7 +148,7 @@ func (q *Queries) FindSongsFromGame(ctx context.Context, gameID int32) ([]Song, for rows.Next() { var i Song if err := rows.Scan( - &i.GameID, + &i.SoundtrackID, &i.SongName, &i.Path, &i.TimesPlayed, @@ -166,14 +166,14 @@ func (q *Queries) FindSongsFromGame(ctx context.Context, gameID int32) ([]Song, } const getSongWithHash = `-- name: GetSongWithHash :one -SELECT game_id, song_name, path, times_played, hash, file_name FROM song WHERE hash = $1 +SELECT soundtrack_id, song_name, path, times_played, hash, file_name FROM song WHERE hash = $1 ` func (q *Queries) GetSongWithHash(ctx context.Context, hash string) (Song, error) { row := q.db.QueryRow(ctx, getSongWithHash, hash) var i Song err := row.Scan( - &i.GameID, + &i.SoundtrackID, &i.SongName, &i.Path, &i.TimesPlayed, diff --git a/internal/db/repository/song_list.sql.go b/internal/db/repository/song_list.sql.go index 0deeae4..c1a31e2 100644 --- a/internal/db/repository/song_list.sql.go +++ b/internal/db/repository/song_list.sql.go @@ -11,7 +11,7 @@ import ( ) const getSongList = `-- name: GetSongList :many -SELECT match_date, match_id, song_no, game_name, song_name +SELECT match_date, match_id, song_no, soundtrack_name, song_name FROM song_list WHERE match_date = $1 ORDER BY song_no DESC @@ -30,7 +30,7 @@ func (q *Queries) GetSongList(ctx context.Context, matchDate time.Time) ([]SongL &i.MatchDate, &i.MatchID, &i.SongNo, - &i.GameName, + &i.SoundtrackName, &i.SongName, ); err != nil { return nil, err @@ -44,16 +44,16 @@ func (q *Queries) GetSongList(ctx context.Context, matchDate time.Time) ([]SongL } const insertSongInList = `-- name: InsertSongInList :exec -INSERT INTO song_list (match_date, match_id, song_no, game_name, song_name) +INSERT INTO song_list (match_date, match_id, song_no, soundtrack_name, song_name) VALUES ($1, $2, $3, $4, $5) ` type InsertSongInListParams struct { - MatchDate time.Time `json:"match_date"` - MatchID int32 `json:"match_id"` - SongNo int32 `json:"song_no"` - GameName *string `json:"game_name"` - SongName *string `json:"song_name"` + MatchDate time.Time `json:"match_date"` + MatchID int32 `json:"match_id"` + SongNo int32 `json:"song_no"` + SoundtrackName *string `json:"soundtrack_name"` + SongName *string `json:"song_name"` } func (q *Queries) InsertSongInList(ctx context.Context, arg InsertSongInListParams) error { @@ -61,7 +61,7 @@ func (q *Queries) InsertSongInList(ctx context.Context, arg InsertSongInListPara arg.MatchDate, arg.MatchID, arg.SongNo, - arg.GameName, + arg.SoundtrackName, arg.SongName, ) return err diff --git a/internal/db/repository/soundtrack.sql.go b/internal/db/repository/soundtrack.sql.go new file mode 100644 index 0000000..bc38704 --- /dev/null +++ b/internal/db/repository/soundtrack.sql.go @@ -0,0 +1,246 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.31.1 +// source: soundtrack.sql + +package repository + +import ( + "context" +) + +const addSoundtrackPlayed = `-- name: AddSoundtrackPlayed :exec +UPDATE soundtrack SET times_played = times_played + 1, last_played = now() WHERE id = $1 +` + +func (q *Queries) AddSoundtrackPlayed(ctx context.Context, id int32) error { + _, err := q.db.Exec(ctx, addSoundtrackPlayed, id) + return err +} + +const clearSoundtracks = `-- name: ClearSoundtracks :exec +DELETE FROM soundtrack +` + +func (q *Queries) ClearSoundtracks(ctx context.Context) error { + _, err := q.db.Exec(ctx, clearSoundtracks) + return err +} + +const findAllSoundtracks = `-- name: FindAllSoundtracks :many +SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash +FROM soundtrack +WHERE deleted IS NULL +ORDER BY soundtrack_name +` + +func (q *Queries) FindAllSoundtracks(ctx context.Context) ([]Soundtrack, error) { + rows, err := q.db.Query(ctx, findAllSoundtracks) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Soundtrack + for rows.Next() { + var i Soundtrack + if err := rows.Scan( + &i.ID, + &i.SoundtrackName, + &i.Added, + &i.Deleted, + &i.LastChanged, + &i.Path, + &i.TimesPlayed, + &i.LastPlayed, + &i.NumberOfSongs, + &i.Hash, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getAllSoundtracksIncludingDeleted = `-- name: GetAllSoundtracksIncludingDeleted :many +SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash +FROM soundtrack +ORDER BY soundtrack_name +` + +func (q *Queries) GetAllSoundtracksIncludingDeleted(ctx context.Context) ([]Soundtrack, error) { + rows, err := q.db.Query(ctx, getAllSoundtracksIncludingDeleted) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Soundtrack + for rows.Next() { + var i Soundtrack + if err := rows.Scan( + &i.ID, + &i.SoundtrackName, + &i.Added, + &i.Deleted, + &i.LastChanged, + &i.Path, + &i.TimesPlayed, + &i.LastPlayed, + &i.NumberOfSongs, + &i.Hash, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getIdBySoundtrackName = `-- name: GetIdBySoundtrackName :one +SELECT id FROM soundtrack WHERE soundtrack_name = $1 +` + +func (q *Queries) GetIdBySoundtrackName(ctx context.Context, soundtrackName string) (int32, error) { + row := q.db.QueryRow(ctx, getIdBySoundtrackName, soundtrackName) + var id int32 + err := row.Scan(&id) + return id, err +} + +const getSoundtrackById = `-- name: GetSoundtrackById :one +SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash +FROM soundtrack +WHERE id = $1 +AND deleted IS NULL +` + +func (q *Queries) GetSoundtrackById(ctx context.Context, id int32) (Soundtrack, error) { + row := q.db.QueryRow(ctx, getSoundtrackById, id) + var i Soundtrack + err := row.Scan( + &i.ID, + &i.SoundtrackName, + &i.Added, + &i.Deleted, + &i.LastChanged, + &i.Path, + &i.TimesPlayed, + &i.LastPlayed, + &i.NumberOfSongs, + &i.Hash, + ) + return i, err +} + +const getSoundtrackNameById = `-- name: GetSoundtrackNameById :one +SELECT soundtrack_name FROM soundtrack WHERE id = $1 +` + +func (q *Queries) GetSoundtrackNameById(ctx context.Context, id int32) (string, error) { + row := q.db.QueryRow(ctx, getSoundtrackNameById, id) + var soundtrack_name string + err := row.Scan(&soundtrack_name) + return soundtrack_name, err +} + +const insertSoundtrack = `-- name: InsertSoundtrack :one +INSERT INTO soundtrack (soundtrack_name, path, hash, added) VALUES ($1, $2, $3, now()) returning id +` + +type InsertSoundtrackParams struct { + SoundtrackName string `json:"soundtrack_name"` + Path string `json:"path"` + Hash string `json:"hash"` +} + +func (q *Queries) InsertSoundtrack(ctx context.Context, arg InsertSoundtrackParams) (int32, error) { + row := q.db.QueryRow(ctx, insertSoundtrack, arg.SoundtrackName, arg.Path, arg.Hash) + var id int32 + err := row.Scan(&id) + return id, err +} + +const insertSoundtrackWithExistingId = `-- name: InsertSoundtrackWithExistingId :exec +INSERT INTO soundtrack (id, soundtrack_name, path, hash, added) VALUES ($1, $2, $3, $4, now()) +` + +type InsertSoundtrackWithExistingIdParams struct { + ID int32 `json:"id"` + SoundtrackName string `json:"soundtrack_name"` + Path string `json:"path"` + Hash string `json:"hash"` +} + +func (q *Queries) InsertSoundtrackWithExistingId(ctx context.Context, arg InsertSoundtrackWithExistingIdParams) error { + _, err := q.db.Exec(ctx, insertSoundtrackWithExistingId, + arg.ID, + arg.SoundtrackName, + arg.Path, + arg.Hash, + ) + return err +} + +const removeSoundtrackDeletionDate = `-- name: RemoveSoundtrackDeletionDate :exec +UPDATE soundtrack SET deleted=NULL WHERE id=$1 +` + +func (q *Queries) RemoveSoundtrackDeletionDate(ctx context.Context, id int32) error { + _, err := q.db.Exec(ctx, removeSoundtrackDeletionDate, id) + return err +} + +const resetSoundtrackIdSeq = `-- name: ResetSoundtrackIdSeq :one +SELECT setval('soundtrack_id_seq', (SELECT MAX(id) FROM soundtrack)+1) +` + +func (q *Queries) ResetSoundtrackIdSeq(ctx context.Context) (int64, error) { + row := q.db.QueryRow(ctx, resetSoundtrackIdSeq) + var setval int64 + err := row.Scan(&setval) + return setval, err +} + +const setSoundtrackDeletionDate = `-- name: SetSoundtrackDeletionDate :exec +UPDATE soundtrack SET deleted=now() WHERE deleted IS NULL +` + +func (q *Queries) SetSoundtrackDeletionDate(ctx context.Context) error { + _, err := q.db.Exec(ctx, setSoundtrackDeletionDate) + return err +} + +const updateSoundtrackHash = `-- name: UpdateSoundtrackHash :exec +UPDATE soundtrack SET hash=$1, last_changed=now() WHERE id=$2 +` + +type UpdateSoundtrackHashParams struct { + Hash string `json:"hash"` + ID int32 `json:"id"` +} + +func (q *Queries) UpdateSoundtrackHash(ctx context.Context, arg UpdateSoundtrackHashParams) error { + _, err := q.db.Exec(ctx, updateSoundtrackHash, arg.Hash, arg.ID) + return err +} + +const updateSoundtrackName = `-- name: UpdateSoundtrackName :exec +UPDATE soundtrack SET soundtrack_name=$1, path=$2, last_changed=now() WHERE id=$3 +` + +type UpdateSoundtrackNameParams struct { + Name string `json:"name"` + Path string `json:"path"` + ID int32 `json:"id"` +} + +func (q *Queries) UpdateSoundtrackName(ctx context.Context, arg UpdateSoundtrackNameParams) error { + _, err := q.db.Exec(ctx, updateSoundtrackName, arg.Name, arg.Path, arg.ID) + return err +} diff --git a/internal/db/repository/statistics.sql.go b/internal/db/repository/statistics.sql.go index 129b47d..c531427 100644 --- a/internal/db/repository/statistics.sql.go +++ b/internal/db/repository/statistics.sql.go @@ -12,10 +12,10 @@ import ( const getLastPlayedGames = `-- name: GetLastPlayedGames :many SELECT - g.id as game_id, - g.game_name, - g.times_played as game_played, - g.last_played as game_last_played, + g.id as soundtrack_id, + g.soundtrack_name, + g.times_played as soundtrack_played, + g.last_played as soundtrack_last_played, json_agg( json_build_object( 'song_name', s.song_name, @@ -23,23 +23,23 @@ SELECT 'times_played', s.times_played ) ) as songs -FROM game g -LEFT JOIN song s ON g.id = s.game_id +FROM soundtrack g +LEFT JOIN song s ON g.id = s.soundtrack_id WHERE g.deleted IS NULL AND g.last_played IS NOT NULL -GROUP BY g.id, g.game_name, g.times_played, g.last_played +GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played ORDER BY g.last_played DESC LIMIT $1 ` type GetLastPlayedGamesRow struct { - GameID int32 `json:"game_id"` - GameName string `json:"game_name"` - GamePlayed int32 `json:"game_played"` - GameLastPlayed *time.Time `json:"game_last_played"` - Songs []byte `json:"songs"` + SoundtrackID int32 `json:"soundtrack_id"` + SoundtrackName string `json:"soundtrack_name"` + SoundtrackPlayed int32 `json:"soundtrack_played"` + SoundtrackLastPlayed *time.Time `json:"soundtrack_last_played"` + Songs []byte `json:"songs"` } -// Last played games (most recently played) +// Last played soundtracks (most recently played) func (q *Queries) GetLastPlayedGames(ctx context.Context, limit int32) ([]GetLastPlayedGamesRow, error) { rows, err := q.db.Query(ctx, getLastPlayedGames, limit) if err != nil { @@ -50,10 +50,10 @@ func (q *Queries) GetLastPlayedGames(ctx context.Context, limit int32) ([]GetLas for rows.Next() { var i GetLastPlayedGamesRow if err := rows.Scan( - &i.GameID, - &i.GameName, - &i.GamePlayed, - &i.GameLastPlayed, + &i.SoundtrackID, + &i.SoundtrackName, + &i.SoundtrackPlayed, + &i.SoundtrackLastPlayed, &i.Songs, ); err != nil { return nil, err @@ -68,10 +68,10 @@ func (q *Queries) GetLastPlayedGames(ctx context.Context, limit int32) ([]GetLas const getLeastPlayedGamesWithSongs = `-- name: GetLeastPlayedGamesWithSongs :many SELECT - g.id as game_id, - g.game_name, - g.times_played as game_played, - g.last_played as game_last_played, + g.id as soundtrack_id, + g.soundtrack_name, + g.times_played as soundtrack_played, + g.last_played as soundtrack_last_played, json_agg( json_build_object( 'song_name', s.song_name, @@ -80,23 +80,23 @@ SELECT 'file_name', s.file_name ) ) as songs -FROM game g -LEFT JOIN song s ON g.id = s.game_id +FROM soundtrack g +LEFT JOIN song s ON g.id = s.soundtrack_id WHERE g.deleted IS NULL -GROUP BY g.id, g.game_name, g.times_played, g.last_played -ORDER BY g.times_played ASC, g.game_name +GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played +ORDER BY g.times_played ASC, g.soundtrack_name LIMIT $1 ` type GetLeastPlayedGamesWithSongsRow struct { - GameID int32 `json:"game_id"` - GameName string `json:"game_name"` - GamePlayed int32 `json:"game_played"` - GameLastPlayed *time.Time `json:"game_last_played"` - Songs []byte `json:"songs"` + SoundtrackID int32 `json:"soundtrack_id"` + SoundtrackName string `json:"soundtrack_name"` + SoundtrackPlayed int32 `json:"soundtrack_played"` + SoundtrackLastPlayed *time.Time `json:"soundtrack_last_played"` + Songs []byte `json:"songs"` } -// Least played games with their songs +// Least played soundtracks with their songs func (q *Queries) GetLeastPlayedGamesWithSongs(ctx context.Context, limit int32) ([]GetLeastPlayedGamesWithSongsRow, error) { rows, err := q.db.Query(ctx, getLeastPlayedGamesWithSongs, limit) if err != nil { @@ -107,10 +107,10 @@ func (q *Queries) GetLeastPlayedGamesWithSongs(ctx context.Context, limit int32) for rows.Next() { var i GetLeastPlayedGamesWithSongsRow if err := rows.Scan( - &i.GameID, - &i.GameName, - &i.GamePlayed, - &i.GameLastPlayed, + &i.SoundtrackID, + &i.SoundtrackName, + &i.SoundtrackPlayed, + &i.SoundtrackLastPlayed, &i.Songs, ); err != nil { return nil, err @@ -125,29 +125,29 @@ func (q *Queries) GetLeastPlayedGamesWithSongs(ctx context.Context, limit int32) const getLeastPlayedSongsWithGame = `-- name: GetLeastPlayedSongsWithGame :many SELECT - s.game_id as game_id, - g.game_name, + s.soundtrack_id as soundtrack_id, + g.soundtrack_name, s.song_name, s.path, s.times_played, s.file_name FROM song s -JOIN game g ON s.game_id = g.id +JOIN soundtrack g ON s.soundtrack_id = g.id WHERE g.deleted IS NULL ORDER BY s.times_played ASC, s.song_name LIMIT $1 ` type GetLeastPlayedSongsWithGameRow struct { - GameID int32 `json:"game_id"` - GameName string `json:"game_name"` - SongName string `json:"song_name"` - Path string `json:"path"` - TimesPlayed int32 `json:"times_played"` - FileName *string `json:"file_name"` + SoundtrackID int32 `json:"soundtrack_id"` + SoundtrackName string `json:"soundtrack_name"` + SongName string `json:"song_name"` + Path string `json:"path"` + TimesPlayed int32 `json:"times_played"` + FileName *string `json:"file_name"` } -// Least played songs with their game info +// Least played songs with their soundtrack info func (q *Queries) GetLeastPlayedSongsWithGame(ctx context.Context, limit int32) ([]GetLeastPlayedSongsWithGameRow, error) { rows, err := q.db.Query(ctx, getLeastPlayedSongsWithGame, limit) if err != nil { @@ -158,8 +158,8 @@ func (q *Queries) GetLeastPlayedSongsWithGame(ctx context.Context, limit int32) for rows.Next() { var i GetLeastPlayedSongsWithGameRow if err := rows.Scan( - &i.GameID, - &i.GameName, + &i.SoundtrackID, + &i.SoundtrackName, &i.SongName, &i.Path, &i.TimesPlayed, @@ -177,10 +177,10 @@ func (q *Queries) GetLeastPlayedSongsWithGame(ctx context.Context, limit int32) const getMostPlayedGamesWithSongs = `-- name: GetMostPlayedGamesWithSongs :many SELECT - g.id as game_id, - g.game_name, - g.times_played as game_played, - g.last_played as game_last_played, + g.id as soundtrack_id, + g.soundtrack_name, + g.times_played as soundtrack_played, + g.last_played as soundtrack_last_played, json_agg( json_build_object( 'song_name', s.song_name, @@ -189,23 +189,23 @@ SELECT 'file_name', s.file_name ) ) as songs -FROM game g -LEFT JOIN song s ON g.id = s.game_id +FROM soundtrack g +LEFT JOIN song s ON g.id = s.soundtrack_id WHERE g.deleted IS NULL -GROUP BY g.id, g.game_name, g.times_played, g.last_played -ORDER BY g.times_played DESC, g.game_name +GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played +ORDER BY g.times_played DESC, g.soundtrack_name LIMIT $1 ` type GetMostPlayedGamesWithSongsRow struct { - GameID int32 `json:"game_id"` - GameName string `json:"game_name"` - GamePlayed int32 `json:"game_played"` - GameLastPlayed *time.Time `json:"game_last_played"` - Songs []byte `json:"songs"` + SoundtrackID int32 `json:"soundtrack_id"` + SoundtrackName string `json:"soundtrack_name"` + SoundtrackPlayed int32 `json:"soundtrack_played"` + SoundtrackLastPlayed *time.Time `json:"soundtrack_last_played"` + Songs []byte `json:"songs"` } -// Most played games with their songs +// Most played soundtracks with their songs func (q *Queries) GetMostPlayedGamesWithSongs(ctx context.Context, limit int32) ([]GetMostPlayedGamesWithSongsRow, error) { rows, err := q.db.Query(ctx, getMostPlayedGamesWithSongs, limit) if err != nil { @@ -216,10 +216,10 @@ func (q *Queries) GetMostPlayedGamesWithSongs(ctx context.Context, limit int32) for rows.Next() { var i GetMostPlayedGamesWithSongsRow if err := rows.Scan( - &i.GameID, - &i.GameName, - &i.GamePlayed, - &i.GameLastPlayed, + &i.SoundtrackID, + &i.SoundtrackName, + &i.SoundtrackPlayed, + &i.SoundtrackLastPlayed, &i.Songs, ); err != nil { return nil, err @@ -234,29 +234,29 @@ func (q *Queries) GetMostPlayedGamesWithSongs(ctx context.Context, limit int32) const getMostPlayedSongsWithGame = `-- name: GetMostPlayedSongsWithGame :many SELECT - s.game_id as game_id, - g.game_name, + s.soundtrack_id as soundtrack_id, + g.soundtrack_name, s.song_name, s.path, s.times_played, s.file_name FROM song s -JOIN game g ON s.game_id = g.id +JOIN soundtrack g ON s.soundtrack_id = g.id WHERE g.deleted IS NULL ORDER BY s.times_played DESC, s.song_name LIMIT $1 ` type GetMostPlayedSongsWithGameRow struct { - GameID int32 `json:"game_id"` - GameName string `json:"game_name"` - SongName string `json:"song_name"` - Path string `json:"path"` - TimesPlayed int32 `json:"times_played"` - FileName *string `json:"file_name"` + SoundtrackID int32 `json:"soundtrack_id"` + SoundtrackName string `json:"soundtrack_name"` + SongName string `json:"song_name"` + Path string `json:"path"` + TimesPlayed int32 `json:"times_played"` + FileName *string `json:"file_name"` } -// Most played songs with their game info +// Most played songs with their soundtrack info func (q *Queries) GetMostPlayedSongsWithGame(ctx context.Context, limit int32) ([]GetMostPlayedSongsWithGameRow, error) { rows, err := q.db.Query(ctx, getMostPlayedSongsWithGame, limit) if err != nil { @@ -267,8 +267,8 @@ func (q *Queries) GetMostPlayedSongsWithGame(ctx context.Context, limit int32) ( for rows.Next() { var i GetMostPlayedSongsWithGameRow if err := rows.Scan( - &i.GameID, - &i.GameName, + &i.SoundtrackID, + &i.SoundtrackName, &i.SongName, &i.Path, &i.TimesPlayed, @@ -286,9 +286,9 @@ func (q *Queries) GetMostPlayedSongsWithGame(ctx context.Context, limit int32) ( const getNeverPlayedGames = `-- name: GetNeverPlayedGames :many SELECT - g.id as game_id, - g.game_name, - g.times_played as game_played, + g.id as soundtrack_id, + g.soundtrack_name, + g.times_played as soundtrack_played, g.added, json_agg( json_build_object( @@ -297,19 +297,19 @@ SELECT 'times_played', s.times_played ) ) as songs -FROM game g -LEFT JOIN song s ON g.id = s.game_id +FROM soundtrack g +LEFT JOIN song s ON g.id = s.soundtrack_id WHERE g.deleted IS NULL AND g.times_played = 0 -GROUP BY g.id, g.game_name, g.times_played, g.added -ORDER BY g.game_name +GROUP BY g.id, g.soundtrack_name, g.times_played, g.added +ORDER BY g.soundtrack_name ` type GetNeverPlayedGamesRow struct { - GameID int32 `json:"game_id"` - GameName string `json:"game_name"` - GamePlayed int32 `json:"game_played"` - Added time.Time `json:"added"` - Songs []byte `json:"songs"` + SoundtrackID int32 `json:"soundtrack_id"` + SoundtrackName string `json:"soundtrack_name"` + SoundtrackPlayed int32 `json:"soundtrack_played"` + Added time.Time `json:"added"` + Songs []byte `json:"songs"` } // Games that have never been played (times_played = 0) @@ -323,9 +323,9 @@ func (q *Queries) GetNeverPlayedGames(ctx context.Context) ([]GetNeverPlayedGame for rows.Next() { var i GetNeverPlayedGamesRow if err := rows.Scan( - &i.GameID, - &i.GameName, - &i.GamePlayed, + &i.SoundtrackID, + &i.SoundtrackName, + &i.SoundtrackPlayed, &i.Added, &i.Songs, ); err != nil { @@ -341,10 +341,10 @@ func (q *Queries) GetNeverPlayedGames(ctx context.Context) ([]GetNeverPlayedGame const getOldestPlayedGames = `-- name: GetOldestPlayedGames :many SELECT - g.id as game_id, - g.game_name, - g.times_played as game_played, - g.last_played as game_last_played, + g.id as soundtrack_id, + g.soundtrack_name, + g.times_played as soundtrack_played, + g.last_played as soundtrack_last_played, json_agg( json_build_object( 'song_name', s.song_name, @@ -352,23 +352,23 @@ SELECT 'times_played', s.times_played ) ) as songs -FROM game g -LEFT JOIN song s ON g.id = s.game_id +FROM soundtrack g +LEFT JOIN song s ON g.id = s.soundtrack_id WHERE g.deleted IS NULL AND g.last_played IS NOT NULL -GROUP BY g.id, g.game_name, g.times_played, g.last_played +GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played ORDER BY g.last_played ASC LIMIT $1 ` type GetOldestPlayedGamesRow struct { - GameID int32 `json:"game_id"` - GameName string `json:"game_name"` - GamePlayed int32 `json:"game_played"` - GameLastPlayed *time.Time `json:"game_last_played"` - Songs []byte `json:"songs"` + SoundtrackID int32 `json:"soundtrack_id"` + SoundtrackName string `json:"soundtrack_name"` + SoundtrackPlayed int32 `json:"soundtrack_played"` + SoundtrackLastPlayed *time.Time `json:"soundtrack_last_played"` + Songs []byte `json:"songs"` } -// Oldest played games (least recently played, but has been played at least once) +// Oldest played soundtracks (least recently played, but has been played at least once) func (q *Queries) GetOldestPlayedGames(ctx context.Context, limit int32) ([]GetOldestPlayedGamesRow, error) { rows, err := q.db.Query(ctx, getOldestPlayedGames, limit) if err != nil { @@ -379,10 +379,10 @@ func (q *Queries) GetOldestPlayedGames(ctx context.Context, limit int32) ([]GetO for rows.Next() { var i GetOldestPlayedGamesRow if err := rows.Scan( - &i.GameID, - &i.GameName, - &i.GamePlayed, - &i.GameLastPlayed, + &i.SoundtrackID, + &i.SoundtrackName, + &i.SoundtrackPlayed, + &i.SoundtrackLastPlayed, &i.Songs, ); err != nil { return nil, err @@ -397,25 +397,25 @@ func (q *Queries) GetOldestPlayedGames(ctx context.Context, limit int32) ([]GetO const getStatisticsSummary = `-- name: GetStatisticsSummary :one SELECT - COUNT(*) as total_games, - SUM(CASE WHEN times_played > 0 THEN 1 ELSE 0 END) as played_games, - SUM(CASE WHEN times_played = 0 THEN 1 ELSE 0 END) as never_played_games, - COALESCE(SUM(times_played), 0)::bigint as total_game_plays, - COALESCE(AVG(times_played), 0)::float as avg_game_plays, - COALESCE(MAX(times_played), 0)::bigint as max_game_plays, - COALESCE(MIN(times_played), 0)::bigint as min_game_plays -FROM game + COUNT(*) as total_soundtracks, + SUM(CASE WHEN times_played > 0 THEN 1 ELSE 0 END) as played_soundtracks, + SUM(CASE WHEN times_played = 0 THEN 1 ELSE 0 END) as never_played_soundtracks, + COALESCE(SUM(times_played), 0)::bigint as total_soundtrack_plays, + COALESCE(AVG(times_played), 0)::float as avg_soundtrack_plays, + COALESCE(MAX(times_played), 0)::bigint as max_soundtrack_plays, + COALESCE(MIN(times_played), 0)::bigint as min_soundtrack_plays +FROM soundtrack WHERE deleted IS NULL ` type GetStatisticsSummaryRow struct { - TotalGames int64 `json:"total_games"` - PlayedGames int64 `json:"played_games"` - NeverPlayedGames int64 `json:"never_played_games"` - TotalGamePlays int64 `json:"total_game_plays"` - AvgGamePlays float64 `json:"avg_game_plays"` - MaxGamePlays int64 `json:"max_game_plays"` - MinGamePlays int64 `json:"min_game_plays"` + TotalSoundtracks int64 `json:"total_soundtracks"` + PlayedSoundtracks int64 `json:"played_soundtracks"` + NeverPlayedSoundtracks int64 `json:"never_played_soundtracks"` + TotalSoundtrackPlays int64 `json:"total_soundtrack_plays"` + AvgSoundtrackPlays float64 `json:"avg_soundtrack_plays"` + MaxSoundtrackPlays int64 `json:"max_soundtrack_plays"` + MinSoundtrackPlays int64 `json:"min_soundtrack_plays"` } // Get statistics summary @@ -423,13 +423,13 @@ func (q *Queries) GetStatisticsSummary(ctx context.Context) (GetStatisticsSummar row := q.db.QueryRow(ctx, getStatisticsSummary) var i GetStatisticsSummaryRow err := row.Scan( - &i.TotalGames, - &i.PlayedGames, - &i.NeverPlayedGames, - &i.TotalGamePlays, - &i.AvgGamePlays, - &i.MaxGamePlays, - &i.MinGamePlays, + &i.TotalSoundtracks, + &i.PlayedSoundtracks, + &i.NeverPlayedSoundtracks, + &i.TotalSoundtrackPlays, + &i.AvgSoundtrackPlays, + &i.MaxSoundtrackPlays, + &i.MinSoundtrackPlays, ) return i, err } diff --git a/internal/server/musicHandler.go b/internal/server/musicHandler.go index f908e96..946dab9 100644 --- a/internal/server/musicHandler.go +++ b/internal/server/musicHandler.go @@ -229,8 +229,8 @@ func (m *MusicHandler) GetPreviousSong(ctx *echo.Context) error { return ctx.Stream(http.StatusOK, "audio/mpeg", file) } -// GetAllGames godoc -// @Summary Get all games +// GetAllSoundtracks godoc +// @Summary Get all soundtracks // @Description Returns a list of all games in order // @Tags music // @Accept json @@ -238,17 +238,17 @@ func (m *MusicHandler) GetPreviousSong(ctx *echo.Context) error { // @Success 200 {array} map[string]interface{} // @Failure 423 {string} string "Syncing is in progress" // @Router /music/all/order [get] -func (m *MusicHandler) GetAllGames(ctx *echo.Context) error { +func (m *MusicHandler) GetAllSoundtracks(ctx *echo.Context) error { if backend.Syncing { logging.GetLogger().Info("Syncing is in progress") return ctx.JSON(http.StatusLocked, "Syncing is in progress") } - gameList := backend.GetAllGames() - return ctx.JSON(http.StatusOK, gameList) + soundtrackList := backend.GetAllSoundtracks() + return ctx.JSON(http.StatusOK, soundtrackList) } -// GetAllGamesRandom godoc -// @Summary Get all games random +// GetAllSoundtracksRandom godoc +// @Summary Get all soundtracks random // @Description Returns a list of all games in random order // @Tags music // @Accept json @@ -256,13 +256,13 @@ func (m *MusicHandler) GetAllGames(ctx *echo.Context) error { // @Success 200 {array} map[string]interface{} // @Failure 423 {string} string "Syncing is in progress" // @Router /music/all/random [get] -func (m *MusicHandler) GetAllGamesRandom(ctx *echo.Context) error { +func (m *MusicHandler) GetAllSoundtracksRandom(ctx *echo.Context) error { if backend.Syncing { logging.GetLogger().Info("Syncing is in progress") return ctx.JSON(http.StatusLocked, "Syncing is in progress") } - gameList := backend.GetAllGamesRandom() - return ctx.JSON(http.StatusOK, gameList) + soundtrackList := backend.GetAllSoundtracksRandom() + return ctx.JSON(http.StatusOK, soundtrackList) } // PutPlayed godoc diff --git a/internal/server/routes.go b/internal/server/routes.go index ec8057e..f20bd89 100644 --- a/internal/server/routes.go +++ b/internal/server/routes.go @@ -78,13 +78,13 @@ func (s *Server) RegisterRoutes() http.Handler { sync := NewSyncHandler() syncGroup := e.Group("/sync") - syncGroup.GET("", deprecatedMiddleware(sync.SyncGamesNewOnlyChanges)) + syncGroup.GET("", deprecatedMiddleware(sync.SyncSoundtracksNewOnlyChanges)) syncGroup.GET("/progress", deprecatedMiddleware(sync.SyncProgress)) - syncGroup.GET("/new", deprecatedMiddleware(sync.SyncGamesNewOnlyChanges)) - syncGroup.GET("/full", deprecatedMiddleware(sync.SyncGamesNewFull)) - syncGroup.GET("/new/full", deprecatedMiddleware(sync.SyncGamesNewFull)) - syncGroup.GET("/quick", deprecatedMiddleware(sync.SyncGamesNewOnlyChanges)) - syncGroup.GET("/reset", deprecatedMiddleware(sync.ResetGames)) + syncGroup.GET("/new", deprecatedMiddleware(sync.SyncSoundtracksNewOnlyChanges)) + syncGroup.GET("/full", deprecatedMiddleware(sync.SyncSoundtracksNewFull)) + syncGroup.GET("/new/full", deprecatedMiddleware(sync.SyncSoundtracksNewFull)) + syncGroup.GET("/quick", deprecatedMiddleware(sync.SyncSoundtracksNewOnlyChanges)) + syncGroup.GET("/reset", deprecatedMiddleware(sync.ResetDB)) music := NewMusicHandler() musicGroup := e.Group("/music") @@ -98,9 +98,9 @@ func (s *Server) RegisterRoutes() http.Handler { musicGroup.GET("/list", deprecatedMiddleware(music.GetPlayedSongs)) musicGroup.GET("/next", deprecatedMiddleware(music.GetNextSong)) musicGroup.GET("/previous", deprecatedMiddleware(music.GetPreviousSong)) - musicGroup.GET("/all", deprecatedMiddleware(music.GetAllGamesRandom)) - musicGroup.GET("/all/order", deprecatedMiddleware(music.GetAllGames)) - musicGroup.GET("/all/random", deprecatedMiddleware(music.GetAllGamesRandom)) + musicGroup.GET("/all", deprecatedMiddleware(music.GetAllSoundtracksRandom)) + musicGroup.GET("/all/order", deprecatedMiddleware(music.GetAllSoundtracks)) + musicGroup.GET("/all/random", deprecatedMiddleware(music.GetAllSoundtracksRandom)) musicGroup.PUT("/played", deprecatedMiddleware(music.PutPlayed)) musicGroup.GET("/addQue", deprecatedMiddleware(music.AddLatestToQue)) musicGroup.GET("/addPlayed", deprecatedMiddleware(music.AddLatestPlayed)) diff --git a/internal/server/syncHandler.go b/internal/server/syncHandler.go index 55e378c..88f1d3f 100644 --- a/internal/server/syncHandler.go +++ b/internal/server/syncHandler.go @@ -34,59 +34,59 @@ func (s *SyncHandler) SyncProgress(ctx *echo.Context) error { return ctx.JSON(http.StatusOK, response) } -// SyncGamesNewOnlyChanges godoc -// @Summary Sync games with only changes +// SyncSoundtracksNewOnlyChanges godoc +// @Summary Sync soundtracks with only changes // @Description Starts syncing games with only new changes // @Tags sync // @Accept json // @Produce json -// @Success 200 {string} string "Start syncing games" +// @Success 200 {string} string "Start syncing soundtracks" // @Failure 423 {string} string "Syncing is in progress" // @Router /sync [get] -func (s *SyncHandler) SyncGamesNewOnlyChanges(ctx *echo.Context) error { +func (s *SyncHandler) SyncSoundtracksNewOnlyChanges(ctx *echo.Context) error { if backend.Syncing { logging.GetLogger().Warn("Syncing is already in progress") return ctx.JSON(http.StatusLocked, "Syncing is in progress") } logging.GetLogger().Info("Starting sync with only changes") - go backend.SyncGamesNewOnlyChanges() - return ctx.JSON(http.StatusOK, "Start syncing games") + go backend.SyncSoundtracksNewOnlyChanges() + return ctx.JSON(http.StatusOK, "Start syncing soundtracks") } -// SyncGamesNewFull godoc +// SyncSoundtracksNewFull godoc // @Summary Sync all games fully // @Description Starts a full sync of all games // @Tags sync // @Accept json // @Produce json -// @Success 200 {string} string "Start syncing games full" +// @Success 200 {string} string "Start syncing soundtracks full" // @Failure 423 {string} string "Syncing is in progress" // @Router /sync/full [get] -func (s *SyncHandler) SyncGamesNewFull(ctx *echo.Context) error { +func (s *SyncHandler) SyncSoundtracksNewFull(ctx *echo.Context) error { if backend.Syncing { logging.GetLogger().Warn("Syncing is already in progress") return ctx.JSON(http.StatusLocked, "Syncing is in progress") } logging.GetLogger().Info("Starting full sync") - go backend.SyncGamesNewFull() - return ctx.JSON(http.StatusOK, "Start syncing games full") + go backend.SyncSoundtracksNewFull() + return ctx.JSON(http.StatusOK, "Start syncing soundtracks full") } -// ResetGames godoc -// @Summary Reset games database +// ResetDB godoc +// @Summary Reset soundtracks database // @Description Resets the games database by deleting all games and songs // @Tags sync // @Accept json // @Produce json -// @Success 200 {string} string "Games and songs are deleted from the database" +// @Success 200 {string} string "Soundtracks and songs are deleted from the database" // @Failure 423 {string} string "Syncing is in progress" // @Router /sync/reset [get] -func (s *SyncHandler) ResetGames(ctx *echo.Context) error { +func (s *SyncHandler) ResetDB(ctx *echo.Context) error { if backend.Syncing { logging.GetLogger().Warn("Cannot reset - syncing is in progress") return ctx.JSON(http.StatusLocked, "Syncing is in progress") } - logging.GetLogger().Info("Resetting games database") + logging.GetLogger().Info("Resetting soundtracks database") backend.ResetDB() - return ctx.JSON(http.StatusOK, "Games and songs are deleted from the database") + return ctx.JSON(http.StatusOK, "Soundtracks and songs are deleted from the database") }