aboutsummaryrefslogtreecommitdiff
path: root/server/lib/Cafp/InfiniteDeck.hs
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/Cafp/InfiniteDeck.hs')
-rw-r--r--server/lib/Cafp/InfiniteDeck.hs36
1 files changed, 36 insertions, 0 deletions
diff --git a/server/lib/Cafp/InfiniteDeck.hs b/server/lib/Cafp/InfiniteDeck.hs
new file mode 100644
index 0000000..8772011
--- /dev/null
+++ b/server/lib/Cafp/InfiniteDeck.hs
@@ -0,0 +1,36 @@
+module Cafp.InfiniteDeck
+ ( InfiniteDeck
+ , new
+ , newIO
+ , pop
+ , popN
+ ) where
+
+import Data.List (intercalate)
+import qualified Data.Vector as V
+import System.Random (StdGen, newStdGen)
+import VectorShuffling.Immutable (shuffle)
+
+newtype InfiniteDeck a = InfiniteDeck [a]
+
+instance Show a => Show (InfiniteDeck a) where
+ show (InfiniteDeck xs) =
+ "[" ++ intercalate ", " (map show $ take 5 xs) ++ "...]"
+
+new :: V.Vector a -> StdGen -> InfiniteDeck a
+new vec gen0
+ | V.null vec = error "Cafp.InfiniteDeck.new: empty vector"
+ | otherwise = InfiniteDeck (V.toList x ++ xs)
+ where
+ (x, gen1) = shuffle vec gen0
+ InfiniteDeck xs = new vec gen1
+
+newIO :: V.Vector a -> IO (InfiniteDeck a)
+newIO vec = new vec <$> newStdGen
+
+pop :: InfiniteDeck a -> (a, InfiniteDeck a)
+pop (InfiniteDeck []) = error "Cafp.InfiniteDeck.pop: empty"
+pop (InfiniteDeck (x : xs)) = (x, InfiniteDeck xs)
+
+popN :: Int -> InfiniteDeck a -> ([a], InfiniteDeck a)
+popN n (InfiniteDeck xs) = let (ys, zs) = splitAt n xs in (ys, InfiniteDeck zs)