diff --git a/.meteor/packages b/.meteor/packages index f11e724..238ab32 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -1,28 +1,31 @@ # Meteor packages used by this project, one per line. + # Check this file (and the other files in this directory) into your repository. + # + # 'meteor add' and 'meteor remove' will edit this file for you, + # but you can also edit it by hand. fortawesome:fontawesome momentjs:moment -meteor-base@1.5.1 -mobile-experience@1.1.1 -mongo@1.16.8 -session@1.2.1 -tracker@1.3.3 -logging@1.3.3 -reload@1.3.1 -random@1.2.1 -ejson@1.1.3 +meteor-base@1.5.2 +mobile-experience@1.1.2 +mongo@2.0.2 +session@1.2.2 +tracker@1.3.4 +logging@1.3.5 +reload@1.3.2 +random@1.2.2 +ejson@1.1.4 spacebars -check@1.3.2 -standard-minifier-js@2.8.1 -shell-server@0.5.0 -dynamic-import@0.7.3 -underscore@1.6.0 -fourseven:scss -seba:minifiers-autoprefixer +check@1.4.2 +standard-minifier-js@3.0.0 +shell-server@0.6.0 +dynamic-import@0.7.4 +underscore@1.6.4 blaze-html-templates jquery -msavin:mongol +activitree:scss3 +standard-minifier-css diff --git a/.meteor/release b/.meteor/release index 966586c..c41cba9 100644 --- a/.meteor/release +++ b/.meteor/release @@ -1 +1 @@ -METEOR@2.15 +METEOR@3.0.3 diff --git a/.meteor/versions b/.meteor/versions index 29eb034..f7fd4ff 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -1,82 +1,82 @@ -allow-deny@1.1.1 -autoupdate@1.8.0 -babel-compiler@7.10.5 -babel-runtime@1.5.1 -base64@1.0.12 -binary-heap@1.0.11 -blaze@2.9.0 -blaze-html-templates@2.0.1 -blaze-tools@1.1.4 -boilerplate-generator@1.7.2 -caching-compiler@1.2.2 -caching-html-compiler@1.2.2 -callback-hook@1.5.1 -check@1.3.2 -ddp@1.4.1 -ddp-client@2.6.1 -ddp-common@1.4.0 -ddp-server@2.7.0 -diff-sequence@1.1.2 -dynamic-import@0.7.3 -ecmascript@0.16.8 -ecmascript-runtime@0.8.1 -ecmascript-runtime-client@0.12.1 -ecmascript-runtime-server@0.11.0 -ejson@1.1.3 -es5-shim@4.8.0 -fetch@0.1.4 +activitree:scss3@1.0.3 +allow-deny@2.0.0 +autoupdate@2.0.0 +babel-compiler@7.11.0 +babel-runtime@1.5.2 +base64@1.0.13 +binary-heap@1.0.12 +blaze@3.0.0 +blaze-html-templates@3.0.0 +blaze-tools@2.0.0 +boilerplate-generator@2.0.0 +caching-compiler@2.0.0 +caching-html-compiler@2.0.0 +callback-hook@1.6.0 +check@1.4.2 +core-runtime@1.0.0 +ddp@1.4.2 +ddp-client@3.0.1 +ddp-common@1.4.4 +ddp-server@3.0.1 +diff-sequence@1.1.3 +dynamic-import@0.7.4 +ecmascript@0.16.9 +ecmascript-runtime@0.8.2 +ecmascript-runtime-client@0.12.2 +ecmascript-runtime-server@0.11.1 +ejson@1.1.4 +es5-shim@4.8.1 +facts-base@1.0.2 +fetch@0.1.5 fortawesome:fontawesome@4.7.0 -fourseven:scss@4.16.0 -geojson-utils@1.0.11 -hot-code-push@1.0.4 -html-tools@1.1.4 -htmljs@1.2.1 -id-map@1.1.1 -inter-process-messaging@0.1.1 -jquery@3.0.0 -launch-screen@2.0.0 -logging@1.3.3 -meteor@1.11.5 -meteor-base@1.5.1 -meteortoys:toykit@10.0.0 -minifier-css@1.6.4 -minifier-js@2.7.5 -minimongo@1.9.3 -mobile-experience@1.1.1 -mobile-status-bar@1.1.0 -modern-browsers@0.1.10 -modules@0.20.0 -modules-runtime@0.13.1 +geojson-utils@1.0.12 +hot-code-push@1.0.5 +html-tools@2.0.0 +htmljs@2.0.1 +id-map@1.2.0 +inter-process-messaging@0.1.2 +jquery@3.0.1 +launch-screen@2.0.1 +logging@1.3.5 +meteor@2.0.1 +meteor-base@1.5.2 +minifier-css@2.0.0 +minifier-js@3.0.0 +minimongo@2.0.1 +mobile-experience@1.1.2 +mobile-status-bar@1.1.1 +modern-browsers@0.1.11 +modules@0.20.1 +modules-runtime@0.13.2 momentjs:moment@2.30.1 -mongo@1.16.9 -mongo-decimal@0.1.3 -mongo-dev-server@1.1.0 -mongo-id@1.0.8 -msavin:mongol@10.0.1 -npm-mongo@4.17.2 -observe-sequence@1.0.22 -ordered-dict@1.1.0 -promise@0.12.2 -random@1.2.1 -react-fast-refresh@0.2.8 -reactive-dict@1.3.1 -reactive-var@1.0.12 -reload@1.3.1 -retry@1.1.0 -routepolicy@1.1.1 -seba:minifiers-autoprefixer@2.0.1 -session@1.2.1 -shell-server@0.5.0 -socket-stream-client@0.5.2 -spacebars@1.6.0 -spacebars-compiler@1.3.2 -standard-minifier-js@2.8.1 -templating@1.4.3 -templating-compiler@1.4.2 -templating-runtime@1.6.4 -templating-tools@1.2.3 -tracker@1.3.3 -typescript@4.9.5 -underscore@1.6.1 -webapp@1.13.8 -webapp-hashing@1.1.1 +mongo@2.0.2 +mongo-decimal@0.1.4 +mongo-dev-server@1.1.1 +mongo-id@1.0.9 +npm-mongo@4.17.4 +observe-sequence@2.0.0 +ordered-dict@1.2.0 +promise@1.0.0 +random@1.2.2 +react-fast-refresh@0.2.9 +reactive-dict@1.3.2 +reactive-var@1.0.13 +reload@1.3.2 +retry@1.1.1 +routepolicy@1.1.2 +session@1.2.2 +shell-server@0.6.0 +socket-stream-client@0.5.3 +spacebars@2.0.0 +spacebars-compiler@2.0.0 +standard-minifier-css@1.9.3 +standard-minifier-js@3.0.0 +templating@1.4.4 +templating-compiler@2.0.0 +templating-runtime@2.0.0 +templating-tools@2.0.0 +tracker@1.3.4 +typescript@5.4.3 +underscore@1.6.4 +webapp@2.0.2 +webapp-hashing@1.1.2 diff --git a/.postcss.config.js b/.postcss.config.js new file mode 100644 index 0000000..a47ef4f --- /dev/null +++ b/.postcss.config.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: { + autoprefixer: {}, + }, +}; diff --git a/client/lib/methods.js b/client/lib/methods.js index 99ca133..f2ddd7e 100644 --- a/client/lib/methods.js +++ b/client/lib/methods.js @@ -1,10 +1,10 @@ Meteor.methods({ // Meteor methods stubs to mimic real methods called on backend // for the sake of latency compensation. - flipUpCard: function(gameId, thisMove, lastMove) { - return Games.update( - {_id: gameId, 'grid.idx': thisMove.cardIdx}, - {$set: {'grid.$.class': 'turned-up player-' + thisMove.playerIdx}} + async flipUpCard(gameId, thisMove, lastMove) { + return await Games.updateAsync( + { _id: gameId, "grid.idx": thisMove.cardIdx }, + { $set: { "grid.$.class": "turned-up player-" + thisMove.playerIdx } } ); - } -}); \ No newline at end of file + }, +}); diff --git a/client/lib/startup.js b/client/lib/startup.js index 25e476f..a16dddc 100644 --- a/client/lib/startup.js +++ b/client/lib/startup.js @@ -1,34 +1,40 @@ -Meteor.startup(function() { - Session.set('message', 'test message'); - if (!(localStorage.getItem('sm_deviceId'))) { +Meteor.startup(async function () { + Session.set("message", "test message"); + if (!localStorage.getItem("sm_deviceId")) { // if no sm_deviceId, then try to get it from sm_gameId query // if search fails genereate new id - var newId = new Meteor.Collection.ObjectID; - localStorage.setItem('sm_deviceId', newId._str); + var newId = new Meteor.Collection.ObjectID(); + localStorage.setItem("sm_deviceId", newId._str); } - Session.set('deviceId', localStorage.sm_deviceId); - Session.set('gameId', localStorage.sm_gameId); - + Session.set("deviceId", localStorage.sm_deviceId); + Session.set("gameId", localStorage.sm_gameId); // override current game if linked to new game if (window.location.hash) { var urlHash = window.location.hash.substring(1); var urlOrigin = window.location.origin; if (urlHash.length === 17) { - Session.set('gameId', ''); - localStorage.setItem('sm_gameId', ''); - Games.update( - {_id: urlHash}, - {$addToSet: {players: {device: Session.get('deviceId'), matches: [], totalScore: 0, deviceName: 'Green'}}}, - function(err, res) { - Session.set('gameId', urlHash); - localStorage.setItem('sm_gameId', urlHash); - window.location.href = urlOrigin; - - Session.set('message', 'Game on! Player 2 has the first move.'); + Session.set("gameId", ""); + localStorage.setItem("sm_gameId", ""); + await Games.updateAsync( + { _id: urlHash }, + { + $addToSet: { + players: { + device: Session.get("deviceId"), + matches: [], + totalScore: 0, + deviceName: "Green", + }, + }, } ); - } + Session.set("gameId", urlHash); + localStorage.setItem("sm_gameId", urlHash); + window.location.href = urlOrigin; + + Session.set("message", "Game on! Player 2 has the first move."); + } } -}); \ No newline at end of file +}); diff --git a/client/templates/gameControl/gameContol.js b/client/templates/gameControl/gameContol.js index 3e18cbd..65082bb 100644 --- a/client/templates/gameControl/gameContol.js +++ b/client/templates/gameControl/gameContol.js @@ -1,87 +1,112 @@ -Template.GameControl.helpers ({ - gamesWaiting: function() { - var gameList = Games.find({players: {$size: 1}, gameStatus: 'fresh'}).fetch(); +Template.GameControl.helpers({ + gamesWaiting: async function () { + var gameList = await Games.find({ + players: { $size: 1 }, + gameStatus: "fresh", + }).fetchAsync(); if (gameList.length > 0) { return gameList; } }, - gameInProgress: function() { - var isDirty = Games.find({_id: Session.get('gameId'), gameStatus: 'dirty'}); - if (isDirty.count()) { - Games.remove({_id: Session.get('gameId')}); - Session.set('gameId', ''); - localStorage.setItem('sm_gameId', ''); - alert('Your opponent has left the game.'); + gameInProgress: async function () { + var dirtyCount = await Games.find({ + _id: Session.get("gameId"), + gameStatus: "dirty", + }).countAsync(); + if (dirtyCount > 0) { + await Games.removeAsync({ _id: Session.get("gameId") }); + Session.set("gameId", ""); + localStorage.setItem("sm_gameId", ""); + alert("Your opponent has left the game."); } - return Session.get('gameId'); + return Session.get("gameId"); }, - gameCompleted: function() { - - } + gameCompleted: function () {}, }); -Template.GameControl.events ({ - 'click #instructions': function(evt) { +Template.GameControl.events({ + "click #instructions": function (evt) { var instructionSymbol = document.getElementById("instructionsSymbol"); var instructionText = document.getElementById("instructionsWrapper"); if (instructionText.classList.contains("instructions-hidden")) { instructionSymbol.innerHTML = ''; instructionText.classList.remove("instructions-hidden"); - } - else { + } else { instructionSymbol.innerHTML = ''; instructionText.classList.add("instructions-hidden"); } }, - 'click section.waiting-queue': function(evt) { + "click section.waiting-queue": async function (evt) { var joinGameId = this._id; - Games.update( - {_id: joinGameId}, - {$addToSet: {players: {device: Session.get('deviceId'), matches: [], totalScore: 0, deviceName: 'Green'}}}, - function(err, res) { - Session.set('gameId', joinGameId); - localStorage.setItem('sm_gameId', joinGameId); + await Games.updateAsync( + { _id: joinGameId }, + { + $addToSet: { + players: { + device: Session.get("deviceId"), + matches: [], + totalScore: 0, + deviceName: "Green", + }, + }, } ); + Session.set("gameId", joinGameId); + localStorage.setItem("sm_gameId", joinGameId); }, - 'click #new-game-little': function(evt) { - var gameSize = 'Little'; + "click #new-game-little": async function (evt) { + var gameSize = "Little"; - Meteor.call('newGame', Session.get('deviceId'), gameSize, function(err, res) { - var newGameId = res; - Session.set('gameId', newGameId); - localStorage.setItem ('sm_gameId', Session.get('gameId')); - }); + await Meteor.callAsync("newGame", Session.get("deviceId"), gameSize).then( + function (res) { + var newGameId = res; + Session.set("gameId", newGameId); + localStorage.setItem("sm_gameId", Session.get("gameId")); + } + ); }, - 'click #new-game-big': function(evt) { - var gameSize = 'Big'; + "click #new-game-big": async function (evt) { + var gameSize = "Big"; - Meteor.call('newGame', Session.get('deviceId'), gameSize, function(err, res) { - var newGameId = res; - Session.set('gameId', newGameId); - localStorage.setItem ('sm_gameId', Session.get('gameId')); - }); + await Meteor.callAsync("newGame", Session.get("deviceId"), gameSize).then( + function (res) { + var newGameId = res; + Session.set("gameId", newGameId); + localStorage.setItem("sm_gameId", Session.get("gameId")); + } + ); }, - 'click #leave-game': function(evt) { - var conf = window.confirm('Really? End this game?'); + "click #leave-game": async function (evt) { + var conf = window.confirm("Really? End this game?"); if (conf == true) { - Meteor.call('leaveGame', Session.get('gameId'), Session.get('deviceId')); - Session.set('gameId', ''); - localStorage.setItem('sm_gameId', ''); + await Meteor.callAsync( + "leaveGame", + Session.get("gameId"), + Session.get("deviceId") + ).then(function (res) { + // console.log(res); + }); + Session.set("gameId", ""); + localStorage.setItem("sm_gameId", ""); } }, - 'click #restart-game': function(evt) { - Meteor.call('newGame', Session.get('deviceId'), null, Session.get('gameId'), function(err, res) { - console.log(res); + "click #restart-game": async function (evt) { + await Meteor.callAsync( + "newGame", + Session.get("deviceId"), + null, + Session.get("gameId") + ).then(function (res) { + // console.log(res); }); - } + }, }); diff --git a/client/templates/grid/grid.js b/client/templates/grid/grid.js index 3428d84..a75b794 100644 --- a/client/templates/grid/grid.js +++ b/client/templates/grid/grid.js @@ -1,36 +1,36 @@ -Template.Grid.helpers ({ - shuffledCards: function() { - if (Session.get('gameId')) { - var curGameId = Session.get('gameId'); - var game = Grids.findOne(curGameId); +Template.Grid.helpers({ + shuffledCards: async function () { + if (Session.get("gameId")) { + var curGameId = Session.get("gameId"); + var game = await Grids.findOneAsync(curGameId); if (game) return game.grid; return false; } - } + }, }); Template.Grid.events({ - 'click li': function(evt) { + "click li": async function (evt) { evt.preventDefault(); var thisMove = { //cardIdx: parseInt(evt.target.id.split('-')[1]), cardIdx: this.idx, - turnIdx: 1, // 1 or 2 - playerIdx: 1 // 0 or 1 + turnIdx: 1, // 1 or 2 + playerIdx: 1, // 0 or 1 }; - if (this.class.indexOf('turned-up') >= 0) return false; - var curGameData = Games.findOne({_id: Session.get('gameId')}); + if (this.class.indexOf("turned-up") >= 0) return false; + var curGameData = await Games.findOneAsync({ _id: Session.get("gameId") }); if (curGameData.players.length < 2) return false; var lastMove = curGameData.moves.pop(); - if (typeof lastMove !== 'undefined') { + if (typeof lastMove !== "undefined") { if (lastMove.turnIdx === 2) { // Next player first pick - thisMove.playerIdx = (lastMove.playerIdx) === 1 ? 0 : 1; + thisMove.playerIdx = lastMove.playerIdx === 1 ? 0 : 1; thisMove.turnIdx = 1; - Session.set('message', 'Choose a second card.'); + Session.set("message", "Choose a second card."); } else { // Same player second pick if (thisMove.cardIdx === lastMove.cardIdx) return false; @@ -39,8 +39,17 @@ Template.Grid.events({ } } - if (Session.get('deviceId') === curGameData.players[thisMove.playerIdx].device) { - Meteor.call('flipUpCard', Session.get('gameId'), thisMove, lastMove); + if ( + Session.get("deviceId") === curGameData.players[thisMove.playerIdx].device + ) { + await Meteor.callAsync( + "flipUpCard", + Session.get("gameId"), + thisMove, + lastMove + ).then(function (res) { + // console.log(res); + }); } - } + }, }); diff --git a/client/templates/matches/matches.html b/client/templates/matches/matches.html index dcd6c1d..e464def 100644 --- a/client/templates/matches/matches.html +++ b/client/templates/matches/matches.html @@ -1,19 +1,16 @@ - - {{#with scoreBoard}} - - {{#if your.url}} - - - Waiting for Challenger! - To invite someone to play with you, copy and send them this link: - {{your.url}} - Your game will start when an opponent joins. - - - {{/if}} - + + {{#let board=scoreBoard}} {{#with board}} {{#if your.url}} + + + Waiting for Challenger! + To invite someone to play with you, copy and send them this link: + {{your.url}} + Your game will start when an opponent joins. + + + {{/if}} - - - - - {{my.name}}: {{my.score}} + + + {{my.name}}: {{my.score}} + + + + + {{your.name}}: {{your.score}} + + + + + + My Matches + + + {{#each my.matches}} + + + {{score}} + + {{/each}} + - - - {{your.name}}: {{your.score}} + + Opponent's Matches + + + {{#each your.matches}} + + + {{score}} + + {{/each}} + + - - - - My Matches - - - {{#each my.matches}} - - - {{score}} - - {{/each}} - - - - - Opponent's Matches - - - {{#each your.matches}} - - - {{score}} - - {{/each}} - - - - - - {{/with}} + {{/with}} {{/let}} diff --git a/client/templates/matches/matches.js b/client/templates/matches/matches.js index 19f9675..a416c87 100644 --- a/client/templates/matches/matches.js +++ b/client/templates/matches/matches.js @@ -1,49 +1,53 @@ Template.Matches.helpers({ - scoreBoard: function() { + scoreBoard: async function () { var gameScore = { my: {}, your: {}, }; - var curGame = Games.findOne({_id: Session.get('gameId')}, { - transform: function(doc) { - var lastMove = doc.moves.pop(); - if (lastMove) { - if (lastMove.turnIdx === 1) { - doc.players[lastMove.playerIdx].myTurn = true; - } else if (lastMove.playerIdx === 0) { - doc.players[1].myTurn = true; + await Games.findOneAsync( + { _id: Session.get("gameId") }, + { + transform: function (doc) { + var lastMove = doc.moves.pop(); + if (lastMove) { + if (lastMove.turnIdx === 1) { + doc.players[lastMove.playerIdx].myTurn = true; + } else if (lastMove.playerIdx === 0) { + doc.players[1].myTurn = true; + } else { + doc.players[0].myTurn = true; + } } else { - doc.players[0].myTurn = true; + if (doc.players.length === 2) doc.players[1].myTurn = true; } - } else { - if (doc.players.length === 2) doc.players[1].myTurn = true; - } - for (i = 0; i <= 1; i++) { - if (doc.players[i]) { - if (doc.players[i].device === Session.get('deviceId')) { - gameScore.my.playerIdx = i; - gameScore.my.name = doc.players[i].deviceName; - gameScore.my.score = doc.players[i].totalScore; - gameScore.my.turn = doc.players[i].myTurn; - gameScore.my.matches = doc.players[i].matches; + for (i = 0; i <= 1; i++) { + if (doc.players[i]) { + if (doc.players[i].device === Session.get("deviceId")) { + gameScore.my.playerIdx = i; + gameScore.my.name = doc.players[i].deviceName; + gameScore.my.score = doc.players[i].totalScore; + gameScore.my.turn = doc.players[i].myTurn; + gameScore.my.matches = doc.players[i].matches; + } else { + gameScore.your.playerIdx = i; + gameScore.your.name = doc.players[i].deviceName; + gameScore.your.score = doc.players[i].totalScore; + gameScore.your.turn = doc.players[i].myTurn; + gameScore.your.matches = doc.players[i].matches; + } } else { - gameScore.your.playerIdx = i; - gameScore.your.name = doc.players[i].deviceName; - gameScore.your.score = doc.players[i].totalScore; - gameScore.your.turn = doc.players[i].myTurn; - gameScore.your.matches = doc.players[i].matches; + url = Meteor.absoluteUrl() + "#" + Session.get("gameId"); + gameScore.your.name = "Waiting for challenger"; + gameScore.your.url = url; + gameScore.your.turn = true; } - } else { - url = Meteor.absoluteUrl() + '#' + Session.get('gameId'); - gameScore.your.name = 'Waiting for challenger'; - gameScore.your.url = url; - gameScore.your.turn = true; } - } - return gameScore; + return gameScore; + }, } - }); + ); + if (gameScore) return gameScore; - } + }, }); diff --git a/mobile-config.js b/mobile-config.js index 431e312..1990a59 100644 --- a/mobile-config.js +++ b/mobile-config.js @@ -1,10 +1,10 @@ App.info({ - id: 'com.meteor.gridmatch', - name: 'GridMatch', - description: 'A game that requires concentration', - author: 'Paul Laskowski', - email: 'paul@warmbowski.com', - website: 'https://gridmatch.herokuapp.com' + id: "com.meteor.gridmatch", + name: "GridMatch", + description: "A game that requires concentration", + author: "Paul Laskowski", + email: "paul@warmbowski.com", + website: "https://gridmatch.meteorapp.com", }); -App.setPreference('Orientation', 'default'); +App.setPreference("Orientation", "default"); diff --git a/models/games.js b/models/games.js index 24ec22a..6d203a6 100644 --- a/models/games.js +++ b/models/games.js @@ -1,19 +1,19 @@ -Grids = new Meteor.Collection('grids'); -Games = new Meteor.Collection('games'); +Grids = new Meteor.Collection("grids"); +Games = new Meteor.Collection("games"); Games.allow({ - update: function(userId, doc, fieldNames, modifier) { - if (_.contains(fieldNames, 'grid')) { + updateAsync: function (userId, doc, fieldNames, modifier) { + if (_.contains(fieldNames, "grid")) { return modifier.$set; } - if (_.contains(fieldNames, 'players')) { + if (_.contains(fieldNames, "players")) { return modifier.$addToSet.players; } else { return modifier.$pull.players; } }, - remove: function(userId, doc) { + removeAsync: function (userId, doc) { return true; - } -}); \ No newline at end of file + }, +}); diff --git a/package-lock.json b/package-lock.json index 2ec9bf1..3858c02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,26 +1,339 @@ { "name": "gridmatch", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 3, "requires": true, - "dependencies": { - "@babel/runtime": { + "packages": { + "": { + "name": "gridmatch", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@babel/runtime": "^7.12.5", + "jquery": "^3.6.4" + }, + "devDependencies": { + "autoprefixer": "^10.4.20", + "postcss": "^8.4.47", + "postcss-load-config": "^6.0.1" + } + }, + "node_modules/@babel/runtime": { "version": "7.12.5", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", - "requires": { + "dependencies": { "regenerator-runtime": "^0.13.4" } }, - "jquery": { + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/browserslist": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001662", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001662.tgz", + "integrity": "sha512-sgMUVwLmGseH8ZIrm1d51UbrhqMCH3jvS7gF/M6byuHOnKyLOBL7W8yz5V02OHwgLGA36o/AFhWzzh4uc5aqTA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.27", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.27.tgz", + "integrity": "sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw==", + "dev": true, + "license": "ISC" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/jquery": { "version": "3.6.4", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.4.tgz", "integrity": "sha512-v28EW9DWDFpzcD9O5iyJXg3R3+q+mET5JhnjJzQUZMHOv67bpSIHq81GEYpPNZHG+XXHsfSme3nxp/hndKEcsQ==" }, - "regenerator-runtime": { + "node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "dev": true, + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/regenerator-runtime": { "version": "0.13.7", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } } } } diff --git a/package.json b/package.json index 828cb0f..57703aa 100644 --- a/package.json +++ b/package.json @@ -18,5 +18,10 @@ "dependencies": { "@babel/runtime": "^7.12.5", "jquery": "^3.6.4" + }, + "devDependencies": { + "autoprefixer": "^10.4.20", + "postcss": "^8.4.47", + "postcss-load-config": "^6.0.1" } } diff --git a/server/lib/methods.js b/server/lib/methods.js index d207911..50dc81f 100644 --- a/server/lib/methods.js +++ b/server/lib/methods.js @@ -1,6 +1,6 @@ Meteor.methods({ newGame: function (deviceId, gameSize, gameId) { - const initializeGame = function (replayId, deviceId, deck) { + const initializeGame = async function (replayId, deviceId, deck) { var cardsShuffled = deck.shuffleDeck().map(function (value, index) { var score; if (value < this.bombs) { @@ -19,7 +19,7 @@ Meteor.methods({ // initialize new game entry in db if (replayId) { - return Games.update( + return await Games.updateAsync( { _id: replayId }, { $set: { @@ -33,7 +33,7 @@ Meteor.methods({ } ); } else { - return Games.insert({ + return await Games.insertAsync({ grid: cardsShuffled, gridSize: gameSize, gameStatus: "fresh", @@ -62,8 +62,8 @@ Meteor.methods({ return initializeGame(gameId, deviceId, deck); }, - leaveGame: function (gameId, deviceId) { - Games.update( + leaveGame: async function (gameId, deviceId) { + await Games.updateAsync( { _id: gameId }, { $pull: { players: { device: deviceId } }, @@ -72,13 +72,13 @@ Meteor.methods({ ); }, - removeGame: function (gameId) { + removeGame: async function (gameId) { //only remove dirty game - Games.remove({ _id: gameId, gameStatus: "dirty" }); + await Games.removeAsync({ _id: gameId, gameStatus: "dirty" }); }, - flipUpCard: function (gameId, thisMove, lastMove) { - Games.update( + flipUpCard: async function (gameId, thisMove, lastMove) { + await Games.updateAsync( { _id: gameId, "grid.idx": thisMove.cardIdx }, { $set: { "grid.$.class": "turned-up player-" + thisMove.playerIdx }, @@ -87,14 +87,14 @@ Meteor.methods({ ); if (thisMove.turnIdx === 2) { - curGameData = Games.findOne({ _id: gameId }); + curGameData = await Games.findOneAsync({ _id: gameId }); if ( curGameData.grid[thisMove.cardIdx].val === curGameData.grid[lastMove.cardIdx].val ) { var thisMatch = curGameData.grid[thisMove.cardIdx]; if (thisMove.playerIdx === 0) { - Games.update( + await Games.updateAsync( { _id: gameId }, { $set: { @@ -105,7 +105,7 @@ Meteor.methods({ } ); } else { - Games.update( + await Games.updateAsync( { _id: gameId }, { $set: { @@ -118,12 +118,12 @@ Meteor.methods({ } return "Match Found"; } else { - Meteor.setTimeout(function () { - Games.update( + Meteor.setTimeout(async function () { + await Games.updateAsync( { _id: gameId, "grid.idx": thisMove.cardIdx }, { $set: { "grid.$.class": "turned-down" } } ); - Games.update( + await Games.updateAsync( { _id: gameId, "grid.idx": lastMove.cardIdx }, { $set: { "grid.$.class": "turned-down" } } ); diff --git a/server/pubs/games.js b/server/pubs/games.js index 75e43f1..bfda3ee 100644 --- a/server/pubs/games.js +++ b/server/pubs/games.js @@ -1,57 +1,61 @@ // When publishing a list of games, keep each card val/score a secret. -Meteor.publish('allGames', function(gameId) { +Meteor.publish("allGames", function (gameId) { if (gameId) { - return Games.find({_id: gameId}, {fields: {'grid.val': 0, 'grid.score': 0}}); + return Games.find( + { _id: gameId }, + { fields: { "grid.val": 0, "grid.score": 0 } } + ); } else { - return Games.find({players: {$size: 1}}, {fields: {grid: 0}}); + return Games.find({ players: { $size: 1 } }, { fields: { grid: 0 } }); } }); -// When publishing the current game in play, publish a separate Grids collection of +// When publishing the current game in play, publish a separate Grids collection of // cards that only reveals the val/score of cards that have been turned up. -Meteor.publish('myGame', function (gameId) { +Meteor.publish("myGame", async function (gameId) { var self = this; if (!gameId) return; check(gameId, String); - var fixGrid = function(array) { - //console.log('fixGrid'); + var fixGrid = function (array) { + // console.log("fixGrid"); for (i = 0; i < array.length; i++) { - if (array[i].class === 'turned-down') { - array[i].val = ''; - array[i].score = ''; + if (array[i].class === "turned-down") { + array[i].val = ""; + array[i].score = ""; } } return array; }; - var cursor = Games.find({_id: gameId}); - var game = cursor.fetch()[0]; - if (typeof game !== 'object') return; - + var cursor = Games.find({ _id: gameId }); + var games = await cursor.fetchAsync(); + var game = games[0]; + if (typeof game !== "object") return; + var gridArray; - var handle = cursor.observeChanges({ - removed: function(id) { - //console.log('removed'); + var handle = await cursor.observeChanges({ + removed: function (id) { + // console.log('removed'); self.removed("grids", id); }, - changed: function(id, fields) { - //console.log('changed'); + changed: function (id, fields) { + // console.log('changed'); if (fields.grid) { gridArray = fixGrid(fields.grid); - self.changed("grids", id, {grid: gridArray}); + self.changed("grids", id, { grid: gridArray }); } - } + }, }); - //console.log('init'); + // console.log('init'); gridArray = fixGrid(game.grid); - self.added('grids', gameId, {grid: gridArray}); + self.added("grids", gameId, { grid: gridArray }); self.ready(); self.onStop(function () { - //console.log('stop'); + // console.log('stop'); handle.stop(); }); });
{{your.url}}
Your game will start when an opponent joins.