135 lines
2.7 KiB
TypeScript

import Journal from './Journal';
const DEFAULT_EPSILON = 0.01;
function create_key(steps: number[]): string {
return steps.join(':');
}
class Daemon {
/**
* @type {Number}
*/
base;
/**
* @type {Number}
*/
humanCount;
/**
* @type {Number}
*/
robotCount;
/**
* @type {Number}
*/
epsilon;
/**
* @type {Object}
*/
weights = {};
constructor(
base: number,
humanCount: number,
robotCount: number,
epsilon: number = DEFAULT_EPSILON
) {
this.base = base;
this.humanCount = humanCount;
this.robotCount = robotCount;
this.epsilon = epsilon;
}
get power(): number {
return this.humanCount + this.robotCount;
}
predict(journal: Journal): number {
const steps = this._getStepSlice(journal);
const proposals: number[] = [];
for (let i = 0; i < this.base; ++i) {
const weight = this._getWeight([...steps, i]);
proposals.push(weight);
}
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[]}
*/
private _getStepSlice(journal) {
return journal.getLastMovements(this.humanCount, this.robotCount);
}
/**
* @param {Number} stepNumber
*
* @returns {Number}
*
* @private
*/
private _getAdjustmentWeight(stepNumber) {
return Math.pow(1 + this.epsilon, stepNumber);
}
/**
* @param {Number[]} steps
*
* @returns {Number}
*
* @private
*/
private _getWeight(steps: number[]): number {
const key = create_key(steps);
const weight = this.weights[key];
return weight as number;
}
/**
* @param {Number[]} steps
* @param {Number} value
*
* @returns {Number}
*
* @private
*/
private _setWeight(steps, value) {
const key = create_key(steps);
this.weights[key] = value;
}
/**
* @param {Number[]} steps
* @param {Number} weight
*
* @private
*/
private _adjustWeight(steps, weight) {
const currentWeight = this._getWeight(steps);
const newWeight = currentWeight + weight;
this._setWeight(steps, newWeight);
}
}
export default Daemon;