{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE QuasiQuotes #-}
module Modelling.ActivityDiagram.EnterAS (
EnterASInstance(..),
EnterASConfig(..),
EnterASSolution(..),
defaultEnterASConfig,
checkEnterASConfig,
enterASAlloy,
checkEnterASInstance,
enterActionSequence,
enterASTask,
enterASInitial,
enterASSyntax,
enterASEvaluation,
enterASSolution,
enterAS,
defaultEnterASInstance
) where
import Capabilities.Alloy (MonadAlloy, getInstances)
import Capabilities.PlantUml (MonadPlantUml)
import Capabilities.WriteFile (MonadWriteFile)
import Modelling.ActivityDiagram.ActionSequences (generateActionSequence, validActionSequence)
import Modelling.ActivityDiagram.Auxiliary.ActionSequences (actionSequencesAlloy)
import Modelling.ActivityDiagram.Config (
AdConfig (..),
checkAdConfig,
defaultAdConfig,
)
import Modelling.ActivityDiagram.Datatype (
AdConnection (..),
AdNode (..),
UMLActivityDiagram (..),
isActionNode,
isObjectNode,
)
import Modelling.ActivityDiagram.Instance (parseInstance)
import Modelling.ActivityDiagram.PlantUMLConverter (
PlantUmlConfig (..),
defaultPlantUmlConfig,
drawAdToFile,
)
import Modelling.ActivityDiagram.Shuffle (shuffleAdNames)
import Modelling.Auxiliary.Common (getFirstInstance)
import Control.Applicative (Alternative ((<|>)))
import Control.Monad (unless)
import Control.Monad.Catch (MonadThrow)
import Control.OutputCapable.Blocks (
ArticleToUse (IndefiniteArticle),
GenericOutputCapable (..),
LangM,
Language,
Rated,
OutputCapable,
($=<<),
english,
german,
translate,
printSolutionAndAssert,
yesNo,
)
import Control.Monad.Random (
RandT,
RandomGen,
evalRandT,
mkStdGen,
)
import Data.List (intercalate, intersect)
import Data.List.Extra (nubOrd)
import Data.Map (Map)
import Data.Maybe (isNothing)
import Data.String.Interpolate (i, iii)
import GHC.Generics (Generic)
import Modelling.Auxiliary.Output (
addPretext,
extra
)
import System.Random.Shuffle (shuffleM)
data EnterASInstance = EnterASInstance {
EnterASInstance -> UMLActivityDiagram
activityDiagram :: UMLActivityDiagram,
EnterASInstance -> PlantUmlConfig
drawSettings :: PlantUmlConfig,
EnterASInstance -> [String]
sampleSequence :: [String],
EnterASInstance -> Bool
showSolution :: Bool,
EnterASInstance -> Maybe (Map Language String)
addText :: Maybe (Map Language String)
} deriving (EnterASInstance -> EnterASInstance -> Bool
(EnterASInstance -> EnterASInstance -> Bool)
-> (EnterASInstance -> EnterASInstance -> Bool)
-> Eq EnterASInstance
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: EnterASInstance -> EnterASInstance -> Bool
== :: EnterASInstance -> EnterASInstance -> Bool
$c/= :: EnterASInstance -> EnterASInstance -> Bool
/= :: EnterASInstance -> EnterASInstance -> Bool
Eq, (forall x. EnterASInstance -> Rep EnterASInstance x)
-> (forall x. Rep EnterASInstance x -> EnterASInstance)
-> Generic EnterASInstance
forall x. Rep EnterASInstance x -> EnterASInstance
forall x. EnterASInstance -> Rep EnterASInstance x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. EnterASInstance -> Rep EnterASInstance x
from :: forall x. EnterASInstance -> Rep EnterASInstance x
$cto :: forall x. Rep EnterASInstance x -> EnterASInstance
to :: forall x. Rep EnterASInstance x -> EnterASInstance
Generic, ReadPrec [EnterASInstance]
ReadPrec EnterASInstance
Int -> ReadS EnterASInstance
ReadS [EnterASInstance]
(Int -> ReadS EnterASInstance)
-> ReadS [EnterASInstance]
-> ReadPrec EnterASInstance
-> ReadPrec [EnterASInstance]
-> Read EnterASInstance
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS EnterASInstance
readsPrec :: Int -> ReadS EnterASInstance
$creadList :: ReadS [EnterASInstance]
readList :: ReadS [EnterASInstance]
$creadPrec :: ReadPrec EnterASInstance
readPrec :: ReadPrec EnterASInstance
$creadListPrec :: ReadPrec [EnterASInstance]
readListPrec :: ReadPrec [EnterASInstance]
Read, Int -> EnterASInstance -> ShowS
[EnterASInstance] -> ShowS
EnterASInstance -> String
(Int -> EnterASInstance -> ShowS)
-> (EnterASInstance -> String)
-> ([EnterASInstance] -> ShowS)
-> Show EnterASInstance
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> EnterASInstance -> ShowS
showsPrec :: Int -> EnterASInstance -> ShowS
$cshow :: EnterASInstance -> String
show :: EnterASInstance -> String
$cshowList :: [EnterASInstance] -> ShowS
showList :: [EnterASInstance] -> ShowS
Show)
data EnterASConfig = EnterASConfig {
EnterASConfig -> AdConfig
adConfig :: AdConfig,
EnterASConfig -> Bool
hideBranchConditions :: Bool,
EnterASConfig -> Maybe Integer
maxInstances :: Maybe Integer,
EnterASConfig -> Maybe Bool
objectNodeOnEveryPath :: Maybe Bool,
EnterASConfig -> (Int, Int)
answerLength :: !(Int, Int),
EnterASConfig -> Bool
printSolution :: Bool,
:: Maybe (Map Language String)
} deriving ((forall x. EnterASConfig -> Rep EnterASConfig x)
-> (forall x. Rep EnterASConfig x -> EnterASConfig)
-> Generic EnterASConfig
forall x. Rep EnterASConfig x -> EnterASConfig
forall x. EnterASConfig -> Rep EnterASConfig x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. EnterASConfig -> Rep EnterASConfig x
from :: forall x. EnterASConfig -> Rep EnterASConfig x
$cto :: forall x. Rep EnterASConfig x -> EnterASConfig
to :: forall x. Rep EnterASConfig x -> EnterASConfig
Generic, ReadPrec [EnterASConfig]
ReadPrec EnterASConfig
Int -> ReadS EnterASConfig
ReadS [EnterASConfig]
(Int -> ReadS EnterASConfig)
-> ReadS [EnterASConfig]
-> ReadPrec EnterASConfig
-> ReadPrec [EnterASConfig]
-> Read EnterASConfig
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS EnterASConfig
readsPrec :: Int -> ReadS EnterASConfig
$creadList :: ReadS [EnterASConfig]
readList :: ReadS [EnterASConfig]
$creadPrec :: ReadPrec EnterASConfig
readPrec :: ReadPrec EnterASConfig
$creadListPrec :: ReadPrec [EnterASConfig]
readListPrec :: ReadPrec [EnterASConfig]
Read, Int -> EnterASConfig -> ShowS
[EnterASConfig] -> ShowS
EnterASConfig -> String
(Int -> EnterASConfig -> ShowS)
-> (EnterASConfig -> String)
-> ([EnterASConfig] -> ShowS)
-> Show EnterASConfig
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> EnterASConfig -> ShowS
showsPrec :: Int -> EnterASConfig -> ShowS
$cshow :: EnterASConfig -> String
show :: EnterASConfig -> String
$cshowList :: [EnterASConfig] -> ShowS
showList :: [EnterASConfig] -> ShowS
Show)
defaultEnterASConfig :: EnterASConfig
defaultEnterASConfig :: EnterASConfig
defaultEnterASConfig = EnterASConfig {
adConfig :: AdConfig
adConfig = AdConfig
defaultAdConfig {
actionLimits :: (Int, Int)
actionLimits = (Int
6, Int
8),
objectNodeLimits :: (Int, Int)
objectNodeLimits = (Int
1, Int
5),
maxNamedNodes :: Int
maxNamedNodes = Int
7,
activityFinalNodes :: Int
activityFinalNodes = Int
0,
flowFinalNodes :: Int
flowFinalNodes = Int
2
},
hideBranchConditions :: Bool
hideBranchConditions = Bool
True,
maxInstances :: Maybe Integer
maxInstances = Integer -> Maybe Integer
forall a. a -> Maybe a
Just Integer
50,
objectNodeOnEveryPath :: Maybe Bool
objectNodeOnEveryPath = Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True,
answerLength :: (Int, Int)
answerLength = (Int
5, Int
8),
printSolution :: Bool
printSolution = Bool
False,
extraText :: Maybe (Map Language String)
extraText = Maybe (Map Language String)
forall a. Maybe a
Nothing
}
checkEnterASConfig :: EnterASConfig -> Maybe String
checkEnterASConfig :: EnterASConfig -> Maybe String
checkEnterASConfig EnterASConfig
conf =
AdConfig -> Maybe String
checkAdConfig (EnterASConfig -> AdConfig
adConfig EnterASConfig
conf)
Maybe String -> Maybe String -> Maybe String
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> EnterASConfig -> Maybe String
checkEnterASConfig' EnterASConfig
conf
checkEnterASConfig' :: EnterASConfig -> Maybe String
checkEnterASConfig' :: EnterASConfig -> Maybe String
checkEnterASConfig' EnterASConfig {
AdConfig
adConfig :: EnterASConfig -> AdConfig
adConfig :: AdConfig
adConfig,
Maybe Integer
maxInstances :: EnterASConfig -> Maybe Integer
maxInstances :: Maybe Integer
maxInstances,
Maybe Bool
objectNodeOnEveryPath :: EnterASConfig -> Maybe Bool
objectNodeOnEveryPath :: Maybe Bool
objectNodeOnEveryPath,
(Int, Int)
answerLength :: EnterASConfig -> (Int, Int)
answerLength :: (Int, Int)
answerLength
}
| Just Integer
instances <- Maybe Integer
maxInstances, Integer
instances Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
1
= String -> Maybe String
forall a. a -> Maybe a
Just String
"The parameter 'maxInstances' must either be set to a positive value or to Nothing"
| Maybe Bool
objectNodeOnEveryPath Maybe Bool -> Maybe Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True Bool -> Bool -> Bool
&& (Int, Int) -> Int
forall a b. (a, b) -> a
fst (AdConfig -> (Int, Int)
objectNodeLimits AdConfig
adConfig) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
1
= String -> Maybe String
forall a. a -> Maybe a
Just String
"Setting the parameter 'objectNodeOnEveryPath' to True implies at least 1 Object Node occurring"
| (Int, Int) -> Int
forall a b. (a, b) -> a
fst (Int, Int)
answerLength Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0
= String -> Maybe String
forall a. a -> Maybe a
Just String
"The parameter 'answerLength' should not contain non-negative values"
| (Int -> Int -> Bool) -> (Int, Int) -> Bool
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
(>) (Int, Int)
answerLength
= String -> Maybe String
forall a. a -> Maybe a
Just [iii|
The second value of parameter 'answerLength'
should be greater than or equal to its first value.
|]
| Bool
otherwise
= Maybe String
forall a. Maybe a
Nothing
enterASAlloy :: EnterASConfig -> String
enterASAlloy :: EnterASConfig -> String
enterASAlloy EnterASConfig {
AdConfig
adConfig :: EnterASConfig -> AdConfig
adConfig :: AdConfig
adConfig,
Maybe Bool
objectNodeOnEveryPath :: EnterASConfig -> Maybe Bool
objectNodeOnEveryPath :: Maybe Bool
objectNodeOnEveryPath
} = AdConfig -> Maybe Bool -> String
actionSequencesAlloy AdConfig
adConfig Maybe Bool
objectNodeOnEveryPath
checkEnterASInstance :: EnterASInstance -> Maybe String
checkEnterASInstance :: EnterASInstance -> Maybe String
checkEnterASInstance EnterASInstance
inst
| PlantUmlConfig -> Bool
suppressNodeNames (EnterASInstance -> PlantUmlConfig
drawSettings EnterASInstance
inst)
= String -> Maybe String
forall a. a -> Maybe a
Just String
"'suppressNodeNames' must be set to 'False' for this task type"
| Bool
otherwise
= Maybe String
forall a. Maybe a
Nothing
checkEnterASInstanceForConfig :: EnterASInstance -> EnterASConfig -> Maybe String
checkEnterASInstanceForConfig :: EnterASInstance -> EnterASConfig -> Maybe String
checkEnterASInstanceForConfig EnterASInstance
inst EnterASConfig {
(Int, Int)
answerLength :: EnterASConfig -> (Int, Int)
answerLength :: (Int, Int)
answerLength
}
| [String] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
solution Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< (Int, Int) -> Int
forall a b. (a, b) -> a
fst (Int, Int)
answerLength
= String -> Maybe String
forall a. a -> Maybe a
Just [iii|
Solution should not be shorter than
the first value of parameter 'answerLength'.
|]
| [String] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
solution Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> (Int, Int) -> Int
forall a b. (a, b) -> b
snd (Int, Int)
answerLength
= String -> Maybe String
forall a. a -> Maybe a
Just [iii|
Solution should not be longer than
the second value of parameter 'answerLength'.
|]
| Bool
otherwise
= Maybe String
forall a. Maybe a
Nothing
where solution :: [String]
solution = EnterASInstance -> [String]
sampleSequence EnterASInstance
inst
newtype EnterASSolution = EnterASSolution {
EnterASSolution -> [String]
sampleSolution :: [String]
} deriving (Int -> EnterASSolution -> ShowS
[EnterASSolution] -> ShowS
EnterASSolution -> String
(Int -> EnterASSolution -> ShowS)
-> (EnterASSolution -> String)
-> ([EnterASSolution] -> ShowS)
-> Show EnterASSolution
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> EnterASSolution -> ShowS
showsPrec :: Int -> EnterASSolution -> ShowS
$cshow :: EnterASSolution -> String
show :: EnterASSolution -> String
$cshowList :: [EnterASSolution] -> ShowS
showList :: [EnterASSolution] -> ShowS
Show, EnterASSolution -> EnterASSolution -> Bool
(EnterASSolution -> EnterASSolution -> Bool)
-> (EnterASSolution -> EnterASSolution -> Bool)
-> Eq EnterASSolution
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: EnterASSolution -> EnterASSolution -> Bool
== :: EnterASSolution -> EnterASSolution -> Bool
$c/= :: EnterASSolution -> EnterASSolution -> Bool
/= :: EnterASSolution -> EnterASSolution -> Bool
Eq)
enterActionSequence :: UMLActivityDiagram -> EnterASSolution
enterActionSequence :: UMLActivityDiagram -> EnterASSolution
enterActionSequence UMLActivityDiagram
ad =
EnterASSolution {sampleSolution :: [String]
sampleSolution=UMLActivityDiagram -> [String]
generateActionSequence UMLActivityDiagram
ad}
enterASTask
:: (MonadPlantUml m, MonadWriteFile m, OutputCapable m)
=> FilePath
-> EnterASInstance
-> LangM m
enterASTask :: forall (m :: * -> *).
(MonadPlantUml m, MonadWriteFile m, OutputCapable m) =>
String -> EnterASInstance -> LangM m
enterASTask String
path EnterASInstance
task = do
LangM m -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
GenericLangM l m () -> GenericLangM l m ()
paragraph (LangM m -> LangM m) -> LangM m -> LangM m
forall a b. (a -> b) -> a -> b
$ State (Map Language String) () -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
State (Map l String) () -> GenericLangM l m ()
translate (State (Map Language String) () -> LangM m)
-> State (Map Language String) () -> LangM m
forall a b. (a -> b) -> a -> b
$ do
String -> State (Map Language String) ()
english String
"Consider the following activity diagram:"
String -> State (Map Language String) ()
german String
"Betrachten Sie folgendes Aktivitätsdiagramm:"
String -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
String -> GenericLangM l m ()
image (String -> LangM m) -> m String -> LangM m
forall (m :: * -> *) a l b.
Monad m =>
(a -> GenericLangM l m b) -> m a -> GenericLangM l m b
$=<< String -> PlantUmlConfig -> UMLActivityDiagram -> m String
forall (m :: * -> *).
(MonadPlantUml m, MonadWriteFile m) =>
String -> PlantUmlConfig -> UMLActivityDiagram -> m String
drawAdToFile String
path (EnterASInstance -> PlantUmlConfig
drawSettings EnterASInstance
task) (UMLActivityDiagram -> m String) -> UMLActivityDiagram -> m String
forall a b. (a -> b) -> a -> b
$ EnterASInstance -> UMLActivityDiagram
activityDiagram EnterASInstance
task
LangM m -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
GenericLangM l m () -> GenericLangM l m ()
paragraph (LangM m -> LangM m) -> LangM m -> LangM m
forall a b. (a -> b) -> a -> b
$ do
State (Map Language String) () -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
State (Map l String) () -> GenericLangM l m ()
translate (State (Map Language String) () -> LangM m)
-> State (Map Language String) () -> LangM m
forall a b. (a -> b) -> a -> b
$ do
String -> State (Map Language String) ()
english [iii|
State an action sequence (i.e., a sequence of action nodes)
which lets all flows terminate in an execution of this diagram,
by entering a list of action names.
\n
For example, |]
String -> State (Map Language String) ()
german [iii|
Geben Sie eine Aktionsfolge (d.h., eine Folge von Aktionsknoten) an,
welche in einem Ablauf dieses Diagramms alle Flüsse terminieren lässt,
indem Sie eine Liste von Aktionsnamen angeben.
\n
Zum Beispiel drückt |]
String -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
String -> GenericLangM l m ()
code (String -> LangM m) -> String -> LangM m
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall a. Show a => a -> String
show [String]
enterASInitial
State (Map Language String) () -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
State (Map l String) () -> GenericLangM l m ()
translate (State (Map Language String) () -> LangM m)
-> State (Map Language String) () -> LangM m
forall a b. (a -> b) -> a -> b
$ do
String -> State (Map Language String) ()
english [i|expresses the execution of A followed by B (under the assumption that both are action nodes of the diagram).|]
String -> State (Map Language String) ()
german [i|die Ausführung von A gefolgt von B aus (unter der Annahme, dass beides Aktionsknoten des Diagramms sind).|]
pure ()
Maybe (Map Language String) -> LangM m
forall (m :: * -> *).
OutputCapable m =>
Maybe (Map Language String) -> LangM m
extra (Maybe (Map Language String) -> LangM m)
-> Maybe (Map Language String) -> LangM m
forall a b. (a -> b) -> a -> b
$ EnterASInstance -> Maybe (Map Language String)
addText EnterASInstance
task
pure ()
enterASInitial :: [String]
enterASInitial :: [String]
enterASInitial = [String
"A", String
"B"]
enterASSyntax
:: OutputCapable m
=> EnterASInstance
-> [String]
-> LangM m
enterASSyntax :: forall (m :: * -> *).
OutputCapable m =>
EnterASInstance -> [String] -> LangM m
enterASSyntax EnterASInstance
task [String]
sub = LangM' m () -> LangM' m ()
forall (m :: * -> *) a. OutputCapable m => LangM' m a -> LangM' m a
addPretext (LangM' m () -> LangM' m ()) -> LangM' m () -> LangM' m ()
forall a b. (a -> b) -> a -> b
$ do
let adNames :: [String]
adNames = (AdNode -> String) -> [AdNode] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map AdNode -> String
name
([AdNode] -> [String]) -> [AdNode] -> [String]
forall a b. (a -> b) -> a -> b
$ (AdNode -> Bool) -> [AdNode] -> [AdNode]
forall a. (a -> Bool) -> [a] -> [a]
filter (\AdNode
n -> AdNode -> Bool
isActionNode AdNode
n Bool -> Bool -> Bool
|| AdNode -> Bool
isObjectNode AdNode
n)
([AdNode] -> [AdNode]) -> [AdNode] -> [AdNode]
forall a b. (a -> b) -> a -> b
$ UMLActivityDiagram -> [AdNode]
nodes
(UMLActivityDiagram -> [AdNode]) -> UMLActivityDiagram -> [AdNode]
forall a b. (a -> b) -> a -> b
$ EnterASInstance -> UMLActivityDiagram
activityDiagram EnterASInstance
task
Bool -> LangM' m () -> LangM' m ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
Bool -> GenericLangM l m () -> GenericLangM l m ()
assertion ((String -> Bool) -> [String] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
adNames) [String]
sub) (LangM' m () -> LangM' m ()) -> LangM' m () -> LangM' m ()
forall a b. (a -> b) -> a -> b
$ State (Map Language String) () -> LangM' m ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
State (Map l String) () -> GenericLangM l m ()
translate (State (Map Language String) () -> LangM' m ())
-> State (Map Language String) () -> LangM' m ()
forall a b. (a -> b) -> a -> b
$ do
String -> State (Map Language String) ()
english String
"Referenced node names are part of the given activity diagram?"
String -> State (Map Language String) ()
german String
"Referenzierte Knotennamen sind Bestandteil des gegebenen Aktivitätsdiagramms?"
enterASEvaluation
:: OutputCapable m
=> EnterASInstance
-> [String]
-> Rated m
enterASEvaluation :: forall (m :: * -> *).
OutputCapable m =>
EnterASInstance -> [String] -> Rated m
enterASEvaluation EnterASInstance
task [String]
sub = do
let correct :: Bool
correct = [String] -> UMLActivityDiagram -> Bool
validActionSequence [String]
sub (UMLActivityDiagram -> Bool) -> UMLActivityDiagram -> Bool
forall a b. (a -> b) -> a -> b
$ EnterASInstance -> UMLActivityDiagram
activityDiagram EnterASInstance
task
points :: Rational
points = if Bool
correct then Rational
1 else Rational
0
maybeSolutionString :: Maybe String
maybeSolutionString =
if EnterASInstance -> Bool
showSolution EnterASInstance
task
then String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall a. Show a => a -> String
show ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ EnterASInstance -> [String]
sampleSequence EnterASInstance
task
else Maybe String
forall a. Maybe a
Nothing
Bool -> LangM m -> LangM m
forall (m :: * -> *). OutputCapable m => Bool -> LangM m -> LangM m
yesNo Bool
correct (LangM m -> LangM m) -> LangM m -> LangM m
forall a b. (a -> b) -> a -> b
$ State (Map Language String) () -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
State (Map l String) () -> GenericLangM l m ()
translate (State (Map Language String) () -> LangM m)
-> State (Map Language String) () -> LangM m
forall a b. (a -> b) -> a -> b
$ do
String -> State (Map Language String) ()
english String
"The submitted action sequence is correct?"
String -> State (Map Language String) ()
german String
"Die eingereichte Aktionsfolge ist korrekt?"
let objectNames :: [String]
objectNames = (AdNode -> String) -> [AdNode] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map AdNode -> String
name ([AdNode] -> [String]) -> [AdNode] -> [String]
forall a b. (a -> b) -> a -> b
$ (AdNode -> Bool) -> [AdNode] -> [AdNode]
forall a. (a -> Bool) -> [a] -> [a]
filter AdNode -> Bool
isObjectNode ([AdNode] -> [AdNode]) -> [AdNode] -> [AdNode]
forall a b. (a -> b) -> a -> b
$ UMLActivityDiagram -> [AdNode]
nodes (UMLActivityDiagram -> [AdNode]) -> UMLActivityDiagram -> [AdNode]
forall a b. (a -> b) -> a -> b
$ EnterASInstance -> UMLActivityDiagram
activityDiagram EnterASInstance
task
objectNamesInSubmission :: [String]
objectNamesInSubmission = [String] -> [String]
forall a. Ord a => [a] -> [a]
nubOrd ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ [String]
sub [String] -> [String] -> [String]
forall a. Eq a => [a] -> [a] -> [a]
`intersect` [String]
objectNames
Bool -> LangM m -> LangM m
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([String] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
objectNamesInSubmission) (LangM m -> LangM m) -> LangM m -> LangM m
forall a b. (a -> b) -> a -> b
$ do
State (Map Language String) () -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
State (Map l String) () -> GenericLangM l m ()
translate (State (Map Language String) () -> LangM m)
-> State (Map Language String) () -> LangM m
forall a b. (a -> b) -> a -> b
$ do
String -> State (Map Language String) ()
english String
"The following referenced nodes are object nodes and thus not actions:"
String -> State (Map Language String) ()
german String
"Die folgenden referenzierten Knoten sind Objektknoten und damit keine Aktionen:"
String -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
String -> GenericLangM l m ()
code (String -> LangM m) -> String -> LangM m
forall a b. (a -> b) -> a -> b
$ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " [String]
objectNamesInSubmission
pure ()
ArticleToUse -> Maybe String -> Rational -> Rated m
forall (m :: * -> *).
OutputCapable m =>
ArticleToUse -> Maybe String -> Rational -> Rated m
printSolutionAndAssert ArticleToUse
IndefiniteArticle Maybe String
maybeSolutionString Rational
points
pure Rational
points
enterASSolution
:: EnterASInstance
-> [String]
enterASSolution :: EnterASInstance -> [String]
enterASSolution = EnterASInstance -> [String]
sampleSequence
enterAS
:: (MonadAlloy m, MonadThrow m)
=> EnterASConfig
-> Int
-> Int
-> m EnterASInstance
enterAS :: forall (m :: * -> *).
(MonadAlloy m, MonadThrow m) =>
EnterASConfig -> Int -> Int -> m EnterASInstance
enterAS EnterASConfig
config Int
segment Int
seed = do
let g :: StdGen
g = Int -> StdGen
mkStdGen (Int -> StdGen) -> Int -> StdGen
forall a b. (a -> b) -> a -> b
$ (Int
segment Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
seed
RandT StdGen m EnterASInstance -> StdGen -> m EnterASInstance
forall (m :: * -> *) g a. Monad m => RandT g m a -> g -> m a
evalRandT (EnterASConfig -> RandT StdGen m EnterASInstance
forall (m :: * -> *) g.
(MonadAlloy m, MonadThrow m, RandomGen g) =>
EnterASConfig -> RandT g m EnterASInstance
getEnterASTask EnterASConfig
config) StdGen
g
getEnterASTask
:: (MonadAlloy m, MonadThrow m, RandomGen g)
=> EnterASConfig
-> RandT g m EnterASInstance
getEnterASTask :: forall (m :: * -> *) g.
(MonadAlloy m, MonadThrow m, RandomGen g) =>
EnterASConfig -> RandT g m EnterASInstance
getEnterASTask EnterASConfig
config = do
[AlloyInstance]
alloyInstances <- Maybe Integer -> Maybe Int -> String -> RandT g m [AlloyInstance]
forall (m :: * -> *).
MonadAlloy m =>
Maybe Integer -> Maybe Int -> String -> m [AlloyInstance]
getInstances
(EnterASConfig -> Maybe Integer
maxInstances EnterASConfig
config)
Maybe Int
forall a. Maybe a
Nothing
(String -> RandT g m [AlloyInstance])
-> String -> RandT g m [AlloyInstance]
forall a b. (a -> b) -> a -> b
$ EnterASConfig -> String
enterASAlloy EnterASConfig
config
[UMLActivityDiagram]
randomInstances <- [AlloyInstance] -> RandT g m [AlloyInstance]
forall (m :: * -> *) a. MonadRandom m => [a] -> m [a]
shuffleM [AlloyInstance]
alloyInstances RandT g m [AlloyInstance]
-> ([AlloyInstance] -> RandT g m [UMLActivityDiagram])
-> RandT g m [UMLActivityDiagram]
forall a b. RandT g m a -> (a -> RandT g m b) -> RandT g m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (AlloyInstance -> RandT g m UMLActivityDiagram)
-> [AlloyInstance] -> RandT g m [UMLActivityDiagram]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM AlloyInstance -> RandT g m UMLActivityDiagram
forall (m :: * -> *).
MonadThrow m =>
AlloyInstance -> m UMLActivityDiagram
parseInstance
[UMLActivityDiagram]
ad <- (UMLActivityDiagram -> RandT g m UMLActivityDiagram)
-> [UMLActivityDiagram] -> RandT g m [UMLActivityDiagram]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (((Map String String, UMLActivityDiagram) -> UMLActivityDiagram)
-> RandT g m (Map String String, UMLActivityDiagram)
-> RandT g m UMLActivityDiagram
forall a b. (a -> b) -> RandT g m a -> RandT g m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Map String String, UMLActivityDiagram) -> UMLActivityDiagram
forall a b. (a, b) -> b
snd (RandT g m (Map String String, UMLActivityDiagram)
-> RandT g m UMLActivityDiagram)
-> (UMLActivityDiagram
-> RandT g m (Map String String, UMLActivityDiagram))
-> UMLActivityDiagram
-> RandT g m UMLActivityDiagram
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UMLActivityDiagram
-> RandT g m (Map String String, UMLActivityDiagram)
forall (m :: * -> *).
MonadRandom m =>
UMLActivityDiagram -> m (Map String String, UMLActivityDiagram)
shuffleAdNames) [UMLActivityDiagram]
randomInstances
[EnterASInstance] -> RandT g m EnterASInstance
forall (m :: * -> *) a. MonadThrow m => [a] -> m a
getFirstInstance
([EnterASInstance] -> RandT g m EnterASInstance)
-> [EnterASInstance] -> RandT g m EnterASInstance
forall a b. (a -> b) -> a -> b
$ (EnterASInstance -> Bool) -> [EnterASInstance] -> [EnterASInstance]
forall a. (a -> Bool) -> [a] -> [a]
filter (Maybe String -> Bool
forall a. Maybe a -> Bool
isNothing (Maybe String -> Bool)
-> (EnterASInstance -> Maybe String) -> EnterASInstance -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (EnterASInstance -> EnterASConfig -> Maybe String
`checkEnterASInstanceForConfig` EnterASConfig
config))
([EnterASInstance] -> [EnterASInstance])
-> [EnterASInstance] -> [EnterASInstance]
forall a b. (a -> b) -> a -> b
$ (UMLActivityDiagram -> EnterASInstance)
-> [UMLActivityDiagram] -> [EnterASInstance]
forall a b. (a -> b) -> [a] -> [b]
map (\UMLActivityDiagram
x -> EnterASInstance {
activityDiagram :: UMLActivityDiagram
activityDiagram=UMLActivityDiagram
x,
drawSettings :: PlantUmlConfig
drawSettings = PlantUmlConfig
defaultPlantUmlConfig {
suppressBranchConditions :: Bool
suppressBranchConditions = EnterASConfig -> Bool
hideBranchConditions EnterASConfig
config
},
sampleSequence :: [String]
sampleSequence = EnterASSolution -> [String]
sampleSolution (EnterASSolution -> [String]) -> EnterASSolution -> [String]
forall a b. (a -> b) -> a -> b
$ UMLActivityDiagram -> EnterASSolution
enterActionSequence UMLActivityDiagram
x,
showSolution :: Bool
showSolution = EnterASConfig -> Bool
printSolution EnterASConfig
config,
addText :: Maybe (Map Language String)
addText = EnterASConfig -> Maybe (Map Language String)
extraText EnterASConfig
config
}) [UMLActivityDiagram]
ad
defaultEnterASInstance :: EnterASInstance
defaultEnterASInstance :: EnterASInstance
defaultEnterASInstance = EnterASInstance {
activityDiagram :: UMLActivityDiagram
activityDiagram = UMLActivityDiagram {
nodes :: [AdNode]
nodes = [
AdActionNode {label :: Int
label = Int
1, name :: String
name = String
"A"},
AdActionNode {label :: Int
label = Int
2, name :: String
name = String
"E"},
AdActionNode {label :: Int
label = Int
3, name :: String
name = String
"F"},
AdActionNode {label :: Int
label = Int
4, name :: String
name = String
"G"},
AdActionNode {label :: Int
label = Int
5, name :: String
name = String
"D"},
AdActionNode {label :: Int
label = Int
6, name :: String
name = String
"B"},
AdObjectNode {label :: Int
label = Int
7, name :: String
name = String
"C"},
AdDecisionNode {label :: Int
label = Int
8},
AdDecisionNode {label :: Int
label = Int
9},
AdMergeNode {label :: Int
label = Int
10},
AdMergeNode {label :: Int
label = Int
11},
AdForkNode {label :: Int
label = Int
12},
AdJoinNode {label :: Int
label = Int
13},
AdFlowFinalNode {label :: Int
label = Int
14},
AdFlowFinalNode {label :: Int
label = Int
15},
AdInitialNode {label :: Int
label = Int
16}
],
connections :: [AdConnection]
connections = [
AdConnection {from :: Int
from = Int
1, to :: Int
to = Int
10, guard :: String
guard = String
""},
AdConnection {from :: Int
from = Int
2, to :: Int
to = Int
13, guard :: String
guard = String
""},
AdConnection {from :: Int
from = Int
3, to :: Int
to = Int
10, guard :: String
guard = String
""},
AdConnection {from :: Int
from = Int
4, to :: Int
to = Int
8, guard :: String
guard = String
""},
AdConnection {from :: Int
from = Int
5, to :: Int
to = Int
12, guard :: String
guard = String
""},
AdConnection {from :: Int
from = Int
6, to :: Int
to = Int
9, guard :: String
guard = String
""},
AdConnection {from :: Int
from = Int
7, to :: Int
to = Int
5, guard :: String
guard = String
""},
AdConnection {from :: Int
from = Int
8, to :: Int
to = Int
11, guard :: String
guard = String
"a"},
AdConnection {from :: Int
from = Int
8, to :: Int
to = Int
13, guard :: String
guard = String
"b"},
AdConnection {from :: Int
from = Int
9, to :: Int
to = Int
1, guard :: String
guard = String
"a"},
AdConnection {from :: Int
from = Int
9, to :: Int
to = Int
3, guard :: String
guard = String
"b"},
AdConnection {from :: Int
from = Int
10, to :: Int
to = Int
15, guard :: String
guard = String
""},
AdConnection {from :: Int
from = Int
11, to :: Int
to = Int
4, guard :: String
guard = String
""},
AdConnection {from :: Int
from = Int
12, to :: Int
to = Int
2, guard :: String
guard = String
""},
AdConnection {from :: Int
from = Int
12, to :: Int
to = Int
6, guard :: String
guard = String
""},
AdConnection {from :: Int
from = Int
12, to :: Int
to = Int
11, guard :: String
guard = String
""},
AdConnection {from :: Int
from = Int
13, to :: Int
to = Int
14, guard :: String
guard = String
""},
AdConnection {from :: Int
from = Int
16, to :: Int
to = Int
7, guard :: String
guard = String
""}
]
},
drawSettings :: PlantUmlConfig
drawSettings = PlantUmlConfig
defaultPlantUmlConfig,
sampleSequence :: [String]
sampleSequence = [String
"D",String
"E",String
"G",String
"B",String
"F"],
showSolution :: Bool
showSolution = Bool
False,
addText :: Maybe (Map Language String)
addText = Maybe (Map Language String)
forall a. Maybe a
Nothing
}