homepage/source/_assets/predictor/Daemon.js

146 lines
2.8 KiB
JavaScript

const DEFAULT_EPSILON = 0.01;
/**
* @param {Number[]} steps
*
* @returns {String}
*/
function create_key(steps) {
return steps.join(':');
}
class Daemon {
/**
* @type {Number}
*/
base;
/**
* @type {Number}
*/
humanCount;
/**
* @type {Number}
*/
robotCount;
/**
* @type {Number}
*/
epsilon;
/**
* @type {Object}
*/
weights = {};
/**
* @param {Number} base
* @param {Number} humanCount
* @param {Number} robotCount
* @param {Number} epsilon
*/
constructor(base, humanCount, robotCount, epsilon = DEFAULT_EPSILON) {
this.base = base;
this.humanCount = humanCount;
this.robotCount = robotCount;
this.epsilon = epsilon;
}
/**
* @returns {Number}
*/
get power() {
return this.humanCount + this.robotCount;
}
/**
* @param {Journal} journal
*
* @returns {Number}
*/
predict(journal) {
const steps = this._getStepSlice(journal);
const proposals = [];
for (let i = 0; i < this.base; ++i) {
proposals[i] = this._getWeight([...steps, i]);
}
const maxWeight = Math.max(...proposals);
return proposals.indexOf(maxWeight);
}
/**
* @param {Journal} journal
* @param {Number} humanValue
*/
adjust(journal, humanValue) {
const steps = this._getStepSlice(journal);
const adjustmentWeight = this._getAdjustmentWeight(journal.length);
this._adjustWeight([...steps, humanValue], adjustmentWeight);
}
/**
* @param {Journal} journal
*
* @returns {Number[]}
*/
_getStepSlice(journal) {
return journal.getLastMovements(this.humanCount, this.robotCount);
}
/**
* @param {Number} stepNumber
*
* @returns {Number}
*
* @private
*/
_getAdjustmentWeight(stepNumber) {
return Math.pow(1 + this.epsilon, stepNumber);
}
/**
* @param {Number[]} steps
*
* @returns {Number}
*
* @private
*/
_getWeight(steps) {
const key = create_key(steps);
const weight = this.weights[key];
return weight === undefined ? 0 : weight;
}
/**
* @param {Number[]} steps
* @param {Number} value
*
* @returns {Number}
*
* @private
*/
_setWeight(steps, value) {
const key = create_key(steps);
this.weights[key] = value;
}
/**
* @param {Number[]} steps
* @param {Number} weight
*
* @private
*/
_adjustWeight(steps, weight) {
const currentWeight = this._getWeight(steps);
const newWeight = currentWeight + weight;
this._setWeight(steps, newWeight);
}
}
export default Daemon;