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) whereimport Control.Monadimport qualified Data.ByteString.Char8 as BSimport Data.Csv (FromField (..), ToField (..))import Data.Text (Text)import Data.Text.Encoding (decodeUtf8Lenient)import Refinedimport Numeric.Naturalnewtype NonEmptyText = NonEmptyText {runText :: Refined NonEmpty Text}deriving (Show, Eq, Ord)newtype PositiveNumber = PositiveNumber {runNumber :: Refined Positive Natural}deriving (Show, Eq, Ord)instance FromField NonEmptyText whereparseField s = NonEmptyText <$> (refineFail . decodeUtf8Lenient $ s)instance FromField PositiveNumber whereparseField s =maybemzero((fmap PositiveNumber . refineFail) . fromIntegral . fst)(BS.readInt s)instance ToField NonEmptyText wheretoField = toField . unrefine . runTextinstance ToField PositiveNumber wheretoField = toField . unrefine . runNumbertoText :: NonEmptyText -> TexttoText = unrefine . runText
import GHC.Naturalimport GHC.Generics (Generic)newtype NonEmptyText = NonEmptyText {runText :: Refined NonEmpty Text}deriving (Show, Eq, Ord)
import Util
mainboard, sideboard :: Categorymainboard = 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 whereparseField s =maybemzero((fmap PositiveNumber . refineFail) . fromIntegral . fst)(BS.readInt s)
mainboard, sideboard :: CategoryNamemainboard = NonEmptyText $$(refineTH "Mainboard")sideboard = NonEmptyText $$(refineTH "Sideboard")
instance ToField NonEmptyText wheretoField = toField . unrefine . runText
mkCard :: CardName -> CategoryName -> Copies -> CardmkCard cardName primary copies =let categoryName = toText primaryin 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-> DeckListupdate f a b =let tuple x = (category x, quantity x)toCard (category, quantity) x = x {category, quantity}in case Deck.find a b ofNothing -> bJust y -> insert (flip toCard y . f $ tuple y) b