<commit_before>/* global API_HOST */
import React from 'react';
import heroes from 'dotaconstants/json/heroes.json';
import runes from 'dotaconstants/json/runes.json';
import items from 'dotaconstants/json/items.json';
import orderTypes from 'dotaconstants/json/order_types.json';
import itemIds from 'dotaconstants/json/item_ids.json';
import abilityIds from 'dotaconstants/json/ability_ids.json';
import abilityKeys from 'dotaconstants/json/ability_keys.json';
import heroNames from 'dotaconstants/json/hero_names.json';
import laneRole from 'dotaconstants/json/lane_role.json';
import strings from 'lang';
import {
  formatSeconds,
  abbreviateNumber,
  transformations,
  percentile,
  sum,
} from 'utility';
import Heatmap from 'components/Heatmap';
import {
  TableHeroImage,
  inflictorWithValue,
} from 'components/Visualizations';
import ReactTooltip from 'react-tooltip';
import NavigationMoreHoriz from 'material-ui/svg-icons/navigation/more-horiz';
import ActionOpenInNew from 'material-ui/svg-icons/action/open-in-new';
import SocialPerson from 'material-ui/svg-icons/social/person';
import styles from './Match.css';

export const heroTd = (row, col, field, index, hideName, party) => (
  <TableHeroImage
    image={heroes[row.hero_id] && API_HOST + heroes[row.hero_id].img}
    title={row.name || row.personaname || strings.general_anonymous}
    registered={row.last_login}
    accountId={row.account_id}
    subtitle={
      <span>
        {row.solo_competitive_rank || strings.general_unknown}
        <section
          data-hint={strings.th_solo_mmr}
          data-hint-position="bottom"
        >
          <SocialPerson />
        </section>
        {strings.th_mmr}
      </span>
    }
    playerSlot={row.player_slot}
    hideText={hideName}
    confirmed={row.account_id && row.name}
    party={party}
  />
);

export const heroTdColumn = {
  displayName: 'Player',
  field: 'player_slot',
  displayFn: heroTd,
  sortFn: true,
};

const parties = (row, match) => {
  if (match.parties && Object.values(match.parties).reduce(sum) > 0) {
    const i = match.players.findIndex(player => player.player_slot === row.player_slot);
    const partyPrev = match.parties[(match.players[i - 1] || {}).player_slot] === match.parties[match.players[i].player_slot];
    const partyNext = match.parties[(match.players[i + 1] || {}).player_slot] === match.parties[match.players[i].player_slot];
    if (!partyPrev && partyNext) {
      return <div data-next />;
    }
    if (partyPrev && partyNext) {
      return <div data-prev-next />;
    }
    if (partyPrev && !partyNext) {
      return <div data-prev />;
    }
  }
  return null;
};

