{-# LANGUAGE DeriveGeneric, GeneralizedNewtypeDeriving #-}
-- | Per-actor analytics of personal feats.
module Game.LambdaHack.Common.Analytics
  ( FactionAnalytics, ActorAnalytics, GenerationAnalytics
  , KillMap, Analytics(..), KillHow(..)
  , emptyAnalytics, addFactionKill, addActorKill
#ifdef EXPOSE_INTERNAL
    -- * Internal operations
  , addKill
#endif
  ) where

import Prelude ()

import Game.LambdaHack.Core.Prelude

import           Data.Binary
import qualified Data.EnumMap.Strict as EM
import           GHC.Generics (Generic)

import Game.LambdaHack.Common.Types
import Game.LambdaHack.Definition.Defs

-- | Summary analytics data for each faction.
type FactionAnalytics = EM.EnumMap FactionId Analytics

-- | Analytics data for each live actor.
type ActorAnalytics = EM.EnumMap ActorId Analytics

-- | Statistics of possible and actual generation of items for each lore kind.
type GenerationAnalytics = EM.EnumMap SLore (EM.EnumMap ItemId Int)

-- | Labels of individual kill count analytics.
data KillHow =
    KillKineticMelee
  | KillKineticRanged
  | KillKineticBlast
  | KillKineticPush
  | KillOtherMelee
  | KillOtherRanged
  | KillOtherBlast
  | KillOtherPush
  | KillActorLaunch
  | KillTileLaunch
  | KillDropLaunch
  | KillCatch
  deriving (Int -> KillHow -> ShowS
[KillHow] -> ShowS
KillHow -> String
(Int -> KillHow -> ShowS)
-> (KillHow -> String) -> ([KillHow] -> ShowS) -> Show KillHow
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [KillHow] -> ShowS
$cshowList :: [KillHow] -> ShowS
show :: KillHow -> String
$cshow :: KillHow -> String
showsPrec :: Int -> KillHow -> ShowS
$cshowsPrec :: Int -> KillHow -> ShowS
Show, KillHow -> KillHow -> Bool
(KillHow -> KillHow -> Bool)
-> (KillHow -> KillHow -> Bool) -> Eq KillHow
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: KillHow -> KillHow -> Bool
$c/= :: KillHow -> KillHow -> Bool
== :: KillHow -> KillHow -> Bool
$c== :: KillHow -> KillHow -> Bool
Eq, Int -> KillHow
KillHow -> Int
KillHow -> [KillHow]
KillHow -> KillHow
KillHow -> KillHow -> [KillHow]
KillHow -> KillHow -> KillHow -> [KillHow]
(KillHow -> KillHow)
-> (KillHow -> KillHow)
-> (Int -> KillHow)
-> (KillHow -> Int)
-> (KillHow -> [KillHow])
-> (KillHow -> KillHow -> [KillHow])
-> (KillHow -> KillHow -> [KillHow])
-> (KillHow -> KillHow -> KillHow -> [KillHow])
-> Enum KillHow
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: KillHow -> KillHow -> KillHow -> [KillHow]
$cenumFromThenTo :: KillHow -> KillHow -> KillHow -> [KillHow]
enumFromTo :: KillHow -> KillHow -> [KillHow]
$cenumFromTo :: KillHow -> KillHow -> [KillHow]
enumFromThen :: KillHow -> KillHow -> [KillHow]
$cenumFromThen :: KillHow -> KillHow -> [KillHow]
enumFrom :: KillHow -> [KillHow]
$cenumFrom :: KillHow -> [KillHow]
fromEnum :: KillHow -> Int
$cfromEnum :: KillHow -> Int
toEnum :: Int -> KillHow
$ctoEnum :: Int -> KillHow
pred :: KillHow -> KillHow
$cpred :: KillHow -> KillHow
succ :: KillHow -> KillHow
$csucc :: KillHow -> KillHow
Enum, (forall x. KillHow -> Rep KillHow x)
-> (forall x. Rep KillHow x -> KillHow) -> Generic KillHow
forall x. Rep KillHow x -> KillHow
forall x. KillHow -> Rep KillHow x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep KillHow x -> KillHow
$cfrom :: forall x. KillHow -> Rep KillHow x
Generic)

instance Binary KillHow

type KillMap = EM.EnumMap FactionId (EM.EnumMap ItemId Int)

-- | Statistics of past events concerning an actor.
newtype Analytics = Analytics
  { Analytics -> EnumMap KillHow KillMap
akillCounts :: EM.EnumMap KillHow KillMap
  }
  deriving (Int -> Analytics -> ShowS
[Analytics] -> ShowS
Analytics -> String
(Int -> Analytics -> ShowS)
-> (Analytics -> String)
-> ([Analytics] -> ShowS)
-> Show Analytics
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Analytics] -> ShowS
$cshowList :: [Analytics] -> ShowS
show :: Analytics -> String
$cshow :: Analytics -> String
showsPrec :: Int -> Analytics -> ShowS
$cshowsPrec :: Int -> Analytics -> ShowS
Show, Analytics -> Analytics -> Bool
(Analytics -> Analytics -> Bool)
-> (Analytics -> Analytics -> Bool) -> Eq Analytics
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Analytics -> Analytics -> Bool
$c/= :: Analytics -> Analytics -> Bool
== :: Analytics -> Analytics -> Bool
$c== :: Analytics -> Analytics -> Bool
Eq, Get Analytics
[Analytics] -> Put
Analytics -> Put
(Analytics -> Put)
-> Get Analytics -> ([Analytics] -> Put) -> Binary Analytics
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [Analytics] -> Put
$cputList :: [Analytics] -> Put
get :: Get Analytics
$cget :: Get Analytics
put :: Analytics -> Put
$cput :: Analytics -> Put
Binary)

