From 1012666e1f8c9d9dd9305f4c1bd4d780fd0531a4 Mon Sep 17 00:00:00 2001 From: distributive Date: Mon, 30 Oct 2023 05:13:17 +0000 Subject: [PATCH] Updated restrictions to support the new API format and reformatted the output of card banlist history queries --- .../Plugins/Netrunner/Type/Restriction.hs | 4 +- .../Plugins/Netrunner/Utility/Card.hs | 2 +- .../Plugins/Netrunner/Utility/Legality.hs | 48 ++++++++++++------- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/Sahasrara/Plugins/Netrunner/Type/Restriction.hs b/src/Sahasrara/Plugins/Netrunner/Type/Restriction.hs index 505a32b..416fb9f 100644 --- a/src/Sahasrara/Plugins/Netrunner/Type/Restriction.hs +++ b/src/Sahasrara/Plugins/Netrunner/Type/Restriction.hs @@ -24,9 +24,9 @@ data Restriction = Restriction pointLimit :: !(Maybe Int), banned :: ![Text], restricted :: ![Text], - universalFactionCost :: !(Map Int [Text]), + universalFactionCost :: !(Map Text Int), globalPenalty :: ![Text], - points :: !(Map Int [Text]), + points :: !(Map Text Int), bannedSubtypes :: ![Text] } deriving (Eq, Show, Generic) diff --git a/src/Sahasrara/Plugins/Netrunner/Utility/Card.hs b/src/Sahasrara/Plugins/Netrunner/Utility/Card.hs index 3108b5f..8b2be42 100644 --- a/src/Sahasrara/Plugins/Netrunner/Utility/Card.hs +++ b/src/Sahasrara/Plugins/Netrunner/Utility/Card.hs @@ -45,7 +45,7 @@ toPrintings api card = filter ((== code card) . cardCode) $ printings api -- | @toLatestPrinting@ gets the most recent printing of a card. -- Assumes they're ordered oldest first toLatestPrinting :: NrApi -> Card -> Printing -toLatestPrinting api card = last $ toPrintings api card +toLatestPrinting api card = head $ toPrintings api card -- | @toFaction@ takes a card and attempts to find its faction. toFaction :: NrApi -> Card -> Faction diff --git a/src/Sahasrara/Plugins/Netrunner/Utility/Legality.hs b/src/Sahasrara/Plugins/Netrunner/Utility/Legality.hs index db813e5..efee9c3 100644 --- a/src/Sahasrara/Plugins/Netrunner/Utility/Legality.hs +++ b/src/Sahasrara/Plugins/Netrunner/Utility/Legality.hs @@ -2,9 +2,8 @@ -- Description : Handles the representation of card legality in Netrunner. module Sahasrara.Plugins.Netrunner.Utility.Legality where -import Data.List (nub, nubBy) -import Data.Map (elems, keys) -import qualified Data.Map as Map +import Data.List (groupBy, nub, nubBy, sortBy) +import Data.Map (Map, findWithDefault, keys, lookup) import Data.Maybe (fromMaybe, mapMaybe) import Data.Text (Text, intercalate, toLower) import qualified Data.Text as T @@ -85,10 +84,7 @@ isRestricted restriction card = elem (Card.code card) $ restricted restriction -- | @toUniversalFactionCost@ gets a card's universal cost under a restriction. toUniversalFactionCost :: Restriction -> Card -> Int -toUniversalFactionCost restriction Card {Card.code = code} = - case keys $ Map.filter (code `elem`) $ universalFactionCost restriction of - [] -> 0 - (x : _) -> x +toUniversalFactionCost restriction Card {Card.code = code} = findWithDefault 0 code $ universalFactionCost restriction -- | @hasGlobalPenalty@ determines if a card had a global penalty under a restriction. hasGlobalPenalty :: Restriction -> Card -> Bool @@ -96,10 +92,7 @@ hasGlobalPenalty restriction card = elem (Card.code card) $ globalPenalty restri -- | @toPoints@ gets a card's points under a restriction. toPoints :: Restriction -> Card -> Int -toPoints restriction Card {Card.code = code} = - case keys $ Map.filter (code `elem`) $ points restriction of - [] -> 0 - (x : _) -> x +toPoints restriction Card {Card.code = code} = findWithDefault 0 code $ points restriction -- | @cycleLegality@ gets the legality of a given cycle under a given snapshot. cycleLegality :: NrApi -> Snapshot -> CardCycle -> Legality @@ -142,22 +135,41 @@ listRestrictions api format = -- | @listHistory@ lists each restriction of the given format and the state of -- the given card under each version. listHistory :: NrApi -> Format -> Card -> Text -listHistory api format card = intercalate "\n" $ map toText snapshots +listHistory api format card = intercalate "\n" condensed where snapshots :: [Snapshot] -- Doesn't use toRestrictions because we need the snapshots for their card pools - snapshots = reverse $ filter (\s -> restrictionCode s /= Nothing) $ nubBy (\a b -> restrictionCode a == restrictionCode b) $ toSnapshots api format + snapshots = reverse $ filter (\s -> restrictionCode s /= Nothing && toLegality api s card /= Invalid) $ nubBy (\a b -> restrictionCode a == restrictionCode b) $ toSnapshots api format + groups :: [[Snapshot]] + groups = groupBy (\a b -> toLegality api a card == toLegality api b card) snapshots + condensed :: [Text] + condensed = concatMap takeFirstLast groups + takeFirstLast :: [Snapshot] -> [Text] + takeFirstLast xs = if length xs < 4 + then toText <$> xs + else [toText $ head xs, formatSkip xs, toText $ last xs] + formatSkip :: [Snapshot] -> Text -- Should never be given a list with fewer than 4 elements + formatSkip [] = "`#ERROR`" + formatSkip (x:xs) = legalityToSymbol (toLegality api x card) <> " _unchanged " <> (T.pack $ show $ length xs - 1) <> " updates_" toText :: Snapshot -> Text toText snapshot = let restriction = fromMaybe defaultRestriction $ toRestriction api snapshot - in legalityToSymbol (toLegality api snapshot card) <> " " <> Restriction.name restriction <> formatActive restriction + in legalityToSymbol (toLegality api snapshot card) <> " " <> formatActive restriction formatActive :: Restriction -> Text - formatActive r = if isActiveRestriction api format r then " (active)" else "" + formatActive r = if isActiveRestriction api format r + then "**" <> Restriction.name r <> " (active)**" + else Restriction.name r -- | @affectedCards@ gets all cards affected by a given restriction. affectedCards :: NrApi -> Restriction -> [Card] -affectedCards api r = - let codes = concat [banned r, restricted r, concat $ reverse $ elems (universalFactionCost r), globalPenalty r, concat $ reverse $ elems (points r)] - in mapMaybe (fromCardCode api) $ nub codes +affectedCards api r = mapMaybe (fromCardCode api) $ nub codes + where + codes :: [Text] + codes = concat [banned r, restricted r, sortBy (valueOf $ universalFactionCost r) $ keys (universalFactionCost r), globalPenalty r, sortBy (valueOf $ points r) $ keys (points r)] + valueOf :: Map Text Int -> Text -> Text -> Ordering + valueOf mapping a b = + let vA = lookup a mapping + vB = lookup b mapping + in if vA > vB then LT else if vA < vB then GT else EQ -- | @listAffectedCards@ lists all the cards affected by a restriction. -- The output is (additional text, corp cards, runner cards).