-
Notifications
You must be signed in to change notification settings - Fork 1
Getting Started
Writing a Flex-Tasks configuration from scratch can feel daunting. It’s usually easier to start by editing an existing file: either the template shown on this page or a working configuration already used in Autotool.
The following task template is a minimal functioning configuration you can directly paste into Autotool. The task itself is intentionally simple and a bit nonsensical, but it serves as a basic example of how to write a configuration. The full version of this template includes inline commentary, which has been removed here for brevity. You can have a look at the full version (also the default in Autotool), if you're interested.
Toggle task template view
taskName: DefaultConfig
=============================================
module Global where
type Submission = (Int,Int)
type DescData = (Int,Int,Int)
type TaskData = (DescData,Submission)
=============================================
module TaskSettings where
import Control.OutputCapable.Blocks (LangM, OutputCapable)
validateSettings :: OutputCapable m => LangM m
validateSettings = pure ()
=============================================
{-# language OverloadedStrings #-}
{-# language QuasiQuotes #-}
module TaskData (getTask) where
import FlexTask.GenUtil (fromGen)
import FlexTask.Generic.Form
import FlexTask.YesodConfig (Rendered, Widget)
import Control.Monad.Random (MonadRandom)
import Data.String.Interpolate (i)
import Test.QuickCheck.Gen
import Yesod (RenderMessage(..), fieldSettingsLabel)
import Global
data Label = Product | Sum
instance RenderMessage a Label where
renderMessage _ ("de":_) Product = "Produkt"
renderMessage _ ("de":_) Sum = "Summe"
renderMessage _ _ Product = "Product"
renderMessage _ _ Sum = "Sum"
getTask :: MonadRandom m => m (TaskData, String, Rendered Widget)
getTask = fromGen $ do
numbers@(n1,n2,n3) <- (,,) <$> intInRange <*> intInRange <*> intInRange
let checkData = (product [n1,n2,n3], sum [n1,n2,n3])
pure ((numbers, checkData), checkers, form)
where
intInRange = chooseInt (1,6)
fieldNames :: [[FieldInfo]]
fieldNames = [[fromLabel Product], [fromLabel Sum]]
where
fromLabel = single. fieldSettingsLabel
form :: Rendered Widget
form = formify (Nothing :: Maybe Submission) fieldNames
checkers :: String
checkers = [i|
{-\# language ApplicativeDo \#-}
module Check (checkSyntax, checkSemantics) where
import Control.OutputCapable.Blocks
import Global
checkSyntax :: OutputCapable m => FilePath -> TaskData -> Submission -> LangM m
checkSyntax _ _ _ = pure () -- nothing to check here
checkSemantics :: OutputCapable m => FilePath -> TaskData -> Submission -> Rated m
checkSemantics _ (_,sol) try
| try == sol = pure 1.0
| otherwise = do
refuse $ indent $ translate $ do
german "semantisch falsch"
english "semantically wrong"
pure 0.0
|]
=============================================
{-# language ApplicativeDo #-}
{-# language QuasiQuotes #-}
module Description (description) where
import Control.OutputCapable.Blocks
import Data.String.Interpolate (i)
import Global
description :: OutputCapable m => FilePath -> TaskData -> LangM m
description _ ((one,two,three),_) = do
paragraph $ translate $ do
german "Ich würfle drei Zahlen."
english "I throw a die three times."
paragraph $ translate $ do
german [i|Die erste ist #{one}, die zweite ist #{two}, die letzte ist #{three}.|]
english [i|On the first throw I roll #{one}, the second #{two} and on the third one #{three}.|]
indent $ paragraph $ translate $ do
german "Was sind Summe und Produkt dieser Zahlen?"
english "What are the sum and the product of these numbers?"
pure ()
=============================================
module Parse (parseSubmission) where
import Control.OutputCapable.Blocks (
LangM',
ReportT,
OutputCapable,
)
import FlexTask.Generic.Parse (formParser, parseWithOrReport, reportWithFieldNumber)
import Global
parseSubmission ::
(Monad m, OutputCapable (ReportT o m))
=> String
-> LangM' (ReportT o m) Submission
parseSubmission = parseWithOrReport formParser reportWithFieldNumber
There are a number of other Flex-Tasks configurations that are currently used for Autotool tasks. Feel free to use them as a basis for your own exercises. They can be found in the following locations:
- proplogic.flex (example for custom form; lengthy feedback)
- composeFormula.flex (example for slightly tweaked existing task)
- Task34.flex (Uses JavaScript to embed interactive elements)
- Task35.flex (Example for single-field list input)
- Task41.flex (very similar to the above)
← Previous: Basic Task Structure | Next: Configuring a Task in Autotool →
Author: patrick.ritzenfeld@uni-due.de