Skip to content
Snippets Groups Projects
Select Git revision
  • 34488ce52bca4031a81c57b9b1ee79ce5c4858c6
  • main default protected
  • 75389691-a67c-422a-91e9-aa58bfb5-main-patch-32205
  • test-pipe
  • extended-scripts
  • structured-badges
  • guix-pipeline
  • cabal-pipeline
8 results

Badges.hs

Blame
  • Badges.hs 2.25 KiB
    {-# LANGUAGE DeriveAnyClass    #-}
    {-# LANGUAGE DeriveGeneric     #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE RecordWildCards   #-}
    
    -- | module defining Badge types and utility functions
    module Badges where
    
    import           Data.Aeson      (Options (fieldLabelModifier, sumEncoding),
                                      SumEncoding (UntaggedValue), ToJSON (toJSON),
                                      defaultOptions, genericToJSON, (.=))
    import qualified Data.Aeson      as A
    import           Data.Char       (toLower)
    import           Data.Text       (Text)
    import           GHC.Generics    (Generic)
    import           Text.Regex.TDFA ((=~))
    
    
    data BadgeArea =
       BadgePoint
       { areaX :: Double
       , areaY :: Double
       }
     | BadgeRect
       { areaX         :: Double
       , areaY         :: Double
       , areaWidth     :: Double
       , areaHeight    :: Double
       , areaIsEllipse :: Bool
       }
      deriving (Ord, Eq, Generic, Show)
    
    newtype BadgeToken = BadgeToken Text
      deriving (Eq, Ord, Show)
    
    instance ToJSON BadgeArea where
      toJSON = genericToJSON defaultOptions
        { fieldLabelModifier = drop 4 . map toLower
        , sumEncoding = UntaggedValue }
    
    instance ToJSON BadgeToken where
      toJSON (BadgeToken text) = toJSON text
    
    parseToken :: Text -> Maybe BadgeToken
    parseToken text = if text =~ ("^[a-zA-Z0-9]{50}$" :: Text) -- TODO: add character limit
      then Just (BadgeToken text)
      else Nothing
    
    data Badge = Badge BadgeToken BadgeArea
      deriving (Ord, Eq, Generic, Show)
    
    badgeJsonArray :: A.KeyValue a => Badge -> [a]
    badgeJsonArray (Badge token area) =
      [ "token" .= token ] <> areaObject
      where areaObject = case area of
             BadgePoint x y -> [ "x" .= x
                               , "y" .= y
                               , "type" .= A.String "point"
                               ]
             BadgeRect {..} -> [ "x" .= areaX
                               , "y" .= areaY
                               , "width" .= areaWidth
                               , "height" .= areaHeight
                               , "type" .= if areaIsEllipse
                                    then A.String "ellipse"
                                    else A.String "rectangle"
                               ]
    
    badgeJson :: FilePath -> Badge -> A.Value
    badgeJson mappath badge = A.object (badgeJsonArray badge <> [ "map" .= mappath ])