Compare commits
26 Commits
main
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
| 893ffe4aa4 | |||
| f71602f385 | |||
|
|
539b3c02f5 | ||
| 3ab800f967 | |||
| 69223a513f | |||
| 80e67f41d7 | |||
| c2aa53ac88 | |||
| 21ffed5566 | |||
| 1197fcbcad | |||
|
|
9e542c64ba | ||
|
|
907284b098 | ||
|
|
877f6cd529 | ||
|
|
13fe8d511e | ||
| 6eb2d78f8c | |||
|
|
6e97d11f43 | ||
|
|
0226cb9cfb | ||
|
|
ae1cd8944c | ||
|
|
88e25143bf | ||
|
|
a34dec4f43 | ||
|
|
f51f89e3b0 | ||
|
|
2a47eb6b20 | ||
|
|
85267bfe2c | ||
|
|
62bf421c9b | ||
|
|
fd9be97387 | ||
|
|
bc829346ae | ||
|
|
2e0c68a636 |
14
.devcontainer/Dockerfile
Normal file
14
.devcontainer/Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
||||
# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster
|
||||
ARG VARIANT=16-bullseye
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT}
|
||||
|
||||
# [Optional] Uncomment this section to install additional OS packages.
|
||||
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
||||
|
||||
# [Optional] Uncomment if you want to install an additional version of node using nvm
|
||||
# ARG EXTRA_NODE_VERSION=10
|
||||
# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}"
|
||||
|
||||
# [Optional] Uncomment if you want to install more global node modules
|
||||
# RUN su node -c "npm install -g <your-package-list-here>"
|
||||
55
.devcontainer/base.Dockerfile
Normal file
55
.devcontainer/base.Dockerfile
Normal file
@@ -0,0 +1,55 @@
|
||||
# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster
|
||||
ARG VARIANT=16-bullseye
|
||||
FROM node:${VARIANT}
|
||||
|
||||
# [Option] Install zsh
|
||||
ARG INSTALL_ZSH="true"
|
||||
# [Option] Upgrade OS packages to their latest versions
|
||||
ARG UPGRADE_PACKAGES="true"
|
||||
|
||||
# Install needed packages, yarn, nvm and setup non-root user. Use a separate RUN statement to add your own dependencies.
|
||||
ARG USERNAME=node
|
||||
ARG USER_UID=1000
|
||||
ARG USER_GID=$USER_UID
|
||||
ARG NPM_GLOBAL=/usr/local/share/npm-global
|
||||
ENV NVM_DIR=/usr/local/share/nvm
|
||||
ENV NVM_SYMLINK_CURRENT=true \
|
||||
PATH=${NPM_GLOBAL}/bin:${NVM_DIR}/current/bin:${PATH}
|
||||
COPY library-scripts/*.sh library-scripts/*.env /tmp/library-scripts/
|
||||
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
# Remove imagemagick due to https://security-tracker.debian.org/tracker/CVE-2019-10131
|
||||
&& apt-get purge -y imagemagick imagemagick-6-common \
|
||||
# Install common packages, non-root user, update yarn and install nvm
|
||||
&& bash /tmp/library-scripts/common-debian.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" "${UPGRADE_PACKAGES}" "true" "true" \
|
||||
# Install yarn, nvm
|
||||
&& rm -rf /opt/yarn-* /usr/local/bin/yarn /usr/local/bin/yarnpkg \
|
||||
&& bash /tmp/library-scripts/node-debian.sh "${NVM_DIR}" "none" "${USERNAME}" \
|
||||
# Configure global npm install location, use group to adapt to UID/GID changes
|
||||
&& if ! cat /etc/group | grep -e "^npm:" > /dev/null 2>&1; then groupadd -r npm; fi \
|
||||
&& usermod -a -G npm ${USERNAME} \
|
||||
&& umask 0002 \
|
||||
&& mkdir -p ${NPM_GLOBAL} \
|
||||
&& touch /usr/local/etc/npmrc \
|
||||
&& chown ${USERNAME}:npm ${NPM_GLOBAL} /usr/local/etc/npmrc \
|
||||
&& chmod g+s ${NPM_GLOBAL} \
|
||||
&& npm config -g set prefix ${NPM_GLOBAL} \
|
||||
&& sudo -u ${USERNAME} npm config -g set prefix ${NPM_GLOBAL} \
|
||||
# Install eslint
|
||||
&& su ${USERNAME} -c "umask 0002 && npm install -g eslint" \
|
||||
&& npm cache clean --force > /dev/null 2>&1 \
|
||||
# Install python-is-python3 on bullseye to prevent node-gyp regressions
|
||||
&& . /etc/os-release \
|
||||
&& if [ "${VERSION_CODENAME}" = "bullseye" ]; then apt-get -y install --no-install-recommends python-is-python3; fi \
|
||||
# Clean up
|
||||
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* /root/.gnupg /tmp/library-scripts
|
||||
|
||||
# [Optional] Uncomment this section to install additional OS packages.
|
||||
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
||||
|
||||
# [Optional] Uncomment if you want to install an additional version of node using nvm
|
||||
# ARG EXTRA_NODE_VERSION=10
|
||||
# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}"
|
||||
|
||||
# [Optional] Uncomment if you want to install more global node modules
|
||||
# RUN su node -c "npm install -g <your-package-list-here>""
|
||||
32
.devcontainer/devcontainer.json
Normal file
32
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,32 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.238.0/containers/javascript-node
|
||||
{
|
||||
"name": "Node.js",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
// Update 'VARIANT' to pick a Node version: 18, 16, 14.
|
||||
// Append -bullseye or -buster to pin to an OS version.
|
||||
// Use -bullseye variants on local arm64/Apple Silicon.
|
||||
"args": { "VARIANT": "16-bullseye" }
|
||||
},
|
||||
|
||||
// Configure tool-specific properties.
|
||||
"customizations": {
|
||||
// Configure properties specific to VS Code.
|
||||
"vscode": {
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
// "postCreateCommand": "yarn install",
|
||||
|
||||
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
||||
"remoteUser": "node"
|
||||
}
|
||||
@@ -16,8 +16,8 @@ function createWindow(): BrowserWindow {
|
||||
win = new BrowserWindow({
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
width: 650,
|
||||
height: 700,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
allowRunningInsecureContent: (serve) ? true : false,
|
||||
|
||||
4897
package-lock.json
generated
4897
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
26
package.json
26
package.json
@@ -45,14 +45,20 @@
|
||||
"lint": "ng lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/common": "13.3.1",
|
||||
"@angular/compiler": "13.3.1",
|
||||
"@angular/core": "13.3.1",
|
||||
"@angular/forms": "13.3.1",
|
||||
"@angular/language-service": "13.3.1",
|
||||
"@angular/platform-browser": "13.3.1",
|
||||
"@angular/platform-browser-dynamic": "13.3.1",
|
||||
"@angular/router": "13.3.1",
|
||||
"@angular/animations": "13.3.11",
|
||||
"@angular/cdk": "^13.0.0",
|
||||
"@angular/common": "13.3.11",
|
||||
"@angular/compiler": "13.3.11",
|
||||
"@angular/core": "13.3.11",
|
||||
"@angular/forms": "13.3.11",
|
||||
"@angular/language-service": "13.3.11",
|
||||
"@angular/platform-browser": "13.3.11",
|
||||
"@angular/platform-browser-dynamic": "13.3.11",
|
||||
"@angular/router": "13.3.11",
|
||||
"@nebular/eva-icons": "9.0.3",
|
||||
"@nebular/theme": "9.0.3",
|
||||
"@tensorflow/tfjs": "1.7.4",
|
||||
"eva-icons": "^1.1.2",
|
||||
"rxjs": "7.5.5",
|
||||
"tslib": "^2.1.0",
|
||||
"zone.js": "~0.11.5"
|
||||
@@ -66,12 +72,14 @@
|
||||
"@angular-eslint/schematics": "13.1.0",
|
||||
"@angular-eslint/template-parser": "13.1.0",
|
||||
"@angular/cli": "13.3.1",
|
||||
"@angular/compiler-cli": "13.3.1",
|
||||
"@angular/compiler-cli": "13.3.11",
|
||||
"@ngx-translate/core": "14.0.0",
|
||||
"@ngx-translate/http-loader": "7.0.0",
|
||||
"@playwright/test": "1.20.2",
|
||||
"@schematics/angular": "13.3.1",
|
||||
"@types/jasmine": "3.10.3",
|
||||
"@types/jasminewd2": "2.0.10",
|
||||
"@types/long": "4.0.2",
|
||||
"@types/node": "17.0.23",
|
||||
"@typescript-eslint/eslint-plugin": "5.17.0",
|
||||
"@typescript-eslint/parser": "5.17.0",
|
||||
|
||||
164
src/app/ai.service.ts
Normal file
164
src/app/ai.service.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
||||
/* eslint-disable space-before-function-paren */
|
||||
/* eslint-disable prefer-const */
|
||||
/* eslint-disable @typescript-eslint/quotes */
|
||||
/* eslint-disable @typescript-eslint/member-ordering */
|
||||
import * as tf from "@tensorflow/tfjs";
|
||||
|
||||
export class AiService {
|
||||
|
||||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
async doPredict(myBoard) {
|
||||
const tenseBlock = tf.tensor([myBoard]);
|
||||
const result = await this.currentModel.predict(tenseBlock);
|
||||
|
||||
const flatty = result.flatten();
|
||||
const maxy = flatty.argMax();
|
||||
const move = await maxy.data();
|
||||
const allMoves = await flatty.data();
|
||||
|
||||
flatty.dispose();
|
||||
tenseBlock.dispose();
|
||||
result.dispose();
|
||||
maxy.dispose();
|
||||
return [move[0], allMoves];
|
||||
};
|
||||
|
||||
private currentModel;
|
||||
flipX(arr) {
|
||||
return [arr.slice(6), arr.slice(3, 6), arr.slice(0, 3)].flat();
|
||||
};
|
||||
|
||||
flipY(arr) {
|
||||
return this.flipX(arr.slice().reverse());
|
||||
}
|
||||
// Creates a 1 hot of the diff
|
||||
showMove(first, second) {
|
||||
let result = [];
|
||||
first.forEach((move, i) => {
|
||||
result.push(Math.abs(move - second[i]));
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
getMoves (block) {
|
||||
let x = [];
|
||||
let y = [];
|
||||
// Make all the moves
|
||||
for (let i = 0; i < block.length - 1; i++) {
|
||||
const theMove = this.showMove(block[i], block[i + 1]);
|
||||
// Normal move
|
||||
x.push(block[i]);
|
||||
y.push(theMove);
|
||||
// Flipped X move
|
||||
x.push(this.flipX(block[i]));
|
||||
y.push(this.flipX(theMove));
|
||||
// Inverted Move
|
||||
x.push(block[i].slice().reverse());
|
||||
y.push(theMove.slice().reverse());
|
||||
// Flipped Y move
|
||||
x.push(this.flipY(block[i]));
|
||||
y.push(this.flipY(theMove));
|
||||
}
|
||||
return { x, y };
|
||||
};
|
||||
|
||||
constructModel() {
|
||||
this.currentModel && this.currentModel.dispose();
|
||||
tf.disposeVariables();
|
||||
|
||||
const model = tf.sequential();
|
||||
|
||||
model.add(
|
||||
tf.layers.dense({
|
||||
inputShape: [9],
|
||||
units: 64,
|
||||
activation: "relu"
|
||||
})
|
||||
);
|
||||
|
||||
model.add(
|
||||
tf.layers.dense({
|
||||
units: 64,
|
||||
activation: "relu"
|
||||
})
|
||||
);
|
||||
|
||||
model.add(
|
||||
tf.layers.dense({
|
||||
units: 9,
|
||||
activation: "softmax"
|
||||
})
|
||||
);
|
||||
|
||||
const learningRate = 0.005;
|
||||
model.compile({
|
||||
optimizer: tf.train.adam(learningRate),
|
||||
loss: "categoricalCrossentropy",
|
||||
metrics: ["accuracy"]
|
||||
});
|
||||
|
||||
this.currentModel = model;
|
||||
return model;
|
||||
};
|
||||
|
||||
getModel() {
|
||||
if (this.currentModel) {
|
||||
return this.currentModel;
|
||||
} else {
|
||||
return this.constructModel();
|
||||
}
|
||||
};
|
||||
|
||||
async trainOnGames(games, setState) {
|
||||
const model = this.constructModel();
|
||||
// model.dispose();
|
||||
let AllX = [];
|
||||
let AllY = [];
|
||||
|
||||
// console.log("Games in", JSON.stringify(games));
|
||||
games.forEach((game) => {
|
||||
AllX = AllX.concat(game.x);
|
||||
AllY = AllY.concat(game.y);
|
||||
});
|
||||
|
||||
// Tensorfy!
|
||||
console.log(AllX);
|
||||
const stackedX = tf.stack(AllX);
|
||||
const stackedY = tf.stack(AllY);
|
||||
await this.trainModel(model, stackedX, stackedY);
|
||||
|
||||
// clean up!
|
||||
stackedX.dispose();
|
||||
stackedY.dispose();
|
||||
|
||||
setState(model);
|
||||
// return updatedModel;
|
||||
};
|
||||
|
||||
async trainModel (model, stackedX, stackedY) {
|
||||
const allCallbacks = {
|
||||
// onTrainBegin: log => console.log(log),
|
||||
// onTrainEnd: log => console.log(log),
|
||||
// onEpochBegin: (epoch, log) => console.log(epoch, log),
|
||||
onEpochEnd: (epoch, log) => console.log(epoch, log)
|
||||
// onBatchBegin: (batch, log) => console.log(batch, log),
|
||||
// onBatchEnd: (batch, log) => console.log(batch, log)
|
||||
};
|
||||
|
||||
await model.fit(stackedX, stackedY, {
|
||||
epochs: 100,
|
||||
shuffle: true,
|
||||
batchSize: 32,
|
||||
callbacks: allCallbacks
|
||||
});
|
||||
|
||||
console.log("Model Trained");
|
||||
|
||||
return model;
|
||||
};
|
||||
}
|
||||
@@ -1 +1,15 @@
|
||||
<app-board></app-board>
|
||||
<nb-layout>
|
||||
|
||||
<nb-layout-header fixed>
|
||||
<!-- Insert header here -->
|
||||
</nb-layout-header>
|
||||
|
||||
<nb-layout-column>
|
||||
<app-board></app-board>
|
||||
</nb-layout-column>
|
||||
|
||||
<nb-layout-footer fixed>
|
||||
<!-- Insert footer here -->
|
||||
</nb-layout-footer>
|
||||
|
||||
</nb-layout>
|
||||