diff --git a/dist/bundle.js b/dist/bundle.js index fb3297d914302c64035d83b819a8fbe1c07cc7f2..3785a2fc7d3de9ca669519fe181a2c19ba80e8e4 100644 --- a/dist/bundle.js +++ b/dist/bundle.js @@ -6234,7 +6234,7 @@ eval("var g;\n\n// This works in non-strict mode\ng = (function() {\n\treturn th /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ConfigView\", function() { return ConfigView; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.js\");\n/* harmony import */ var vue_class_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vue-class-component */ \"./node_modules/vue-class-component/dist/vue-class-component.common.js\");\n/* harmony import */ var vue_class_component__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(vue_class_component__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _render__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./render */ \"./src/render.ts\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n\n\n\n\nvar ConfigView = /** @class */ (function (_super) {\n __extends(ConfigView, _super);\n function ConfigView() {\n var _this = _super.call(this) || this;\n console.log(\"a new config view was placed\");\n return _this;\n }\n ConfigView.prototype.create = function () {\n Object(_render__WEBPACK_IMPORTED_MODULE_2__[\"create\"])(this.config);\n Object(_render__WEBPACK_IMPORTED_MODULE_2__[\"render\"])();\n this.config.created = true;\n };\n ConfigView.prototype.toggleTimer = function () {\n if (this.config.started && this.intervalId !== undefined) {\n clearInterval(this.intervalId);\n this.config.started = false;\n }\n else {\n this.intervalId = setInterval(function () {\n var l = Object(_render__WEBPACK_IMPORTED_MODULE_2__[\"getLife\"])();\n if (l)\n l.stepGame();\n Object(_render__WEBPACK_IMPORTED_MODULE_2__[\"render\"])();\n }, this.config.period);\n this.config.started = true;\n }\n };\n ConfigView = __decorate([\n vue_class_component__WEBPACK_IMPORTED_MODULE_1___default()({\n props: {\n config: Object\n },\n template: \"\\n <div>\\n <div class=\\\"form-row align-items-center\\\">\\n <div class=\\\"col\\\">\\n <div class=\\\"input-group\\\"> \\n <div class=\\\"input-group-prepend\\\">\\n <span class=\\\"input-group-text\\\" >Cols</span>\\n </div>\\n <input type=\\\"number\\\" class=\\\"form-control\\\" v-model:value=\\\"config.w\\\" />\\n </div> \\n </div>\\n <div class=\\\"col\\\">\\n <div class=\\\"input-group\\\"> \\n <div class=\\\"input-group-prepend\\\">\\n <span class=\\\"input-group-text\\\" >Rows</span>\\n </div>\\n <input type=\\\"number\\\" class=\\\"form-control\\\" v-model:value=\\\"config.h\\\" />\\n </div> \\n </div>\\n <div class=\\\"col\\\">\\n <button class=\\\"btn btn-primary mb-2\\\" v-bind:disabled=\\\"config.created\\\" v-on:click=\\\"create\\\">Create</button>\\n </div>\\n <div class=\\\"col\\\">\\n <div class=\\\"input-group\\\"> \\n <div class=\\\"input-group-prepend\\\">\\n <span class=\\\"input-group-text\\\" >ms</span>\\n </div>\\n <input type=\\\"number\\\" class=\\\"form-control\\\" v-model:value=\\\"config.period\\\" />\\n </div> \\n </div>\\n <div class=\\\"col\\\">\\n <button class=\\\"btn btn-primary mb-2\\\" v-bind:disabled=\\\"!config.created\\\" v-on:click=\\\"toggleTimer\\\">\\n {{ config.started ? \\\"Stop\\\" : \\\"Start\\\" }}\\n </button>\\n </div> \\n </div>\\n </div>\\n \"\n })\n ], ConfigView);\n return ConfigView;\n}(vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]));\n\n\n//# sourceURL=webpack:///./src/gameConfig.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ConfigView\", function() { return ConfigView; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.js\");\n/* harmony import */ var vue_class_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vue-class-component */ \"./node_modules/vue-class-component/dist/vue-class-component.common.js\");\n/* harmony import */ var vue_class_component__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(vue_class_component__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _render__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./render */ \"./src/render.ts\");\n/* harmony import */ var _index__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./index */ \"./src/index.ts\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n\n\n\n\n\nvar ConfigView = /** @class */ (function (_super) {\n __extends(ConfigView, _super);\n function ConfigView() {\n var _this = _super.call(this) || this;\n console.log(\"a new config view was placed\");\n return _this;\n }\n ConfigView.prototype.create = function () {\n Object(_index__WEBPACK_IMPORTED_MODULE_3__[\"create\"])(this.config);\n this.config.created = true;\n };\n ConfigView.prototype.toggleTimer = function () {\n if (this.config.started && this.intervalId !== undefined) {\n clearInterval(this.intervalId);\n this.config.started = false;\n }\n else {\n this.intervalId = setInterval(function () {\n var l = Object(_render__WEBPACK_IMPORTED_MODULE_2__[\"getLife\"])();\n if (l)\n l.stepGame();\n Object(_render__WEBPACK_IMPORTED_MODULE_2__[\"render\"])();\n }, this.config.period);\n this.config.started = true;\n }\n };\n ConfigView = __decorate([\n vue_class_component__WEBPACK_IMPORTED_MODULE_1___default()({\n props: {\n config: Object\n },\n template: \"\\n <div>\\n <div class=\\\"form-row align-items-center\\\">\\n <div class=\\\"col\\\">\\n <div class=\\\"input-group\\\"> \\n <div class=\\\"input-group-prepend\\\">\\n <span class=\\\"input-group-text\\\" >Cols</span>\\n </div>\\n <input type=\\\"number\\\" class=\\\"form-control\\\" v-model:value=\\\"config.w\\\" />\\n </div> \\n </div>\\n <div class=\\\"col\\\">\\n <div class=\\\"input-group\\\"> \\n <div class=\\\"input-group-prepend\\\">\\n <span class=\\\"input-group-text\\\" >Rows</span>\\n </div>\\n <input type=\\\"number\\\" class=\\\"form-control\\\" v-model:value=\\\"config.h\\\" />\\n </div> \\n </div>\\n <div class=\\\"col\\\">\\n <button class=\\\"btn btn-primary mb-2\\\" v-bind:disabled=\\\"config.created\\\" v-on:click=\\\"create\\\">Create</button>\\n </div>\\n <div class=\\\"col\\\">\\n <div class=\\\"input-group\\\"> \\n <div class=\\\"input-group-prepend\\\">\\n <span class=\\\"input-group-text\\\" >ms</span>\\n </div>\\n <input type=\\\"number\\\" class=\\\"form-control\\\" v-model:value=\\\"config.period\\\" />\\n </div> \\n </div>\\n <div class=\\\"col\\\">\\n <button class=\\\"btn btn-primary mb-2\\\" v-bind:disabled=\\\"!config.created\\\" v-on:click=\\\"toggleTimer\\\">\\n {{ config.started ? \\\"Stop\\\" : \\\"Start\\\" }}\\n </button>\\n </div> \\n </div>\\n </div>\\n \"\n })\n ], ConfigView);\n return ConfigView;\n}(vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]));\n\n\n//# sourceURL=webpack:///./src/gameConfig.ts?"); /***/ }), @@ -6246,7 +6246,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) * /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\nvar Life = /** @class */ (function () {\n function Life(w, h) {\n if (w === void 0) { w = 40; }\n if (h === void 0) { h = 20; }\n this.w = w;\n this.h = h;\n this.board = this.emptyBoard();\n }\n Life.prototype.boardIndex = function (x, y) {\n return y * this.w + x;\n };\n Life.prototype.x = function (index) {\n return index % this.w;\n };\n Life.prototype.y = function (index) {\n return Math.floor(index / this.w);\n };\n Life.prototype.emptyBoard = function () {\n var arr = [];\n for (var i = 0; i < this.h * this.w; i++) {\n arr.push(0);\n }\n return arr;\n };\n /**\n * If the cell is dead, set it to p, otherwise set it to zero\n */\n Life.prototype.toggleCell = function (x, y, p) {\n var b = this.boardIndex(x, y);\n if (this.isAlive(x, y)) {\n this.board[b] = 0;\n }\n else {\n this.board[b] = p;\n }\n };\n /**\n * Returns 1 if blue, -1 if red, 0 if dead\n */\n Life.prototype.isAlive = function (x, y) {\n var b = this.boardIndex(x, y);\n if ((x >= 0) && (y >= 0) && (x < this.w) && (y < this.h)) {\n return this.board[b];\n }\n else {\n return 0;\n }\n };\n Life.prototype.blueNeighbours = function (x, y) {\n var live = 0;\n for (var _i = 0, _a = [x - 1, x, x + 1]; _i < _a.length; _i++) {\n var i = _a[_i];\n for (var _b = 0, _c = [y - 1, y, y + 1]; _b < _c.length; _b++) {\n var j = _c[_b];\n if (this.isAlive(i, j) > 0 && (i != x || j != y)) {\n live++;\n }\n }\n }\n return live;\n };\n Life.prototype.redNeighbours = function (x, y) {\n var live = 0;\n for (var _i = 0, _a = [x - 1, x, x + 1]; _i < _a.length; _i++) {\n var i = _a[_i];\n for (var _b = 0, _c = [y - 1, y, y + 1]; _b < _c.length; _b++) {\n var j = _c[_b];\n if (this.isAlive(i, j) < 0 && (i != x || j != y)) {\n live++;\n }\n }\n }\n return live;\n };\n /**\n * Performs the game rule for what the next state of a cell should be\n */\n Life.nextCellState = function (state, redNeighbours, blueNeighbours) {\n var neighbours = redNeighbours + blueNeighbours;\n if (state == 0) {\n if (neighbours == 3) {\n if (redNeighbours > blueNeighbours) {\n return -1;\n }\n else {\n return 0;\n }\n }\n else {\n return state;\n }\n }\n else {\n if (neighbours == 2 || neighbours == 3) {\n return state;\n }\n else {\n return 0;\n }\n }\n };\n Life.prototype.stepGame = function () {\n var nextBoard = this.emptyBoard();\n for (var x = 0; x < this.w; x++) {\n for (var y = 0; y < this.h; y++) {\n var index = this.boardIndex(x, y);\n var alive = this.isAlive(x, y);\n var redNeighbours = this.redNeighbours(x, y);\n var blueNeighbours = this.blueNeighbours(x, y);\n nextBoard[this.boardIndex(x, y)] = Life.nextCellState(alive, redNeighbours, blueNeighbours);\n }\n }\n this.board = nextBoard;\n };\n return Life;\n}());\n/* harmony default export */ __webpack_exports__[\"default\"] = (Life);\n\n\n//# sourceURL=webpack:///./src/gameOfLife.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./index */ \"./src/index.ts\");\n\nvar Life = /** @class */ (function () {\n function Life(w, h) {\n if (w === void 0) { w = 40; }\n if (h === void 0) { h = 20; }\n this.w = w;\n this.h = h;\n this.board = this.emptyBoard();\n }\n Life.prototype.boardIndex = function (x, y) {\n return y * this.w + x;\n };\n Life.prototype.x = function (index) {\n return index % this.w;\n };\n Life.prototype.y = function (index) {\n return Math.floor(index / this.w);\n };\n Life.prototype.emptyBoard = function () {\n var arr = [];\n for (var i = 0; i < this.h * this.w; i++) {\n arr.push(0);\n }\n return arr;\n };\n /**\n * If the cell is dead, set it to p, otherwise set it to zero\n */\n Life.prototype.toggleCell = function (x, y, p) {\n var b = this.boardIndex(x, y);\n if (this.isAlive(x, y)) {\n this.board[b] = 0;\n }\n else {\n this.board[b] = p;\n }\n };\n /**\n * Returns 1 if blue, -1 if red, 0 if dead\n */\n Life.prototype.isAlive = function (x, y) {\n var b = this.boardIndex(x, y);\n if ((x >= 0) && (y >= 0) && (x < this.w) && (y < this.h)) {\n return this.board[b];\n }\n else {\n return 0;\n }\n };\n Life.prototype.blueNeighbours = function (x, y) {\n var live = 0;\n for (var _i = 0, _a = [x - 1, x, x + 1]; _i < _a.length; _i++) {\n var i = _a[_i];\n for (var _b = 0, _c = [y - 1, y, y + 1]; _b < _c.length; _b++) {\n var j = _c[_b];\n if (this.isAlive(i, j) > 0 && (i != x || j != y)) {\n live++;\n }\n }\n }\n return live;\n };\n Life.prototype.redNeighbours = function (x, y) {\n var live = 0;\n for (var _i = 0, _a = [x - 1, x, x + 1]; _i < _a.length; _i++) {\n var i = _a[_i];\n for (var _b = 0, _c = [y - 1, y, y + 1]; _b < _c.length; _b++) {\n var j = _c[_b];\n if (this.isAlive(i, j) < 0 && (i != x || j != y)) {\n live++;\n }\n }\n }\n return live;\n };\n /**\n * Performs the game rule for what the next state of a cell should be\n */\n Life.nextCellState = function (state, redNeighbours, blueNeighbours) {\n var neighbours = redNeighbours + blueNeighbours;\n if (state == 0) {\n if (neighbours == 3) {\n if (redNeighbours > blueNeighbours) {\n return -1;\n }\n else {\n return 0;\n }\n }\n else {\n return state;\n }\n }\n else {\n if (neighbours == 2 || neighbours == 3) {\n return state;\n }\n else {\n return 0;\n }\n }\n };\n Life.prototype.stepGame = function () {\n var nextBoard = this.emptyBoard();\n for (var x = 0; x < this.w; x++) {\n for (var y = 0; y < this.h; y++) {\n var index = this.boardIndex(x, y);\n var alive = this.isAlive(x, y);\n var redNeighbours = this.redNeighbours(x, y);\n var blueNeighbours = this.blueNeighbours(x, y);\n nextBoard[this.boardIndex(x, y)] = Life.nextCellState(alive, redNeighbours, blueNeighbours);\n }\n }\n this.board = nextBoard;\n };\n Life.jsStartGame = function (w, h) {\n return {\n kind: \"startGame\", w: w, h: h\n };\n };\n Life.jsConnected = function () {\n return { kind: \"connected\" };\n };\n Life.jsGameState = function (w, h, board) {\n return {\n kind: \"gameState\", w: w, h: h, board: board\n };\n };\n Life.jsPlayerNumber = function (p) {\n return {\n kind: \"playerNumber\", p: p\n };\n };\n Life.jsToggle = function (x, y, p) {\n return {\n kind: \"toggle\", x: x, y: y, p: p\n };\n };\n Life.handleMessage = function (message) {\n switch (message.kind) {\n case \"startGame\":\n var g = new Life(message.w, message.h);\n var msg = Life.jsGameState(g.w, g.h, g.board);\n Object(_index__WEBPACK_IMPORTED_MODULE_0__[\"sendMessage\"])(msg);\n break;\n case \"gameState\":\n if (Life.game !== undefined && Life.game.w == message.w && Life.game.h == message.h) {\n Life.game.board = message.board;\n // TODO: re-render the board\n }\n else {\n Life.game = new Life(message.w, message.h);\n Life.game.board = message.board;\n }\n break;\n case \"playerNumber\":\n if (Life.player === undefined) {\n Life.player = -message.p;\n // TODO: send back my player number\n }\n else {\n // do nothing, the other player is just telling me their number, but I've got mine\n }\n break;\n case \"toggle\":\n if (Life.game !== undefined) {\n Life.game.toggleCell(message.x, message.y, message.p);\n // TODO: broadcast the new game-state?\n }\n }\n };\n Life.game = undefined;\n Life.player = undefined;\n return Life;\n}());\n/* harmony default export */ __webpack_exports__[\"default\"] = (Life);\n\n\n//# sourceURL=webpack:///./src/gameOfLife.ts?"); /***/ }), @@ -6254,11 +6254,11 @@ eval("__webpack_require__.r(__webpack_exports__);\nvar Life = /** @class */ (fun /*!**********************!*\ !*** ./src/index.ts ***! \**********************/ -/*! no exports provided */ +/*! exports provided: sendMessage, create */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.js\");\n/* harmony import */ var _render__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./render */ \"./src/render.ts\");\n/* harmony import */ var _gameConfig__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./gameConfig */ \"./src/gameConfig.ts\");\n\n\n\n//\nvar gameId = (new URL(document.location.toString())).searchParams.get(\"gameId\");\nfunction getGame(gameId) {\n fetch(\"/life/getGame?gameId=\" + gameId)\n .then(function (data) { return data.json(); })\n .then(function (arr) {\n /*\n {\n player: 1\n board: [.....]\n }\n */\n });\n}\nfunction openSocket(gameId) {\n var wsUrl = \"ws\" + window.location.origin.slice(4) + \"/life/gameSocket?gameId=\" + gameId;\n var ws = new WebSocket(wsUrl);\n ws.onmessage = function (evt) { console.log(evt); };\n ws.onopen = function (evt) { ws.send(\"Connected, this message is from the client\"); };\n}\nif (gameId != null) {\n openSocket(gameId);\n}\nelse {\n console.log(\"We had no game Id\");\n}\n/**\n * This is (for now) going to trigger getting everything set up\n */\nif (gameId !== null) {\n getGame(gameId);\n}\nvar config = {\n w: 40,\n h: 20,\n started: false,\n created: false,\n period: 500\n};\nvar v = new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]({\n el: \"#app\",\n template: \"\\n <div>\\n <ConfigView :config=\\\"config\\\"></ConfigView> \\n </div>\\n \",\n data: {\n config: config\n },\n components: {\n ConfigView: _gameConfig__WEBPACK_IMPORTED_MODULE_2__[\"ConfigView\"]\n }\n});\nconsole.log(\"loaded vue\");\nconsole.log(v);\ndocument.getElementById(\"step\").addEventListener(\"click\", function () {\n var l = Object(_render__WEBPACK_IMPORTED_MODULE_1__[\"getLife\"])();\n if (l)\n l.stepGame();\n Object(_render__WEBPACK_IMPORTED_MODULE_1__[\"render\"])();\n});\n\n\n//# sourceURL=webpack:///./src/index.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sendMessage\", function() { return sendMessage; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"create\", function() { return create; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.js\");\n/* harmony import */ var _render__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./render */ \"./src/render.ts\");\n/* harmony import */ var _gameConfig__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./gameConfig */ \"./src/gameConfig.ts\");\n/* harmony import */ var _gameOfLife__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./gameOfLife */ \"./src/gameOfLife.ts\");\n\n\n\n\n//\nvar gameId = (new URL(document.location.toString())).searchParams.get(\"gameId\");\nvar ws = undefined;\nfunction getGame(gameId) {\n fetch(\"/life/getGame?gameId=\" + gameId)\n .then(function (data) { return data.json(); })\n .then(function (arr) {\n /*\n {\n player: 1\n board: [.....]\n }\n */\n });\n}\nfunction openSocket(gameId) {\n var wsUrl = \"ws\" + window.location.origin.slice(4) + \"/life/gameSocket?gameId=\" + gameId;\n ws = new WebSocket(wsUrl);\n ws.onmessage = function (evt) {\n console.log(evt);\n _gameOfLife__WEBPACK_IMPORTED_MODULE_3__[\"default\"].handleMessage(JSON.parse(evt.data));\n if (_gameOfLife__WEBPACK_IMPORTED_MODULE_3__[\"default\"].game !== undefined) {\n Object(_render__WEBPACK_IMPORTED_MODULE_1__[\"render\"])();\n }\n };\n ws.onopen = function (evt) { ws.send(\"Connected, this message is from the client\"); };\n ws.onclose = function (evt) { openSocket(gameId); };\n}\nfunction sendMessage(msg) {\n console.log(\"sending \" + msg);\n if (ws !== undefined) {\n ws.send(JSON.stringify(msg));\n }\n}\nif (gameId != null) {\n openSocket(gameId);\n}\nelse {\n console.log(\"We had no game Id\");\n}\n/**\n * This is (for now) going to trigger getting everything set up\n */\nif (gameId !== null) {\n getGame(gameId);\n}\nvar config = {\n w: 40,\n h: 20,\n started: false,\n created: false,\n period: 500\n};\nfunction create(config) {\n console.log(\"create!\");\n sendMessage(_gameOfLife__WEBPACK_IMPORTED_MODULE_3__[\"default\"].jsStartGame(config.w, config.h));\n}\nvar v = new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]({\n el: \"#app\",\n template: \"\\n <div>\\n <ConfigView :config=\\\"config\\\"></ConfigView> \\n </div>\\n \",\n data: {\n config: config\n },\n components: {\n ConfigView: _gameConfig__WEBPACK_IMPORTED_MODULE_2__[\"ConfigView\"]\n }\n});\nconsole.log(\"loaded vue\");\nconsole.log(v);\ndocument.getElementById(\"step\").addEventListener(\"click\", function () {\n var l = Object(_render__WEBPACK_IMPORTED_MODULE_1__[\"getLife\"])();\n if (l)\n l.stepGame();\n Object(_render__WEBPACK_IMPORTED_MODULE_1__[\"render\"])();\n});\n\n\n//# sourceURL=webpack:///./src/index.ts?"); /***/ }), @@ -6266,11 +6266,11 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue_ /*!***********************!*\ !*** ./src/render.ts ***! \***********************/ -/*! exports provided: getLife, create, render */ +/*! exports provided: getLife, render */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getLife\", function() { return getLife; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"create\", function() { return create; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony import */ var _gameOfLife__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./gameOfLife */ \"./src/gameOfLife.ts\");\n/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! d3 */ \"./node_modules/d3/index.js\");\n\n\nvar foo = \"bar\";\nvar life = new _gameOfLife__WEBPACK_IMPORTED_MODULE_0__[\"default\"](0, 0);\nfunction create(config) {\n console.log(config.w);\n life = new _gameOfLife__WEBPACK_IMPORTED_MODULE_0__[\"default\"](config.w, config.h);\n render();\n}\nvar game = d3__WEBPACK_IMPORTED_MODULE_1__[\"select\"](\"#game\").append(\"g\");\nvar cellSize = 20;\n\nfunction getLife() {\n return life;\n}\n// TODO: Update this depending on which player we are\nvar player = -1;\nfunction render() {\n console.log(\"rendering\");\n var update = game.selectAll(\"rect\").data(life.board);\n update.attr(\"class\", function (d) {\n if (d == 0) {\n return \"cell\";\n }\n else if (d > 0) {\n return \"cell alive blue\";\n }\n else {\n return \"cell alive red\";\n }\n });\n update.enter()\n .append(\"rect\")\n .attr(\"class\", function (d) {\n return d ? \"cell alive\" : \"cell\";\n })\n .attr(\"x\", function (val, i) {\n return life.x(i) * cellSize;\n })\n .attr(\"y\", function (val, i) {\n return life.y(i) * cellSize;\n })\n .attr(\"width\", cellSize)\n .attr(\"height\", cellSize)\n .on(\"click\", function (d, i) {\n var x = life.x(i);\n var y = life.y(i);\n life.toggleCell(x, y, player);\n render();\n });\n}\n\n\n//# sourceURL=webpack:///./src/render.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getLife\", function() { return getLife; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony import */ var _gameOfLife__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./gameOfLife */ \"./src/gameOfLife.ts\");\n/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! d3 */ \"./node_modules/d3/index.js\");\n\n\nvar foo = \"bar\";\nvar game = d3__WEBPACK_IMPORTED_MODULE_1__[\"select\"](\"#game\").append(\"g\");\nvar cellSize = 20;\n\nfunction getLife() {\n return _gameOfLife__WEBPACK_IMPORTED_MODULE_0__[\"default\"].game;\n}\n// TODO: Update this depending on which player we are\nvar player = -1;\nfunction render() {\n console.log(\"rendering\");\n var life = _gameOfLife__WEBPACK_IMPORTED_MODULE_0__[\"default\"].game;\n var update = game.selectAll(\"rect\").data(life.board);\n update.attr(\"class\", function (d) {\n if (d == 0) {\n return \"cell\";\n }\n else if (d > 0) {\n return \"cell alive blue\";\n }\n else {\n return \"cell alive red\";\n }\n });\n update.enter()\n .append(\"rect\")\n .attr(\"class\", function (d) {\n return d ? \"cell alive\" : \"cell\";\n })\n .attr(\"x\", function (val, i) {\n return life.x(i) * cellSize;\n })\n .attr(\"y\", function (val, i) {\n return life.y(i) * cellSize;\n })\n .attr(\"width\", cellSize)\n .attr(\"height\", cellSize)\n .on(\"click\", function (d, i) {\n var x = life.x(i);\n var y = life.y(i);\n life.toggleCell(x, y, player);\n render();\n });\n}\n\n\n//# sourceURL=webpack:///./src/render.ts?"); /***/ }) diff --git a/src/gameConfig.ts b/src/gameConfig.ts index 03456ec0574ad4c063f35db9e20c4e70408dabe5..96e28b052aeaac1be5d524ced4263f3f830e779e 100644 --- a/src/gameConfig.ts +++ b/src/gameConfig.ts @@ -1,6 +1,8 @@ import Vue from "vue" import Component from 'vue-class-component' -import { create, render, getLife } from './render' +import { render, getLife } from './render' + +import { create } from "./index" export { GameConfig as GameConfig, @@ -69,7 +71,6 @@ class ConfigView extends Vue { create() { create(this.config!) - render() this.config!.created = true } diff --git a/src/gameOfLife.ts b/src/gameOfLife.ts index c7d912b3d1f4d7701dd0f52c440c8d0e57a08190..330cff52308fecb2ca909b7b389b6b75dd6aa7af 100644 --- a/src/gameOfLife.ts +++ b/src/gameOfLife.ts @@ -1,4 +1,6 @@ +import { sendMessage } from "./index" + export default class Life { board: Array<number> @@ -117,6 +119,78 @@ export default class Life { this.board = nextBoard } + static jsStartGame(w:number, h:number):any { + return { + kind:"startGame", w:w, h:h + } + } + + static jsConnected():any { + return { kind: "connected" } + } + + static jsGameState(w:number, h:number, board:Array<number>):any { + return { + kind:"gameState", w:w, h:h, board:board + } + } + + static jsPlayerNumber(p:number):any { + return { + kind:"playerNumber", p:p + } + } + + static jsToggle(x:number, y:number, p:number):any { + return { + kind:"toggle", x:x, y:y, p:p + } + } + + static game: Life | undefined = undefined; + + static player: number | undefined = undefined; + + static handleMessage(message:any) { + switch (message.kind) { + case "startGame": + let g = new Life(message.w, message.h); + let msg = Life.jsGameState(g.w, g.h, g.board); + sendMessage(msg); + + break; + + case "gameState": + if (Life.game !== undefined && Life.game.w == message.w && Life.game.h == message.h) { + Life.game.board = message.board + // TODO: re-render the board + } else { + Life.game = new Life(message.w, message.h) + Life.game.board = message.board + } + + break; + + case "playerNumber": + if (Life.player === undefined) { + Life.player = -message.p + // TODO: send back my player number + } else { + // do nothing, the other player is just telling me their number, but I've got mine + } + + break; + + case "toggle": + if (Life.game !== undefined) { + Life.game.toggleCell(message.x, message.y, message.p) + // TODO: broadcast the new game-state? + } + } + + + } + } diff --git a/src/index.ts b/src/index.ts index b87d984d30a0bb86e7af1cc52222c2a3ad0c704f..ac3bb5b5ad631db6c92b63e33f4049f5beaca0cb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,12 @@ import Vue from "vue"; import { render, getLife } from "./render" import { ConfigView, GameConfig } from "./gameConfig" - +import Life from "./gameOfLife"; // let gameId = (new URL(document.location.toString())).searchParams.get("gameId"); +let ws: WebSocket | undefined = undefined; + function getGame(gameId:string) { fetch("/life/getGame?gameId=" + gameId) @@ -21,11 +23,27 @@ function getGame(gameId:string) { function openSocket(gameId:string) { let wsUrl = "ws" + window.location.origin.slice(4) + "/life/gameSocket?gameId=" + gameId - let ws = new WebSocket(wsUrl) - ws.onmessage = (evt) => { console.log(evt) } - ws.onopen = (evt) => { ws.send("Connected, this message is from the client") } + ws = new WebSocket(wsUrl) + ws.onmessage = (evt) => { + console.log(evt) + Life.handleMessage(JSON.parse(evt.data)) + if (Life.game !== undefined) { + render() + } + } + ws.onopen = (evt) => { ws!.send("Connected, this message is from the client") } + ws.onclose = (evt) => { openSocket(gameId) } +} + + +export function sendMessage(msg:any) { + console.log("sending " + msg) + if (ws !== undefined) { + ws.send(JSON.stringify(msg)) + } } + if (gameId != null) { openSocket(gameId) } else { @@ -48,6 +66,11 @@ let config:GameConfig = { period: 500 } +export function create(config:GameConfig) { + console.log("create!") + sendMessage(Life.jsStartGame(config.w, config.h)) +} + let v = new Vue({ el: "#app", template: ` diff --git a/src/render.ts b/src/render.ts index cad4d5f8812c812d3f9137e6f82116d165d0ede2..01dd1ed2a7439b7f94818d02653f9a2cf881b5ca 100644 --- a/src/render.ts +++ b/src/render.ts @@ -4,25 +4,16 @@ import * as d3 from "d3" let foo = "bar" -let life:Life = new Life(0,0) - -function create(config:GameConfig) { - console.log(config.w) - life = new Life(config.w, config.h) - render() -} - const game = d3.select("#game").append("g") const cellSize = 20 export { getLife as getLife, - create as create, render as render } function getLife() { - return life + return Life.game } // TODO: Update this depending on which player we are @@ -30,6 +21,8 @@ let player = -1; function render() { console.log("rendering") + + let life = Life.game! let update = game.selectAll("rect").data(life.board)