Skip to content

Commit

Permalink
Save time upon finishing scenario (#1118)
Browse files Browse the repository at this point in the history
- closes #1111
  • Loading branch information
xsebek committed Feb 18, 2023
1 parent e72ca4c commit 22af444
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 17 deletions.
10 changes: 5 additions & 5 deletions src/Swarm/Game/ScenarioInfo.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ module Swarm.Game.ScenarioInfo (
scenarioStatus,
scenarioBestTime,
scenarioBestTicks,
updateScenarioInfoOnQuit,
updateScenarioInfoOnFinish,
ScenarioInfoPair,

-- * Scenario collection
Expand Down Expand Up @@ -153,13 +153,13 @@ scenarioBestTime :: Lens' ScenarioInfo ScenarioStatus
-- | The best status of the scenario, measured in game ticks.
scenarioBestTicks :: Lens' ScenarioInfo ScenarioStatus

-- | Update the current @ScenarioInfo@ record when quitting a game.
-- | Update the current @ScenarioInfo@ record when finishing a game.
--
-- Note that when comparing "best" times, shorter is not always better!
-- As long as the scenario is not completed (e.g. some do not have win condition)
-- we consider having fun _longer_ to be better.
updateScenarioInfoOnQuit :: ZonedTime -> Integer -> Bool -> ScenarioInfo -> ScenarioInfo
updateScenarioInfoOnQuit z ticks completed (ScenarioInfo p s bTime bTicks) = case s of
updateScenarioInfoOnFinish :: ZonedTime -> Integer -> Bool -> ScenarioInfo -> ScenarioInfo
updateScenarioInfoOnFinish z ticks completed si@(ScenarioInfo p s bTime bTicks) = case s of
InProgress start _ _ ->
let el = (diffUTCTime `on` zonedTimeToUTC) z start
cur = (if completed then Complete else InProgress) start el ticks
Expand All @@ -168,7 +168,7 @@ updateScenarioInfoOnQuit z ticks completed (ScenarioInfo p s bTime bTicks) = cas
InProgress {} | not completed && f b > f cur -> b -- keep longer progress (fun!)
_ -> cur -- otherwise update with current
in ScenarioInfo p cur (best _scenarioElapsed bTime) (best _scenarioElapsedTicks bTicks)
_ -> error "Logical error: trying to quit scenario which is not in progress!"
_ -> si

-- ----------------------------------------------------------------------------
-- Scenario Item
Expand Down
41 changes: 29 additions & 12 deletions src/Swarm/TUI/Controller.hs
Original file line number Diff line number Diff line change
Expand Up @@ -427,19 +427,25 @@ handleModalEvent = \case
where
refreshList lw = nestEventM' lw $ handleListEventWithSeparators ev shouldSkipSelection

-- | Write the @ScenarioInfo@ out to disk when exiting a game.
saveScenarioInfoOnQuit :: (MonadIO m, MonadState AppState m) => m ()
saveScenarioInfoOnQuit = do
getNormalizedCurrentScenarioPath :: (MonadIO m, MonadState AppState m) => m (Maybe FilePath)
getNormalizedCurrentScenarioPath =
-- the path should be normalized and good to search in scenario collection
use (gameState . currentScenarioPath) >>= \case
Nothing -> return Nothing
Just p' -> do
gs <- use $ gameState . scenarios
Just <$> liftIO (normalizeScenarioPath gs p')

-- | Write the @ScenarioInfo@ out to disk when finishing a game (i.e. on winning or exit).
saveScenarioInfoOnFinish :: (MonadIO m, MonadState AppState m) => m ()
saveScenarioInfoOnFinish = do
-- Don't save progress if we are in cheat mode
cheat <- use $ uiState . uiCheatMode
unless cheat $ do
-- the path should be normalized and good to search in scenario collection
mp' <- use $ gameState . currentScenarioPath
case mp' of
getNormalizedCurrentScenarioPath >>= \case
Nothing -> return ()
Just p' -> do
gs <- use $ gameState . scenarios
p <- liftIO $ normalizeScenarioPath gs p'
Just p -> do
t <- liftIO getZonedTime
wc <- use $ gameState . winCondition
let won = case wc of
Expand All @@ -448,7 +454,7 @@ saveScenarioInfoOnQuit = do
ts <- use $ gameState . ticks
let currentScenarioInfo :: Traversal' AppState ScenarioInfo
currentScenarioInfo = gameState . scenarios . scenarioItemByPath p . _SISingle . _2
currentScenarioInfo %= updateScenarioInfoOnQuit t ts won
currentScenarioInfo %= updateScenarioInfoOnFinish t ts won
status <- preuse currentScenarioInfo
case status of
Nothing -> return ()
Expand All @@ -461,6 +467,16 @@ saveScenarioInfoOnQuit = do
_ -> return ()
liftIO $ saveScenarioInfo p si

-- | Write the @ScenarioInfo@ out to disk when exiting a game.
saveScenarioInfoOnQuit :: (MonadIO m, MonadState AppState m) => m ()
saveScenarioInfoOnQuit = do
saveScenarioInfoOnFinish
-- Don't save progress if we are in cheat mode
cheat <- use $ uiState . uiCheatMode
unless cheat $ do
getNormalizedCurrentScenarioPath >>= \case
Nothing -> return ()
Just p -> do
-- See what scenario is currently focused in the menu. Depending on how the
-- previous scenario ended (via quit vs. via win), it might be the same as
-- currentScenarioPath or it might be different.
Expand Down Expand Up @@ -777,13 +793,13 @@ doGoalUpdates = do
-- This clears the "flag" that the Lose dialog needs to pop up
gameState . winCondition .= WinConditions (Unwinnable True) x
openModal LoseModal

saveScenarioInfoOnFinish
return True
WinConditions (Won False) x -> do
-- This clears the "flag" that the Win dialog needs to pop up
gameState . winCondition .= WinConditions (Won True) x
openModal WinModal

saveScenarioInfoOnFinish
-- We do NOT advance the New Game menu to the next item here (we
-- used to!), because we do not know if the user is going to
-- select 'keep playing' or 'next challenge'. We maintain the
Expand Down Expand Up @@ -818,7 +834,8 @@ doGoalUpdates = do

-- The "uiGoal" field is necessary at least to "persist" the data that is needed
-- if the player chooses to later "recall" the goals dialog with CTRL+g.
uiState . uiGoal
uiState
. uiGoal
.= GoalDisplay
newGoalTracking
(GR.makeListWidget newGoalTracking)
Expand Down

0 comments on commit 22af444

Please sign in to comment.