From 1f4b46f055d24570857249265238c3d000eead5d Mon Sep 17 00:00:00 2001 From: Jonathan Luk Date: Thu, 5 Sep 2019 22:15:13 +0000 Subject: [PATCH 1/2] Done. --- app/assets/javascripts/tictactoe.js | 171 +++++++++++++++++++++++++++- db/schema.rb | 1 - test/tictactoeTest.js | 75 ++++++------ 3 files changed, 207 insertions(+), 40 deletions(-) diff --git a/app/assets/javascripts/tictactoe.js b/app/assets/javascripts/tictactoe.js index d4da8daca..36943dc91 100644 --- a/app/assets/javascripts/tictactoe.js +++ b/app/assets/javascripts/tictactoe.js @@ -1 +1,170 @@ -// Code your JavaScript / jQuery solution here +$(function() { + displayGames(); + attachListeners(); + savingGameButton(); + clearGame(); +}); + +winningCombinations = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[6,4,2]] +var turn = 0 + +function attachListeners() { + $('td').each(function() { + $(this).click(function(event) { + doTurn(event.target); + }); + }); +} + +function player() { + var player = turn % 2 === 0 ? 'X' : 'O'; + return player; +} + +function updateState(square) { + var playerToken = player(); + $(square).text(playerToken); +} + +function setMessage(message) { + $('#message').text(message); +} + +function doTurn(square) { + if (squareAvailable(square) && !gameOver()) { + updateState(square); + if (checkWinner() || gameTie()) { + saveGame() + resetGame(); + turn = 0; + } else { + turn++; + } + } +} + + +function checkWinner() { + if(gameWon()) { + var state = getState(); + var winningCombination = winningCombinations.filter(function(combination) { + return (state[combination[0]] === state[combination[1]] && state[combination[0]] !== "") && state[combination[1]] == state[combination[2]] + }); + var winner = state[winningCombination[0][1]]; + setMessage(`Player ${winner} Won!`); + return true + } else { + if (gameTie()) { + setMessage(`Tie game.`); + } + return false + } +} + + +function resetGame() { + $('td').each(function(index, el) { + $(el).text(''); + }) + turn = 0; +} + + +function getState() { + var state = [] + var squares = $('td').each(function(index, el) { + state[index] = $(el).text() + }); + return state; +} + +function gameWon() { + var state = getState(); + return winningCombinations.some(function(combination) { + return (state[combination[0]] === state[combination[1]] && state[combination[0]] !== "") && state[combination[1]] == state[combination[2]] + }); +} + +function gameTie(){ + var state = getState(); + if (!gameWon()) { + return state.every(function(square) { + return square != '' + }); + } +} + +function squareAvailable(square) { + return $(square).text() === "" +} + +function gameOver() { + return gameWon() || gameTie() +} + + +function savingGameButton (){ + $('#save').click(function() { + saveGame(); + }) +} + +function saveGame() { + var id = $('table').attr('data-gameid') + if (id) { + $.ajax({ + type: "PATCH", + url: '/games/' + id, + data: { "state": getState()}, + success : function(response, textStatus, jqXhr) { + console.log("Venue Successfully Patched!"); + } + }); + } else { + var createGame = $.post('/games', { state: getState() }); + createGame.done(function(data) { + $('table').attr('data-gameid', data['data']['id']); + }) + } +} + +function displayGames() { + $('#previous').click(function() { + $.get('/games', function(data) { + if (data['data'].length > 0) { + var gamesHTML = '' + for (var i = 0; i < data['data'].length; i++) { + gamesHTML += '' + } + $('#games').html(gamesHTML) + $('#games button').click(function(event) { + loadGame(event.target.textContent); + }) + } + }); + }); +} + +function loadGame(id) { + var state = $.get('/games/' + id, function(data) { + $('td').each(function (index, element) { + $(element).text(data['data']['attributes']['state'][index]) + }); + $('table').attr('data-gameid', data['data']['id']); + refreshTurn(); + }); +} + +function refreshTurn() { + var state = getState(); + turn = state.filter(function(square) { + return square != '' + }).length; +} + +function clearGame() { + $('#clear').click(function() { + resetGame(); + $('table').removeAttr('data-gameid') + }); +} diff --git a/db/schema.rb b/db/schema.rb index 349d9bd29..c9a8a85b7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,4 +1,3 @@ -# encoding: UTF-8 # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. diff --git a/test/tictactoeTest.js b/test/tictactoeTest.js index 9c5f90b61..7201fa85b 100644 --- a/test/tictactoeTest.js +++ b/test/tictactoeTest.js @@ -51,7 +51,6 @@ describe('tictactoe.js', () => { it('returns "O" when the turn count is odd', () => { window.turn = 3; - expect(window.player()).to.equal('O'); }); }); @@ -114,33 +113,33 @@ describe('tictactoe.js', () => { it('returns true when a player wins horizontally', () => { populateBoard(['X', 'X', 'X', '', '', '', 'O', 'O', '']); - // X | X | X + // X | X | X // ----------- - // | | + // | | // ----------- - // O | O | + // O | O | expect(window.checkWinner()).to.be.true; }); it('returns true when a player wins diagonally', () => { populateBoard(['X', 'X', 'O', '', 'O', '', 'O', 'X', '']); - // X | X | O + // X | X | O // ----------- - // | O | + // | O | // ----------- - // O | X | + // O | X | expect(window.checkWinner()).to.be.true; }); it('returns true when a player wins vertically', () => { populateBoard(['O', '', 'X', '', 'O', 'X', 'O', '', 'X']); - // O | | X + // O | | X // ----------- - // | O | X + // | O | X // ----------- - // O | | X + // O | | X expect(window.checkWinner()).to.be.true; }); @@ -149,11 +148,11 @@ describe('tictactoe.js', () => { expect(window.checkWinner()).to.equal(false); populateBoard(['X', 'O', 'X', 'X', 'O', 'X', 'O', 'X', 'O']); - // X | O | X + // X | O | X // ----------- - // X | O | X + // X | O | X // ----------- - // O | X | O + // O | X | O expect(window.checkWinner()).to.equal(false); }); @@ -162,11 +161,11 @@ describe('tictactoe.js', () => { const spy = sandbox.stub(window, 'setMessage'); populateBoard(['', '', '', 'X', 'X', 'X', 'O', 'O', '']); - // | | + // | | // ----------- - // X | X | X + // X | X | X // ----------- - // O | O | + // O | O | window.checkWinner(); @@ -177,11 +176,11 @@ describe('tictactoe.js', () => { const spy = sandbox.stub(window, 'setMessage'); populateBoard(['O', '', '', 'X', 'O', 'X', 'X', '', 'O']); - // O | | + // O | | // ----------- - // X | O | X + // X | O | X // ----------- - // X | | O + // X | | O window.checkWinner(); @@ -229,11 +228,11 @@ describe('tictactoe.js', () => { const spy = sandbox.spy(window, 'setMessage'); populateBoard(['X', 'O', 'X', 'X', 'O', 'X', 'O', '', 'O']); - // X | O | X + // X | O | X // ----------- - // X | O | X + // X | O | X // ----------- - // O | | O + // O | | O window.turn = 8; window.doTurn(squares[7]); @@ -245,11 +244,11 @@ describe('tictactoe.js', () => { sinon.useFakeXMLHttpRequest(); populateBoard(['X', 'X', 'O', 'X', 'O', 'X', '', 'O', 'O']); - // X | X | O + // X | X | O // ----------- - // X | O | X + // X | O | X // ----------- - // | O | O + // | O | O window.turn = 8; window.doTurn(squares[6]); @@ -313,11 +312,11 @@ describe('Gameplay', () => { it('Users cannot play any turns once a game is won or tied', () => { populateBoard(['X', 'X', 'X', '', '', '', 'O', 'O', '']); window.turn = 5; - // X | X | X + // X | X | X // ----------- - // | | + // | | // ----------- - // O | O | + // O | O | squares[4].click(); @@ -329,11 +328,11 @@ describe('Gameplay', () => { sinon.useFakeXMLHttpRequest(); populateBoard(['X', 'O', 'X', 'X', 'O', 'X', 'O', '', 'O']); - // X | O | X + // X | O | X // ----------- - // X | O | X + // X | O | X // ----------- - // O | | O + // O | | O window.turn = 8; window.doTurn(squares[7]); @@ -578,11 +577,11 @@ describe('AJAX interactions with the Rails API', () => { it('auto-saves tie games', () => { populateBoard(['X', 'O', 'X', 'X', 'O', 'X', 'O', '', 'O']); - // X | O | X + // X | O | X // ----------- - // X | O | X + // X | O | X // ----------- - // O | | O + // O | | O window.turn = 8; window.doTurn(squares[7]); @@ -594,11 +593,11 @@ describe('AJAX interactions with the Rails API', () => { it('auto-saves won games', () => { populateBoard(['X', 'X', '', '', '', '', 'O', 'O', '']); window.turn = 4; - // X | X | + // X | X | // ----------- - // | | + // | | // ----------- - // O | O | + // O | O | squares[2].click(); @@ -692,4 +691,4 @@ describe('AJAX interactions with the Rails API', () => { expect(requests[2].url).to.equal('/games/1'); }); }); -}); \ No newline at end of file +}); From 7afd7fc63771363ab9820d44583dc4b1f2cfb679 Mon Sep 17 00:00:00 2001 From: Jonathan Luk Date: Thu, 5 Sep 2019 23:25:02 +0000 Subject: [PATCH 2/2] Done. --- app/assets/javascripts/tictactoe.js | 6 +++--- app/serializers/game_serializer.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/tictactoe.js b/app/assets/javascripts/tictactoe.js index 36943dc91..2682011c8 100644 --- a/app/assets/javascripts/tictactoe.js +++ b/app/assets/javascripts/tictactoe.js @@ -61,7 +61,6 @@ function checkWinner() { } } - function resetGame() { $('td').each(function(index, el) { $(el).text(''); @@ -69,7 +68,6 @@ function resetGame() { turn = 0; } - function getState() { var state = [] var squares = $('td').each(function(index, el) { @@ -134,7 +132,9 @@ function displayGames() { if (data['data'].length > 0) { var gamesHTML = '' for (var i = 0; i < data['data'].length; i++) { - gamesHTML += '' + var date = new Date(data['data'][i]['attributes']['updated-at']).toLocaleString(); + gamesHTML += '' + console.log(data) } $('#games').html(gamesHTML) $('#games button').click(function(event) { diff --git a/app/serializers/game_serializer.rb b/app/serializers/game_serializer.rb index 3af645bb3..e57788189 100644 --- a/app/serializers/game_serializer.rb +++ b/app/serializers/game_serializer.rb @@ -1,3 +1,3 @@ class GameSerializer < ActiveModel::Serializer - attributes :id, :state + attributes :id, :state, :updated_at end