Rewrite lib with typescript
This commit is contained in:
parent
474dae9748
commit
4bdd38ec15
4
.babelrc
4
.babelrc
@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"presets": ["env"],
|
|
||||||
"plugins": ["transform-class-properties"]
|
|
||||||
}
|
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
.idea/
|
.idea/
|
||||||
|
.nyc_output/
|
||||||
|
built/
|
||||||
coverage/
|
coverage/
|
||||||
dist/
|
|
||||||
node_modules/
|
node_modules/
|
||||||
var/
|
var/
|
||||||
|
5
.mocharc.json
Normal file
5
.mocharc.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extension": ["ts"],
|
||||||
|
"spec": "tests/**/*.ts",
|
||||||
|
"require": "ts-node/register"
|
||||||
|
}
|
19
Makefile
Normal file
19
Makefile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
all: test build build-dev
|
||||||
|
|
||||||
|
build:
|
||||||
|
tools/npm run-script build
|
||||||
|
|
||||||
|
build-dev:
|
||||||
|
tools/npm run-script build:dev
|
||||||
|
|
||||||
|
format:
|
||||||
|
tools/npm run-script format
|
||||||
|
|
||||||
|
test:
|
||||||
|
tools/npm run test
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
tools/npm run coverage
|
||||||
|
|
||||||
|
publish:
|
||||||
|
tools/npm publish --access public
|
File diff suppressed because one or more lines are too long
9453
package-lock.json
generated
9453
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
59
package.json
59
package.json
@ -1,46 +1,35 @@
|
|||||||
{
|
{
|
||||||
"name": "predictor",
|
"name": "@anwinged/predictor",
|
||||||
"version": "1.0.0",
|
"version": "0.1.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"module": "lib/predictor.js",
|
"author": "Anton Vakhrushev",
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "built/predictor.js",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/anwinged/predictor.git"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "jest",
|
"test": "mocha",
|
||||||
|
"coverage": "nyc mocha",
|
||||||
"build:dev": "webpack",
|
"build:dev": "webpack",
|
||||||
"build": "WEBPACK_ENV=build webpack",
|
"build": "WEBPACK_ENV=build webpack",
|
||||||
"start:dev": "webpack-dev-server",
|
"format": "prettier --tab-width=4 --single-quote --trailing-comma es5 --write '{src,tests}/**/*.{ts,js}'",
|
||||||
"format": "prettier --tab-width=4 --single-quote --trailing-comma es5 --write '{source,tests}/**/*.js'",
|
|
||||||
"format-md": "prettier --write './*.md'"
|
"format-md": "prettier --write './*.md'"
|
||||||
},
|
},
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel": "^6.23.0",
|
"@types/chai": "^4.2.11",
|
||||||
"babel-jest": "^22.4.4",
|
"@types/mocha": "^7.0.2",
|
||||||
"babel-loader": "^7.1.5",
|
"@types/node": "^13.9.2",
|
||||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
"chai": "^4.2.0",
|
||||||
"babel-plugin-transform-runtime": "^6.23.0",
|
|
||||||
"babel-preset-env": "^1.7.0",
|
|
||||||
"bable-loader": "0.0.1-security",
|
|
||||||
"css-loader": "^0.28.11",
|
|
||||||
"deepmerge": "^2.2.1",
|
"deepmerge": "^2.2.1",
|
||||||
"jest": "^22.4.4",
|
"mocha": "^7.1.1",
|
||||||
"prettier": "^1.18.2",
|
"nyc": "^15.0.0",
|
||||||
"sass-loader": "^7.1.0",
|
"prettier": "^1.19.1",
|
||||||
"style-loader": "^0.21.0",
|
"ts-loader": "^6.2.1",
|
||||||
"vue": "^2.6.10",
|
"ts-node": "^8.7.0",
|
||||||
"webpack": "^4.39.1",
|
"typescript": "^3.8.3",
|
||||||
"webpack-cli": "^3.3.6",
|
"webpack": "^4.42.0",
|
||||||
"webpack-dev-server": "^3.7.2"
|
"webpack-cli": "^3.3.11"
|
||||||
},
|
|
||||||
"jest": {
|
|
||||||
"collectCoverage": true,
|
|
||||||
"collectCoverageFrom": [
|
|
||||||
"**/source/**/*.js",
|
|
||||||
"!**/source/build.js",
|
|
||||||
"!**/source/index.js"
|
|
||||||
],
|
|
||||||
"testMatch": [
|
|
||||||
"**/tests/**/*.js"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
import Move from './Move';
|
|
||||||
|
|
||||||
class Journal {
|
|
||||||
/**
|
|
||||||
* @type {Move[]}
|
|
||||||
*/
|
|
||||||
moves = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Move[]} moves
|
|
||||||
*/
|
|
||||||
constructor(moves = []) {
|
|
||||||
this.moves = moves;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Number} human
|
|
||||||
* @param {Number} robot
|
|
||||||
*/
|
|
||||||
makeMove(human, robot) {
|
|
||||||
this.moves.push(new Move(human, robot));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Number} humanCount
|
|
||||||
* @param {Number} robotCount
|
|
||||||
*
|
|
||||||
* @returns {Number[]}
|
|
||||||
*/
|
|
||||||
getLastMovements(humanCount, robotCount) {
|
|
||||||
const humanMoves = this.moves.map(m => m.human);
|
|
||||||
const robotMoves = this.moves.map(m => m.robot);
|
|
||||||
return [].concat(
|
|
||||||
robotMoves.slice(-robotCount),
|
|
||||||
humanMoves.slice(-humanCount)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {Number}
|
|
||||||
*/
|
|
||||||
get length() {
|
|
||||||
return this.moves.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Journal;
|
|
@ -1,32 +0,0 @@
|
|||||||
import Vue from 'vue';
|
|
||||||
import './style.css';
|
|
||||||
import Predictor from './Predictor';
|
|
||||||
|
|
||||||
new Vue({
|
|
||||||
el: '#app',
|
|
||||||
data: {
|
|
||||||
predictor: new Predictor({
|
|
||||||
base: 3,
|
|
||||||
daemons: [
|
|
||||||
{ human: 3, robot: 3 },
|
|
||||||
{ human: 4, robot: 4 },
|
|
||||||
{ human: 5, robot: 5 },
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
click(v) {
|
|
||||||
const value = parseInt(v, 10);
|
|
||||||
this.pass(value);
|
|
||||||
},
|
|
||||||
press(evt) {
|
|
||||||
const value = parseInt(evt.key, 10) - 1;
|
|
||||||
this.pass(value);
|
|
||||||
},
|
|
||||||
pass(value) {
|
|
||||||
const prediction = this.predictor.pass(value);
|
|
||||||
const step = this.predictor.stepCount();
|
|
||||||
console.log('STEP', step, 'PREDICTED', prediction, 'PASS', value);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
@ -1,20 +0,0 @@
|
|||||||
html, body {
|
|
||||||
width: 100vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app {
|
|
||||||
display: block;
|
|
||||||
margin: 0 auto;
|
|
||||||
width: 200px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.score {
|
|
||||||
font-size: 300%;
|
|
||||||
margin: 2em auto 0.8em;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
@ -1,11 +1,8 @@
|
|||||||
|
import Journal from './Journal';
|
||||||
|
|
||||||
const DEFAULT_EPSILON = 0.01;
|
const DEFAULT_EPSILON = 0.01;
|
||||||
|
|
||||||
/**
|
function create_key(steps: number[]): string {
|
||||||
* @param {Number[]} steps
|
|
||||||
*
|
|
||||||
* @returns {String}
|
|
||||||
*/
|
|
||||||
function create_key(steps) {
|
|
||||||
return steps.join(':');
|
return steps.join(':');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,37 +32,29 @@ class Daemon {
|
|||||||
*/
|
*/
|
||||||
weights = {};
|
weights = {};
|
||||||
|
|
||||||
/**
|
constructor(
|
||||||
* @param {Number} base
|
base: number,
|
||||||
* @param {Number} humanCount
|
humanCount: number,
|
||||||
* @param {Number} robotCount
|
robotCount: number,
|
||||||
* @param {Number} epsilon
|
epsilon: number = DEFAULT_EPSILON
|
||||||
*/
|
) {
|
||||||
constructor(base, humanCount, robotCount, epsilon = DEFAULT_EPSILON) {
|
|
||||||
this.base = base;
|
this.base = base;
|
||||||
this.humanCount = humanCount;
|
this.humanCount = humanCount;
|
||||||
this.robotCount = robotCount;
|
this.robotCount = robotCount;
|
||||||
this.epsilon = epsilon;
|
this.epsilon = epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
get power(): number {
|
||||||
* @returns {Number}
|
|
||||||
*/
|
|
||||||
get power() {
|
|
||||||
return this.humanCount + this.robotCount;
|
return this.humanCount + this.robotCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
predict(journal: Journal): number {
|
||||||
* @param {Journal} journal
|
|
||||||
*
|
|
||||||
* @returns {Number}
|
|
||||||
*/
|
|
||||||
predict(journal) {
|
|
||||||
const steps = this._getStepSlice(journal);
|
const steps = this._getStepSlice(journal);
|
||||||
|
|
||||||
const proposals = [];
|
const proposals: number[] = [];
|
||||||
for (let i = 0; i < this.base; ++i) {
|
for (let i = 0; i < this.base; ++i) {
|
||||||
proposals[i] = this._getWeight([...steps, i]);
|
const weight = this._getWeight([...steps, i]);
|
||||||
|
proposals.push(weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxWeight = Math.max(...proposals);
|
const maxWeight = Math.max(...proposals);
|
||||||
@ -88,7 +77,7 @@ class Daemon {
|
|||||||
*
|
*
|
||||||
* @returns {Number[]}
|
* @returns {Number[]}
|
||||||
*/
|
*/
|
||||||
_getStepSlice(journal) {
|
private _getStepSlice(journal) {
|
||||||
return journal.getLastMovements(this.humanCount, this.robotCount);
|
return journal.getLastMovements(this.humanCount, this.robotCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +88,7 @@ class Daemon {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_getAdjustmentWeight(stepNumber) {
|
private _getAdjustmentWeight(stepNumber) {
|
||||||
return Math.pow(1 + this.epsilon, stepNumber);
|
return Math.pow(1 + this.epsilon, stepNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,10 +99,10 @@ class Daemon {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_getWeight(steps) {
|
private _getWeight(steps: number[]): number {
|
||||||
const key = create_key(steps);
|
const key = create_key(steps);
|
||||||
const weight = this.weights[key];
|
const weight = this.weights[key];
|
||||||
return weight === undefined ? 0 : weight;
|
return weight as number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,7 +113,7 @@ class Daemon {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_setWeight(steps, value) {
|
private _setWeight(steps, value) {
|
||||||
const key = create_key(steps);
|
const key = create_key(steps);
|
||||||
this.weights[key] = value;
|
this.weights[key] = value;
|
||||||
}
|
}
|
||||||
@ -135,7 +124,7 @@ class Daemon {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_adjustWeight(steps, weight) {
|
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);
|
28
src/Journal.ts
Normal file
28
src/Journal.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import Move from './Move';
|
||||||
|
|
||||||
|
class Journal {
|
||||||
|
moves: Move[] = [];
|
||||||
|
|
||||||
|
constructor(moves: Move[] = []) {
|
||||||
|
this.moves = moves;
|
||||||
|
}
|
||||||
|
|
||||||
|
makeMove(human: number, robot: number): void {
|
||||||
|
this.moves.push(new Move(human, robot));
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastMovements(humanCount: number, robotCount: number): number[] {
|
||||||
|
const humanMoves = this.moves.map(m => m.human);
|
||||||
|
const robotMoves = this.moves.map(m => m.robot);
|
||||||
|
return [
|
||||||
|
...robotMoves.slice(-robotCount),
|
||||||
|
...humanMoves.slice(-humanCount),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
get length(): number {
|
||||||
|
return this.moves.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Journal;
|
@ -2,11 +2,11 @@
|
|||||||
* Represents one game move.
|
* Represents one game move.
|
||||||
*/
|
*/
|
||||||
class Move {
|
class Move {
|
||||||
/**
|
public human: number;
|
||||||
* @param {Number} human
|
|
||||||
* @param {Number} robot
|
public robot: number;
|
||||||
*/
|
|
||||||
constructor(human, robot) {
|
constructor(human: number, robot: number) {
|
||||||
this.human = human;
|
this.human = human;
|
||||||
this.robot = robot;
|
this.robot = robot;
|
||||||
}
|
}
|
@ -1,28 +1,23 @@
|
|||||||
|
import Journal from './Journal';
|
||||||
|
import Daemon from './Daemon';
|
||||||
|
|
||||||
const DEFAULT_EPSILON = 0.01;
|
const DEFAULT_EPSILON = 0.01;
|
||||||
|
|
||||||
class Supervisor {
|
class Supervisor {
|
||||||
/**
|
daemons: { daemon: Daemon; rate: number }[] = [];
|
||||||
* @type {{daemon: Daemon, rate: Number}[]}
|
|
||||||
*/
|
|
||||||
daemons = [];
|
|
||||||
|
|
||||||
/**
|
readonly epsilon: number;
|
||||||
* @type {Number}
|
|
||||||
*/
|
|
||||||
epsilon;
|
|
||||||
|
|
||||||
/**
|
constructor(daemons: Daemon[], epsilon: number = DEFAULT_EPSILON) {
|
||||||
* @param {Daemon[]} daemons
|
|
||||||
* @param {Number} epsilon
|
|
||||||
*/
|
|
||||||
constructor(daemons, epsilon = DEFAULT_EPSILON) {
|
|
||||||
if (!daemons || daemons.length === 0) {
|
if (!daemons || daemons.length === 0) {
|
||||||
throw Error('Empty daemon list');
|
throw Error('Empty daemon list');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.daemons = daemons.map(daemon => ({
|
this.daemons = daemons.map(daemon => ({
|
||||||
daemon: daemon,
|
daemon: daemon,
|
||||||
rate: 0,
|
rate: 0,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.epsilon = epsilon;
|
this.epsilon = epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +26,7 @@ class Supervisor {
|
|||||||
*
|
*
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
predict(journal) {
|
predict(journal: Journal): number {
|
||||||
const predictions = this._createPredictions(journal);
|
const predictions = this._createPredictions(journal);
|
||||||
const ordered = this._sortPredictions(predictions);
|
const ordered = this._sortPredictions(predictions);
|
||||||
|
|
||||||
@ -42,7 +37,7 @@ class Supervisor {
|
|||||||
* @param {Journal} journal
|
* @param {Journal} journal
|
||||||
* @param {Number} humanValue
|
* @param {Number} humanValue
|
||||||
*/
|
*/
|
||||||
adjust(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) {
|
||||||
if (prediction.value === humanValue) {
|
if (prediction.value === humanValue) {
|
||||||
@ -61,7 +56,7 @@ class Supervisor {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_createPredictions(journal) {
|
private _createPredictions(journal: Journal) {
|
||||||
return this.daemons.map(daemon => ({
|
return this.daemons.map(daemon => ({
|
||||||
daemon: daemon,
|
daemon: daemon,
|
||||||
power: daemon.daemon.power,
|
power: daemon.daemon.power,
|
||||||
@ -77,7 +72,7 @@ class Supervisor {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_sortPredictions(predictions) {
|
private _sortPredictions(predictions) {
|
||||||
return predictions.sort((result1, result2) => {
|
return predictions.sort((result1, result2) => {
|
||||||
const rateDiff = result2.rate - result1.rate;
|
const rateDiff = result2.rate - result1.rate;
|
||||||
if (Math.abs(rateDiff) > 0.000001) {
|
if (Math.abs(rateDiff) > 0.000001) {
|
||||||
@ -87,14 +82,7 @@ class Supervisor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private _getAdjustmentWeight(stepNumber: number): number {
|
||||||
* @param {Number} stepNumber
|
|
||||||
*
|
|
||||||
* @returns {Number}
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
_getAdjustmentWeight(stepNumber) {
|
|
||||||
return Math.pow(1 + this.epsilon, stepNumber);
|
return Math.pow(1 + this.epsilon, stepNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,49 +0,0 @@
|
|||||||
import expect from 'expect';
|
|
||||||
import Daemon from '../source/Daemon';
|
|
||||||
import Journal from '../source/Journal';
|
|
||||||
|
|
||||||
test('Get prediction for beginning', function() {
|
|
||||||
const m = new Journal();
|
|
||||||
const d = new Daemon(2, 1, 1);
|
|
||||||
expect(d.predict(m)).toEqual(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Can get power', function() {
|
|
||||||
const d = new Daemon(2, 5, 8);
|
|
||||||
expect(d.power).toEqual(13);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('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).toEqual(step.prediction);
|
|
||||||
d.adjust(m, step.human);
|
|
||||||
m.makeMove(step.human, step.prediction);
|
|
||||||
});
|
|
||||||
});
|
|
52
tests/DaemonTest.ts
Normal file
52
tests/DaemonTest.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { it, describe } from 'mocha';
|
||||||
|
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);
|
||||||
|
// });
|
||||||
|
|
||||||
|
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);
|
||||||
|
// });
|
||||||
|
// });
|
@ -1,30 +0,0 @@
|
|||||||
import Journal from '../source/Journal';
|
|
||||||
import Move from '../source/Move';
|
|
||||||
import expect from 'expect';
|
|
||||||
|
|
||||||
test('Create with empty constructor', function() {
|
|
||||||
const m = new Journal();
|
|
||||||
expect(m.getLastMovements(5, 5)).toEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Constructor with human steps', function() {
|
|
||||||
const m = new Journal([new Move(1, 1)]);
|
|
||||||
expect(m.getLastMovements(5, 5)).toEqual([1, 1]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Make steps', function() {
|
|
||||||
const m = new Journal();
|
|
||||||
m.makeMove(1, 0);
|
|
||||||
expect(m.getLastMovements(5, 5)).toEqual([0, 1]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Get slice', function() {
|
|
||||||
const m = new Journal([
|
|
||||||
new Move(1, 1),
|
|
||||||
new Move(0, 1),
|
|
||||||
new Move(0, 1),
|
|
||||||
new Move(1, 0),
|
|
||||||
]);
|
|
||||||
|
|
||||||
expect(m.getLastMovements(2, 2)).toEqual([1, 0, 0, 1]);
|
|
||||||
});
|
|
32
tests/JourlanTest.ts
Normal file
32
tests/JourlanTest.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { it } from 'mocha';
|
||||||
|
import { expect } from 'chai';
|
||||||
|
|
||||||
|
import Journal from '../src/Journal';
|
||||||
|
import Move from '../src/Move';
|
||||||
|
|
||||||
|
it('Create with empty constructor', function() {
|
||||||
|
const m = new Journal();
|
||||||
|
expect(m.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]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Make steps', function() {
|
||||||
|
const m = new Journal();
|
||||||
|
m.makeMove(1, 0);
|
||||||
|
expect(m.getLastMovements(5, 5)).to.eqls([0, 1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Get slice', function() {
|
||||||
|
const m = new Journal([
|
||||||
|
new Move(1, 1),
|
||||||
|
new Move(0, 1),
|
||||||
|
new Move(0, 1),
|
||||||
|
new Move(1, 0),
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(m.getLastMovements(2, 2)).to.eqls([1, 0, 0, 1]);
|
||||||
|
});
|
@ -1,5 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
source .env
|
|
||||||
|
|
||||||
docker pull ${NODE_IMAGE}
|
|
16
tools/node
Executable file
16
tools/node
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
source .env
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
--rm \
|
||||||
|
--interactive \
|
||||||
|
--tty \
|
||||||
|
--init \
|
||||||
|
--user "$(id -u):$(id -g)" \
|
||||||
|
--volume "$PWD:/srv/app" \
|
||||||
|
--workdir /srv/app \
|
||||||
|
${NODE_IMAGE} \
|
||||||
|
node "$@"
|
@ -1,5 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
source .env
|
source .env
|
||||||
|
|
||||||
HOST_CACHE_DIR=$PWD/var/docker-cache/.npm
|
HOST_CACHE_DIR=$PWD/var/docker-cache/.npm
|
||||||
@ -14,10 +16,6 @@ docker run \
|
|||||||
--init \
|
--init \
|
||||||
--user "$UID:$(id -g)" \
|
--user "$UID:$(id -g)" \
|
||||||
--volume "$PWD:/srv/app" \
|
--volume "$PWD:/srv/app" \
|
||||||
--volume "$HOME:$HOME" \
|
|
||||||
--volume "${HOST_CACHE_DIR}:${CONTAINER_CACHE_DIR}" \
|
|
||||||
--expose=9000 \
|
|
||||||
--publish=9000:9000 \
|
|
||||||
--env npm_config_cache="${CONTAINER_CACHE_DIR}" \
|
--env npm_config_cache="${CONTAINER_CACHE_DIR}" \
|
||||||
--workdir /srv/app \
|
--workdir /srv/app \
|
||||||
${NODE_IMAGE} \
|
${NODE_IMAGE} \
|
||||||
|
16
tools/tsc
Executable file
16
tools/tsc
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
source .env
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
--rm \
|
||||||
|
--interactive \
|
||||||
|
--tty \
|
||||||
|
--init \
|
||||||
|
--user "$(id -u):$(id -g)" \
|
||||||
|
--volume "$PWD:/srv/app" \
|
||||||
|
--workdir /srv/app \
|
||||||
|
${NODE_IMAGE} \
|
||||||
|
./node_modules/.bin/tsc "$@"
|
13
tsconfig.json
Normal file
13
tsconfig.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./built",
|
||||||
|
"allowJs": true,
|
||||||
|
"target": "es5",
|
||||||
|
"module": "commonjs",
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"types": ["node", "mocha", "chai"]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"./src/**/*"
|
||||||
|
]
|
||||||
|
}
|
@ -1,19 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Predictor</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<main id="app" class="app" tabindex="0" v-on:keyup="press">
|
|
||||||
<span class="score">
|
|
||||||
{{ predictor.score }}
|
|
||||||
</span>
|
|
||||||
<div class="buttons">
|
|
||||||
<button value="0" v-on:click="click(0)">0</button>
|
|
||||||
<button value="1" v-on:click="click(1)">1</button>
|
|
||||||
<button value="2" v-on:click="click(2)">2</button>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<script src="dist/app.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -5,51 +5,43 @@ const baseConfig = {
|
|||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
test: /\.ts$/,
|
||||||
exclude: /node_modules/,
|
|
||||||
use: {
|
use: {
|
||||||
loader: 'babel-loader',
|
loader: 'ts-loader',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
use: ['style-loader', 'css-loader'],
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildConfig = {
|
const buildConfig = {
|
||||||
mode: 'production',
|
mode: 'production',
|
||||||
entry: path.resolve(__dirname, 'source/build.js'),
|
entry: path.resolve(__dirname, 'src/index.ts'),
|
||||||
output: {
|
output: {
|
||||||
filename: 'predictor.js',
|
filename: 'predictor.min.js',
|
||||||
path: path.resolve(__dirname, 'lib'),
|
path: path.resolve(__dirname, 'built'),
|
||||||
library: 'predictor',
|
library: 'predictor',
|
||||||
libraryTarget: 'umd',
|
libraryTarget: 'umd',
|
||||||
umdNamedDefine: true
|
umdNamedDefine: true
|
||||||
},
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.ts', '.js']
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const devConfig = {
|
const devConfig = {
|
||||||
mode: 'development',
|
mode: 'development',
|
||||||
entry: path.resolve(__dirname, 'source/index.js'),
|
entry: path.resolve(__dirname, 'src/index.ts'),
|
||||||
output: {
|
output: {
|
||||||
filename: 'app.js',
|
filename: 'predictor.js',
|
||||||
path: path.resolve(__dirname, 'web/dist'),
|
path: path.resolve(__dirname, 'built'),
|
||||||
publicPath: 'dist/',
|
library: 'predictor',
|
||||||
|
libraryTarget: 'umd',
|
||||||
|
umdNamedDefine: true
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
extensions: ['.ts', '.js']
|
||||||
'vue$': 'vue/dist/vue.esm.js'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
devServer: {
|
|
||||||
contentBase: path.resolve(__dirname, 'web'),
|
|
||||||
index: 'index.html',
|
|
||||||
host: "0.0.0.0",
|
|
||||||
port: 9000,
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = merge(
|
module.exports = merge(
|
||||||
|
Loading…
Reference in New Issue
Block a user