Restore tests

This commit is contained in:
Anton Vakhrushev 2020-03-22 12:40:58 +03:00
parent 4a18dc5808
commit eb66b6904d
9 changed files with 110 additions and 164 deletions

View File

@ -7,30 +7,15 @@ function create_key(steps: number[]): string {
} }
class Daemon { class Daemon {
/** base: number;
* @type {Number}
*/
base;
/** humanCount: number;
* @type {Number}
*/
humanCount;
/** robotCount: number;
* @type {Number}
*/
robotCount;
/** epsilon: number;
* @type {Number}
*/
epsilon;
/** weights: { [key: string]: number } = {};
* @type {Object}
*/
weights = {};
constructor( constructor(
base: number, base: number,
@ -62,69 +47,31 @@ class Daemon {
return proposals.indexOf(maxWeight); return proposals.indexOf(maxWeight);
} }
/** adjust(journal: Journal, humanValue: number) {
* @param {Journal} journal
* @param {Number} humanValue
*/
adjust(journal, humanValue) {
const steps = this._getStepSlice(journal); const steps = this._getStepSlice(journal);
const adjustmentWeight = this._getAdjustmentWeight(journal.length); const adjustmentWeight = this._getAdjustmentWeight(journal.length);
this._adjustWeight([...steps, humanValue], adjustmentWeight); this._adjustWeight([...steps, humanValue], adjustmentWeight);
} }
/** private _getStepSlice(journal: Journal): number[] {
* @param {Journal} journal
*
* @returns {Number[]}
*/
private _getStepSlice(journal) {
return journal.getLastMovements(this.humanCount, this.robotCount); return journal.getLastMovements(this.humanCount, this.robotCount);
} }
/** private _getAdjustmentWeight(stepNumber: number): number {
* @param {Number} stepNumber
*
* @returns {Number}
*
* @private
*/
private _getAdjustmentWeight(stepNumber) {
return Math.pow(1 + this.epsilon, stepNumber); return Math.pow(1 + this.epsilon, stepNumber);
} }
/**
* @param {Number[]} steps
*
* @returns {Number}
*
* @private
*/
private _getWeight(steps: number[]): number { private _getWeight(steps: number[]): number {
const key = create_key(steps); const key = create_key(steps);
const weight = this.weights[key]; return key in this.weights ? this.weights[key] : 0;
return weight as number;
} }
/** private _setWeight(steps: number[], value: number): void {
* @param {Number[]} steps
* @param {Number} value
*
* @returns {Number}
*
* @private
*/
private _setWeight(steps, value) {
const key = create_key(steps); const key = create_key(steps);
this.weights[key] = value; this.weights[key] = value;
} }
/** private _adjustWeight(steps: number[], weight: number): void {
* @param {Number[]} steps
* @param {Number} weight
*
* @private
*/
private _adjustWeight(steps, weight) {
const currentWeight = this._getWeight(steps); const currentWeight = this._getWeight(steps);
const newWeight = currentWeight + weight; const newWeight = currentWeight + weight;
this._setWeight(steps, newWeight); this._setWeight(steps, newWeight);

View File

@ -3,7 +3,6 @@
*/ */
class Move { class Move {
public human: number; public human: number;
public robot: number; public robot: number;
constructor(human: number, robot: number) { constructor(human: number, robot: number) {

View File

@ -18,22 +18,22 @@ export default class Predictor {
/** /**
* @type {Number} * @type {Number}
*/ */
base; base: number;
/** /**
* @type {Number} * @type {Number}
*/ */
score; score: number;
/** /**
* @type {Journal} * @type {Journal}
*/ */
journal; journal: Journal;
/** /**
* @type {Supervisor} * @type {Supervisor}
*/ */
supervisor; supervisor: Supervisor;
/** /**
* @param {Object} config * @param {Object} config
@ -46,13 +46,8 @@ export default class Predictor {
this.supervisor = new Supervisor(daemons, config.supervisor_epsilon); this.supervisor = new Supervisor(daemons, config.supervisor_epsilon);
} }
/** pass(humanValue: number): number {
* @param {Number|String} humanValue const value = humanValue;
*
* @returns {Number}
*/
pass(humanValue) {
const value = parseInt(humanValue, 10);
if (value < 0 || value >= this.base) { if (value < 0 || value >= this.base) {
throw new Error(`Passed value must be in [0, ${this.base})`); throw new Error(`Passed value must be in [0, ${this.base})`);
} }
@ -70,7 +65,7 @@ export default class Predictor {
* *
* @private * @private
*/ */
_createDaemons(daemonConfigs) { private _createDaemons(daemonConfigs) {
return daemonConfigs.map(config => { return daemonConfigs.map(config => {
return new Daemon( return new Daemon(
this.base, this.base,
@ -81,10 +76,7 @@ export default class Predictor {
}); });
} }
/** stepCount(): number {
* @returns {Number}
*/
stepCount() {
return this.journal.length; return this.journal.length;
} }
} }

View File

@ -21,11 +21,6 @@ class Supervisor {
this.epsilon = epsilon; this.epsilon = epsilon;
} }
/**
* @param {Journal} journal
*
* @returns {Number}
*/
predict(journal: Journal): number { predict(journal: Journal): number {
const predictions = this._createPredictions(journal); const predictions = this._createPredictions(journal);
const ordered = this._sortPredictions(predictions); const ordered = this._sortPredictions(predictions);
@ -33,10 +28,6 @@ class Supervisor {
return ordered[0].value; return ordered[0].value;
} }
/**
* @param {Journal} journal
* @param {Number} humanValue
*/
adjust(journal: Journal, humanValue) { adjust(journal: Journal, humanValue) {
const predictions = this._createPredictions(journal); const predictions = this._createPredictions(journal);
for (const prediction of predictions) { for (const prediction of predictions) {

View File

@ -4,49 +4,51 @@ import { expect } from 'chai';
import Daemon from '../src/Daemon'; import Daemon from '../src/Daemon';
import Journal from '../src/Journal'; import Journal from '../src/Journal';
// it('Get prediction for beginning', function() { describe('Daemon', function() {
// const m = new Journal(); it('Get prediction for beginning', function() {
// const d = new Daemon(2, 1, 1); const journal = new Journal();
// const predicted = d.predict(m); const daemon = new Daemon(2, 1, 1);
// expect(predicted).to.equals(0); const predicted = daemon.predict(journal);
// }); expect(predicted).to.equals(0);
});
it('Can get power', function() { it('Can get power', function() {
const d = new Daemon(2, 5, 8); const d = new Daemon(2, 5, 8);
expect(d.power).to.eqls(13); expect(d.power).to.eqls(13);
});
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);
});
});
}); });
// 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);
// });
// });

View File

@ -4,29 +4,34 @@ import { expect } from 'chai';
import Journal from '../src/Journal'; import Journal from '../src/Journal';
import Move from '../src/Move'; import Move from '../src/Move';
it('Create with empty constructor', function() { describe('Journal', function() {
const m = new Journal(); it('Create with empty constructor', function() {
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() { it('Constructor with human steps', function() {
const m = new Journal([new Move(1, 1)]); const journal = new Journal([new Move(1, 1)]);
expect(m.getLastMovements(5, 5)).to.eqls([1, 1]); expect(journal.length).equals(1);
}); expect(journal.getLastMovements(5, 5)).to.eqls([1, 1]);
});
it('Make steps', function() { it('Make steps', function() {
const m = new Journal(); const journal = new Journal();
m.makeMove(1, 0); journal.makeMove(1, 0);
expect(m.getLastMovements(5, 5)).to.eqls([0, 1]); 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() { it('Get slice', function() {
const m = new Journal([ const m = new Journal([
new Move(1, 1), new Move(1, 1),
new Move(0, 1), new Move(0, 1),
new Move(0, 1), new Move(0, 1),
new Move(1, 0), new Move(1, 0),
]); ]);
expect(m.getLastMovements(2, 2)).to.eqls([1, 0, 0, 1]);
expect(m.getLastMovements(2, 2)).to.eqls([1, 0, 0, 1]); });
}); });

View File

@ -4,13 +4,18 @@ set -eu
source .env source .env
TTY=
if [ -t 1 ] ; then
TTY=--tty
fi
docker run \ docker run \
--rm \ --rm \
--interactive \ --interactive \
--tty \ ${TTY} \
--init \ --init \
--user "$(id -u):$(id -g)" \ --user "$(id -u):$(id -g)" \
--volume "$PWD:/srv/app" \ --volume "$PWD:/app" \
--workdir /srv/app \ --workdir /app \
${NODE_IMAGE} \ ${NODE_IMAGE} \
node "$@" node "$@"

View File

@ -9,14 +9,19 @@ CONTAINER_CACHE_DIR=/tmp/.npm
mkdir -p ${HOST_CACHE_DIR} mkdir -p ${HOST_CACHE_DIR}
TTY=
if [ -t 1 ] ; then
TTY=--tty
fi
docker run \ docker run \
--rm \ --rm \
--interactive \ --interactive \
--tty \ ${TTY} \
--init \ --init \
--user "$UID:$(id -g)" \ --user "$UID:$(id -g)" \
--volume "$PWD:/srv/app" \ --volume "$PWD:/app" \
--env npm_config_cache="${CONTAINER_CACHE_DIR}" \ --env npm_config_cache="${CONTAINER_CACHE_DIR}" \
--workdir /srv/app \ --workdir /app \
${NODE_IMAGE} \ ${NODE_IMAGE} \
npm "$@" npm "$@"

View File

@ -10,7 +10,7 @@ docker run \
--tty \ --tty \
--init \ --init \
--user "$(id -u):$(id -g)" \ --user "$(id -u):$(id -g)" \
--volume "$PWD:/srv/app" \ --volume "$PWD:/app" \
--workdir /srv/app \ --workdir /app \
${NODE_IMAGE} \ ${NODE_IMAGE} \
./node_modules/.bin/tsc "$@" ./node_modules/.bin/tsc "$@"