<commit_before>const _ = require('lodash');
const Entity = require('./entity');
const simulateWorld = require('./simulator');

require('../lib/map-extensions'); // To the reader, my apologies

const MAX_FITNESS = 1000;

function fitness (expectedPosition, entity) {
  const distance = {
    x: Math.abs(expectedPosition.x - entity.x),
    y: Math.abs(expectedPosition.y - entity.y)
  };

  return MAX_FITNESS - Math.sqrt(Math.pow(distance.x, 2) + Math.pow(distance.y, 2));
}

function limitTo (limit, number) {
  return _.max([limit, number]);
}

function meanOfSquares (numbers) {
  return Math.sqrt(_.sum(numbers.map(number => Math.pow(limitTo(0, number), 2)))) / numbers.length;
}

function weightedAverage (scoresPerScenario) {
  return {
    score: meanOfSquares(scoresPerScenario.valuesArray().map(score => score.score)),
    weightedScore: meanOfSquares(scoresPerScenario.valuesArray().map(score => score.weightedScore))
  };
}

function participantInScenario (participant) {
  return (fitnesses, scenario) => {
    return scenario.participants.findIndex(participantKey =>
      participantKey === participant
    ) !== -1;
  };
}

function boilDownIndividualScore (individual, participant, fitnesses, scenarioImportances) {
  if (fitnesses.filter(participantInScenario(participant)).size === 0) {
    return {
      score: 0,
      weightedScore: 0
    };
  }

  return weightedAverage(
    fitnesses
    .filter(participantInScenario(participant))
    .map(fitnessesForScenario => fitnessesForScenario[participant].get(individual))
    .map(meanOfSquares)
    .map((scoreForScenario, scenario) => {
      return {
        score: scoreForScenario,
        weightedScore: scoreForScenario * scenarioImportances[participant][scenario.id]
      };
    })
  );
}

function scoreScenarios (scenarios, individuals) {
  return scenarios.map(scenario => {
    return [scenario, scoreScenario(scenario, individuals)];
  }).reduce((allScenarioScores, score) => {
    const [scenario, scenarioScores] = score;
    return allScenarioScores.set(scenario, scenarioScores);
  }, new Map());
};

function scoreScenario (scenario, individuals) {
  return scenario.participants.map(participant => {
    return {
      [participant]: scoreParticipantOnScenario(scenario, participant, individuals[participant])
    };
  }).reduce((fitnesses, participantFitnesses) => Object.assign(fitnesses, participantFitnesses), {});
}

function scoreParticipantOnScenario (scenario, participant, individuals) {
  return individuals.map(individual => {
    return [individual, scoreIndividualOnScenario(scenario, participant, individual)];
  }).reduce((scenarioScores, individualAndScores) => {
    const [individual, scores] = individualAndScores;
    return scenarioScores.set(individual, scores);
  }, new Map());<commit_msg>Indent a set of chained calls for clarity<commit_after>const _ = require('lodash');
const Entity = require('./entity');
const simulateWorld = require('./simulator');

require('../lib/map-extensions'); // To the reader, my apologies

const MAX_FITNESS = 1000;

function fitness (expectedPosition, entity) {
  const distance = {
    x: Math.abs(expectedPosition.x - entity.x),
    y: Math.abs(expectedPosition.y - entity.y)
  };

  return MAX_FITNESS - Math.sqrt(Math.pow(distance.x, 2) + Math.pow(distance.y, 2));
}

function limitTo (limit, number) {
  return _.max([limit, number]);
}

function meanOfSquares (numbers) {
  return Math.sqrt(_.sum(numbers.map(number => Math.pow(limitTo(0, number), 2)))) / numbers.length;
}

function weightedAverage (scoresPerScenario) {
  return {
    score: meanOfSquares(scoresPerScenario.valuesArray().map(score => score.score)),
    weightedScore: meanOfSquares(scoresPerScenario.valuesArray().map(score => score.weightedScore))
  };
}

function participantInScenario (participant) {
  return (fitnesses, scenario) => {
    return scenario.participants.findIndex(participantKey =>
      participantKey === participant
    ) !== -1;
  };
}

function boilDownIndividualScore (individual, participant, fitnesses, scenarioImportances) {
  if (fitnesses.filter(participantInScenario(participant)).size === 0) {
    return {
      score: 0,
      weightedScore: 0
    };
  }

  return weightedAverage(
    fitnesses
      .filter(participantInScenario(participant))
      .map(fitnessesForScenario => fitnessesForScenario[participant].get(individual))
      .map(meanOfSquares)
      .map((scoreForScenario, scenario) => {
        return {
          score: scoreForScenario,
          weightedScore: scoreForScenario * scenarioImportances[participant][scenario.id]
        };
      }
    )
  );
}

function scoreScenarios (scenarios, individuals) {
  return scenarios.map(scenario => {
    return [scenario, scoreScenario(scenario, individuals)];
  }).reduce((allScenarioScores, score) => {
    const [scenario, scenarioScores] = score;
    return allScenarioScores.set(scenario, scenarioScores);
  }, new Map());
};

function scoreScenario (scenario, individuals) {
  return scenario.participants.map(participant => {
    return {
      [participant]: scoreParticipantOnScenario(scenario, participant, individuals[participant])
    };
  }).reduce((fitnesses, participantFitnesses) => Object.assign(fitnesses, participantFitnesses), {});
}

function scoreParticipantOnScenario (scenario, participant, individuals) {
  return individuals.map(individual => {
    return [individual, scoreIndividualOnScenario(scenario, participant, individual)];
  }).reduce((scenarioScores, individualAndScores) => {
    const [individual, scores] = individualAndScores;
    return scenarioScores.set(individual, scores);
  }, new Map());
{'fraction_non_alphanumeric': 0.1319186560565871, 'fraction_numerical': 0.004244031830238726, 'mean_word_length': 4.627860696517413, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 29, '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': '6113853', 'n_tokens_mistral': 1803, 'n_tokens_neox': 1658, 'n_words': 326}