module ALife.Creatur.Counter
(
Counter(..),
PersistentCounter,
mkPersistentCounter
) where
import ALife.Creatur.Clock (Clock, currentTime, incTime)
import Control.Monad (unless)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.State (StateT, get, gets, modify, put)
import System.Directory (doesFileExist)
class Counter c where
current :: StateT c IO Int
increment :: StateT c IO ()
data PersistentCounter = PersistentCounter {
initialised :: Bool,
time :: Int,
filename :: FilePath
} deriving Show
mkPersistentCounter :: FilePath -> PersistentCounter
mkPersistentCounter = PersistentCounter False (1)
instance Counter PersistentCounter where
current = do
initIfNeeded
gets time
increment = do
t <- current
let t' = t + 1
f <- gets filename
modify (\c -> c { time=t' })
liftIO $ writeFile f $ show t'
initIfNeeded :: StateT PersistentCounter IO ()
initIfNeeded = do
isInitialised <- gets initialised
unless isInitialised $ do
counter <- get
counter' <- liftIO $ initialise counter
put counter'
initialise :: PersistentCounter -> IO PersistentCounter
initialise counter = do
let f = filename counter
fExists <- doesFileExist f
if fExists
then do
s <- readFile f
return $ counter { initialised=True, time=read s }
else return $ counter { initialised=True, time=0 }
instance Clock PersistentCounter where
currentTime = current
incTime = increment