Init
This commit is contained in:
commit
0d4e25dbf8
4
.babelrc
Normal file
4
.babelrc
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"presets": ["env"],
|
||||||
|
"plugins": ["transform-class-properties"]
|
||||||
|
}
|
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.idea/
|
||||||
|
coverage/
|
||||||
|
dist/
|
||||||
|
node_modules/
|
||||||
|
var/
|
12582
package-lock.json
generated
Normal file
12582
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
41
package.json
Normal file
41
package.json
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"name": "app",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "jest",
|
||||||
|
"build": "webpack",
|
||||||
|
"start:dev": "webpack-dev-server",
|
||||||
|
"format": "prettier --tab-width=4 --single-quote --trailing-comma es5 --write '{source,tests}/**/*.js'"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"babel": "^6.23.0",
|
||||||
|
"babel-jest": "^22.4.4",
|
||||||
|
"babel-loader": "^7.1.4",
|
||||||
|
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||||
|
"babel-plugin-transform-runtime": "^6.23.0",
|
||||||
|
"babel-preset-env": "^1.6.1",
|
||||||
|
"bable-loader": "0.0.1-security",
|
||||||
|
"css-loader": "^0.28.11",
|
||||||
|
"jest": "^22.4.4",
|
||||||
|
"prettier": "^1.12.1",
|
||||||
|
"sass-loader": "^7.0.1",
|
||||||
|
"style-loader": "^0.21.0",
|
||||||
|
"vue": "^2.5.16",
|
||||||
|
"webpack": "^4.8.1",
|
||||||
|
"webpack-cli": "^2.1.3",
|
||||||
|
"webpack-dev-server": "^3.1.4"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"collectCoverage": true,
|
||||||
|
"collectCoverageFrom": [
|
||||||
|
"**/source/*.js"
|
||||||
|
],
|
||||||
|
"testMatch": [
|
||||||
|
"**/tests/**/*.js"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
61
source/Daemon.js
Normal file
61
source/Daemon.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
const DEFAULT_EPSILON = 0.01;
|
||||||
|
|
||||||
|
function create_key(steps) {
|
||||||
|
return steps.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Daemon {
|
||||||
|
humanCount;
|
||||||
|
robotCount;
|
||||||
|
epsilon;
|
||||||
|
weights = {};
|
||||||
|
|
||||||
|
constructor(humanCount, robotCount, epsilon = DEFAULT_EPSILON) {
|
||||||
|
this.humanCount = humanCount;
|
||||||
|
this.robotCount = robotCount;
|
||||||
|
this.epsilon = epsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
predict(movements) {
|
||||||
|
const steps = this._getStepSlice(movements);
|
||||||
|
const w0 = this._getWeight([...steps, 0]);
|
||||||
|
const w1 = this._getWeight([...steps, 1]);
|
||||||
|
|
||||||
|
if (w1 > w0) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adjust(movements, humanValue, stepNumber) {
|
||||||
|
const steps = this._getStepSlice(movements);
|
||||||
|
const weightAdjustment = this._getWeightAdjustment(stepNumber);
|
||||||
|
this._adjustWeight([...steps, humanValue], weightAdjustment);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getStepSlice(movements) {
|
||||||
|
return movements.getLastMovements(this.humanCount, this.robotCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getWeightAdjustment(stepNumber) {
|
||||||
|
return Math.pow(1 + this.epsilon, stepNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getWeight(steps) {
|
||||||
|
const key = create_key(steps);
|
||||||
|
const weight = this.weights[key];
|
||||||
|
return weight === undefined ? 0 : weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
_setWeight(steps, value) {
|
||||||
|
const key = create_key(steps);
|
||||||
|
this.weights[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
_adjustWeight(steps, weight) {
|
||||||
|
const currentWeight = this._getWeight(steps);
|
||||||
|
const newWeight = currentWeight + weight;
|
||||||
|
this._setWeight(steps, newWeight);
|
||||||
|
}
|
||||||
|
}
|
23
source/Movements.js
Normal file
23
source/Movements.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
export default class Movements {
|
||||||
|
humanMovements = [];
|
||||||
|
robotMovements = [];
|
||||||
|
|
||||||
|
constructor(human = [], robot = []) {
|
||||||
|
this.humanMovements = human;
|
||||||
|
this.robotMovements = robot;
|
||||||
|
}
|
||||||
|
|
||||||
|
makeHumanMove(value) {
|
||||||
|
this.humanMovements.push(value === 1 ? value : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
makeRobotMove(value) {
|
||||||
|
this.robotMovements.push(value === 1 ? value : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastMovements(humanCount, robotCount) {
|
||||||
|
const humanSlice = this.humanMovements.slice(-humanCount);
|
||||||
|
const robotSlice = this.robotMovements.slice(-robotCount);
|
||||||
|
return [].concat(robotSlice, humanSlice);
|
||||||
|
}
|
||||||
|
}
|
13
source/Predictor.js
Normal file
13
source/Predictor.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import Movements from './Movements';
|
||||||
|
import Supervisor from './Supervisor';
|
||||||
|
|
||||||
|
export default class Predictor {
|
||||||
|
movements;
|
||||||
|
supervisor;
|
||||||
|
score = 0;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.movements = new Movements();
|
||||||
|
this.supervisor = new Supervisor();
|
||||||
|
}
|
||||||
|
}
|
12
source/Supervisor.js
Normal file
12
source/Supervisor.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export default class Supervisor {
|
||||||
|
daemons = [];
|
||||||
|
|
||||||
|
constructor(daemons) {
|
||||||
|
|
||||||
|
this.daemons = daemons;
|
||||||
|
}
|
||||||
|
|
||||||
|
predict(movements) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
15
source/index.js
Normal file
15
source/index.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import Vue from 'vue';
|
||||||
|
import './style.css';
|
||||||
|
import Predictor from './Predictor';
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: '#app',
|
||||||
|
data: {
|
||||||
|
predictor: new Predictor(),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
pass(value) {
|
||||||
|
console.log('PASS', value);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
20
source/style.css
Normal file
20
source/style.css
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
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;
|
||||||
|
}
|
54
tests/DaemonTest.js
Normal file
54
tests/DaemonTest.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import Daemon from '../source/Daemon';
|
||||||
|
import expect from 'expect';
|
||||||
|
import Movements from '../source/Movements';
|
||||||
|
|
||||||
|
test('Get prediction for beginning', function() {
|
||||||
|
const m = new Movements();
|
||||||
|
const d = new Daemon(1, 1);
|
||||||
|
expect(d.predict(m)).toEqual(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Daemon 1-1', function() {
|
||||||
|
const m = new Movements();
|
||||||
|
const d = new Daemon(1, 1);
|
||||||
|
|
||||||
|
const step_slice = s => {
|
||||||
|
return [].concat(
|
||||||
|
s.slice(-1).slice.map(i => i.robot),
|
||||||
|
s.slice(-1).slice.map(i => i.human)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const steps = [
|
||||||
|
{
|
||||||
|
robot: 0,
|
||||||
|
human: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
robot: 0,
|
||||||
|
human: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
robot: 1,
|
||||||
|
human: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
robot: 0,
|
||||||
|
human: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
robot: 1,
|
||||||
|
human: 1,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
steps.forEach((step, index) => {
|
||||||
|
const robot = d.predict(m);
|
||||||
|
// expect(d._getStepSlice(m)).toEqual(step_slice(steps));
|
||||||
|
expect(robot).toEqual(step.robot);
|
||||||
|
d.adjust(m, step.human, index + 1);
|
||||||
|
m.makeHumanMove(step.human);
|
||||||
|
m.makeRobotMove(step.robot);
|
||||||
|
console.log('Step', index + 1, d);
|
||||||
|
});
|
||||||
|
});
|
38
tests/MovementsTest.js
Normal file
38
tests/MovementsTest.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import Movements from '../source/Movements';
|
||||||
|
import expect from 'expect';
|
||||||
|
|
||||||
|
test('Create with empty constructor', function() {
|
||||||
|
const m = new Movements();
|
||||||
|
expect(m.getLastMovements(5, 5)).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Constructor with human steps', function() {
|
||||||
|
const m = new Movements([1, 1]);
|
||||||
|
expect(m.getLastMovements(5, 5)).toEqual([1, 1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Make human step', function() {
|
||||||
|
const m = new Movements();
|
||||||
|
m.makeHumanMove(1);
|
||||||
|
m.makeHumanMove(0);
|
||||||
|
expect(m.getLastMovements(5, 5)).toEqual([1, 0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Make robot step', function() {
|
||||||
|
const m = new Movements();
|
||||||
|
m.makeRobotMove(0);
|
||||||
|
m.makeRobotMove(1);
|
||||||
|
expect(m.getLastMovements(5, 5)).toEqual([0, 1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Make mixed steps', function() {
|
||||||
|
const m = new Movements();
|
||||||
|
m.makeHumanMove(1);
|
||||||
|
m.makeRobotMove(0);
|
||||||
|
expect(m.getLastMovements(5, 5)).toEqual([0, 1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Get slice', function() {
|
||||||
|
const m = new Movements([1, 0, 0, 1], [1, 1, 0, 0]);
|
||||||
|
expect(m.getLastMovements(2, 2)).toEqual([0, 0, 0, 1]);
|
||||||
|
});
|
19
tools/npm
Executable file
19
tools/npm
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
mkdir -p var/docker-cache/.npm
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
--rm \
|
||||||
|
--interactive \
|
||||||
|
--tty \
|
||||||
|
--init \
|
||||||
|
--user "$UID:$(id -g)" \
|
||||||
|
--volume $PWD:/srv/app \
|
||||||
|
--volume $HOME:$HOME \
|
||||||
|
--volume $PWD/var/docker-cache/.npm:/tmp/.npm \
|
||||||
|
--expose=9000 \
|
||||||
|
--publish=9000:9000 \
|
||||||
|
--env npm_config_cache=/tmp/.npm \
|
||||||
|
--workdir /srv/app \
|
||||||
|
node:10 \
|
||||||
|
npm "$@"
|
36
webpack.config.js
Normal file
36
webpack.config.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mode: 'development',
|
||||||
|
entry: path.resolve(__dirname, 'source/index.js'),
|
||||||
|
output: {
|
||||||
|
filename: 'app.js',
|
||||||
|
path: path.resolve(__dirname, 'dist'),
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: {
|
||||||
|
loader: 'babel-loader',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
use: ['style-loader', 'css-loader'],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'vue$': 'vue/dist/vue.esm.js'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
devServer: {
|
||||||
|
contentBase: path.resolve(__dirname, 'dist'),
|
||||||
|
host: "0.0.0.0",
|
||||||
|
port: 9000,
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user