aggregators.py (4653B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\dbuff\common\aggregators.py 2 from __future__ import print_function 3 import dbuff.storage 4 5 class Aggregator(object): 6 __slots__ = ['_sortedInputs', '_continuousInput'] 7 8 def __init__(self, expiryTime, outputValue): 9 if expiryTime is None: 10 self._continuousInput = outputValue 11 self._sortedInputs = [] 12 else: 13 self._continuousInput = None 14 self._sortedInputs = [(expiryTime, outputValue)] 15 16 def HasInputs(self): 17 return len(self._sortedInputs) > 0 or self._continuousInput is not None 18 19 def GetNextExpiryTime(self): 20 if self._sortedInputs: 21 return self._sortedInputs[0][0] 22 if self._continuousInput is None: 23 return 0 24 25 def GetFinalExpiryTime(self): 26 if self._continuousInput is not None: 27 return 28 if self._sortedInputs: 29 return self._sortedInputs[-1][0] 30 31 def GetCurrentOutputValue(self): 32 if self._sortedInputs and self._continuousInput is not None: 33 return self._PickValue(self._continuousInput, self._sortedInputs[0][1]) 34 if self._continuousInput is not None: 35 return self._continuousInput 36 if self._sortedInputs: 37 return self._sortedInputs[0][1] 38 39 def _PickValue(self, *values): 40 raise NotImplementedError() 41 42 def MergeNewTimedInput(self, newExpiryTime, newValue): 43 raise NotImplementedError() 44 45 def SetContinuousInput(self, newValue): 46 if self._continuousInput is None: 47 self._continuousInput = newValue 48 else: 49 self._continuousInput = self._PickValue(self._continuousInput, newValue) 50 51 def ClearContinuousInput(self): 52 self._continuousInput = None 53 54 def DiscardExpiredTimedInputs(self, now): 55 while self._sortedInputs and self._sortedInputs[0][0] < now: 56 self._sortedInputs.pop(0) 57 58 def GetStateForClient(self): 59 return (self.GetCurrentOutputValue(), self.GetFinalExpiryTime()) 60 61 62 class AggregatorMinimum(Aggregator): 63 __slots__ = [] 64 65 def MergeNewTimedInput(self, newExpiryTime, newValue): 66 for expiryTime, value in self._sortedInputs: 67 if expiryTime >= newExpiryTime and value <= newValue: 68 return 69 70 result = [ (expiryTime, value) for expiryTime, value in self._sortedInputs if expiryTime < newExpiryTime and value < newValue ] 71 result.append((newExpiryTime, newValue)) 72 result.extend([ (expiryTime, value) for expiryTime, value in self._sortedInputs if expiryTime > newExpiryTime and value > newValue ]) 73 self._sortedInputs = result 74 75 def _PickValue(self, *values): 76 return min(values) 77 78 79 class AggregatorMaximum(Aggregator): 80 __slots__ = [] 81 82 def MergeNewTimedInput(self, newExpiryTime, newValue): 83 for expiryTime, value in self._sortedInputs: 84 if expiryTime >= newExpiryTime and value >= newValue: 85 return 86 87 result = [ (expiryTime, value) for expiryTime, value in self._sortedInputs if expiryTime < newExpiryTime and value > newValue ] 88 result.append((newExpiryTime, newValue)) 89 result.extend([ (expiryTime, value) for expiryTime, value in self._sortedInputs if expiryTime > newExpiryTime and value < newValue ]) 90 self._sortedInputs = result 91 92 def _PickValue(self, *values): 93 return max(values) 94 95 96 AGGREGATOR_CLASS_BY_MODE = {'Maximum': AggregatorMaximum, 97 'Minimum': AggregatorMinimum} 98 99 def CreateAggregator(dbuffCollectionID, expiryTime, outputValue): 100 dbuffCollection = dbuff.storage.GetDbuffCollection(dbuffCollectionID) 101 aggregateMode = dbuffCollection.aggregateMode 102 aggregatorClass = AGGREGATOR_CLASS_BY_MODE[aggregateMode] 103 return aggregatorClass(expiryTime, outputValue) 104 105 106 if __name__ == '__main__': 107 import random 108 import timeit 109 110 class AggregatorNull(Aggregator): 111 112 def _PickValue(self, *values): 113 pass 114 115 def MergeNewTimedInput(self, newExpiryTime, newValue): 116 pass 117 118 119 for aggregator in [AggregatorNull(555, 1.0), AggregatorMaximum(555, 1.0), AggregatorMinimum(555, 1.0)]: 120 rnd = random.Random('aggregators random seed') 121 timing = timeit.repeat('\nfor expiryTime, value in samples:\n aggregator.MergeNewTimedInput(expiryTime, value)\n ', setup='\nimport random\nfrom __main__ import aggregator, rnd\nnumSamples = 50\nsamples = [(rnd.randint(100, 999), rnd.uniform(0.0, 10.0)) for x in xrange(numSamples)]\n ', number=10000, repeat=5) 122 print('%.3fs [%s]' % (min(timing), aggregator))