These changes are experimental and for learning purpose so they are a bit hard to explain. But in hindsight the old algorithm didn't deal with cards moving between categories correctly. This algorithm works according to ghci testing between two decklists.
M54PYKIOETT3UT4N6HHTAENU4D5HB7MNEFEXM5CX6PJ4FTQIRAAAC 2P34LOESTKTXTUTLVASZEKZ3VEFVHBJDZJ3LLAOGKH3GECC76LCQC 3FF6XAALNQZ7AFOEBJ2WJ3ZYZTG73GWAGJPMZPJGXNUBYUK5XIPAC NOKOPRVXR4V57S3FQGD4JZEZWN4APFH2BNPKNX7B364I23NYD36AC DOPKLXQZP3TDISHODQNI6GZ57EYE42NG225WHSZMQ3L355YVYPNAC 2Z6NDCF6FFB7GMSSSNBDRBADERI4AQSANOVA76EECCRLUKUEECKQC XQBYALGEDBGQIHMEI4FFDGMQCMOPE4SJLBDROYF5YVMU7H5IKV6AC SV5ID4TDECS35D2F4XYBVEFIIVOZYCHV6BTZBS7QYTOTJRDBGCIAC let totalFulfilled = sum . fmap (toNumber @Int) $ Compose reswhen (totalFulfilled < toNumber @Int (x ^. copies)) $resource(x ^. Category.name)( PositiveNumber . unsafeRefine . fromIntegral $toNumber @Int (x ^. copies) - totalFulfilled)
changes <- forM requested $ \x -> dores <- ResourceQueue.take (x ^. _2)
pure $ map (uncurry (Diff.move (x ^. Category.name))) res
let totalTaken = sum . fmap (toNumber @Int) $ Compose resmoves = map (uncurry (`Diff.move` (x ^. _1))) resdeltas =if totalTaken < toNumber @Int (x ^. _2)thenlet difference = toNumber @Int (x ^. _2) - totalTakenin singleton $ Diff.deltaCopies difference (x ^. _1)else mempty
go (mconcat changes ++ acc) mempty mempty
pure $ moves ++ deltasavailable <- gets fstlet deltas =Map.foldrWithKey'(\k a xs -> Diff.deltaCopies (negate (toNumber @Int a)) k : xs)[]availableput (mempty, mempty)pure (acc ++ mconcat changes ++ deltas)go acc xs [] = dochanges <- forM xs $ \x -> fulfillRequest (x ^. copies) (x ^. Category.name)go (acc ++ mconcat changes) mempty mempty
change 0 = accchange n = Diff.deltaCopies n (x ^. Category.name) : accunless (delta == 0) $ doif delta > 0thenresource(x ^. Category.name)(PositiveNumber . unsafeRefine . fromIntegral $ delta)elserequest(x ^. Category.name)(PositiveNumber . unsafeRefine . abs . fromIntegral $ delta)
changes <- case compare delta 0 ofLT -> takeAvailable (PositiveNumber . unsafeRefine . fromIntegral . abs $ delta) (x ^. Category.name)EQ -> pure accGT -> fulfillRequest (PositiveNumber . unsafeRefine . fromIntegral $ delta) (x ^. Category.name)
fulfillRequest count categoryname = dorequests <- ResourceQueue.fulfill countlet totalTaken = sum . fmap (toNumber @Int) $ Compose requestswhen (totalTaken < toNumber @Int count) $resourcecategoryname( PositiveNumber . unsafeRefine . fromIntegral $toNumber @Int count - totalTaken)pure $ map (uncurry (Diff.move categoryname)) requeststakeAvailable count categoryname = doavailable <- ResourceQueue.take count