1+ namespace KludgeBox . Core . Stats ;
2+
3+ public class StatModifiersContainer < TStat >
4+ {
5+ private readonly HashSet < StatModifier < TStat > > _statsModifiers = new ( ) ;
6+
7+ private readonly Dictionary < TStat , double > _cacheAdditive = new ( ) ;
8+ private readonly Dictionary < TStat , double > _cacheMultiplicative = new ( ) ;
9+ private readonly HashSet < ( TStat , StatModifier < TStat > . ModifierType ) > _needToInvalidateCache = new ( ) ;
10+
11+ public void AddStatModifier ( StatModifier < TStat > statModifier )
12+ {
13+ AddTaskToInvalidateCache ( statModifier ) ;
14+ _statsModifiers . Add ( statModifier ) ;
15+ }
16+
17+ public bool RemoveStatModifier ( StatModifier < TStat > statModifier )
18+ {
19+ AddTaskToInvalidateCache ( statModifier ) ;
20+ return _statsModifiers . Remove ( statModifier ) ;
21+ }
22+
23+ public double GetStat ( TStat stat , double baseValue = 0 )
24+ {
25+ double additiveValue = GetStatValue ( stat , StatModifier < TStat > . ModifierType . Additive ) ;
26+ double multiplicativeValue = GetStatValue ( stat , StatModifier < TStat > . ModifierType . Multiplicative ) ;
27+ return ( baseValue + additiveValue ) * multiplicativeValue ;
28+ }
29+
30+ public double GetStatValue ( TStat stat , StatModifier < TStat > . ModifierType type )
31+ {
32+ if ( _needToInvalidateCache . Contains ( ( stat , type ) ) ) RecalculateCache ( stat , type ) ;
33+ return GetCacheInfo ( type ) . Dictionary . GetValueOrDefault ( stat , GetCacheInfo ( type ) . DefaultValue ) ;
34+ }
35+
36+ private void AddTaskToInvalidateCache ( StatModifier < TStat > statModifier )
37+ {
38+ _needToInvalidateCache . Add ( ( statModifier . Stat , statModifier . Type ) ) ;
39+ }
40+
41+ private void RecalculateCache ( TStat stat , StatModifier < TStat > . ModifierType type )
42+ {
43+ GetCacheInfo ( type ) . Dictionary [ stat ] = _statsModifiers
44+ . Where ( sm => sm . Stat . Equals ( stat ) )
45+ . Where ( sm => sm . Type == type )
46+ . Select ( sm => sm . Value )
47+ . Aggregate ( GetCacheInfo ( type ) . DefaultValue , GetCacheInfo ( type ) . Operation ) ;
48+
49+ _needToInvalidateCache . Remove ( ( stat , type ) ) ;
50+ }
51+
52+ private record CacheInfo (
53+ Dictionary < TStat , double > Dictionary ,
54+ Func < double , double , double > Operation ,
55+ double DefaultValue ) ;
56+
57+ private CacheInfo GetCacheInfo ( StatModifier < TStat > . ModifierType type )
58+ {
59+ return type switch
60+ {
61+ StatModifier < TStat > . ModifierType . Additive =>
62+ new CacheInfo ( _cacheAdditive , ( d1 , d2 ) => d1 + d2 , 0 ) ,
63+ StatModifier < TStat > . ModifierType . Multiplicative =>
64+ new CacheInfo ( _cacheMultiplicative , ( d1 , d2 ) => d1 * d2 , 1 ) ,
65+ _ => throw new ArgumentException ( "Unknown ModifierType: " + type )
66+ } ;
67+ }
68+
69+ }
0 commit comments