emptyAnalytics :: Analytics
emptyAnalytics :: Analytics
emptyAnalytics = Analytics :: EnumMap KillHow KillMap -> Analytics
Analytics
  { akillCounts :: EnumMap KillHow KillMap
akillCounts = EnumMap KillHow KillMap
forall k a. EnumMap k a
EM.empty
  }

addKill :: KillHow -> FactionId -> ItemId -> Maybe Analytics -> Analytics
addKill :: KillHow -> FactionId -> ItemId -> Maybe Analytics -> Analytics
addKill KillHow
killHow FactionId
fid ItemId
iid =
  let f :: Maybe Analytics -> Analytics
f Maybe Analytics
Nothing = Analytics :: EnumMap KillHow KillMap -> Analytics
Analytics {akillCounts :: EnumMap KillHow KillMap
akillCounts =
        KillHow -> KillMap -> EnumMap KillHow KillMap
forall k a. Enum k => k -> a -> EnumMap k a
EM.singleton KillHow
killHow (KillMap -> EnumMap KillHow KillMap)
-> KillMap -> EnumMap KillHow KillMap
forall a b. (a -> b) -> a -> b
$ FactionId -> EnumMap ItemId Int -> KillMap
forall k a. Enum k => k -> a -> EnumMap k a
EM.singleton FactionId
fid (EnumMap ItemId Int -> KillMap) -> EnumMap ItemId Int -> KillMap
forall a b. (a -> b) -> a -> b
$ ItemId -> Int -> EnumMap ItemId Int
forall k a. Enum k => k -> a -> EnumMap k a
EM.singleton ItemId
iid Int
1}
      f (Just Analytics
an) = Analytics
an {akillCounts :: EnumMap KillHow KillMap
akillCounts =
        (Maybe KillMap -> Maybe KillMap)
-> KillHow -> EnumMap KillHow KillMap -> EnumMap KillHow KillMap
forall k a.
Enum k =>
(Maybe a -> Maybe a) -> k -> EnumMap k a -> EnumMap k a
EM.alter Maybe KillMap -> Maybe KillMap
g KillHow
killHow (EnumMap KillHow KillMap -> EnumMap KillHow KillMap)
-> EnumMap KillHow KillMap -> EnumMap KillHow KillMap
forall a b. (a -> b) -> a -> b
$ Analytics -> EnumMap KillHow KillMap
akillCounts Analytics
an}
      g :: Maybe KillMap -> Maybe KillMap
g Maybe KillMap
Nothing = KillMap -> Maybe KillMap
forall a. a -> Maybe a
Just (KillMap -> Maybe KillMap) -> KillMap -> Maybe KillMap
forall a b. (a -> b) -> a -> b
$ FactionId -> EnumMap ItemId Int -> KillMap
forall k a. Enum k => k -> a -> EnumMap k a
EM.singleton FactionId
fid (EnumMap ItemId Int -> KillMap) -> EnumMap ItemId Int -> KillMap
forall a b. (a -> b) -> a -> b
$ ItemId -> Int -> EnumMap ItemId Int
forall k a. Enum k => k -> a -> EnumMap k a
EM.singleton ItemId
iid Int
1
      g (Just KillMap
fidMap) = KillMap -> Maybe KillMap
forall a. a -> Maybe a
Just (KillMap -> Maybe KillMap) -> KillMap -> Maybe KillMap
forall a b. (a -> b) -> a -> b
$ (Maybe (EnumMap ItemId Int) -> Maybe (EnumMap ItemId Int))
-> FactionId -> KillMap -> KillMap
forall k a.
Enum k =>
(Maybe a -> Maybe a) -> k -> EnumMap k a -> EnumMap k a
EM.alter Maybe (EnumMap ItemId Int) -> Maybe (EnumMap ItemId Int)
h FactionId
fid KillMap
fidMap
      h :: Maybe (EnumMap ItemId Int) -> Maybe (EnumMap ItemId Int)
