ideas-0.5.8: src/Domain/Logic/FeedbackText.hs
-----------------------------------------------------------------------------
-- Copyright 2009, 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)
--
-- Feedback messages reported for the logic domain. Content to be provided
-- by Josje Lodder.
--
-----------------------------------------------------------------------------
module Domain.Logic.FeedbackText
( feedbackSyntaxError, ruleText, appliedRule
, feedbackBuggy, feedbackNotEquivalent
, feedbackSame
, feedbackOk, feedbackDetour, feedbackUnknown
) where
import Data.Maybe
import Text.Parsing
import Common.Transformation
import Domain.Logic.Rules
import Domain.Logic.BuggyRules
-- This is more general than the logic domain. Perhaps it should
-- be defined elsewhere
feedbackSyntaxError :: SyntaxError -> String
feedbackSyntaxError syntaxError =
case syntaxError of
ParNotClosed token ->
"Opening parenthesis symbol '(' at position " ++ tokenPos token ++ " is not closed."
ParNoOpen token ->
"Closing parenthesis symbol ')' at position " ++ tokenPos token ++ " has no matching opening parenthesis."
ParMismatch token1 token2 ->
"The openening parenthesis at position " ++ tokenPos token1 ++
" does not match with the closing parenthesis at position " ++ tokenPos token2 ++ "."
ErrorMessage txt ->
txt
Unexpected token ->
"Unexpected " ++ showToken token
feedbackBuggy :: Bool -> [Rule a] -> String
feedbackBuggy ready [br]
| br ~= buggyRuleCommImp =
f "Did you think that implication is commutative? This is not the case. "
| br ~= buggyRuleAssImp =
f "Did you think that implication is associative? This is not the case. "
| br ~= buggyRuleImplElim2 =
f "Make sure that you use the rule for implication elimanation, you seemed to use equivalence elimination "
| br ~= buggyRuleEquivElim3 =
f "Make sure that you use the rule for equivalence elimanation, you seemed to use implication elimination "
| br ~= buggyRuleIdemImp =
f "Did you think that implication is idempotent? This is not the case. "
| br ~= buggyRuleIdemEqui =
f "Did you think that equivalence is idempotent? This is not the case. "
| br ~= buggyRuleAndSame =
f "Did you think that phi AND phi is equivalent to True? This is not the case. Idempotency of AND means that phi AND phi is equivalent to phi. "
| br ~= buggyRuleOrSame =
f "Did you think that phi OR phi is equivalent to True? This is not the case. Idempotency of OR means that phi OR phi is equivalent to phi. "
| br ~= buggyRuleAndCompl =
f "Be careful in the application of the the complement-rules "
| br ~= buggyRuleOrCompl =
f "Be careful in the application of the the complement-rules "
| br ~= buggyRuleTrueProp =
f "Be careful in the application of the the True-False rules "
| br ~= buggyRuleFalseProp =
f "Be careful in the application of the the True-False rules "
| br ~= buggyRuleEquivElim1 =
f "Be careful with the elimination of an equivalence; take care of the negations. "
| br ~= buggyRuleEquivElim2 =
f "Be careful with the elimination of an equivalence; make sure that the disjunctions and the conjunctions are at the right place. "
| br ~= buggyRuleImplElim =
f "Be careful with the elimination of an implication; make sure the negation is at the right place. "
| br ~= buggyRuleImplElim1 =
f "Did you try to eliminate an implication? In that case you used an AND instead of an OR "
| br ~= buggyRuleDeMorgan1 =
f "Did you try to apply DeMorgan? Be careful with the negations. "
| br ~= buggyRuleDeMorgan2 =
f "Did you try to apply DeMorgan? Make sure that you remove the outer negation when applying this rule "
| br ~= buggyRuleDeMorgan3 =
f "Did you try to apply DeMorgan? Make sure that you replace AND by OR. "
| br ~= buggyRuleDeMorgan4 =
f "Did you try to apply DeMorgan? Make sure that you replace OR by AND. "
| br ~= buggyRuleDeMorgan5 =
f "Did you try to apply DeMorgan? Take care of the scope of the negations. "
| br ~= buggyRuleNotOverImpl =
f "Did you think that you can distribute a negation over an implication? This is not the case. "
| br ~= buggyRuleParenth1 =
f "Take care of the negations and the parentheses. "
| br ~= buggyRuleParenth2 =
f "Take care of the outer negation when you eliminate an equivalence. "
| br ~= buggyRuleParenth3 =
f "Did you try to apply double negation? At this place this is not allowed, because of the parenthesis between the negations. "
| br ~= buggyRuleAssoc =
f "Did you change the parentheses? This is not allowed in a subformula consisting of a disjunction and a conjunction. "
| br ~= buggyRuleAbsor =
f "Did you try to apply absorption? You cant't apply this rule at this place since the resulting sub formula is not a subformula of the bigger term. "
| br ~= buggyRuleDistr =
f "Did you try to apply distribution? Take care of the place of the disjunctions and the conjunctions. "
| br ~= buggyRuleDistrNot =
f "Did you try to apply distribution? Don't forget the negations!. "
where f = incorrect ready
feedbackBuggy ready _ = incorrect ready ""
feedbackNotEquivalent :: Bool -> String
feedbackNotEquivalent ready = incorrect ready ""
feedbackSame :: String
feedbackSame = "You have submitted a similar term. " ++
"Maybe you inserted or removed parentheses (the tool supports associativity)?"
feedbackOk :: [Rule a] -> (String, Bool)
feedbackOk [one] = (okay (appliedRule one), True)
feedbackOk _ = ("You have combined multiple steps. Press the Back button and perform one step at the time.", False)
-- TODO Bastiaan: welke regel wordt er dan verwacht door de strategie?
feedbackDetour :: Bool -> Maybe (Rule a) -> [Rule a] -> (String, Bool)
feedbackDetour True _ [one] = (appliedRule one ++ " " ++ feedbackFinished, True)
feedbackDetour True _ _ = (feedbackMultipleSteps ++ " " ++ feedbackFinished, True)
feedbackDetour _ _ [one] | one `inGroup`"Commutativity" =
("You have applied one of the commutativity rules correctly. This step is not mandatory, but sometimes helps to simplify the formula.", True)
feedbackDetour _ mexp [one] =
let however = case mexp >>= ruleText of
Just s -> "However, the standard strategy suggests to use " ++ s ++ "."
Nothing -> "However, the standard strategy suggests a different step."
in (appliedRule one ++ " This is correct. " ++ however, True)
feedbackDetour ready _ _ = (feedbackUnknown ready, False)
feedbackUnknown :: Bool -> String
feedbackUnknown ready = feedbackMultipleSteps ++ " " ++ backAndHint ready
feedbackMultipleSteps :: String
feedbackMultipleSteps = "You have combined multiple steps (or made a mistake)."
feedbackFinished :: String
feedbackFinished = "Are you aware that you already reached disjunctive normal form?"
appliedRule :: Rule a -> String
appliedRule r = "You have applied " ++ txt ++ " correctly."
where txt = fromMaybe "some rule" (ruleText r)
ruleText :: Rule a -> Maybe String
ruleText r
| r ~= ruleFalseZeroOr || r ~= ruleTrueZeroOr || r ~= ruleFalseZeroAnd || r ~= ruleTrueZeroAnd || r ~= ruleNotTrue || r ~= ruleNotFalse =
return "one of the False/True rules"
| r ~= ruleComplOr || r ~= ruleComplAnd = return "a complement rule"
| r ~= ruleNotNot = return "double negation"
| r ~= ruleDefImpl = return "implication elimination"
| r ~= ruleDefEquiv = return "equivalence elimination"
| r `inGroup`"Commutativity" = return "commutativity"
| r `inGroup`"Aasociativity" = return "associativity"
| r `inGroup`"DistributionOrOverAnd" = return "distribution of or over and"
| r `inGroup`"DistributionAndOverOr" = return "distribution of and over or"
| r `inGroup`"Idempotency" = return "idempotency"
| r `inGroup`"Absorption" = return "absorption"
| r `inGroup`"De Morgan" = return "De Morgan"
| r `inGroup`"InverseDeMorgan" = return "De Morgan"
| r `inGroup`"InverseDistr" = return "distributivity"
-- TODO Josje: aanvullen met alle regels (ook die ook in de DWA strategie voorkomen)
| otherwise = Nothing
-------------------------------------------------------------------------
-- General text
incorrect :: Bool -> String -> String
incorrect ready s = "This is incorrect. " ++ s ++ backAndHint ready
okay :: String -> String
okay s = "Well done! " ++ s
backAndHint :: Bool -> String
backAndHint ready = "Press the Back button and try again." ++
if ready then "" else " You may ask for a hint."
-------------------------------------------------------------------------
-- Helper functions
(~=) :: Rule a -> Rule b -> Bool
r1 ~= r2 = name r1 == name r2
-- Quick and dirty fix!
inGroup :: Rule a -> String -> Bool
inGroup r n =
let rs = filter (~= r) (logicRules ++ buggyRules)
in n `elem` concatMap ruleGroups rs
showToken :: Token -> String
showToken token = tokenText token ++ " at position " ++ tokenPos token
tokenPos :: Token -> String
tokenPos token =
let p@(l, c) = toPosition token
in if l==1 then show c else show p