packages feed

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