diff --git a/index.html b/index.html
index c91bf59..06a1d0e 100644
--- a/index.html
+++ b/index.html
@@ -188,6 +188,7 @@
+
diff --git a/js/Draw/MLPView.js b/js/Draw/MLPView.js
index 99c3d00..ebeca6d 100644
--- a/js/Draw/MLPView.js
+++ b/js/Draw/MLPView.js
@@ -9,16 +9,13 @@ class MlpView extends Draggable {
this.propsShown = true;
this.selected = false;
this.initialized = false;
- this.buttons = [];
- this.initializeButtons();
+ this.controlButtons = [];
+ this.initButton;
+ this.createToggleMlpButton();
this.initializeLayers(initialLayer);
this.updateBorders();
}
- getToggleMlpButton() {
- return this.buttons[0];
- }
-
isInitialized() {
return this.initialized;
}
@@ -27,12 +24,34 @@ class MlpView extends Draggable {
const btn = new TextButton("Initialize MLP", () => {
this.toggleMlp();
});
- btn.setDimensions(100, 25).disable();
- return btn;
+ btn.setDimensions(100, 35).disable();
+ this.initButton = btn;
+ }
+
+ createGoOnceButton() {
+ const btn = new TextButton("Go Once", () => {
+ console.log("go once");
+ });
+ btn.setDimensions(75, 35).setTheme("green");
+ this.controlButtons.push(btn);
+ }
+ createTogglePlayButton() {
+ const btn = new TextButton("Play", () => {
+ console.log("play");
+ });
+ btn.setDimensions(75, 35).setTheme("cyan");
+ this.controlButtons.push(btn);
+ }
+
+ destroyControlButtons() {
+ this.controlButtons.forEach((b) => b.destroy()); // probably no needed
+ this.controlButtons = [];
}
- initializeButtons() {
- this.buttons.push(this.createToggleMlpButton());
+ createControlButtons() {
+ this.createGoOnceButton();
+ this.createTogglePlayButton();
+ this.updateButtonsCoordinates();
}
initializeLayers(initialLayer) {
@@ -42,21 +61,15 @@ class MlpView extends Draggable {
}
toggleMlp() {
- if (this.initialized) {
- this.destroyMlp();
- this.updateToggleMlpButton("Initialize MLP", "blue");
- } else {
- this.createMlp();
- this.updateToggleMlpButton("Terminate MLP", "red");
- }
+ this.isInitialized() ? this.destroyMlp() : this.initializeMlp();
this.toggleLockLayers();
}
updateToggleMlpButton(text, theme) {
- this.getToggleMlpButton().setText(text).setTheme(theme);
+ this.initButton.setText(text).setTheme(theme);
}
- createMlp() {
+ initializeMlp() {
const layers = this.layers;
const mlp = new MLP([], this.lr, this.batchSize);
for (let i = 1; i < layers.length; i++) {
@@ -70,6 +83,8 @@ class MlpView extends Draggable {
}
this.setOrigin(mlp);
this.initialized = true;
+ this.updateToggleMlpButton("Terminate MLP", "red");
+ this.createControlButtons();
}
clearOrigin() {
@@ -81,6 +96,8 @@ class MlpView extends Draggable {
this.origin.destroy();
this.clearOrigin();
this.initialized = false;
+ this.updateToggleMlpButton("Initialize MLP", "blue");
+ this.destroyControlButtons();
}
select() {
@@ -102,11 +119,14 @@ class MlpView extends Draggable {
}
updateButtonsCoordinates() {
- const buttons = this.buttons;
- buttons[0].setCoordinates(
- this.x + this.w - this.buttons[0].w,
- this.y + this.h + 5,
- );
+ const initBtn = this.initButton;
+ const y = this.y + this.h + 5;
+ initBtn.setCoordinates(this.x + this.w - initBtn.w, y);
+
+ this.controlButtons.forEach((b, i) => {
+ const x = this.x + (this.w - b.w) / 2 + (i % 2 ? 1 : -1) * 40;
+ b.setCoordinates(x, y);
+ });
}
setLabel(label) {
@@ -174,8 +194,8 @@ class MlpView extends Draggable {
}
checkMlpCompleted() {
- const initializeButton = this.buttons[0];
- this.isCompleted() ? initializeButton.enable() : initializeButton.disable();
+ const initBtn = this.initButton;
+ this.isCompleted() ? initBtn.enable() : initBtn.disable();
}
setOrigin(obj) {
@@ -192,15 +212,6 @@ class MlpView extends Draggable {
this.destroy();
}
- destroy() {
- this.getLayers().forEach((l) => l.destroy());
- this.setLayers([]);
- if (editMLPOrganizer.getSelected() == this) {
- editMLPOrganizer.disable();
- }
- mainOrganizer.removeMlpView(this);
- }
-
pushLayer(layer) {
layer.parent = this;
this.getLayers().push(layer);
@@ -237,7 +248,8 @@ class MlpView extends Draggable {
this.getLayers().forEach((layer) => layer.pressed());
if (iManager.isBusy()) return;
- this.buttons.forEach((btn) => btn.handlePressed());
+ this.controlButtons.forEach((btn) => btn.handlePressed());
+ this.initButton.handlePressed();
this.pressed();
}
@@ -281,6 +293,15 @@ class MlpView extends Draggable {
// So we need to call handleRelease to free iManager
}
+ destroy() {
+ this.getLayers().forEach((l) => l.destroy());
+ this.setLayers([]);
+ if (editMLPOrganizer.getSelected() == this) {
+ editMLPOrganizer.disable();
+ }
+ mainOrganizer.removeMlpView(this);
+ }
+
showProps() {
const commands = [
{
@@ -314,6 +335,7 @@ class MlpView extends Draggable {
this.show();
this.isPropsShown() && this.showProps();
this.getLayers().forEach((layer) => layer.draw());
- this.buttons.forEach((btn) => btn.draw());
+ this.controlButtons.forEach((btn) => btn.draw());
+ this.initButton.draw();
}
}
diff --git a/js/Draw/Minors/Buttons/CanvasButton.js b/js/Draw/Minors/Buttons/CanvasButton.js
index 0f36b18..cb11bd1 100644
--- a/js/Draw/Minors/Buttons/CanvasButton.js
+++ b/js/Draw/Minors/Buttons/CanvasButton.js
@@ -32,7 +32,6 @@ class CanvasButton {
destroy() {
this.onClick = null;
- this.img = null;
}
setCoordinates(x, y) {
diff --git a/js/Draw/Minors/Buttons/TextButton.js b/js/Draw/Minors/Buttons/TextButton.js
index ded2830..ca41509 100644
--- a/js/Draw/Minors/Buttons/TextButton.js
+++ b/js/Draw/Minors/Buttons/TextButton.js
@@ -13,17 +13,11 @@ class TextButton extends CanvasButton {
getTheme() {
const alpha = this.isDisabled() ? 125 : 255;
- let defaultColor;
- let activeColor;
- if (this.theme == "blue") {
- defaultColor = [0, 86, 179, alpha];
- activeColor = [0, 123, 255, alpha];
- } else if (this.theme == "red") {
- defaultColor = [244, 63, 94, alpha];
- activeColor = [199, 44, 72, alpha];
- }
-
- return { defaultColor, activeColor };
+ const { defaultColor, activeColor } = themeManager.getTheme(this.theme);
+ return {
+ defaultColor: [...defaultColor, alpha],
+ activeColor: [...activeColor, alpha],
+ };
}
setText(text) {
diff --git a/js/Draw/Minors/Line.js b/js/Draw/Minors/Line.js
index 800af2c..44cf00d 100644
--- a/js/Draw/Minors/Line.js
+++ b/js/Draw/Minors/Line.js
@@ -19,7 +19,7 @@ class Line {
}
getWeight() {
- return this.w?.data.toFixed(4).toString() ?? "";
+ return this.w?.getFixedData(4) ?? "";
}
destroy() {
@@ -48,7 +48,7 @@ class Line {
let offsetX = (lineLength - totalTextWidth) / 2;
let x = x1 + cos(angle) * offsetX;
- let y = y1 + sin(angle) * offsetX;
+ let y = y1 - 2 + sin(angle) * offsetX;
for (let i = 0; i < text.length; i++) {
const commands = [
@@ -57,6 +57,7 @@ class Line {
args: [x, y],
},
{ func: "rotate", args: [angle] },
+ { func: "textSize", args: [8] },
{ func: "text", args: [text[i], 0, 0] },
];
executeDrawingCommands(commands);
diff --git a/js/Draw/NeuronView.js b/js/Draw/NeuronView.js
index e21e642..a12f508 100644
--- a/js/Draw/NeuronView.js
+++ b/js/Draw/NeuronView.js
@@ -5,6 +5,7 @@ class NeuronView {
this.hidden = false;
this.lines = [];
this.origin = null;
+ this.r = 25;
}
clearOrigin() {
@@ -51,19 +52,26 @@ class NeuronView {
this.instance = null;
}
- show() {
+ showOriginProps() {
+ const origin = this.origin;
+ const o = origin.output;
+ const b = origin.b;
const commands = [
- { func: "fill", args: [255] },
- { func: "circle", args: [this.x, this.y, 25, 25] },
- { func: "fill", args: [0] },
- {
- func: "text",
- args: [this.output?.data.toFixed(2), this.x + 30, this.y],
- },
+ { func: "textAlign", args: [CENTER, CENTER] },
+ { func: "textSize", args: [8] },
{
func: "text",
- args: [this.output?.grad.toFixed(2), this.x + 30, this.y + 25],
+ args: [b.getFixedData(2), this.x, this.y - this.r / 2 - 5],
},
+ { func: "text", args: [o.getFixedData(2), this.x, this.y] },
+ ];
+ executeDrawingCommands(commands);
+ }
+
+ show() {
+ const commands = [
+ { func: "fill", args: [255] },
+ { func: "circle", args: [this.x, this.y, this.r] },
];
executeDrawingCommands(commands);
}
@@ -72,6 +80,7 @@ class NeuronView {
if (!this.hidden) {
this.lines.forEach((line) => line.draw());
this.show();
+ this.origin && this.showOriginProps();
}
}
}
diff --git a/js/MLP/Neuron.js b/js/MLP/Neuron.js
index 28e0b66..663e4cf 100644
--- a/js/MLP/Neuron.js
+++ b/js/MLP/Neuron.js
@@ -5,6 +5,7 @@ class Neuron {
() => new Value(Math.random() * 2 - 1),
);
this.b = new Value(Math.random() * 2 - 1);
+ this.output = new Value(0);
this.act_func = ActivationFunction.TANH;
}
diff --git a/js/MLP/Value.js b/js/MLP/Value.js
index 72b93c0..f65edb9 100644
--- a/js/MLP/Value.js
+++ b/js/MLP/Value.js
@@ -8,6 +8,14 @@ class Value {
this.backward = () => {};
}
+ getFixedData(fixedNum) {
+ return this.data.toFixed(fixedNum);
+ }
+
+ getFixedGrad() {
+ return this.grad.toFixed(4);
+ }
+
convert(val) {
return val instanceof Value ? val : new Value(val);
}
diff --git a/js/Managers/themeManager.js b/js/Managers/themeManager.js
new file mode 100644
index 0000000..77a9ff5
--- /dev/null
+++ b/js/Managers/themeManager.js
@@ -0,0 +1,53 @@
+class ThemeManager {
+ constructor() {
+ let CYAN;
+ let BLUE;
+ let ROSE;
+ let YELLOW;
+ let GREEN;
+ let WHITE;
+ let GRAY;
+ let SKY;
+ }
+
+ getTheme(themeColor) {
+ let defaultColor;
+ let activeColor;
+
+ switch (themeColor) {
+ case "blue":
+ defaultColor = [0, 86, 179];
+ activeColor = [0, 123, 255];
+ break;
+ case "red":
+ defaultColor = [244, 63, 94];
+ activeColor = [199, 44, 72];
+ break;
+ case "cyan":
+ defaultColor = [5, 156, 176];
+ activeColor = [6, 182, 212];
+ break;
+ case "yellow":
+ defaultColor = [200, 155, 19];
+ activeColor = [250, 204, 21];
+ break;
+ case "green":
+ defaultColor = [60, 141, 96];
+ activeColor = [74, 222, 128];
+ break;
+ case "white":
+ defaultColor = [255, 255, 255];
+ activeColor = [230, 230, 230];
+ break;
+ case "gray":
+ defaultColor = [107, 114, 128];
+ activeColor = [74, 74, 74];
+ break;
+ default:
+ defaultColor = [74, 144, 226];
+ activeColor = [28, 100, 242];
+ break;
+ }
+ return { defaultColor, activeColor };
+ }
+}
diff --git a/js/canvas.js b/js/canvas.js
index c615526..5f72dc1 100644
--- a/js/canvas.js
+++ b/js/canvas.js
@@ -4,6 +4,7 @@ let editMLPOrganizer;
let iManager;
let tableOrganizer;
let datasetOrganizer;
+let themeManager;
let canvasManager;
@@ -11,6 +12,7 @@ let mainSketch = function (p) {
p.setup = function () {
p.createCanvas(p.windowWidth, p.windowHeight).parent(document.body);
+ themeManager = new ThemeManager();
canvasManager = new CanvasManager(p);
mainOrganizer = new MainOrganizer();
editMLPOrganizer = new EditMLPOrganizer();