module Haverer.PlayerSet (
PlayerSet
, PlayerSetError(..)
, toPlayerSet
, toPlayers
, randomize
, rotate
) where
import BasicPrelude
import Control.Monad.Except
import Control.Monad.Random
import Data.Foldable (Foldable)
import Data.Traversable (Traversable)
import System.Random.Shuffle
data PlayerSetError a = InvalidNumPlayers Int | DuplicatePlayers [a] deriving (Show, Eq)
newtype PlayerSet a = PlayerSet { toPlayers :: [a] } deriving (Show, Eq, Functor, Traversable, Foldable)
toPlayerSet :: Ord a => [a] -> Either (PlayerSetError a) (PlayerSet a)
toPlayerSet playerIds
| numPlayers /= numDistinctPlayers = throwError (DuplicatePlayers playerIds)
| numPlayers < 2 || numPlayers > 4 = throwError (InvalidNumPlayers numPlayers)
| otherwise = (return . PlayerSet) playerIds
where numPlayers = length playerIds
numDistinctPlayers = (length . nub . sort) playerIds
rotate :: PlayerSet a -> PlayerSet a
rotate (PlayerSet (x:xs)) = PlayerSet (xs ++ [x])
rotate _ = error "Empty PlayerSet is impossible"
randomize :: MonadRandom m => PlayerSet a -> m (PlayerSet a)
randomize = map PlayerSet . shuffleM . toPlayers