<commit_before>import React from 'react';
import ImportTarnishedSentinelMedallion from 'Parser/Core/Modules/Items/TarnishedSentinelMedallion';
import ITEMS from 'common/ITEMS';
import SPELLS from 'common/SPELLS';
import { formatNumber } from 'common/format';
import Combatants from 'Parser/Core/Modules/Combatants';
import CooldownThroughputTracker from '../Features/CooldownThroughputTracker';

class TarnishedSentinelMedallion extends ImportTarnishedSentinelMedallion {
  static dependencies = {
    cooldownThroughputTracker: CooldownThroughputTracker,
    combatants: Combatants,
  };

  TS_LENGTH = 15000;
  PAIRING_LEEWAY = 5000; //giving 5 (as agreed upon with Putro) seconds of leeway (so that half of Medallion has TS)
  medallionEnd = 0;
  medallionUptime = [];
  medallionDuration = 20000;

  on_byPlayer_damage(event) {
    const spellId = event.ability.guid;
    if (this.damageAbilities.has(spellId) && event.timestamp > this.medallionEnd) {
      this.medallionEnd = event.timestamp + this.medallionDuration;
      this.medallionUptime.push({ 'start': event.timestamp, 'end': this.medallionEnd });
      this.checkOverlap();
    }
    if (this.damageAbilities.has(spellId)) {
      this.damage += event.amount + (event.absorbed || 0);
    }
  }

  checkOverlap() {
    this.medallionCasts = 0;
    this.medallionCastsWithTS = 0;
    this.medallionUptime.forEach(cast => {
      this.medallionCasts++;
      this.cooldownThroughputTracker.pastCooldowns.forEach(ts => {
        let tsEnd; //because sometimes ts.end is undefined if the parser hasn't gotten there yet
        if (!ts.end) {
          tsEnd = ts.start + this.TS_LENGTH;
        }
        else {
          tsEnd = ts.end;
        }
        if (ts.start > cast.start - this.PAIRING_LEEWAY && tsEnd < cast.end + this.PAIRING_LEEWAY && ts.spell.id === SPELLS.TRUESHOT.id) {
          this.medallionCastsWithTS++;
        }
      });
    });
  }

  item() {
    return {
      item: ITEMS.TARNISHED_SENTINEL_MEDALLION,
      result: (
        <dfn data-tip={`<b> ${formatNumber(this.medallionCastsWithTS)} out of ${formatNumber(this.medallionCasts)} </b> Medallion casts were combined with Trueshot.`}>
          {formatNumber(this.damage)} damage - {this.owner.formatItemDamageDone(this.damage)}
        </dfn>
      ),
    };
  }
}

export default TarnishedSentinelMedallion;
<commit_msg>owl update<commit_after>import React from 'react';
import ImportTarnishedSentinelMedallion from 'Parser/Core/Modules/Items/TarnishedSentinelMedallion';
import ITEMS from 'common/ITEMS';
import SPELLS from 'common/SPELLS';
import { formatNumber } from 'common/format';
import Combatants from 'Parser/Core/Modules/Combatants';
import CooldownThroughputTracker from '../Features/CooldownThroughputTracker';

class TarnishedSentinelMedallion extends ImportTarnishedSentinelMedallion {
  static dependencies = {
    cooldownThroughputTracker: CooldownThroughputTracker,
    combatants: Combatants,
  };

  TS_LENGTH = 15000;
  PAIRING_LEEWAY = 5000; //giving 5 (as agreed upon with Putro) seconds of leeway (so that half of Medallion has TS)
  medallionEnd = 0;
  medallionUptime = [];
  medallionDuration = 20000;
  medallionCasts = 0;

  on_byPlayer_damage(event) {
    const spellId = event.ability.guid;
    if (this.damageAbilities.has(spellId) && event.timestamp > this.medallionEnd) {
      this.medallionEnd = event.timestamp + this.medallionDuration;
      this.medallionUptime.push({ 'start': event.timestamp, 'end': this.medallionEnd });
      this.checkOverlap();
    }
    if (this.damageAbilities.has(spellId)) {
      this.damage += event.amount + (event.absorbed || 0);
    }
  }

  on_byPlayer_cast(event){
    const buffId = event.ability.guid;
    if(buffId !== SPELLS.SPECTRAL_OWL.id) {
      return;
    }
    this.medallionCasts += 1;
  }


  checkOverlap() {
    this.medallionCastsWithTS = 0;
    this.medallionUptime.forEach(cast => {
      this.cooldownThroughputTracker.pastCooldowns.forEach(ts => {
        let tsEnd; //because sometimes ts.end is undefined if the parser hasn't gotten there yet
        if (!ts.end) {
          tsEnd = ts.start + this.TS_LENGTH;
        }
        else {
          tsEnd = ts.end;
        }
        if (ts.start > cast.start - this.PAIRING_LEEWAY && tsEnd < cast.end + this.PAIRING_LEEWAY && ts.spell.id === SPELLS.TRUESHOT.id) {
          this.medallionCastsWithTS++;
        }
      });
    });
  }

  item() {
    return {
      item: ITEMS.TARNISHED_SENTINEL_MEDALLION,
      result: (
        <dfn data-tip={`<b> ${formatNumber(this.medallionCastsWithTS)} out of ${formatNumber(this.medallionCasts)} </b> Medallion casts were combined with Trueshot.`}>
          {formatNumber(this.damage)} damage - {this.owner.formatItemDamageDone(this.damage)}
        </dfn>
      ),
    };
  }
}

export default TarnishedSentinelMedallion;

{'fraction_non_alphanumeric': 0.1160107150216361, 'fraction_numerical': 0.008036266227076035, 'mean_word_length': 3.322350845948353, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2145835', 'n_tokens_mistral': 1713, 'n_tokens_neox': 1636, 'n_words': 313}