Restore tests
This commit is contained in:
parent
4a18dc5808
commit
eb66b6904d
@ -7,30 +7,15 @@ function create_key(steps: number[]): string {
|
||||
}
|
||||
|
||||
class Daemon {
|
||||
/**
|
||||
* @type {Number}
|
||||
*/
|
||||
base;
|
||||
base: number;
|
||||
|
||||
/**
|
||||
* @type {Number}
|
||||
*/
|
||||
humanCount;
|
||||
humanCount: number;
|
||||
|
||||
/**
|
||||
* @type {Number}
|
||||
*/
|
||||
robotCount;
|
||||
robotCount: number;
|
||||
|
||||
/**
|
||||
* @type {Number}
|
||||
*/
|
||||
epsilon;
|
||||
epsilon: number;
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
*/
|
||||
weights = {};
|
||||
weights: { [key: string]: number } = {};
|
||||
|
||||
constructor(
|
||||
base: number,
|
||||
@ -62,69 +47,31 @@ class Daemon {
|
||||
return proposals.indexOf(maxWeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Journal} journal
|
||||
* @param {Number} humanValue
|
||||
*/
|
||||
adjust(journal, humanValue) {
|
||||
adjust(journal: Journal, humanValue: number) {
|
||||
const steps = this._getStepSlice(journal);
|
||||
const adjustmentWeight = this._getAdjustmentWeight(journal.length);
|
||||
this._adjustWeight([...steps, humanValue], adjustmentWeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Journal} journal
|
||||
*
|
||||
* @returns {Number[]}
|
||||
*/
|
||||
private _getStepSlice(journal) {
|
||||
private _getStepSlice(journal: Journal): number[] {
|
||||
return journal.getLastMovements(this.humanCount, this.robotCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number} stepNumber
|
||||
*
|
||||
* @returns {Number}
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _getAdjustmentWeight(stepNumber) {
|
||||
private _getAdjustmentWeight(stepNumber: number): number {
|
||||
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;
|
||||
return key in this.weights ? this.weights[key] : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number[]} steps
|
||||
* @param {Number} value
|
||||
*
|
||||
* @returns {Number}
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _setWeight(steps, value) {
|
||||
private _setWeight(steps: number[], value: number): void {
|
||||
const key = create_key(steps);
|
||||
this.weights[key] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number[]} steps
|
||||
* @param {Number} weight
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _adjustWeight(steps, weight) {
|
||||
private _adjustWeight(steps: number[], weight: number): void {
|
||||
const currentWeight = this._getWeight(steps);
|
||||
const newWeight = currentWeight + weight;
|
||||
this._setWeight(steps, newWeight);
|
||||
|
@ -3,7 +3,6 @@
|
||||
*/
|
||||
class Move {
|
||||
public human: number;
|
||||
|
||||
public robot: number;
|
||||
|
||||
constructor(human: number, robot: number) {
|
||||
|
@ -18,22 +18,22 @@ export default class Predictor {
|
||||
/**
|
||||
* @type {Number}
|
||||
*/
|
||||
base;
|
||||
base: number;
|
||||
|
||||
/**
|
||||
* @type {Number}
|
||||
*/
|
||||
score;
|
||||
score: number;
|
||||
|
||||
/**
|
||||
* @type {Journal}
|
||||
*/
|
||||
journal;
|
||||
journal: Journal;
|
||||
|
||||
/**
|
||||
* @type {Supervisor}
|
||||
*/
|
||||
supervisor;
|
||||
supervisor: Supervisor;
|
||||
|
||||
/**
|
||||
* @param {Object} config
|
||||
@ -46,13 +46,8 @@ export default class Predictor {
|
||||
this.supervisor = new Supervisor(daemons, config.supervisor_epsilon);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number|String} humanValue
|
||||
*
|
||||
* @returns {Number}
|
||||
*/
|
||||
pass(humanValue) {
|
||||
const value = parseInt(humanValue, 10);
|
||||
pass(humanValue: number): number {
|
||||
const value = humanValue;
|
||||
if (value < 0 || value >= this.base) {
|
||||
throw new Error(`Passed value must be in [0, ${this.base})`);
|
||||
}
|
||||
@ -70,7 +65,7 @@ export default class Predictor {
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_createDaemons(daemonConfigs) {
|
||||
private _createDaemons(daemonConfigs) {
|
||||
return daemonConfigs.map(config => {
|
||||
return new Daemon(
|
||||
this.base,
|
||||
@ -81,10 +76,7 @@ export default class Predictor {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Number}
|
||||
*/
|
||||
stepCount() {
|
||||
stepCount(): number {
|
||||
return this.journal.length;
|
||||
}
|
||||
}
|
||||
|
@ -21,11 +21,6 @@ class Supervisor {
|
||||
this.epsilon = epsilon;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Journal} journal
|
||||
*
|
||||
* @returns {Number}
|
||||
*/
|
||||
predict(journal: Journal): number {
|
||||
const predictions = this._createPredictions(journal);
|
||||
const ordered = this._sortPredictions(predictions);
|
||||
@ -33,10 +28,6 @@ class Supervisor {
|
||||
return ordered[0].value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Journal} journal
|
||||
* @param {Number} humanValue
|
||||
*/
|
||||
adjust(journal: Journal, humanValue) {
|
||||
const predictions = this._createPredictions(journal);
|
||||
for (const prediction of predictions) {
|
||||
|
@ -4,49 +4,51 @@ import { expect } from 'chai';
|
||||
import Daemon from '../src/Daemon';
|
||||
import Journal from '../src/Journal';
|
||||
|
||||
// it('Get prediction for beginning', function() {
|
||||
// const m = new Journal();
|
||||
// const d = new Daemon(2, 1, 1);
|
||||
// const predicted = d.predict(m);
|
||||
// expect(predicted).to.equals(0);
|
||||
// });
|
||||
describe('Daemon', function() {
|
||||
it('Get prediction for beginning', function() {
|
||||
const journal = new Journal();
|
||||
const daemon = new Daemon(2, 1, 1);
|
||||
const predicted = daemon.predict(journal);
|
||||
expect(predicted).to.equals(0);
|
||||
});
|
||||
|
||||
it('Can get power', function() {
|
||||
const d = new Daemon(2, 5, 8);
|
||||
expect(d.power).to.eqls(13);
|
||||
});
|
||||
|
||||
// it('Daemon 1-1', function() {
|
||||
// const m = new Journal();
|
||||
// const d = new Daemon(2, 1, 1);
|
||||
//
|
||||
// const steps = [
|
||||
// {
|
||||
// prediction: 0,
|
||||
// human: 1,
|
||||
// },
|
||||
// {
|
||||
// prediction: 0,
|
||||
// human: 1,
|
||||
// },
|
||||
// {
|
||||
// prediction: 1,
|
||||
// human: 1,
|
||||
// },
|
||||
// {
|
||||
// prediction: 0,
|
||||
// human: 1,
|
||||
// },
|
||||
// {
|
||||
// prediction: 1,
|
||||
// human: 1,
|
||||
// },
|
||||
// ];
|
||||
//
|
||||
// steps.forEach(step => {
|
||||
// const prediction = d.predict(m);
|
||||
// expect(prediction).to.eqls(step.prediction);
|
||||
// d.adjust(m, step.human);
|
||||
// m.makeMove(step.human, step.prediction);
|
||||
// });
|
||||
// });
|
||||
it('Daemon 1-1', function() {
|
||||
const journal = new Journal();
|
||||
const daemon = new Daemon(2, 1, 1, 0.1);
|
||||
|
||||
const steps = [
|
||||
{
|
||||
prediction: 0,
|
||||
human: 1,
|
||||
},
|
||||
{
|
||||
prediction: 0,
|
||||
human: 1,
|
||||
},
|
||||
{
|
||||
prediction: 1,
|
||||
human: 1,
|
||||
},
|
||||
{
|
||||
prediction: 0,
|
||||
human: 1,
|
||||
},
|
||||
{
|
||||
prediction: 1,
|
||||
human: 1,
|
||||
},
|
||||
];
|
||||
|
||||
steps.forEach(step => {
|
||||
const prediction = daemon.predict(journal);
|
||||
expect(prediction).to.eqls(step.prediction);
|
||||
daemon.adjust(journal, step.human);
|
||||
journal.makeMove(step.human, step.prediction);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -4,20 +4,25 @@ import { expect } from 'chai';
|
||||
import Journal from '../src/Journal';
|
||||
import Move from '../src/Move';
|
||||
|
||||
describe('Journal', function() {
|
||||
it('Create with empty constructor', function() {
|
||||
const m = new Journal();
|
||||
expect(m.getLastMovements(5, 5)).to.eqls([]);
|
||||
const journal = new Journal();
|
||||
expect(journal.length).to.equals(0);
|
||||
expect(journal.getLastMovements(5, 5)).to.eqls([]);
|
||||
});
|
||||
|
||||
it('Constructor with human steps', function() {
|
||||
const m = new Journal([new Move(1, 1)]);
|
||||
expect(m.getLastMovements(5, 5)).to.eqls([1, 1]);
|
||||
const journal = new Journal([new Move(1, 1)]);
|
||||
expect(journal.length).equals(1);
|
||||
expect(journal.getLastMovements(5, 5)).to.eqls([1, 1]);
|
||||
});
|
||||
|
||||
it('Make steps', function() {
|
||||
const m = new Journal();
|
||||
m.makeMove(1, 0);
|
||||
expect(m.getLastMovements(5, 5)).to.eqls([0, 1]);
|
||||
const journal = new Journal();
|
||||
journal.makeMove(1, 0);
|
||||
journal.makeMove(1, 1);
|
||||
expect(journal.length).to.equals(2);
|
||||
expect(journal.getLastMovements(2, 2)).to.eqls([0, 1, 1, 1]);
|
||||
});
|
||||
|
||||
it('Get slice', function() {
|
||||
@ -27,6 +32,6 @@ it('Get slice', function() {
|
||||
new Move(0, 1),
|
||||
new Move(1, 0),
|
||||
]);
|
||||
|
||||
expect(m.getLastMovements(2, 2)).to.eqls([1, 0, 0, 1]);
|
||||
});
|
||||
});
|
||||
|
11
tools/node
11
tools/node
@ -4,13 +4,18 @@ set -eu
|
||||
|
||||
source .env
|
||||
|
||||
TTY=
|
||||
if [ -t 1 ] ; then
|
||||
TTY=--tty
|
||||
fi
|
||||
|
||||
docker run \
|
||||
--rm \
|
||||
--interactive \
|
||||
--tty \
|
||||
${TTY} \
|
||||
--init \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
--volume "$PWD:/srv/app" \
|
||||
--workdir /srv/app \
|
||||
--volume "$PWD:/app" \
|
||||
--workdir /app \
|
||||
${NODE_IMAGE} \
|
||||
node "$@"
|
||||
|
11
tools/npm
11
tools/npm
@ -9,14 +9,19 @@ CONTAINER_CACHE_DIR=/tmp/.npm
|
||||
|
||||
mkdir -p ${HOST_CACHE_DIR}
|
||||
|
||||
TTY=
|
||||
if [ -t 1 ] ; then
|
||||
TTY=--tty
|
||||
fi
|
||||
|
||||
docker run \
|
||||
--rm \
|
||||
--interactive \
|
||||
--tty \
|
||||
${TTY} \
|
||||
--init \
|
||||
--user "$UID:$(id -g)" \
|
||||
--volume "$PWD:/srv/app" \
|
||||
--volume "$PWD:/app" \
|
||||
--env npm_config_cache="${CONTAINER_CACHE_DIR}" \
|
||||
--workdir /srv/app \
|
||||
--workdir /app \
|
||||
${NODE_IMAGE} \
|
||||
npm "$@"
|
||||
|
Loading…
Reference in New Issue
Block a user