diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..8b797b3 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,9 @@ +repos: + - repo: https://github.com/pre-commit/mirrors-eslint + rev: "v8.28.0" + hooks: + - id: eslint + - repo: https://github.com/pre-commit/mirrors-prettier + rev: "v2.7.1" + hooks: + - id: prettier diff --git a/.prettierrc.json b/.prettierrc.json index 0967ef4..2589fad 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1 +1,3 @@ -{} +{ + "vueIndentScriptAndStyle": true +} diff --git a/README.md b/README.md index e7a8642..34b63fe 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ Explore 1D and 2D cellular automata, with a few bells and whistles. +![rules73](./example.png) + ## Project setup ``` @@ -11,7 +13,7 @@ npm install ### Compiles and hot-reloads for development ``` -npm run serve +npm run dev ``` ### Compiles and minifies for production @@ -26,9 +28,15 @@ npm run build npm run lint ``` +### Format files + +``` +npm run format +``` + ### Customize configuration -See [Configuration Reference](https://cli.vuejs.org/config/). +See [Configuration Reference](https://vitejs.dev/guide/). ### References diff --git a/example.png b/example.png new file mode 100644 index 0000000..f42f4e1 Binary files /dev/null and b/example.png differ diff --git a/package-lock.json b/package-lock.json index 3b9c46f..931d38d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +10,9 @@ "dependencies": { "@vitejs/plugin-vue": "^3.2.0", "install": "^0.13.0", + "pinia": "^2.0.27", "vite": "^3.2.4", - "vue": "3.2", - "vuex": "4.1" + "vue": "3.2" }, "devDependencies": { "eslint": "^8.28.0", @@ -1548,6 +1548,56 @@ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, + "node_modules/pinia": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.27.tgz", + "integrity": "sha512-nOnXP0OFeL8R4WjAHsterU+11vptda643gH02xKNtSCDPiRzVfRYodOLihLDoa0gL1KKuQKV+KOzEgdt3YvqEw==", + "dependencies": { + "@vue/devtools-api": "^6.4.5", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@vue/composition-api": "^1.4.0", + "typescript": ">=4.4.4", + "vue": "^2.6.14 || ^3.2.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/postcss": { "version": "8.4.19", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz", @@ -1969,17 +2019,6 @@ "eslint": ">=6.0.0" } }, - "node_modules/vuex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.1.0.tgz", - "integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==", - "dependencies": { - "@vue/devtools-api": "^6.0.0-beta.11" - }, - "peerDependencies": { - "vue": "^3.2.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3083,6 +3122,23 @@ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, + "pinia": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.27.tgz", + "integrity": "sha512-nOnXP0OFeL8R4WjAHsterU+11vptda643gH02xKNtSCDPiRzVfRYodOLihLDoa0gL1KKuQKV+KOzEgdt3YvqEw==", + "requires": { + "@vue/devtools-api": "^6.4.5", + "vue-demi": "*" + }, + "dependencies": { + "vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "requires": {} + } + } + }, "postcss": { "version": "8.4.19", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz", @@ -3324,14 +3380,6 @@ "semver": "^7.3.6" } }, - "vuex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.1.0.tgz", - "integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==", - "requires": { - "@vue/devtools-api": "^6.0.0-beta.11" - } - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 8590f1b..0788df7 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "dependencies": { "@vitejs/plugin-vue": "^3.2.0", "install": "^0.13.0", + "pinia": "^2.0.27", "vite": "^3.2.4", - "vue": "3.2", - "vuex": "4.1" + "vue": "3.2" }, "devDependencies": { "eslint": "^8.28.0", diff --git a/src/App.vue b/src/App.vue index 1519d90..b86443a 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,66 +1,153 @@ - diff --git a/src/components/CanvasBoard.vue b/src/components/CanvasBoard.vue index a7edc56..f0a9129 100644 --- a/src/components/CanvasBoard.vue +++ b/src/components/CanvasBoard.vue @@ -1,146 +1,149 @@ diff --git a/src/components/MainMenu.vue b/src/components/MainMenu.vue index 86166fd..a1c3488 100644 --- a/src/components/MainMenu.vue +++ b/src/components/MainMenu.vue @@ -1,5 +1,5 @@ diff --git a/src/components/Menu2dCA.vue b/src/components/Menu2dCA.vue index 2d268b1..49b5cb0 100644 --- a/src/components/Menu2dCA.vue +++ b/src/components/Menu2dCA.vue @@ -1,56 +1,33 @@ diff --git a/src/components/MenuCellProperties.vue b/src/components/MenuCellProperties.vue index a88bf50..49b07f9 100644 --- a/src/components/MenuCellProperties.vue +++ b/src/components/MenuCellProperties.vue @@ -34,29 +34,27 @@ diff --git a/src/components/MenuElementaryCA.vue b/src/components/MenuElementaryCA.vue index 3d4d30b..cfb99c6 100644 --- a/src/components/MenuElementaryCA.vue +++ b/src/components/MenuElementaryCA.vue @@ -1,5 +1,5 @@ diff --git a/src/components/MenuGeneralOptions.vue b/src/components/MenuGeneralOptions.vue index 66cb8aa..f12b8f2 100644 --- a/src/components/MenuGeneralOptions.vue +++ b/src/components/MenuGeneralOptions.vue @@ -56,40 +56,40 @@ diff --git a/src/components/MenuReset.vue b/src/components/MenuReset.vue new file mode 100644 index 0000000..ad90d12 --- /dev/null +++ b/src/components/MenuReset.vue @@ -0,0 +1,36 @@ + + + diff --git a/src/components/MenuRow.vue b/src/components/MenuRow.vue index 1db739a..164414f 100644 --- a/src/components/MenuRow.vue +++ b/src/components/MenuRow.vue @@ -3,73 +3,103 @@

