<commit_before>// @flow
import { createSelector } from 'reselect'
import createCachedSelector from 're-reselect'

import { entities, getCurrentPlayer, type entitySelector } from './entities.js'
import { sortOrderSort } from 'utils'
import * as calc from 'utils/calculated/'

export const getSpecificQc = (state: Object, id: number) =>
  entities(state).qcs[id]
const qcIdMemoizer = (state, id) => id

const getQcMerits = state => entities(state).qc_merits

// $FlowFixMe
export const getMeritsForQc = createCachedSelector(
  [getSpecificQc, getQcMerits],
  (qc, merits) => qc.qc_merits.map(m => merits[m]).sort(sortOrderSort)
)(qcIdMemoizer)

export const getQcAttacks = (state: Object) => entities(state).qc_attacks

// $FlowFixMe
export const getAttacksForQc = createCachedSelector(
  [getSpecificQc, getQcAttacks],
  (qc, attacks) => qc.qc_attacks.map(m => attacks[m]).sort(sortOrderSort)
)(qcIdMemoizer)

export const getQcCharms = (state: Object) => entities(state).qc_charms

// $FlowFixMe
export const getCharmsForQc = createCachedSelector(
  [getSpecificQc, getQcCharms],
  (qc, charms) => qc.qc_charms.map(m => charms[m]).sort(sortOrderSort)
)(qcIdMemoizer)

// $FlowFixMe
export const getPenaltiesForQc = createCachedSelector(
  [getSpecificQc, getMeritsForQc],
  (character, merits) => {
    const meritNames = merits.map(m => m.name.toLowerCase())
    return {
      onslaught: character.onslaught,
      wound: calc.woundPenalty(character, meritNames),
    }
  }
)(qcIdMemoizer)

// $FlowFixMe
export const getPoolsAndRatingsForQc = createCachedSelector(
  [getSpecificQc, getMeritsForQc, getPenaltiesForQc],
  (qc, merits, penalties) => {
    const meritNames = [...new Set(merits.map(m => m.name.toLowerCase()))]
    const tiny = meritNames.some(m => m.toLowerCase().includes('tiny creature'))
      ? [{ label: 'tiny creature', bonus: 2, situational: true }]
      : undefined

    return {
      guile: calc.qcRating(qc, qc.guile, penalties.wound),
      resolve: calc.qcRating(qc, qc.resolve, penalties.wound),
      appearance: calc.appearanceRating(
        { attr_appearance: qc.appearance },
        meritNames
      ),

      evasion: calc.qcRating(
        qc,
        qc.evasion,
        penalties.wound + penalties.onslaught,
        tiny
      ),
      parry: calc.qcRating(qc, qc.parry, penalties.wound + penalties.onslaught),
      senses: calc.qcRating(qc, qc.senses, penalties.wound),
      joinBattle: calc.qcPool(qc, qc.join_battle, penalties.wound),
    }
  }
)(qcIdMemoizer)

export const doIOwnQc: entitySelector<boolean> = createSelector(
  [getCurrentPlayer, getSpecificQc],
  (player, qc) => qc !== undefined && player.id === qc.player_id
)

export const amIStOfQc: entitySelector<boolean> = createSelector(
  [getCurrentPlayer, getSpecificQc, entities],
  (player, qc, ents) =>
    qc != null &&
    qc.chronicle_id != null &&
    ents.chronicles[qc.chronicle_id] &&
    ents.chronicles[qc.chronicle_id].st_id === player.id
)

export const canISeeQc: entitySelector<boolean> = createSelector(
  [getSpecificQc, doIOwnQc, amIStOfQc],
  (qc, doI, amI) => !qc.hidden || doI || amI
)

export const canIEditQc: entitySelector<boolean> = createSelector(
  [doIOwnQc, amIStOfQc],
  (doI, amI) => doI || amI
)

export const canIDeleteQc = doIOwnQc<commit_msg>Fix QC excellencies on Senses pool<commit_after>// @flow
import { createSelector } from 'reselect'
import createCachedSelector from 're-reselect'

