Skip to content

Commit 0b04f9b

Browse files
Merge pull request #33 from UncleJunVIP/features-play-history
Features play history
2 parents 697c3e3 + ba9797a commit 0b04f9b

26 files changed

+1064
-59
lines changed

app/game_manager.go

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,92 @@ func handleScreenTransition(currentScreen models.Screen, result interface{}, cod
148148
return handleArchiveManagementTransition(currentScreen, result, code)
149149
case models.ScreenNames.ArchiveOptions:
150150
return handleArchiveOptionsTransition(currentScreen, result, code)
151+
case models.ScreenNames.PlayHistoryList:
152+
return handlePlayHistoryListTransition(result, code)
153+
case models.ScreenNames.PlayHistoryGameList:
154+
return handlePlayHistoryGameListTransition(currentScreen, result, code)
155+
case models.ScreenNames.PlayHistoryGameDetails:
156+
return handlePlayHistoryGameDetailsTransition(currentScreen, result, code)
157+
case models.ScreenNames.PlayHistoryGameHistory:
158+
return handlePlayHistoryGameHistoryTransition(currentScreen, result, code)
151159
default:
152160
state.ReturnToMain()
153161
return ui.InitMainMenu()
154162
}
155163
}
156164

165+
func handlePlayHistoryListTransition(result interface{}, code int) models.Screen {
166+
switch code {
167+
case ExitCodeSuccess:
168+
state.AddNewMenuPosition()
169+
return ui.InitPlayHistoryGamesListScreen(result.(string), "")
170+
default:
171+
state.RemoveMenuPositions(1)
172+
return ui.InitToolsScreen()
173+
}
174+
}
175+
176+
func handlePlayHistoryGameListTransition(currentScreen models.Screen, result interface{}, code int) models.Screen {
177+
ptgls := currentScreen.(ui.PlayHistoryGamesListScreen)
178+
179+
switch code {
180+
case ExitCodeSuccess:
181+
state.AddNewMenuPosition()
182+
return ui.InitPlayHistoryGameDetailsScreenFromPlayHistory(ptgls.Console, ptgls.SearchFilter, result.(models.PlayHistoryAggregate))
183+
case ExitCodeCancel:
184+
if ptgls.SearchFilter != "" {
185+
state.UpdateCurrentMenuPosition(0, 0)
186+
return ui.InitPlayHistoryGamesListScreen(ptgls.Console, "")
187+
}
188+
189+
state.RemoveMenuPositions(1)
190+
return ui.InitPlayHistoryListScreen()
191+
case ExitCodeAction, ExitCodeError:
192+
searchFilter := result.(string)
193+
194+
if searchFilter != "" {
195+
state.UpdateCurrentMenuPosition(0, 0)
196+
return ui.InitPlayHistoryGamesListScreen(ptgls.Console, searchFilter)
197+
}
198+
199+
return ui.InitPlayHistoryGamesListScreen(ptgls.Console, "")
200+
case ExitCodeEmpty:
201+
if ptgls.SearchFilter != "" {
202+
utils.ShowTimedMessage(fmt.Sprintf("No results found for %s!", ptgls.SearchFilter), shortMessageDelay)
203+
state.UpdateCurrentMenuPosition(0, 0)
204+
return ui.InitPlayHistoryGamesListScreen(ptgls.Console, "")
205+
}
206+
207+
utils.ShowTimedMessage(fmt.Sprintf("%s history is empty!", ptgls.Console), longMessageDelay)
208+
state.RemoveMenuPositions(1)
209+
return ui.InitPlayHistoryListScreen()
210+
default:
211+
state.RemoveMenuPositions(1)
212+
return ui.InitPlayHistoryListScreen()
213+
}
214+
}
215+
216+
func handlePlayHistoryGameHistoryTransition(currentScreen models.Screen, result interface{}, code int) models.Screen {
217+
ptghs := currentScreen.(ui.PlayHistoryGameHistoryScreen)
218+
return ui.InitPlayHistoryGameDetailsScreenFromSelf(ptghs.Console, ptghs.SearchFilter, ptghs.GameAggregate,
219+
ptghs.Game, ptghs.RomDirectory, ptghs.PreviousRomDirectory, ptghs.PlayHistoryOrigin)
220+
}
221+
222+
func handlePlayHistoryGameDetailsTransition(currentScreen models.Screen, result interface{}, code int) models.Screen {
223+
ptgds := currentScreen.(ui.PlayHistoryGameDetailsScreen)
224+
switch code {
225+
case ExitCodeSuccess:
226+
return ui.InitPlayHistoryGameHistoryScreen(ptgds.Console, ptgds.SearchFilter, ptgds.GameAggregate,
227+
ptgds.Game, ptgds.RomDirectory, ptgds.PreviousRomDirectory, ptgds.PlayHistoryOrigin)
228+
default:
229+
state.RemoveMenuPositions(1)
230+
if ptgds.PlayHistoryOrigin {
231+
return ui.InitPlayHistoryGamesListScreen(ptgds.Console, ptgds.SearchFilter)
232+
}
233+
return ui.InitActionsScreen(ptgds.Game, ptgds.RomDirectory, ptgds.PreviousRomDirectory, ptgds.SearchFilter)
234+
}
235+
}
236+
157237
func handleMainMenuTransition(result interface{}, code int) models.Screen {
158238
switch code {
159239
case ExitCodeSuccess:
@@ -340,6 +420,8 @@ func handleToolsTransition(result interface{}, code int) models.Screen {
340420
switch selection {
341421
case "Global Actions":
342422
return ui.InitGlobalActionsScreen()
423+
case "Play History":
424+
return ui.InitPlayHistoryListScreen()
343425
}
344426
return ui.InitToolsScreen()
345427
case ExitCodeAction:
@@ -481,6 +563,9 @@ func executeGameAction(as ui.ActionsScreen, action sum.Int[models.Action]) model
481563
return handleDeleteRomAction(as)
482564
case models.Actions.Nuke:
483565
return handleNukeAction(as)
566+
case models.Actions.PlayHistoryOpen:
567+
state.AddNewMenuPosition()
568+
return ui.InitPlayHistoryGameDetailsScreenFromActions(as.Game, as.RomDirectory, as.PreviousRomDirectory, as.SearchFilter)
484569
default:
485570
state.RemoveMenuPositions(1)
486571
return ui.InitGamesListWithPreviousDirectory(as.RomDirectory, as.PreviousRomDirectory, as.SearchFilter)
@@ -614,7 +699,7 @@ func handleBulkDownloadArt(ba ui.BulkOptionsScreen) {
614699
gaba.ProcessMessageOptions{ShowThemeBackground: true},
615700
func() (interface{}, error) {
616701
for _, game := range ba.Games {
617-
if artPath := utils.FindArt(ba.RomDirectory, game, state.GetAppState().Config.ArtDownloadType); artPath != "" {
702+
if artPath := utils.FindArt(ba.RomDirectory, game, state.GetAppState().Config.ArtDownloadType, state.GetAppState().Config.FuzzySearchThreshold); artPath != "" {
618703
artPaths = append(artPaths, artPath)
619704
}
620705
}

models/actions.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ type Action struct {
2020
CollectionDelete,
2121
CollectionAdd,
2222

23+
PlayHistoryOpen,
24+
PlayHistoryAdopt,
25+
2326
GlobalDownloadArt,
2427
GlobalClearRecents sum.Int[Action]
2528
}
@@ -40,6 +43,8 @@ var ActionMap = map[string]sum.Int[Action]{
4043
"Rename Collection": Actions.CollectionRename,
4144
"Delete Collection": Actions.CollectionDelete,
4245
"Add to Collection": Actions.CollectionAdd,
46+
47+
"View Play Details": Actions.PlayHistoryOpen,
4348
}
4449

4550
var GlobalActionMap = map[string]sum.Int[Action]{
@@ -81,6 +86,11 @@ var ArchiveActionKeys = []string{
8186
"Delete Archive",
8287
}
8388

89+
var PlayHistoryActionKeys = []string{
90+
//"Rehome Orphaned History",
91+
//"Delete Existing History",
92+
}
93+
8494
var ActionNames = map[sum.Int[Action]]string{}
8595

8696
func init() {

models/app_state.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ type AppState struct {
88
Config *Config
99

1010
MenuPositionList []MenuPositionPointer
11+
12+
GamePlayMap map[string][]PlayHistoryAggregate
13+
ConsolePlayMap map[string]int
14+
TotalPlay int
15+
16+
CollectionMap map[string][]Collection
1117
}
1218

1319
func (a AppState) MarshalLogObject(enc zapcore.ObjectEncoder) error {

models/config.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import (
77
)
88

99
type Config struct {
10-
ArtDownloadType sum.Int[shared.ArtDownloadType] `yaml:"art_download_type"`
10+
ArtDownloadType sum.Int[shared.ArtDownloadType] `yaml:"art_download_type"`
1111
FuzzySearchThreshold float64 `yaml:"fuzzy_search_threshold"`
12-
HideEmpty bool `yaml:"hide_empty"`
13-
ShowArt bool `yaml:"show_art"`
14-
LogLevel string `yaml:"log_level"`
12+
HideEmpty bool `yaml:"hide_empty"`
13+
ShowArt bool `yaml:"show_art"`
14+
LogLevel string `yaml:"log_level"`
15+
PlayHistoryShowCollections bool `yaml:"play_history_show_collections"`
16+
PlayHistoryShowArchives bool `yaml:"play_history_show_archives"`
1517
}
1618

1719
func (c *Config) MarshalLogObject(enc zapcore.ObjectEncoder) error {

models/play_history.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package models
2+
3+
import "time"
4+
5+
type PlayHistoryAggregate struct {
6+
Id []int
7+
Name string
8+
Path string
9+
PlayTimeTotal int
10+
PlayCountTotal int
11+
FirstPlayedTime time.Time
12+
LastPlayedTime time.Time
13+
}
14+
15+
type PlayHistoryGranular struct {
16+
PlayTime int
17+
StartTime int
18+
UpdateTime int
19+
}

models/screens.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ type ScreenName struct {
2727
CollectionManagement,
2828
CollectionCreate,
2929

30+
PlayHistoryActions,
31+
PlayHistoryGameDetails,
32+
PlayHistoryGameHistory,
33+
PlayHistoryGameList,
34+
PlayHistoryList,
35+
3036
GlobalActions sum.Int[ScreenName]
3137
}
3238

pak.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "Game Manager",
3-
"version": "v2.4.1",
3+
"version": "v2.5.0",
44
"type": "TOOL",
55
"description": "A one-stop pak for all your game management needs.",
66
"author": "K-Wall & redria7",
@@ -10,6 +10,7 @@
1010
"BRICK": ".github/resources/banner.png"
1111
},
1212
"changelog": {
13+
"v2.5.0": "Added a new Play History tool allowing for viewing of all current game tracking history. Includes total hours, hours by console, hours by game, ROM location tagging, ROM collection tagging, a play summary screen, and a granular detail screen. Play summary and granular detail screens can also be accessed from game actions.",
1314
"v2.4.1": "Added clear recently played to the global actions tool. Thanks madeleineostoja for the suggestion!",
1415
"v2.3.0": "Enhanced art searching that uses a fallback Jaccard Similarity with configurable threshold when art with an exact filename match does not exist.",
1516
"v2.2.2": "Archiving / Unarchiving Multi Disk and BIN/CUE games now works as intended. Nested folders now work with the Global Actions Missing Art tool. Shoved Global Actions into a Tool Menu for future Pak expansion.",

state/state.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"go.uber.org/atomic"
66
"gopkg.in/yaml.v3"
77
"nextui-game-manager/models"
8+
"nextui-game-manager/utils"
89
"os"
910
"sync"
1011
)
@@ -111,3 +112,47 @@ func GetCurrentMenuPosition() (int, int) {
111112

112113
return selectedIndex, selectedPosition
113114
}
115+
116+
func GetPlayMaps() (map[string][]models.PlayHistoryAggregate, map[string]int, int) {
117+
temp := GetAppState()
118+
if temp.GamePlayMap == nil {
119+
updatePlayMaps()
120+
temp = GetAppState()
121+
}
122+
return temp.GamePlayMap, temp.ConsolePlayMap, temp.TotalPlay
123+
}
124+
125+
func updatePlayMaps() {
126+
temp := GetAppState()
127+
temp.GamePlayMap, temp.ConsolePlayMap, temp.TotalPlay = utils.GenerateCurrentGameStats()
128+
UpdateAppState(temp)
129+
}
130+
131+
func ClearPlayMaps() {
132+
temp := GetAppState()
133+
temp.GamePlayMap = nil
134+
temp.ConsolePlayMap = nil
135+
temp.TotalPlay = 0
136+
UpdateAppState(temp)
137+
}
138+
139+
func GetCollectionMap() map[string][]models.Collection {
140+
temp := GetAppState()
141+
if temp.CollectionMap == nil {
142+
updateCollectionMap()
143+
temp = GetAppState()
144+
}
145+
return temp.CollectionMap
146+
}
147+
148+
func updateCollectionMap() {
149+
temp := GetAppState()
150+
temp.CollectionMap = utils.GenerateCollectionMap()
151+
UpdateAppState(temp)
152+
}
153+
154+
func ClearCollectionMap() {
155+
temp := GetAppState()
156+
temp.CollectionMap = nil
157+
UpdateAppState(temp)
158+
}

ui/actions.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ func (a ActionsScreen) Draw() (action interface{}, exitCode int, e error) {
4949
actions = utils.InsertIntoSlice(actions, 1, "Delete Art")
5050
}
5151

52+
gamePlayMap, _, _ := state.GetPlayMaps()
53+
gameAggregate, _ := utils.CollectGameAggregateFromGame(a.Game, gamePlayMap)
54+
if gameAggregate.PlayCountTotal != 0 {
55+
actions = append(actions, "View Play Details")
56+
}
57+
5258
var actionEntries []gabagool.MenuItem
5359
for _, action := range actions {
5460
actionEntries = append(actionEntries, gabagool.MenuItem{

ui/add_to_collection.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ func (a AddToCollectionScreen) Draw() (collection interface{}, exitCode int, e e
161161

162162
if selection.IsSome() && !selection.Unwrap().ActionTriggered && selection.Unwrap().SelectedIndex != -1 {
163163
state.UpdateCurrentMenuPosition(selection.Unwrap().SelectedIndex, selection.Unwrap().VisiblePosition)
164+
state.ClearCollectionMap()
164165
selectedCol := selection.Unwrap().SelectedItem.Metadata.(models.Collection)
165166

166167
_, err := utils.AddCollectionGames(selectedCol, a.Games)

0 commit comments

Comments
 (0)