export const overviewColumns = match => [{
  displayName: 'Player',
  field: 'player_slot',
  displayFn: (row, col, field, i) => heroTd(row, col, field, i, false, parties(row, match)),
  sortFn: true,
}, {
  displayName: strings.th_level,
  tooltip: strings.tooltip_level,
  field: 'level',
  sortFn: true,
  maxFn: true,
}, {
  displayName: strings.th_kills,
  tooltip: strings.tooltip_kills,
  field: 'kills',
  sortFn: true,
  displayFn: transformations.kda,
}, {
  displayName: strings.th_deaths,
  tooltip: strings.tooltip_deaths,
  field: 'deaths',
  sortFn: true,
}, {
  displayName: strings.th_assists,
  tooltip: strings.tooltip_assists,
  field: 'assists',
  sortFn: true,
}, {
  displayName: strings.th_gold_per_min,
  tooltip: strings.tooltip_gold_per_min,
  field: 'gold_per_min',
  sortFn: true,
  color: styles.golden,
}, {
  displayName: strings.th_xp_per_min,
  tooltip: strings.tooltip_xp_per_min,
  field: 'xp_per_min',
  sortFn: true,
}, {
  displayName: strings.th_last_hits,
  tooltip: strings.tooltip_last_hits,
  field: 'last_hits',
  sortFn: true,
}, {
  displayName: strings.th_denies,
  tooltip: strings.tooltip_denies,
  field: 'denies',
  sortFn: true,
}, {
  displayName: strings.th_hero_damage,
  tooltip: strings.tooltip_hero_damage,
  field: 'hero_damage',
  displayFn: row => abbreviateNumber(row.hero_damage),
  sortFn: true,
}, {
  displayName: strings.th_hero_healing,
  tooltip: strings.tooltip_hero_healing,
  field: 'hero_healing',
  displayFn: row => abbreviateNumber(row.hero_healing),
  sortFn: true,
}, {
  displayName: strings.th_tower_damage,
  tooltip: strings.tooltip_tower_damage,
  field: 'tower_damage',
  displayFn: row => abbreviateNumber(row.tower_damage),
  sortFn: true,
}, {
  displayName: (
    <span className={styles.thGold}>
      <img src={`${API_HOST}/apps/dota2/images/tooltips/gold.png`} role="presentation" />
      {strings.th_gold}
    </span>
  ),
  tooltip: strings.tooltip_gold,
  field: 'gold_per_min',
  displayFn: row => abbreviateNumber((row.gold_per_min * row.duration) / 60),
  sortFn: true,
  color: styles.golden,
}, {
  displayName: strings.th_items,
  tooltip: strings.tooltip_items,
  field: 'items',
  displayFn: (row) => {
    const itemArray = [];
    const itemBearArray = [];
    for (let i = 0; i < 6; i += 1) {
      const itemKey = itemIds[row[`item_${i}`]];
      const firstPurchase = row.first_purchase_time && row.first_purchase_time[itemKey];

      if (items[itemKey]) {
        itemArray.push(
          inflictorWithValue(itemKey, formatSeconds(firstPurchase))
        );
      }

      if (row.hero_id === 80 && row.additional_units) {
        const itemBearKey = itemIds[row.additional_units[0][`item_${i}`]];
        const firstBearPurchase = row.first_purchase_time && row.first_purchase_time[itemBearKey];

        if (items[itemBearKey]) {
          itemBearArray.push(
            inflictorWithValue(itemBearKey, formatSeconds(firstBearPurchase))
          );
        }
      }
    }<commit_msg>Rename const for additional unit items, added comment that explains why we should use hero_id<commit_after>/* global API_HOST */
import React from 'react';
import heroes from 'dotaconstants/json/heroes.json';
import runes from 'dotaconstants/json/runes.json';
import items from 'dotaconstants/json/items.json';
import orderTypes from 'dotaconstants/json/order_types.json';
import itemIds from 'dotaconstants/json/item_ids.json';
import abilityIds from 'dotaconstants/json/ability_ids.json';
import abilityKeys from 'dotaconstants/json/ability_keys.json';
import heroNames from 'dotaconstants/json/hero_names.json';
import laneRole from 'dotaconstants/json/lane_role.json';
import strings from 'lang';
import {
  formatSeconds,
  abbreviateNumber,
  transformations,
  percentile,
  sum,
} from 'utility';
import Heatmap from 'components/Heatmap';
import {
  TableHeroImage,
  inflictorWithValue,
} from 'components/Visualizations';
import ReactTooltip from 'react-tooltip';
import NavigationMoreHoriz from 'material-ui/svg-icons/navigation/more-horiz';
import ActionOpenInNew from 'material-ui/svg-icons/action/open-in-new';
import SocialPerson from 'material-ui/svg-icons/social/person';
import styles from './Match.css';

export const heroTd = (row, col, field, index, hideName, party) => (
  <TableHeroImage
    image={heroes[row.hero_id] && API_HOST + heroes[row.hero_id].img}
    title={row.name || row.personaname || strings.general_anonymous}
    registered={row.last_login}
    accountId={row.account_id}
    subtitle={
      <span>
        {row.solo_competitive_rank || strings.general_unknown}
        <section
          data-hint={strings.th_solo_mmr}
          data-hint-position="bottom"
        >
          <SocialPerson />
        </section>
        {strings.th_mmr}
      </span>
    }
    playerSlot={row.player_slot}
    hideText={hideName}
    confirmed={row.account_id && row.name}
    party={party}
  />
);

export const heroTdColumn = {
  displayName: 'Player',
  field: 'player_slot',
  displayFn: heroTd,
  sortFn: true,
};

const parties = (row, match) => {
  if (match.parties && Object.values(match.parties).reduce(sum) > 0) {
    const i = match.players.findIndex(player => player.player_slot === row.player_slot);
    const partyPrev = match.parties[(match.players[i - 1] || {}).player_slot] === match.parties[match.players[i].player_slot];
    const partyNext = match.parties[(match.players[i + 1] || {}).player_slot] === match.parties[match.players[i].player_slot];
    if (!partyPrev && partyNext) {
      return <div data-next />;
    }
    if (partyPrev && partyNext) {
      return <div data-prev-next />;
    }
    if (partyPrev && !partyNext) {
      return <div data-prev />;
    }
  }
  return null;
};

export const overviewColumns = match => [{
  displayName: 'Player',
  field: 'player_slot',
  displayFn: (row, col, field, i) => heroTd(row, col, field, i, false, parties(row, match)),
  sortFn: true,
}, {
  displayName: strings.th_level,
  tooltip: strings.tooltip_level,
  field: 'level',
  sortFn: true,
  maxFn: true,
}, {
  displayName: strings.th_kills,
  tooltip: strings.tooltip_kills,
  field: 'kills',
  sortFn: true,
  displayFn: transformations.kda,
}, {
  displayName: strings.th_deaths,
  tooltip: strings.tooltip_deaths,
  field: 'deaths',
  sortFn: true,
}, {
  displayName: strings.th_assists,
  tooltip: strings.tooltip_assists,
  field: 'assists',
  sortFn: true,
}, {
  displayName: strings.th_gold_per_min,
  tooltip: strings.tooltip_gold_per_min,
  field: 'gold_per_min',
  sortFn: true,
  color: styles.golden,
}, {
  displayName: strings.th_xp_per_min,
  tooltip: strings.tooltip_xp_per_min,
  field: 'xp_per_min',
  sortFn: true,
}, {
  displayName: strings.th_last_hits,
  tooltip: strings.tooltip_last_hits,
  field: 'last_hits',
  sortFn: true,
}, {
  displayName: strings.th_denies,
  tooltip: strings.tooltip_denies,
  field: 'denies',
  sortFn: true,
}, {
  displayName: strings.th_hero_damage,
  tooltip: strings.tooltip_hero_damage,
  field: 'hero_damage',
  displayFn: row => abbreviateNumber(row.hero_damage),
  sortFn: true,
}, {
  displayName: strings.th_hero_healing,
  tooltip: strings.tooltip_hero_healing,
  field: 'hero_healing',
  displayFn: row => abbreviateNumber(row.hero_healing),
  sortFn: true,
}, {
  displayName: strings.th_tower_damage,
  tooltip: strings.tooltip_tower_damage,
  field: 'tower_damage',
  displayFn: row => abbreviateNumber(row.tower_damage),
  sortFn: true,
}, {
  displayName: (
    <span className={styles.thGold}>
      <img src={`${API_HOST}/apps/dota2/images/tooltips/gold.png`} role="presentation" />
      {strings.th_gold}
    </span>
  ),
  tooltip: strings.tooltip_gold,
  field: 'gold_per_min',
  displayFn: row => abbreviateNumber((row.gold_per_min * row.duration) / 60),
  sortFn: true,
  color: styles.golden,
}, {
  displayName: strings.th_items,
  tooltip: strings.tooltip_items,
  field: 'items',
  displayFn: (row) => {
    const itemArray = [];
    const itemBearArray = [];
    for (let i = 0; i < 6; i += 1) {
      const itemKey = itemIds[row[`item_${i}`]];
      const firstPurchase = row.first_purchase_time && row.first_purchase_time[itemKey];

      if (items[itemKey]) {
        itemArray.push(
          inflictorWithValue(itemKey, formatSeconds(firstPurchase))
        );
      }

      // Use hero_id because Meepo showing up as an additional unit in some matches http://dev.dota2.com/showthread.php?t=132401
      if (row.hero_id === 80 && row.additional_units) {
        const additionalItemKey = itemIds[row.additional_units[0][`item_${i}`]];
        const additionalFirstPurchase = row.first_purchase_time && row.first_purchase_time[additionalItemKey];

        if (items[additionalItemKey]) {
          itemBearArray.push(
            inflictorWithValue(additionalItemKey, formatSeconds(additionalFirstPurchase))
          );
        }
      }
    }
{'fraction_non_alphanumeric': 0.13561964146531566, 'fraction_numerical': 0.002684680003464103, 'mean_word_length': 3.9308283518360376, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 49, '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': '394892', 'n_tokens_mistral': 4036, 'n_tokens_neox': 3933, 'n_words': 764}