For now these resides in Util module until they find a more proper home
A5WEQR35VYRX4XL5DWHFJPW3BGMIHIWFNCKG767LLNPMOIJ557MQC
46RN2SQLFV5QN52CEGRSYYT2XGSO54L2S3RILAJRMTABQ5OFSMNAC
WU7LMADNTO7KABPB5KQOCTLEKHBOSNKZMYJJ2INUB4AX7FURUYNAC
6HVV4SABYL2YWFSYVMJINDQPY4HUSLBTVT6MFTWD4ZV274PCSFLAC
AZMUPEVSHVB3TWP57JUNP7MHBDTI6YNRJPQYEROP6PFMTQ3EABDAC
DOPKLXQZP3TDISHODQNI6GZ57EYE42NG225WHSZMQ3L355YVYPNAC
SNYOEZI7JMTLJNLM2YTAHBPJEKK2BJZJDOHRIX5676JCF2VNET3QC
Y6ZRZNGIYQLPYPV5PK6PA6FWMG3RQFKRJXVMBUYMW2WQ7ZT5O5WAC
FCKXFNKSGWZEQ5P4MPTJQM55EZC7J7R7UOP7SV3XXYSLJPC55ELAC
O7ZBGSRLERE2KAOQHQTO5B3MOMW5Z2JRR33GG3TBCTXIMXBRF3UQC
XBFPOITOZLMUZROJCW2YAUHFTVKPZMRO5GQL36BACBS2ELIU4R4QC
XAMFHYIWLYWVS52I3PNB7QB2YUBJQI3ORGFRTJOKW55GOFTYWRYQC
P2KQ6PRM6HH2NQFXCTQIMGTAKXIG6BQ32IBYTKBSP4NWTZ4JLGGAC
C3BUGSBWBKOXFFB6TIHDLQVFV65OKKW6KEUVMP4O2XP3RYMPJ5QAC
FUOJJ2E7WNHF2NNKBI7MF254TU5Z5VOEKMO2XAJMY7RDOUQTMG6QC
WIHPB3GXBYKWLOVPHSLFXHBCX53ZXAQ6LRJMYUQYDE4BRYV6YSMQC
R6GLORFO6COA5R7GFFHEZW7FXFJIJB6PTCSF3GBUZSETCE6IW23QC
6VA5CXBLQPHAZ2SL37OZVOI6D52HFXQUGLONJWAA7JSA7SCORBMAC
OQQ45NRBSXM5JXRTLDLP7CEBR4LPBAFY46AQHZTO2TXJMRKQVJNAC
module Util (
NonEmptyText (..),
PositiveNumber (..),
toText
) where
import Control.Monad
import qualified Data.ByteString.Char8 as BS
import Data.Csv (FromField (..), ToField (..))
import Data.Text (Text)
import Data.Text.Encoding (decodeUtf8Lenient)
import Refined
import Numeric.Natural
newtype NonEmptyText = NonEmptyText {runText :: Refined NonEmpty Text}
deriving (Show, Eq, Ord)
newtype PositiveNumber = PositiveNumber {runNumber :: Refined Positive Natural}
deriving (Show, Eq, Ord)
instance FromField NonEmptyText where
parseField s = NonEmptyText <$> (refineFail . decodeUtf8Lenient $ s)
instance FromField PositiveNumber where
parseField s =
maybe
mzero
((fmap PositiveNumber . refineFail) . fromIntegral . fst)
(BS.readInt s)
instance ToField NonEmptyText where
toField = toField . unrefine . runText
instance ToField PositiveNumber where
toField = toField . unrefine . runNumber
toText :: NonEmptyText -> Text
toText = unrefine . runText
import GHC.Natural
import GHC.Generics (Generic)
newtype NonEmptyText = NonEmptyText {runText :: Refined NonEmpty Text}
deriving (Show, Eq, Ord)
import Util
mainboard, sideboard :: Category
mainboard = NonEmptyText $$(refineTH "Mainboard")
sideboard = NonEmptyText $$(refineTH "Sideboard")
newtype PositiveNumber = PositiveNumber {runNumber :: Refined Positive Natural}
deriving (Show, Eq, Ord)
{ name :: !CardName
-- ^ Name of the card
, quantity :: !PositiveNumber
-- ^ Number of cards in a deck
, category :: !Category
-- ^ Main category of the card in a deck
{ _name :: !CardName
, _categories :: Map Text Copies
instance FromField PositiveNumber where
parseField s =
maybe
mzero
((fmap PositiveNumber . refineFail) . fromIntegral . fst)
(BS.readInt s)
mainboard, sideboard :: CategoryName
mainboard = NonEmptyText $$(refineTH "Mainboard")
sideboard = NonEmptyText $$(refineTH "Sideboard")
instance ToField NonEmptyText where
toField = toField . unrefine . runText
mkCard :: CardName -> CategoryName -> Copies -> Card
mkCard cardName primary copies =
let categoryName = toText primary
in Card {_name = cardName, _categories = Map.singleton categoryName copies}
{- | Update a `Card` in a `DeckList`. @`update` f a b@ applies the function @f@ on the card
| if it exists, otherwise it leaves the `DeckList` unchanged.
-}
update ::
((Category, PositiveNumber) -> (Category, PositiveNumber))
-> CardName
-> DeckList
-> DeckList
update f a b =
let tuple x = (category x, quantity x)
toCard (category, quantity) x = x {category, quantity}
in case Deck.find a b of
Nothing -> b
Just y -> insert (flip toCard y . f $ tuple y) b