| 32 | |
| 33 | |
| 34 | class FitDamageStatsGraph(FitGraph): |
| 35 | |
| 36 | def __init__(self, *args, **kwargs): |
| 37 | super().__init__(*args, **kwargs) |
| 38 | self._timeCache = TimeCache() |
| 39 | self._projectedCache = ProjectedDataCache() |
| 40 | |
| 41 | def _clearInternalCache(self, reason, extraData): |
| 42 | # Here, we care only about fit changes and graph changes. |
| 43 | # - Input changes are irrelevant as time cache cares only about |
| 44 | # time input, and it regenerates once time goes beyond cached value |
| 45 | # - Option changes are irrelevant as cache contains "raw" damage |
| 46 | # values which do not rely on any graph options |
| 47 | if reason in (GraphCacheCleanupReason.fitChanged, GraphCacheCleanupReason.fitRemoved): |
| 48 | self._timeCache.clearForFit(extraData) |
| 49 | self._projectedCache.clearForFit(extraData) |
| 50 | elif reason == GraphCacheCleanupReason.graphSwitched: |
| 51 | self._timeCache.clearAll() |
| 52 | self._projectedCache.clearAll() |
| 53 | |
| 54 | # UI stuff |
| 55 | internalName = 'dmgStatsGraph' |
| 56 | name = _t('Damage Stats') |
| 57 | xDefs = [ |
| 58 | XDef(handle='distance', unit='km', label=_t('Distance'), mainInput=('distance', 'km')), |
| 59 | XDef(handle='time', unit='s', label=_t('Time'), mainInput=('time', 's')), |
| 60 | XDef(handle='tgtSpeed', unit='m/s', label=_t('Target speed'), mainInput=('tgtSpeed', '%')), |
| 61 | XDef(handle='tgtSpeed', unit='%', label=_t('Target speed'), mainInput=('tgtSpeed', '%')), |
| 62 | XDef(handle='tgtSigRad', unit='m', label=_t('Target signature radius'), mainInput=('tgtSigRad', '%')), |
| 63 | XDef(handle='tgtSigRad', unit='%', label=_t('Target signature radius'), mainInput=('tgtSigRad', '%'))] |
| 64 | inputs = [ |
| 65 | Input(handle='distance', unit='km', label=_t('Distance'), iconID=1391, defaultValue=None, defaultRange=(0, 100), |
| 66 | mainTooltip=_t('Distance between the attacker and the target, as seen in overview (surface-to-surface)'), |
| 67 | secondaryTooltip=_t('Distance between the attacker and the target, as seen in overview (surface-to-surface)\nWhen set, places the target that far away from the attacker\nWhen not set, attacker\'s weapons always hit the target')), |
| 68 | Input(handle='time', unit='s', label=_t('Time'), iconID=1392, defaultValue=None, defaultRange=(0, 80), |
| 69 | secondaryTooltip=_t('When set, uses attacker\'s exact damage stats at a given time\nWhen not set, uses attacker\'s damage stats as shown in stats panel of main window')), |
| 70 | Input(handle='tgtSpeed', unit='%', label=_t('Target speed'), iconID=1389, defaultValue=100, defaultRange=(0, 100)), |
| 71 | Input(handle='tgtSigRad', unit='%', label=_t('Target signature'), iconID=1390, defaultValue=100, defaultRange=(100, 200), conditions=[ |
| 72 | (('tgtSigRad', 'm'), None), |
| 73 | (('tgtSigRad', '%'), None)])] |
| 74 | srcVectorDef = VectorDef(lengthHandle='atkSpeed', lengthUnit='%', angleHandle='atkAngle', angleUnit='degrees', label=_t('Attacker')) |
| 75 | tgtVectorDef = VectorDef(lengthHandle='tgtSpeed', lengthUnit='%', angleHandle='tgtAngle', angleUnit='degrees', label=_t('Target')) |
| 76 | hasTargets = True |
| 77 | srcExtraCols = ('Dps', 'Volley', 'Speed', 'Radius') |
| 78 | |
| 79 | @property |
| 80 | def yDefs(self): |
| 81 | ignoreResists = GraphSettings.getInstance().get('ignoreResists') |
| 82 | return [ |
| 83 | YDef(handle='dps', unit=None, label=_t('DPS') if ignoreResists else _t('Effective DPS')), |
| 84 | YDef(handle='volley', unit=None, label=_t('Volley') if ignoreResists else _t('Effective volley')), |
| 85 | YDef(handle='damage', unit=None, label=_t('Damage inflicted') if ignoreResists else _t('Effective damage inflicted'))] |
| 86 | |
| 87 | @property |
| 88 | def tgtExtraCols(self): |
| 89 | cols = [] |
| 90 | if not GraphSettings.getInstance().get('ignoreResists'): |
| 91 | cols.append('Target Resists') |
nothing calls this directly
no test coverage detected