{{ rowTitle }}

- diff --git a/src/components/preset.js b/src/components/preset.js new file mode 100644 index 0000000..0eee491 --- /dev/null +++ b/src/components/preset.js @@ -0,0 +1,95 @@ +const presetRuleset = [ + { + name: "rule 73", + rules: { + 100: 0, + 101: 0, + 110: 1, + 111: 0, + "011": 1, + "010": 0, + "001": 0, + "000": 1, + }, + }, + { + name: "rule 86", + rules: { + 100: 1, + 101: 0, + 110: 0, + 111: 1, + "011": 0, + "010": 1, + "001": 0, + "000": 1, + }, + }, + { + name: "rule 90", + rules: { + 100: 1, + 101: 0, + 110: 1, + 111: 0, + "011": 0, + "010": 0, + "001": 1, + "000": 0, + }, + }, + { + name: "rule 45?", + rules: { + 100: 0, + 101: 0, + 110: 1, + 111: 0, + "011": 1, + "010": 0, + "001": 1, + "000": 1, + }, + }, + { + name: "rule 54?", + rules: { + 100: 1, + 101: 0, + 110: 1, + 111: 1, + "011": 0, + "010": 1, + "001": 1, + "000": 0, + }, + }, + { + name: "unknown rule", + rules: { + 100: 0, + 101: 0, + 110: 0, + 111: 1, + "011": 0, + "010": 0, + "001": 1, + "000": 1, + }, + }, +]; + +const initialStates = [ + { + id: "onecell", + name: "One cell at center", + description: "State with a single cell in the middle", + }, + { + id: "random", + name: "Random cell", + description: "State populated with random cells", + }, +]; + +export { presetRuleset, initialStates }; diff --git a/src/main.js b/src/main.js index a965a4f..de57635 100644 --- a/src/main.js +++ b/src/main.js @@ -1,9 +1,10 @@ import { createApp } from "vue"; import App from "./App.vue"; -import { store } from "./store"; +import { createPinia } from "pinia"; const app = createApp(App); +const pinia = createPinia(); -app.use(store); +app.use(pinia); app.mount("#app"); diff --git a/src/modules/preset.js b/src/modules/preset.js new file mode 100644 index 0000000..0eee491 --- /dev/null +++ b/src/modules/preset.js @@ -0,0 +1,95 @@ +const presetRuleset = [ + { + name: "rule 73", + rules: { + 100: 0, + 101: 0, + 110: 1, + 111: 0, + "011": 1, + "010": 0, + "001": 0, + "000": 1, + }, + }, + { + name: "rule 86", + rules: { + 100: 1, + 101: 0, + 110: 0, + 111: 1, + "011": 0, + "010": 1, + "001": 0, + "000": 1, + }, + }, + { + name: "rule 90", + rules: { + 100: 1, + 101: 0, + 110: 1, + 111: 0, + "011": 0, + "010": 0, + "001": 1, + "000": 0, + }, + }, + { + name: "rule 45?", + rules: { + 100: 0, + 101: 0, + 110: 1, + 111: 0, + "011": 1, + "010": 0, + "001": 1, + "000": 1, + }, + }, + { + name: "rule 54?", + rules: { + 100: 1, + 101: 0, + 110: 1, + 111: 1, + "011": 0, + "010": 1, + "001": 1, + "000": 0, + }, + }, + { + name: "unknown rule", + rules: { + 100: 0, + 101: 0, + 110: 0, + 111: 1, + "011": 0, + "010": 0, + "001": 1, + "000": 1, + }, + }, +]; + +const initialStates = [ + { + id: "onecell", + name: "One cell at center", + description: "State with a single cell in the middle", + }, + { + id: "random", + name: "Random cell", + description: "State populated with random cells", + }, +]; + +export { presetRuleset, initialStates }; diff --git a/src/store/index.js b/src/store/index.js deleted file mode 100644 index 129ef94..0000000 --- a/src/store/index.js +++ /dev/null @@ -1,174 +0,0 @@ -/* TODO: terminology is to be changed for : -canvas/board : -currently, the canvas object is named board, -while the structure used to store automata current state is named "board" as well. This is confusing -drawing board could be enough to lift any ambiguity - -rules: -confusion bewteen ruleset and rules. -it's never clear if we refers to a rule or the whole (named) set -*/ -import { createStore } from "vuex"; - -export const store = createStore({ - strict: process.env.NODE_ENV !== "production", - state: { - rules1d: { - name: "rule 73", - rules: { - 111: 0, - 110: 1, - 101: 0, - 100: 0, - "011": 1, - "010": 0, - "001": 0, - "000": 1, - }, - }, - cellProperties: { - size: 3, - liveColor: "#000000", - deadColor: "#F5F5F5", - }, - canvasWidth: 0, - canvasHeight: 0, - boardWidth: 0, - boardHeight: 0, - refreshRate: 300, - initial1dState: "onecell", - activeMenu: "", - drawingDirection: "y", - lastBoard: {}, - draw1d: false, - draw2d: false, - draw2dLast: false, - reset: false, - canDraw: true, - }, - mutations: { - update1dSingleRule(state, data) { - state.rules1d.name = data.name; - state.rules1d.rules[data.rule] = data.value; - }, - update1dRules(state, data) { - state.rules1d = data; - }, - setCellProperties(state, data) { - state.cellProperties[data.name] = data.value; - }, - setCanvasWidth(state, data) { - state.canvasWidth = data; - }, - setCanvasHeight(state, data) { - state.canvasHeight = data; - }, - setRefreshRate(state, data) { - state.refreshRate = data; - }, - setInitial1dState(state, data) { - state.initial1dState = data; - }, - setActiveMenu(state, data) { - state.activeMenu = data; - }, - setDrawingDirection(state, data) { - state.drawingDirection = data; - }, - setLastBoard(state, data) { - state.lastBoard = data; - }, - setCanvas(state, data) { - state.canvas = data; - }, - setContext(state, data) { - state.ctx = data; - }, - toggleDraw1d(state, data) { - state.draw1d = data; - }, - toggleDraw2d(state, data) { - state.draw2d = data; - }, - toggleDraw2dLast(state, data) { - state.draw2dLast = data; - }, - toggleReset(state, data) { - state.reset = data; - }, - canDraw(state, data) { - state.canDraw = data; - }, - }, - getters: { - getCellProperties(state) { - return state.cellProperties; - }, - get1dRules(state) { - return state.rules1d; - }, - getRule1d(state) { - return state.rules1d; - }, - getCanvasWidth(state) { - return state.canvasWidth; - }, - getCanvasHeight(state) { - return state.canvasHeight; - }, - getRefreshRate(state) { - return state.refreshRate; - }, - getInitial1dState(state) { - return state.initial1dState; - }, - getActiveMenu(state) { - return state.activeMenu; - }, - getDrawingDirection(state) { - return state.drawingDirection; - }, - getLastBoard(state) { - return state.lastBoard; - }, - getDraw1d(state) { - return state.draw1d; - }, - getDraw2d(state) { - return state.draw2d; - }, - getDraw2dLast(state) { - return state.draw2dLast; - }, - getReset(state) { - return state.reset; - }, - getCanDraw(state) { - return state.canDraw; - }, - }, - actions: { - draw1d({ commit }) { - commit("toggleDraw1d", true); - }, - draw2d({ commit }) { - commit("canDraw", true); - commit("toggleDraw2d", true); - }, - draw2dLast({ commit }) { - commit("canDraw", true); - commit("toggleDraw2dLast", true); - }, - reset({ dispatch, commit }) { - dispatch("stop"); - commit("toggleReset", true); - }, - stop({ commit }) { - commit("toggleDraw1d", false); - commit("toggleDraw2d", false); - commit("toggleDraw2dLast", false); - commit("canDraw", false); - }, - }, - modules: {}, -}); diff --git a/src/stores/index.js b/src/stores/index.js new file mode 100644 index 0000000..a3ef16e --- /dev/null +++ b/src/stores/index.js @@ -0,0 +1,72 @@ +import { defineStore } from "pinia"; + +export const globalStore = defineStore("globalStore", { + state: () => { + return { + ruleset1d: { + name: "rule 73", + rules: { + 111: 0, + 110: 1, + 101: 0, + 100: 0, + "011": 1, + "010": 0, + "001": 0, + "000": 1, + }, + }, + cellProperties: { + size: 3, + liveColor: "#000000", + deadColor: "#F5F5F5", + }, + canvasWidth: 0, + canvasHeight: 0, + boardWidth: 0, + boardHeight: 0, + refreshRate: 300, + initial1dState: "onecell", + drawingDirection: "y", + lastBoard: {}, + draw1d: false, + draw2d: false, + draw2dLast: false, + reset: false, + canDraw: true, + }; + }, + actions: { + setBoardWidth() { + this.boardWidth = Math.floor(this.canvasWidth / this.cellProperties.size); + }, + setBoardHeight() { + this.boardHeight = Math.floor( + this.canvasHeight / this.cellProperties.size + ); + }, + toggleDraw1d() { + this.draw1d = true; + }, + toggleDraw2d() { + this.toggleStop(); + this.canDraw = true; + this.draw2d = true; + }, + toggleDraw2dLast() { + this.toggleStop(); + this.canDraw = true; + this.draw2dLast = true; + }, + toggleReset() { + this.toggleStop(); + this.reset = true; + }, + toggleStop() { + this.draw1d = false; + this.draw2d = false; + this.draw2dLast = false; + this.canDraw = false; + }, + }, +}); diff --git a/vue.config.js b/vue.config.js deleted file mode 100644 index 680f0de..0000000 --- a/vue.config.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - configureWebpack: { - devServer: { - overlay: { - warnings: true, - errors: true, - }, - watchOptions: { - ignored: [/node_modules/, /public/, /\.#/], - }, - }, - }, -};