import { entities, getCurrentPlayer, type entitySelector } from './entities.js'
import { sortOrderSort } from 'utils'
import * as calc from 'utils/calculated/'

export const getSpecificQc = (state: Object, id: number) =>
  entities(state).qcs[id]
const qcIdMemoizer = (state, id) => id

const getQcMerits = state => entities(state).qc_merits

// $FlowFixMe
export const getMeritsForQc = createCachedSelector(
  [getSpecificQc, getQcMerits],
  (qc, merits) => qc.qc_merits.map(m => merits[m]).sort(sortOrderSort)
)(qcIdMemoizer)

export const getQcAttacks = (state: Object) => entities(state).qc_attacks

// $FlowFixMe
export const getAttacksForQc = createCachedSelector(
  [getSpecificQc, getQcAttacks],
  (qc, attacks) => qc.qc_attacks.map(m => attacks[m]).sort(sortOrderSort)
)(qcIdMemoizer)

export const getQcCharms = (state: Object) => entities(state).qc_charms

// $FlowFixMe
export const getCharmsForQc = createCachedSelector(
  [getSpecificQc, getQcCharms],
  (qc, charms) => qc.qc_charms.map(m => charms[m]).sort(sortOrderSort)
)(qcIdMemoizer)

// $FlowFixMe
export const getPenaltiesForQc = createCachedSelector(
  [getSpecificQc, getMeritsForQc],
  (character, merits) => {
    const meritNames = merits.map(m => m.name.toLowerCase())
    return {
      onslaught: character.onslaught,
      wound: calc.woundPenalty(character, meritNames),
    }
  }
)(qcIdMemoizer)

// $FlowFixMe
export const getPoolsAndRatingsForQc = createCachedSelector(
  [getSpecificQc, getMeritsForQc, getPenaltiesForQc],
  (qc, merits, penalties) => {
    const meritNames = [...new Set(merits.map(m => m.name.toLowerCase()))]
    const tiny = meritNames.some(m => m.toLowerCase().includes('tiny creature'))
      ? [{ label: 'tiny creature', bonus: 2, situational: true }]
      : undefined

    return {
      guile: calc.qcRating(qc, qc.guile, penalties.wound),
      resolve: calc.qcRating(qc, qc.resolve, penalties.wound),
      appearance: calc.appearanceRating(
        { attr_appearance: qc.appearance },
        meritNames
      ),

      evasion: calc.qcRating(
        qc,
        qc.evasion,
        penalties.wound + penalties.onslaught,
        tiny
      ),
      parry: calc.qcRating(qc, qc.parry, penalties.wound + penalties.onslaught),
      senses: calc.qcPool(qc, qc.senses, penalties.wound),
      joinBattle: calc.qcPool(qc, qc.join_battle, penalties.wound),
    }
  }
)(qcIdMemoizer)

export const doIOwnQc: entitySelector<boolean> = createSelector(
  [getCurrentPlayer, getSpecificQc],
  (player, qc) => qc !== undefined && player.id === qc.player_id
)

export const amIStOfQc: entitySelector<boolean> = createSelector(
  [getCurrentPlayer, getSpecificQc, entities],
  (player, qc, ents) =>
    qc != null &&
    qc.chronicle_id != null &&
    ents.chronicles[qc.chronicle_id] &&
    ents.chronicles[qc.chronicle_id].st_id === player.id
)

export const canISeeQc: entitySelector<boolean> = createSelector(
  [getSpecificQc, doIOwnQc, amIStOfQc],
  (qc, doI, amI) => !qc.hidden || doI || amI
)

export const canIEditQc: entitySelector<boolean> = createSelector(
  [doIOwnQc, amIStOfQc],
  (doI, amI) => doI || amI
)

export const canIDeleteQc = doIOwnQc
{'fraction_non_alphanumeric': 0.13361611876988336, 'fraction_numerical': 0.0003029843963035904, 'mean_word_length': 4.264752791068581, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 51, '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': '2211954', 'n_tokens_mistral': 2452, 'n_tokens_neox': 2343, 'n_words': 474}