ideas-0.7: src/Service/FeedbackText.hs
-----------------------------------------------------------------------------
-- Copyright 2010, Open Universiteit Nederland. This file is distributed
-- under the terms of the GNU General Public License. For more information,
-- see the file "LICENSE.txt", which is included in the distribution.
-----------------------------------------------------------------------------
-- |
-- Maintainer : bastiaan.heeren@ou.nl
-- Stability : provisional
-- Portability : portable (depends on ghc)
--
-----------------------------------------------------------------------------
module Service.FeedbackText
( ExerciseText(..)
, onefirsttext, submittext, derivationtext, submitHelper
) where
import Common.Library hiding (derivation)
import Data.Maybe
import Common.Utils
import Service.Diagnose (restartIfNeeded)
import Service.ExercisePackage
import Service.State
import Service.Submit
import Service.BasicServices
------------------------------------------------------------
-- Services
derivationtext :: Monad m => State a -> Maybe String -> m [(String, Context a)]
derivationtext state _event = do
exText <- exerciseText state
xs <- derivation Nothing state
return (map (first (showRule exText)) xs)
onefirsttext :: Monad m => State a -> Maybe String -> m (Bool, String, State a)
onefirsttext state event =
case onefirst state of
Just (r, _, s) -> do
exText <- exerciseText state
let mtxt = fromContext (stateContext s) >>= useToRewrite exText r state
msg = case mtxt of
Just txt | event /= Just "hint button" -> txt
_ -> "Use " ++ showRule exText r
return (True, msg, s)
_ -> return (False, "Sorry, no hint available", state)
submittext :: Monad m => State a -> String -> Maybe String -> m (Bool, String, State a)
submittext state input _event = do
exText <- exerciseText state
return $
case parser (exercise (exercisePkg state)) input of
Left err ->
(False, feedbackSyntaxError exText err, state)
Right a ->
let result = submit state a
(txt, b) = submitHelper exText state a result
in case getResultState result of
Just new | b -> (True, txt, restartIfNeeded new)
_ -> (False, txt, state)
-- Feedback messages for submit service (free student input). The boolean
-- indicates whether the student is allowed to continue (True), or forced
-- to go back to the previous state (False)
submitHelper :: ExerciseText a -> State a -> a -> Result a -> (String, Bool)
submitHelper exText old a result =
case result of
Buggy rs -> ( fromMaybe "" (youRewroteInto old a) ++
feedbackBuggy exText (ready old) rs
, False)
NotEquivalent -> ( fromMaybe "" (youRewroteInto old a) ++
feedbackNotEquivalent exText (ready old)
, False)
Ok rs _
| null rs -> (feedbackSame exText, False)
| otherwise -> feedbackOk exText rs
Detour rs _ -> feedbackDetour exText (ready old) (expected old) rs
Unknown _ -> ( fromMaybe "" (youRewroteInto old a) ++
feedbackUnknown exText (ready old)
, False)
where
expected s = do
xs <- allfirsts s
fmap fst3 (safeHead xs)
------------------------------------------------------------
-- Helper functions
showRule :: ExerciseText a -> Rule (Context a) -> String
showRule exText r =
fromMaybe ("rule " ++ showId r) (ruleText exText r)
useToRewrite :: ExerciseText a -> Rule (Context a) -> State a -> a -> Maybe String
useToRewrite exText r old = rewriteIntoText True txt old
where
txt = "Use " ++ showRule exText r ++ " to rewrite "
youRewroteInto :: State a -> a -> Maybe String
youRewroteInto = rewriteIntoText False "You rewrote "
rewriteIntoText :: Bool -> String -> State a -> a -> Maybe String
rewriteIntoText mode txt old a = do
let ex = exercise (exercisePkg old)
p <- fromContext (stateContext old)
(p1, a1) <- difference ex mode p a
return $ txt ++ prettyPrinter ex p1
++ " into " ++ prettyPrinter ex a1 ++ ". "
exerciseText :: Monad m => State a -> m (ExerciseText a)
exerciseText =
let msg = "No support for textual feedback"
in maybe (fail msg) return . getExerciseText . exercisePkg