extractRatings
This commit is contained in:
parent
710fec9b18
commit
0a40a8bf70
@ -4,6 +4,7 @@
|
|||||||
{-# LANGUAGE NamedFieldPuns #-}
|
{-# LANGUAGE NamedFieldPuns #-}
|
||||||
{-# LANGUAGE ViewPatterns #-}
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE TupleSections #-}
|
||||||
{-# LANGUAGE DeriveGeneric, DeriveDataTypeable #-}
|
{-# LANGUAGE DeriveGeneric, DeriveDataTypeable #-}
|
||||||
|
|
||||||
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||||
@ -13,7 +14,10 @@ module Handler.Utils.Zip.Rating
|
|||||||
( Rating(..)
|
( Rating(..)
|
||||||
, getRating
|
, getRating
|
||||||
, formatRating
|
, formatRating
|
||||||
|
, RatingException(..)
|
||||||
|
, UnicodeException(..)
|
||||||
, parseRating
|
, parseRating
|
||||||
|
, extractRatings
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Import hiding ((</>))
|
import Import hiding ((</>))
|
||||||
@ -25,6 +29,7 @@ import Control.Monad.Trans.Maybe
|
|||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
import qualified Data.Text.Encoding as Text
|
import qualified Data.Text.Encoding as Text
|
||||||
|
import Data.Text.Encoding.Error (UnicodeException(..))
|
||||||
|
|
||||||
import qualified Data.Text.Lazy.Encoding as Lazy.Text
|
import qualified Data.Text.Lazy.Encoding as Lazy.Text
|
||||||
|
|
||||||
@ -48,6 +53,18 @@ data Rating = Rating
|
|||||||
, ratingPoints :: Maybe Points
|
, ratingPoints :: Maybe Points
|
||||||
} deriving (Read, Show, Eq, Generic, Typeable)
|
} deriving (Read, Show, Eq, Generic, Typeable)
|
||||||
|
|
||||||
|
type Rating' = ( Maybe Points
|
||||||
|
, Maybe Text -- ^ Rating comment
|
||||||
|
)
|
||||||
|
|
||||||
|
data RatingException = RatingNotUnicode UnicodeException -- ^ Rating failed to parse as unicode
|
||||||
|
| RatingMissingSeparator -- ^ Could not split rating header from comments
|
||||||
|
| RatingMultiple -- ^ Encountered multiple point values in rating
|
||||||
|
| RatingInvalid String -- ^ Failed to parse rating point value
|
||||||
|
deriving (Show, Eq, Generic, Typeable)
|
||||||
|
|
||||||
|
instance Exception RatingException
|
||||||
|
|
||||||
|
|
||||||
getRating :: SubmissionId -> YesodDB UniWorX (Maybe Rating)
|
getRating :: SubmissionId -> YesodDB UniWorX (Maybe Rating)
|
||||||
getRating ratingSubmissionId = runMaybeT $ do
|
getRating ratingSubmissionId = runMaybeT $ do
|
||||||
@ -76,32 +93,39 @@ formatRating Rating{..} = let
|
|||||||
]
|
]
|
||||||
in Lazy.Text.encodeUtf8 $ displayT doc
|
in Lazy.Text.encodeUtf8 $ displayT doc
|
||||||
|
|
||||||
|
parseRating :: MonadThrow m => ByteString -> m Rating'
|
||||||
parseRating :: ByteString
|
|
||||||
-> Either Text ( Maybe Points
|
|
||||||
, Maybe Text -- ^ Rating comment
|
|
||||||
)
|
|
||||||
parseRating input = do
|
parseRating input = do
|
||||||
inputText <- first tshow $ Text.decodeUtf8' input
|
inputText <- either (throw . RatingNotUnicode) return $ Text.decodeUtf8' input
|
||||||
let
|
let
|
||||||
(headerLines, commentLines) = break (sep `Text.isInfixOf`) $ Text.lines inputText
|
(headerLines, commentLines) = break (sep `Text.isInfixOf`) $ Text.lines inputText
|
||||||
ratingLines = filter (rating `Text.isInfixOf`) headerLines
|
ratingLines = filter (rating `Text.isInfixOf`) headerLines
|
||||||
sep = "Beginn der Kommentare"
|
sep = "Beginn der Kommentare"
|
||||||
rating = "Bewertung:"
|
rating = "Bewertung:"
|
||||||
comment' <- case commentLines of
|
comment' <- case commentLines of
|
||||||
(_:commentLines') -> Right . Text.strip $ Text.unlines commentLines'
|
(_:commentLines') -> return . Text.strip $ Text.unlines commentLines'
|
||||||
_ -> Left $ "Missing separator “" <> sep <> "”"
|
_ -> throw RatingMissingSeparator
|
||||||
let
|
let
|
||||||
comment
|
comment
|
||||||
| Text.null comment' = Nothing
|
| Text.null comment' = Nothing
|
||||||
| otherwise = Just comment'
|
| otherwise = Just comment'
|
||||||
ratingLine' <- case ratingLines of
|
ratingLine' <- case ratingLines of
|
||||||
[l] -> Right l
|
[l] -> return l
|
||||||
_ -> Left $ "Multiple occurances of “" <> rating <> "”"
|
_ -> throw RatingMultiple
|
||||||
let
|
let
|
||||||
(_, ratingLine) = Text.breakOnEnd rating ratingLine'
|
(_, ratingLine) = Text.breakOnEnd rating ratingLine'
|
||||||
ratingStr = Text.unpack $ Text.strip ratingLine
|
ratingStr = Text.unpack $ Text.strip ratingLine
|
||||||
rating <- case () of
|
rating <- case () of
|
||||||
_ | null ratingStr -> return Nothing
|
_ | null ratingStr -> return Nothing
|
||||||
| otherwise -> first tshow $ Just <$> readEither ratingStr
|
| otherwise -> either (throw . RatingInvalid) return $ Just <$> readEither ratingStr
|
||||||
return (rating, comment)
|
return (rating, comment)
|
||||||
|
|
||||||
|
|
||||||
|
extractRatings :: MonadThrow m => (FilePath -> Maybe SubmissionId) -> Conduit File m (Either File (SubmissionId, Rating'))
|
||||||
|
extractRatings isRating = void . runMaybeT $ do
|
||||||
|
f@(File{..}) <- MaybeT await
|
||||||
|
|
||||||
|
lift $ case () of
|
||||||
|
_ | Just sId <- isRating fileTitle
|
||||||
|
, Just content' <- fileContent
|
||||||
|
-> yieldM $ Right . (sId, ) <$> parseRating content'
|
||||||
|
| otherwise -> yield $ Left f
|
||||||
|
|||||||
@ -22,7 +22,7 @@ instance Arbitrary Rating where
|
|||||||
ratingCourseName <- arbitrary
|
ratingCourseName <- arbitrary
|
||||||
ratingSheetName <- arbitrary
|
ratingSheetName <- arbitrary
|
||||||
ratingSubmissionId <- SubmissionKey . SqlBackendKey <$> arbitrary
|
ratingSubmissionId <- SubmissionKey . SqlBackendKey <$> arbitrary
|
||||||
ratingComment <- fmap Text.strip <$> arbitrary `suchThat` maybe True (not . Text.null)
|
ratingComment <- (fmap Text.strip <$> arbitrary) `suchThat` maybe True (not . Text.null)
|
||||||
ratingPoints <- arbitrary
|
ratingPoints <- arbitrary
|
||||||
return Rating{..}
|
return Rating{..}
|
||||||
|
|
||||||
@ -30,4 +30,4 @@ instance Arbitrary Rating where
|
|||||||
spec :: Spec
|
spec :: Spec
|
||||||
spec = describe "Rating files" $ do
|
spec = describe "Rating files" $ do
|
||||||
it "have compatible formatting/parsing" . property $
|
it "have compatible formatting/parsing" . property $
|
||||||
\rating@(Rating{..}) -> parseRating (Lazy.ByteString.toStrict $ formatRating rating) `shouldBe` Right (ratingPoints, ratingComment)
|
\rating@(Rating{..}) -> parseRating (Lazy.ByteString.toStrict $ formatRating rating) >>= (`shouldBe` (ratingPoints, ratingComment))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user