h Maybe (EnumMap ItemId Int)
Nothing = EnumMap ItemId Int -> Maybe (EnumMap ItemId Int)
forall a. a -> Maybe a
Just (EnumMap ItemId Int -> Maybe (EnumMap ItemId Int))
-> EnumMap ItemId Int -> Maybe (EnumMap ItemId Int)
forall a b. (a -> b) -> a -> b
$ ItemId -> Int -> EnumMap ItemId Int
forall k a. Enum k => k -> a -> EnumMap k a
EM.singleton ItemId
iid Int
1
      h (Just EnumMap ItemId Int
iidMap) = EnumMap ItemId Int -> Maybe (EnumMap ItemId Int)
forall a. a -> Maybe a
Just (EnumMap ItemId Int -> Maybe (EnumMap ItemId Int))
-> EnumMap ItemId Int -> Maybe (EnumMap ItemId Int)
forall a b. (a -> b) -> a -> b
$ (Maybe Int -> Maybe Int)
-> ItemId -> EnumMap ItemId Int -> EnumMap ItemId Int
forall k a.
Enum k =>
(Maybe a -> Maybe a) -> k -> EnumMap k a -> EnumMap k a
EM.alter Maybe Int -> Maybe Int
forall a. Num a => Maybe a -> Maybe a
i ItemId
iid EnumMap ItemId Int
iidMap
      i :: Maybe a -> Maybe a
i Maybe a
Nothing = a -> Maybe a
forall a. a -> Maybe a
Just a
1
      i (Just a
n) = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$ a
n a -> a -> a
forall a. Num a => a -> a -> a
+ a
1
  in Maybe Analytics -> Analytics
f

addFactionKill :: FactionId -> KillHow -> FactionId -> ItemId
               -> FactionAnalytics
               -> FactionAnalytics
addFactionKill :: FactionId
-> KillHow
-> FactionId
-> ItemId
-> FactionAnalytics
-> FactionAnalytics
addFactionKill FactionId
fidOfKiller KillHow
killHow FactionId
fid ItemId
iid =
  (Maybe Analytics -> Maybe Analytics)
-> FactionId -> FactionAnalytics -> FactionAnalytics
forall k a.
Enum k =>
(Maybe a -> Maybe a) -> k -> EnumMap k a -> EnumMap k a
EM.alter (Analytics -> Maybe Analytics
forall a. a -> Maybe a
Just (Analytics -> Maybe Analytics)
-> (Maybe Analytics -> Analytics)
-> Maybe Analytics
-> Maybe Analytics
forall b c a. (b -> c) -> (a -> b) -> a -> c
. KillHow -> FactionId -> ItemId -> Maybe Analytics -> Analytics
addKill KillHow
killHow FactionId
fid ItemId
iid) FactionId
fidOfKiller

addActorKill :: ActorId -> KillHow -> FactionId -> ItemId
             -> ActorAnalytics
             -> ActorAnalytics
addActorKill :: ActorId
-> KillHow
-> FactionId
-> ItemId
-> ActorAnalytics
-> ActorAnalytics
addActorKill ActorId
aid KillHow
killHow FactionId
fid ItemId
iid =
  (Maybe Analytics -> Maybe Analytics)
-> ActorId -> ActorAnalytics -> ActorAnalytics
forall k a.
Enum k =>
(Maybe a -> Maybe a) -> k -> EnumMap k a -> EnumMap k a
EM.alter (Analytics -> Maybe Analytics
forall a. a -> Maybe a
Just (Analytics -> Maybe Analytics)
-> (Maybe Analytics -> Analytics)
-> Maybe Analytics
-> Maybe Analytics
forall b c a. (b -> c) -> (a -> b) -> a -> c
. KillHow -> FactionId -> ItemId -> Maybe Analytics -> Analytics
addKill KillHow
killHow FactionId
fid ItemId
iid) ActorId
aid