module Ideas.Service.State
(
State, makeState, makeNoState, emptyStateContext, emptyState
, exercise, statePrefix, stateContext, stateTerm
, withoutPrefix, stateLabels, suitable, finished, firsts, microsteps
) where
import Data.Function
import Data.List
import Data.Maybe
import Ideas.Common.Library hiding (suitable, ready, (:~>))
import Ideas.Common.Strategy.Choice
import Ideas.Common.Strategy.Sequence
data State a = State
{ exercise :: Exercise a
, statePrefix :: Prefix (Context a)
, stateContext :: Context a
}
instance Show (State a) where
show s = unlines $ "State {" : map (" "++) xs ++ ["}"]
where
xs = [ "exercise = " ++ showId s
, "prefix = " ++ show (statePrefix s)
, "term = " ++ prettyPrinterContext (exercise s) (stateContext s)
]
instance HasId (State a) where
getId = getId . exercise
changeId f s = s { exercise = changeId f (exercise s) }
instance HasEnvironment (State a) where
environment = environment . stateContext
setEnvironment env s =
s { stateContext = setEnvironment env (stateContext s) }
instance Firsts (State a) where
type Elem (State a) = (Step (Context a), Context a)
firsts st = firstsOrdered cmp st
where
cmp = ruleOrdering (exercise st) `on` (stepRule . fst)
menu st = fmap f (menu (majorPrefix (statePrefix st)))
where
f Done = Done
f (info :~> p) = info :~> State (exercise st) p (snd info)
microsteps :: State a -> [((Step (Context a), Context a), State a)]
microsteps st = concatMap f (bests (menu (statePrefix st)))
where
f Done = []
f (info :~> p) = [(info, State (exercise st) p (snd info))]
stateTerm :: State a -> a
stateTerm = fromMaybe (error "invalid term") . fromContext . stateContext
makeState :: Exercise a -> Prefix (Context a) -> Context a -> State a
makeState = State
makeNoState :: Exercise a -> Context a -> State a
makeNoState = flip makeState noPrefix
emptyStateContext :: Exercise a -> Context a -> State a
emptyStateContext ex ca =
let pr = emptyPrefix (strategy ex) ca
in makeState ex pr ca
emptyState :: Exercise a -> a -> State a
emptyState ex = emptyStateContext ex . inContext ex
withoutPrefix :: State a -> Bool
withoutPrefix = null . prefixPaths . statePrefix
suitable :: State a -> Bool
suitable st = isSuitable (exercise st) (stateTerm st)
finished :: State a -> Bool
finished st = isReady (exercise st) (stateTerm st)
stateLabels :: State a -> [[Id]]
stateLabels st = map make (prefixPaths (statePrefix st))
where
ex = exercise st
make path =
let (xs, _) = replayPath path (strategy ex) (stateContext st)
in nub [l | Enter l <- xs] \\ [l | Exit l <- xs]