summaryrefslogtreecommitdiff
path: root/lambda-calcul/haskell/src/Minilang/App.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lambda-calcul/haskell/src/Minilang/App.hs')
-rw-r--r--lambda-calcul/haskell/src/Minilang/App.hs68
1 files changed, 34 insertions, 34 deletions
diff --git a/lambda-calcul/haskell/src/Minilang/App.hs b/lambda-calcul/haskell/src/Minilang/App.hs
index 0174547..4340708 100644
--- a/lambda-calcul/haskell/src/Minilang/App.hs
+++ b/lambda-calcul/haskell/src/Minilang/App.hs
@@ -20,19 +20,19 @@ import Data.Text.Encoding (decodeUtf8, encodeUtf8)
import Data.Time (getCurrentTime)
import Minilang.API (Challenge (..), LambdaAPI, Score (..), Token (..), User (..), newToken)
import Minilang.Lambda.Parser (pretty)
-import Minilang.REPL (withInputs, replEnvWith)
+import Minilang.REPL (replEnvWith, withInputs)
import Minilang.REPL.Purer (PurerEnv (..))
-import Minilang.REPL.Types (Command (..), Content (..), Evaluator (..), In (..), Out (..), initialREPL)
+import Minilang.REPL.Types (Command (..), Content (..), Evaluator (..), In (..), Out (..))
import Network.Wai.Application.Static (defaultFileServerSettings, staticApp)
-import Servant (ServerT, err400, err500, errBody, (:<|>) (..), err404)
+import Servant (ServerT, err400, err404, err500, errBody, (:<|>) (..))
import Servant.Server (Application, Handler (..), Tagged (..))
import System.Random (StdGen)
data Env = Env
- { gen :: TVar StdGen,
- users :: TVar (Map Token Score),
- challenges :: [Challenge],
- evaluator :: Evaluator
+ { gen :: TVar StdGen
+ , users :: TVar (Map Token Score)
+ , challenges :: [Challenge]
+ , evaluator :: Evaluator
}
makeEnv :: StdGen -> [Challenge] -> Evaluator -> IO Env
@@ -72,7 +72,7 @@ registerUser user@(User name) = do
pure token
unregisterUser :: (MonadReader Env m, MonadIO m) => Maybe Token -> m Score
-unregisterUser Nothing = liftIO $ throwM $ err400 {errBody = "Missing token"}
+unregisterUser Nothing = liftIO $ throwM $ err400{errBody = "Missing token"}
unregisterUser (Just token) = do
checkUserToken token
score <-
@@ -84,7 +84,7 @@ unregisterUser (Just token) = do
writeTVar tvar updatedMap
pure score
case score of
- Nothing -> liftIO $ throwM $ err400 {errBody = "User does not exist"}
+ Nothing -> liftIO $ throwM $ err400{errBody = "User does not exist"}
Just s -> pure s
checkDuplicateUser :: (MonadIO m, MonadReader Env m) => Text -> m ()
@@ -93,10 +93,10 @@ checkDuplicateUser name =
usersMap <- readTVar user
when (isUserRegistered name usersMap) $
throwM $
- err400 {errBody = "User already registered"}
+ err400{errBody = "User already registered"}
isUserRegistered :: Text -> Map Token Score -> Bool
-isUserRegistered name = Map.foldr (\Score {user = User {username}} acc -> username == name || acc) False
+isUserRegistered name = Map.foldr (\Score{user = User{username}} acc -> username == name || acc) False
generateToken :: (MonadReader Env m, MonadIO m) => m Token
generateToken =
@@ -116,11 +116,11 @@ getUser :: (MonadIO m, MonadReader Env m) => Maybe Token -> m Score
getUser mToken = do
usersMap <- asks users >>= liftIO . readTVarIO
case mToken >>= (`Map.lookup` usersMap) of
- Nothing -> liftIO $ throwM $ err404 {errBody = "User does not exist"}
+ Nothing -> liftIO $ throwM $ err404{errBody = "User does not exist"}
Just score -> pure score
getChallenge :: (MonadReader Env m, MonadIO m) => Maybe Token -> m Challenge
-getChallenge Nothing = liftIO $ throwM $ err400 {errBody = "Missing token"}
+getChallenge Nothing = liftIO $ throwM $ err400{errBody = "Missing token"}
getChallenge (Just token) = do
checkUserToken token
getCurrentChallenge token
@@ -129,7 +129,7 @@ checkUserToken :: (MonadReader Env m, MonadIO m) => Token -> m ()
checkUserToken token = do
usersMap <- asks users >>= liftIO . readTVarIO
case Map.lookup token usersMap of
- Nothing -> liftIO $ throwM $ err400 {errBody = "Token " <> LBS.fromStrict (encodeUtf8 (unToken token)) <> " does not exist"}
+ Nothing -> liftIO $ throwM $ err400{errBody = "Token " <> LBS.fromStrict (encodeUtf8 (unToken token)) <> " does not exist"}
Just _ -> pure ()
updateUserLastTest :: (MonadIO m, MonadReader Env m) => Token -> TestResult -> m ()
@@ -138,28 +138,28 @@ updateUserLastTest token result = do
asks users >>= \user -> liftIO $ atomically $ do
usersMap <- readTVar user
case Map.lookup token usersMap of
- Nothing -> throwM $ err400 {errBody = "Cannot update last test: Invalid token"}
+ Nothing -> throwM $ err400{errBody = "Cannot update last test: Invalid token"}
Just score -> do
- let updatedScore = score {lastTest = Just time, lastResult = Just (isSuccess result)}
+ let updatedScore = score{lastTest = Just time, lastResult = Just (isSuccess result)}
updatedMap = Map.insert token updatedScore usersMap
writeTVar user updatedMap
postAnswer :: (MonadReader Env m, MonadIO m) => Maybe Token -> Text -> m ()
-postAnswer Nothing _ = liftIO $ throwM $ err400 {errBody = "Missing token"}
-postAnswer (Just token) expected = do
+postAnswer Nothing _ = liftIO $ throwM $ err400{errBody = "Missing token"}
+postAnswer (Just token) answer = do
checkUserToken token
- Challenge {expr} <- getCurrentChallenge token
+ Challenge{level, expr} <- getCurrentChallenge token
ev <- asks evaluator
- let PurerEnv {outputs} = withInputs (replEnvWith ev) [Com (Load (Data expr))]
- result = evaluateOutputs outputs expected
+ let PurerEnv{outputs} = withInputs (replEnvWith ev) [Com (Load (Data expr))]
+ result = evaluateAnswer level outputs answer
updateUserLastTest token result
case result of
TestSucceeded ->
upgradeUserChallenge token
TestFailed msg ->
- liftIO $ throwM $ err400 {errBody = "Test failed: " <> LBS.fromStrict (encodeUtf8 msg)}
+ liftIO $ throwM $ err400{errBody = "Test failed: " <> LBS.fromStrict (encodeUtf8 msg)}
TestErrored msg ->
- liftIO $ throwM $ err500 {errBody = "Error evaluating answer: " <> LBS.fromStrict (encodeUtf8 msg)}
+ liftIO $ throwM $ err500{errBody = "Error evaluating answer: " <> LBS.fromStrict (encodeUtf8 msg)}
data TestResult = TestSucceeded | TestFailed Text | TestErrored Text
@@ -167,17 +167,17 @@ isSuccess :: TestResult -> Bool
isSuccess TestSucceeded = True
isSuccess _ = False
-evaluateOutputs :: [Out] -> Text -> TestResult
-evaluateOutputs outputs expected =
+evaluateAnswer :: Int -> [Out] -> Text -> TestResult
+evaluateAnswer grade outputs answer =
case outputs of
[Bye, Evaluated ast _ _] ->
- if pretty ast /= expected
- then TestFailed "Incorrect result"
+ if pretty ast /= answer
+ then TestFailed $ "Incorrect result for question " <> pack (show grade) <> " got " <> answer <> ", try again"
else TestSucceeded
[Bye] ->
- if expected == ""
+ if answer == ""
then TestSucceeded
- else TestFailed "Incorrect result"
+ else TestFailed $ "Incorrect result for question " <> pack (show grade) <> " got " <> answer <> ", try again"
[Bye, Msg msg] -> TestFailed msg
_ -> TestErrored $ pack $ show outputs
@@ -186,20 +186,20 @@ upgradeUserChallenge token = do
asks users >>= \user -> liftIO $ atomically $ do
usersMap <- readTVar user
case Map.lookup token usersMap of
- Nothing -> throwM $ err400 {errBody = "Cannot update last test: Invalid token"}
+ Nothing -> throwM $ err400{errBody = "Cannot update last test: Invalid token"}
Just score -> do
- let updatedScore = score {grade = succ (grade score)}
+ let updatedScore = score{grade = succ (grade score)}
updatedMap = Map.insert token updatedScore usersMap
writeTVar user updatedMap
getCurrentChallenge :: (MonadIO m, MonadReader Env m) => Token -> m Challenge
getCurrentChallenge token = do
- Env {users, challenges} <- ask
+ Env{users, challenges} <- ask
liftIO $ atomically $ do
usersMap <- readTVar users
case Map.lookup token usersMap of
- Nothing -> throwM $ err400 {errBody = "Cannot find challenge: Invalid token"}
- Just Score {grade} ->
+ Nothing -> throwM $ err400{errBody = "Cannot find challenge: Invalid token"}
+ Just Score{grade} ->
pure $ challenges !! grade
-- | Serve static resources under `public/` directory