diff --git a/build/index.html b/build/index.html index 00eb541..5dbe047 100644 --- a/build/index.html +++ b/build/index.html @@ -1,10 +1,56 @@ - - Tic-Tac-Toe - - - - - + + Tic-Tac-Toe + + + + + + + + + + +
+ +
+

Tic-Tac-Gradient

+
+ +
+
    +
    + +
    + +
    + +
    + +
    + +
    + + + +
    + + + + + + + + + + + + + + diff --git a/build/styles/index.css b/build/styles/index.css new file mode 100644 index 0000000..c514986 --- /dev/null +++ b/build/styles/index.css @@ -0,0 +1,85 @@ +h1, h2, h3 { + font-family: 'Press Start 2P', cursive; + text-align: center; + color: grey; +} + +h1 { + font-size: 4vw; + margin: 3vw; + +} + +h2, h3 { + font-size: 2vw; + margin-bottom: 0; +} + +body { + margin: 10px 10%; + background-color: white; +} + +#ttt-board, #played-games { + width: 60%; + margin: 0 auto; +} + +li { + list-style: none; + border: .25vw solid white; + background-color: rgba(128, 128, 128, 0.4); + min-height: 11vw; + min-width: 11vw; + border-radius: .25rem; + padding: .25vw; +} + +#players { + margin-bottom: 2vw; +} + +#played-games > li { + padding: 4vw; + margin: 1vw; +} + +#played-games > li:hover { + background-color: rgba(128, 128, 128, 1); + padding: 2vw; + padding-top: 3vw; +} + +#played-games > li:hover h3::before { + font-family: FontAwesome; + content: '\f1f8'; + color: white; + padding-left: 15vw; + font-size: 3vw; + padding-top: 0; + padding-bottom: 0; +} + +/*X Gradient*/ + +.X0 { background-color: #4A9E9D; } + +.X1 { background-color: #4C8E99; } + +.X2 { background-color: #4F8396; } + +.X3 { background-color: #536B90; } + +.X4 { background-color: #565D8E; } + +/*O Gradient*/ + +.O0 { background-color: #FFC271; } + +.O1 { background-color: #FFB670; } + +.O2 { background-color: #FFA570; } + +.O3 { background-color: #FF936F; } + +.O4 { background-color: #FF8A6F; } diff --git a/spec/board.spec.js b/spec/board.spec.js new file mode 100644 index 0000000..04d1b7b --- /dev/null +++ b/spec/board.spec.js @@ -0,0 +1,55 @@ +// Do not remove +import Board from 'app/models/board'; + +describe('Board', function() { + + var testBoard = new Board(); + + describe('Board', function() { + it('should be defined', function() { + expect(testBoard).toBeDefined(); + }); + + it('should have a grid', function() { + expect(testBoard.get('grid')).toBeDefined(); + }); + + }); + + describe('grid', function() { + + var grid = testBoard.get('grid'); + + it('should be an array', function() { + expect(Array.isArray(grid)).toBe(true); + }); + + it('should be 3 long', function() { + expect(grid.length).toEqual(3); + }); + + it('should be made of sub-arrays', function() { + grid.forEach(function(array) { + expect(Array.isArray(array)).toBe(true); + }); + }); + + it('each sub-arrays should have a length of 3', function() { + grid.forEach(function(array) { + expect(array.length).toEqual(3); + }); + }); + + it('each sub-arrays should default values of null', function() { + grid.forEach(function(array) { + array.forEach(function(element){ + expect(element).toBeNull(); + + }); + }); + }); + + + + }); +}); diff --git a/spec/player.spec.js b/spec/player.spec.js new file mode 100644 index 0000000..438d920 --- /dev/null +++ b/spec/player.spec.js @@ -0,0 +1,25 @@ +// Do not remove +import Player from 'app/models/player'; + +describe('Player', function() { + + var testPlayerX = new Player({name: "Testy", marker: "X"}); + var testPlayerO = new Player({name: "Crabby", marker: "O"}); + + describe('Player', function() { + it('should be defined', function() { + expect(testPlayerX).toBeDefined(); + }); + + it('should have a name', function() { + expect(testPlayerX.get('name')).toEqual("Testy"); + }); + + it('should be assigned a marker', function() { + expect(testPlayerX.get('marker')).toEqual("X"); + expect(testPlayerO.get('marker')).toEqual("O"); + }); + + }); + +}); diff --git a/spec/tictactoe.spec.js b/spec/tictactoe.spec.js new file mode 100644 index 0000000..e4e1350 --- /dev/null +++ b/spec/tictactoe.spec.js @@ -0,0 +1,286 @@ +// Do not remove +import TicTacToe from 'app/models/tictactoe'; + +jasmine.getEnv().topSuite().beforeEach({fn: function() { + //log in as admin +}}); + +describe('TicTacToe', function() { + + var testTicTacToe; + beforeEach(function(){ + testTicTacToe = new TicTacToe(); + }); + + afterEach(function(){ + testTicTacToe.destroy(); + }); + + + describe('TicTacToe', function() { + it('should be defined', function() { + expect(testTicTacToe).toBeDefined(); + }); + + it('should have a board', function() { + expect(testTicTacToe.get('board')).toBeDefined(); + }); + + it('should have two players', function() { + expect(testTicTacToe.get('player1')).toBeDefined(); + expect(testTicTacToe.get('player2')).toBeDefined(); + }); + + it('should have turns', function() { + expect(testTicTacToe.get('turns')).toBeDefined(); + }); + + }); + + describe('playTurn and outputResult', function() { + var playTicTacToe = new TicTacToe(); + + var tieTicTacToe = new TicTacToe(); + var winTicTacToe = new TicTacToe(); + + + it('should return FALSE when the game has not ended', function() { + expect(playTicTacToe.playTurn([0,0])).toBeFalsy(); + }); + + it('should output the correct message when the game is tied', function() { + tieTicTacToe.playTurn([0,0]); + tieTicTacToe.playTurn([0,1]); + tieTicTacToe.playTurn([0,2]); + tieTicTacToe.playTurn([1,0]); + tieTicTacToe.playTurn([1,2]); + tieTicTacToe.playTurn([1,1]); + tieTicTacToe.playTurn([2,0]); + tieTicTacToe.playTurn([2,2]); + + expect(tieTicTacToe.playTurn([2,1])).toEqual("The Game is Over. You have tied."); + }); + + it('should output the correct message when someone wins', function() { + winTicTacToe.playTurn([0,0]); + winTicTacToe.playTurn([0,1]); + winTicTacToe.playTurn([1,1]); + winTicTacToe.playTurn([2,1]); + + var winnerName = winTicTacToe.get('players')[winTicTacToe.currentPlayer].name; + + expect(winTicTacToe.playTurn([2,2])).toEqual("The Game is Over. " + winnerName + " has won!" ); + }); + + }); + + describe('isValidPlacement', function() { + + it('should return false if the placement on the board does not exist', function() { + expect(testTicTacToe.isValidPlacement([0, 1000])).toBeFalsy(); + }); + + it('should return false if the placement on the board is already occupied', function() { + + var occupiedGrid = [ + ['X', 'O', null], + [null, null, null], + [null, null, null] + ]; + + var occupiedTicTacToe = new TicTacToe(); + occupiedTicTacToe.get('board').set('grid', occupiedGrid); + + expect(occupiedTicTacToe.isValidPlacement([0,0])).toBeFalsy(); + + var test = new TicTacToe(); + }); + + it('should return true if the placement on the board is not occupied', function() { + expect(testTicTacToe.isValidPlacement([0, 1])).toBeTruthy(); + }); + + }); + + describe('updateBoard', function() { + + it('should change the boards current value to the given marker', function() { + var boardPosition = [0,0]; + var row = boardPosition[0]; + var column = boardPosition[1]; + + var boardValue = testTicTacToe.get('board').get('grid')[row][column]; + + expect(boardValue).toBeNull(); + + testTicTacToe.updateBoard(boardPosition, "X"); + + var boardValueUpdate = testTicTacToe.get('board').get('grid')[row][column]; + + expect(boardValueUpdate).toEqual("X"); + + }); + + }); + + describe('endMove', function() { + + it('should increment the games turns by 1 AND change the current player when turns are less than 5', function() { + var gameTurns = testTicTacToe.get('turns'); + var originalPlayer = testTicTacToe.get('currentPlayer'); + + testTicTacToe.endMove(); + + expect(testTicTacToe.get('turns')).toEqual(gameTurns + 1); + expect(testTicTacToe.get('currentPlayer')).not.toEqual(originalPlayer); + + }); + + it('should increment the games turns by 1 AND change the current player when turns are equal to or more than 5 and no one has won', function() { + var turnTicTacToe = new TicTacToe(); + + turnTicTacToe.set('turns', 5); + var gameTurns = turnTicTacToe.get('turns'); + var originalPlayer = turnTicTacToe.get('currentPlayer'); + + turnTicTacToe.endMove(); + + expect(turnTicTacToe.get('turns')).toEqual(gameTurns + 1); + expect(turnTicTacToe.get('currentPlayer')).not.toEqual(originalPlayer); + + // turns are now greater than 5 because of endMove increment + var gameTurns2 = turnTicTacToe.get('turns'); + var originalPlayer2 = turnTicTacToe.get('currentPlayer'); + + turnTicTacToe.endMove(); + + expect(turnTicTacToe.get('turns')).toEqual(gameTurns2 + 1); + expect(turnTicTacToe.get('currentPlayer')).not.toEqual(originalPlayer2); + + }); + + it('should increment the games turns by 1 AND NOT change the current player when turns are equal to or more than 5 AND someone has won', function() { + var horizontalGrid = [ + ['X', 'X', 'X'], + ['O', null, 'O'], + [null, null, null] + ]; + var wonTicTacToe = new TicTacToe(); + + wonTicTacToe.get('board').set('grid', horizontalGrid); + wonTicTacToe.set('turns', 5); + + + var gameTurns = wonTicTacToe.get('turns'); + var originalPlayer = wonTicTacToe.get('currentPlayer'); + + wonTicTacToe.endMove(); + + expect(wonTicTacToe.get('turns')).toEqual(gameTurns + 1); + expect(wonTicTacToe.get('currentPlayer')).toEqual(originalPlayer); + + }); + + }); + + describe('addTurn', function() { + + it('should increment the games turns by 1', function() { + var gameTurns = testTicTacToe.get('turns'); + + testTicTacToe.addTurn(); + + expect(testTicTacToe.get('turns')).toEqual(gameTurns + 1); + }); + + }); + + describe('hasWon', function() { + + it('should return FALSE if no one has won', function() { + // incomplete board (contains null) + expect(testTicTacToe.hasWon()).toBeFalsy(); + // complete board (tie) + var tieGrid = [ + ['X', 'O', 'X'], + ['O', 'X', 'O'], + ['O', 'X', 'O'] + ]; + var tieTicTacToe = new TicTacToe(); + + tieTicTacToe.get('board').set('grid', tieGrid); + + expect(tieTicTacToe.hasWon()).toBeFalsy(); + }); + + it('should not match nulls when evaluating markers for matches', function() { + expect(testTicTacToe.hasWon()).toBeFalsy(); + }); + + it('should return TRUE if 3 markers match horizontally', function() { + var horizontalGrid = [ + ['X', 'X', 'X'], + ['O', null, 'O'], + [null, null, null] + ]; + var horizontalTicTacToe = new TicTacToe(); + + horizontalTicTacToe.get('board').set('grid', horizontalGrid); + + expect(horizontalTicTacToe.hasWon()).toBeTruthy(); + }); + + it('should return TRUE if 3 markers match vertically', function() { + var verticalGrid = [ + ['X', 'O', 'X'], + ['X', 'O', 'O'], + ['X', null, null] + ]; + var verticalTicTacToe = new TicTacToe(); + + verticalTicTacToe.get('board').set('grid', verticalGrid); + + expect(verticalTicTacToe.hasWon()).toBeTruthy(); + }); + + it('should return TRUE if 3 markers match diagonally', function() { + var diagonalBottomGrid = [ + ['X', 'O', 'X'], + ['O', 'X', 'O'], + ['X', null, null] + ]; + var diagonalBottomTicTacToe = new TicTacToe(); + + diagonalBottomTicTacToe.get('board').set('grid', diagonalBottomGrid); + expect(diagonalBottomTicTacToe.hasWon()).toBeTruthy(); + + var diagonalTopGrid = [ + ['X', 'O', 'X'], + ['O', 'X', null], + ['O', null, 'X'] + ]; + var diagonalTopTicTacToe = new TicTacToe(); + + diagonalTopTicTacToe.get('board').set('grid', diagonalTopGrid); + expect(diagonalTopTicTacToe.hasWon()).toBeTruthy(); + }); + + }); + + describe('changePlayers', function() { + + it('change the current player to next player and back again', function() { + var originalPlayer = testTicTacToe.get('currentPlayer'); + + testTicTacToe.changePlayers(); + expect(testTicTacToe.get('currentPlayer')).not.toEqual(originalPlayer); + + testTicTacToe.changePlayers(); + expect(testTicTacToe.get('currentPlayer')).toEqual(originalPlayer); + + + }); + + }); + +}); diff --git a/src/app.js b/src/app.js new file mode 100644 index 0000000..28bcc7a --- /dev/null +++ b/src/app.js @@ -0,0 +1,18 @@ +import $ from 'jquery'; + +import ApplicationView from 'app/views/application_view'; +import Games from 'app/collections/games'; + +$(document).ready(function() { + var games = new Games({ + + }); + + + var appView = new ApplicationView({ + el: '#application', + model: games + }); + + appView.render(); +}); diff --git a/src/.keep b/src/app/collections/.keep similarity index 100% rename from src/.keep rename to src/app/collections/.keep diff --git a/src/app/collections/games.js b/src/app/collections/games.js new file mode 100644 index 0000000..6509de4 --- /dev/null +++ b/src/app/collections/games.js @@ -0,0 +1,20 @@ +import Backbone from 'backbone'; + +import TicTacToe from 'app/models/tictactoe'; +import Game from 'app/models/game'; + + +var Games = Backbone.Collection.extend({ + model: Game, + game: new TicTacToe({}), + url: 'https://safe-mesa-21103.herokuapp.com/api/v1/games', + parse: function(data) { + return data; + } + +}); + +module.exports = Games; + +// DO NOT REMOVE THIS +export default Games; diff --git a/src/app/models/board.js b/src/app/models/board.js new file mode 100644 index 0000000..2de3a1d --- /dev/null +++ b/src/app/models/board.js @@ -0,0 +1,26 @@ +import Backbone from 'backbone'; + +const Board = Backbone.Model.extend({ + + defaults: { + grid : [ + [null, null, null], + [null, null, null], + [null, null, null] + ] + }, + + initialize: function() { + this.set('grid', [ + [null, null, null], + [null, null, null], + [null, null, null] + ]); + } + +}); + +module.exports = Board; + +// DO NOT REMOVE THIS +export default Board; diff --git a/src/app/models/game.js b/src/app/models/game.js new file mode 100644 index 0000000..d94c6b5 --- /dev/null +++ b/src/app/models/game.js @@ -0,0 +1,34 @@ +import Backbone from 'backbone'; + +const Game = Backbone.Model.extend({ +// this model is a wrapper for the API that is formatted like the API is + initialize: function(options) { + this.board = options.board; + this.players = options.players; + this.marker = options.outcome; + + switch (this.marker) { + case 'X': + this.outcome = 'Player1'; + break; + case 'O': + this.outcome = 'Player2'; + break; + case 'draw': + this.outcome = 'No one'; + break; + default: + this.outcome = 'Unknown person'; + break; + } + + this.playet_at = options.played_at; + + } + +}); + +module.exports = Game; + +// DO NOT REMOVE THIS +export default Game; diff --git a/src/app/models/player.js b/src/app/models/player.js new file mode 100644 index 0000000..cac3698 --- /dev/null +++ b/src/app/models/player.js @@ -0,0 +1,16 @@ +import Backbone from 'backbone'; + +const Player = Backbone.Model.extend({ + + initialize: function(options) { + this.name = options.name; + this.marker = options.marker; + + } + +}); + +module.exports = Player; + +// DO NOT REMOVE THIS +export default Player; diff --git a/src/app/models/tictactoe.js b/src/app/models/tictactoe.js new file mode 100644 index 0000000..2ad6f31 --- /dev/null +++ b/src/app/models/tictactoe.js @@ -0,0 +1,240 @@ +import Backbone from 'backbone'; + +import Board from 'app/models/board'; +import Player from 'app/models/player'; + +const TicTacToe = Backbone.Model.extend({ + defaults: { + board: new Board(), + player1: new Player({ name: "Player1", marker: "X" }), + player2: new Player({ name: "Player2", marker: "O" }), + players: [], + turns: 0 + }, + + initialize: function(options) { + + var playersHash = [this.get('player1'), this.get('player2')]; + + this.set('players', playersHash); + + this.set('board', new Board()); + + this.currentPlayer = 0; + + var sample = function(array = [0,1]) { + var index = Math.floor ( Math.random() * array.length ); + return array[index]; + }; + + this.set('currentPlayer', sample()); + + // make an empty 'json object' for sending the completed game to the API + this.json = {}; + + + }, + + + playTurn: function(prompt) { + // A turn will: + + // - know who the current player is + + var player = this.get('players')[this.get('currentPlayer')]; + + // - prompt for placement + var placement = prompt; + + // - check that the placement is valid + // - will return FALSE or valid placement position + if (this.isValidPlacement(placement) && !this.hasWon() ) { + + // - update the board with a valid placement and players marker + this.updateBoard(placement, player.get('marker')); + } else { + // - if FALSE, reprompt/reclick + return false; + } + + // - end the move + this.endMove(); + + // if outputResult is FALSE, the game continues. Otherwise, we return a string of the result of the game. + return this.outputResult(player); + }, + + outputResult: function(player) { + + var playerName = player.name; + // - check if has won or if tie and report information + + var result = ""; + if (this.hasWon() || this.get('turns') == 9) { + result += "The Game is Over. "; + if(this.hasWon()) { + result += playerName + " has won!"; + } else { + result += "You have tied."; + } + return result; + } + + return false; + }, + + isValidPlacement: function(placement) { + // To be valid: + // - get the placement + // format of placement argument: [rowIndex, columnIndex] + // - check the board for valid placement + // - return FALSE if not valid + // - return the placement if valid + + this.placement = placement; + this.row = this.placement[0]; + this.column = this.placement[1]; + + var boardPosition = this.get('board').get('grid')[this.row][this.column]; + + if ( boardPosition === null ) { + return true; + } else { + return false; + } + + }, + + updateBoard: function(boardPosition, marker) { + this.marker = marker; + + this.boardPosition = boardPosition; + this.row = this.boardPosition[0]; + this.column = this.boardPosition[1]; + + this.gridCopy = this.get('board').get('grid'); + + this.gridCopy[this.row][this.column] = this.marker; + + this.get('board').set('grid', this.gridCopy); + + return this.get('board'); + }, + + endMove: function() { + // Ending the move will: + // - increment the turns counter by 1 + // - check if the game has been won + // - switch current player + + this.addTurn(); + if (this.get('turns') >= 5 && !this.hasWon()) { + // only change players if hasWon is false after 5 turns + this.changePlayers(); + } else if (this.get('turns') < 5) { + // for the first 4 turns, always changePlayers because there is no chance of victory + this.changePlayers(); + } + + }, + + addTurn: function() { + var endingValue = this.get('turns') + 1; + this.set('turns', endingValue); + }, + + hasWon: function() { + // grid[row][column] + var grid = this.get('board').get('grid'); + + // A horizontal match victory - all columns in same row are equal and none is null + for (var i = 0; i < 3; i++) { + if(grid[i][0] == grid[i][1] && grid[i][0] == grid[i][2] && grid[i][0] !== null){ + return true; + } + } + + // A vertical match victory - all rows in same column are equal and none is null + for (var j = 0; j < 3; j++) { + if(grid[0][j] == grid[1][j] && grid[0][j] == grid[2][j] && grid[0][j] !== null){ + return true; + } + } + + // A diagonal match victory - need to validate two cases: + // - starting in the bottom left + if(grid[2][0] == grid[1][1] && grid[2][0] == grid[0][2] && grid[2][0] !== null){ + return true; + } + // - starting in the top left + if(grid[0][0] == grid[1][1] && grid[0][0] == grid[2][2] && grid[0][0] !== null){ + return true; + } + + return false; + }, + + changePlayers: function() { + this.set('currentPlayer', ((this.get('currentPlayer') === 0) ? 1 : 0)); + + }, + + getJson: function() { +// { +// "id": 1, +// "board": [ +// "X", +// " ", +// "O", +// "X", +// "O", +// " ", +// "X", +// " ", +// " " +// ], +// "players": [ +// "X Player", +// "O Player" +// ], +// "outcome": "X", +// "played_at": "2016-11-20T22:59:10Z" +// } + + this.grid = this.get('board').get('grid'); + + this.jsonBoard = [].concat.apply([], this.grid); + // replace null + this.replaceNull(this.jsonBoard); + + this.jsonPlayers = [ + this.get('player1').get('name'), this.get('player2').get('name') + ]; + this.jsonOutcome = (this.hasWon() ? this.get('players')[this.get('currentPlayer')].get('marker') : 'draw'); + this.jsonPlayedAt = new Date(new Date().getTime()); + + + this.json = { + "board": this.jsonBoard, + "players": this.jsonPlayers, + "outcome": this.jsonOutcome, + "played_at": this.jsonPlayedAt + }; + + return this.json; + + }, + + replaceNull: function (arr) { + for (var i = 0, l = arr.length; i < l; i++) { + if (arr[i] === null) arr[i] = ' '; + } + return arr; + } + +}); + +module.exports = TicTacToe; + +// DO NOT REMOVE THIS +export default TicTacToe; diff --git a/src/app/views/application_view.js b/src/app/views/application_view.js new file mode 100644 index 0000000..971c029 --- /dev/null +++ b/src/app/views/application_view.js @@ -0,0 +1,83 @@ +import Backbone from 'backbone'; +import BoardView from 'app/views/board_view'; +import PlayerView from 'app/views/player_view'; +import SquareView from 'app/views/square_view'; +import GamesView from 'app/views/games_view'; + +// models +import Board from 'app/models/board'; +import Player from 'app/models/player'; +import TicTacToe from 'app/models/tictactoe'; + +const ApplicationView = Backbone.View.extend({ + initialize: function() { + + this.ticTacToe = this.model.game; + + this.board = this.ticTacToe.get('board'); + this.players = this.ticTacToe.get('players'); + + this.listenTo(this, 'change', this.render); + + }, + + playTurn: function(marker) { + var isPlayable = this.ticTacToe.isValidPlacement(marker.position); + var lastTurn = this.ticTacToe.playTurn(marker.position); + + if ( !isPlayable ) { + alert("Invalid move! Pls try again."); + } else if ( isPlayable && !lastTurn) { + this.trigger('change'); + } else if ( lastTurn ) { + alert( lastTurn ); + // send competeled game to the api + // create a new game + + this.model.create(this.ticTacToe.getJson()); + this.trigger('change'); + + } + + this.trigger('change'); + }, + + render: function() { + // we need to fetch up here for updates to show - idk why? + this.model.fetch(); + + + const playerView = new PlayerView({ + players: this.players, + el: this.$('#players'), + currentPlayer: this.ticTacToe.get('currentPlayer') + }); + + const boardView = new BoardView({ + model: this.board, + el: this.$('main') + }); + + this.listenTo(boardView, 'squareSelected', this.playTurn); + + playerView.render(); + boardView.render(); + + + const self = this; + + this.model.fetch().done(function() { + const gamesView = new GamesView({ + model: self.model, + el: self.$('body') + }); + + // gamesView.render(); + + }); + + return this; + } +}); + +export default ApplicationView; diff --git a/src/app/views/board_view.js b/src/app/views/board_view.js new file mode 100644 index 0000000..f51ead1 --- /dev/null +++ b/src/app/views/board_view.js @@ -0,0 +1,57 @@ +import _ from 'underscore'; +import Backbone from 'backbone'; +import SquareView from 'app/views/square_view'; + +const BoardView = Backbone.View.extend({ + initialize: function(options){ + // we re-render the board when the model is updated (a square has been filled) + this.listenTo(this.model, 'change', this.render); + }, + + turn: function() { + // triggers an event + }, + + selectedSquare: function(marker) { + // we need to pass this up to the board which will update the model + this.trigger('squareSelected', marker); + + // We return false to tell jQuery not to run any more event handlers. + + return false; + }, + + + render: function() { + + const boardSquares = Backbone.$('#board-squares'); + boardSquares.empty(); + // loop within a loop - we need to have access to the larger this + + const self = this; + this.grid = this.model.get('grid'); + + this.grid.forEach(function(row, index) { + + var length = row.length; + for (var i = 0; i < length; i++) { + var column = i; + const square = new SquareView({ + model: row[i], + position: [index, column], + tagName: 'li', + numberClass: index + i + }); + + self.listenTo(square, 'select', self.selectedSquare); + boardSquares.append(square.el).addClass('row small-up-3'); + } + + }); + + return this; + } + +}); + +export default BoardView; diff --git a/src/app/views/game_view.js b/src/app/views/game_view.js new file mode 100644 index 0000000..defef4a --- /dev/null +++ b/src/app/views/game_view.js @@ -0,0 +1,26 @@ +import _ from 'underscore'; +import Backbone from 'backbone'; + +const GameView = Backbone.View.extend({ + initialize: function(options){ + }, + + events: { + 'click': 'onClick' + }, + + onClick: function(e) { + this.trigger('selectGame', this.model); + + // We return false to tell jQuery not to run any more event handlers. + + return false; + }, + + render: function() { + } + + +}); + +export default GameView; diff --git a/src/app/views/games_view.js b/src/app/views/games_view.js new file mode 100644 index 0000000..9bb9d80 --- /dev/null +++ b/src/app/views/games_view.js @@ -0,0 +1,45 @@ +import _ from 'underscore'; +import Backbone from 'backbone'; + +import GameView from 'app/views/game_view'; + +const GamesView = Backbone.View.extend({ + initialize: function(options){ + this.template = _.template(Backbone.$('#tmpl-results').html()); + this.render(); + }, + + selectedGame: function(game) { + console.log(game); + game.destroy(); + this.render(); + }, + + render: function() { + const gamesSquares = Backbone.$('#played-games'); + gamesSquares.empty(); + + + var games = this.model.models; + var length = games.length; + + for (var i = 0; i < length; i++) { + var outcome = games[i].outcome; + + const result = new GameView( { + outcome: outcome, + tagName: 'li', + model: games[i] + } ); + + this.listenTo(result, 'selectGame', this.selectedGame); + + gamesSquares.prepend(result.$el.append(this.template({ results : outcome }))); + + } + + } + +}); + +export default GamesView; diff --git a/src/app/views/player_view.js b/src/app/views/player_view.js new file mode 100644 index 0000000..86f4f39 --- /dev/null +++ b/src/app/views/player_view.js @@ -0,0 +1,39 @@ +import _ from 'underscore'; +import Backbone from 'backbone'; + +const PlayerView = Backbone.View.extend({ + initialize: function(options){ + + this.players = options.players; + + this.template = _.template(Backbone.$('#tmpl-player').html()); + + // helper function to wrap ugly random + // function sample(array) { + // var index = Math.floor ( Math.random() * array.length ); + // return array[index]; + // } + + this.currentPlayerID = options.currentPlayer; + + }, + + + + render: function() { + + const playerSection = Backbone.$('#players'); + + this.currentPlayer = this.players[this.currentPlayerID]; + this.currentPlayerTmpl = this.template(this.currentPlayer); + + playerSection.html(this.currentPlayerTmpl); + + this.currentPlayerID = ((this.currentPlayerID === 0) ? 1 : 0); + + return this; + } + +}); + +export default PlayerView; diff --git a/src/app/views/square_view.js b/src/app/views/square_view.js new file mode 100644 index 0000000..d89eeee --- /dev/null +++ b/src/app/views/square_view.js @@ -0,0 +1,34 @@ +import _ from 'underscore'; +import Backbone from 'backbone'; + +const SquareView = Backbone.View.extend({ + initialize: function(options){ + + // clicks to tell the board to update itself + this.model = options.model; + this.position = options.position; + this.class = options.numberClass; + + this.render(); + }, + + events: { + 'click': 'onClick' + }, + + onClick: function(e) { + this.trigger('select', this); + + // We return false to tell jQuery not to run any more event handlers. + + return false; + }, + + render: function() { + this.$el.addClass('column').addClass(this.model + this.class); + return this; + } + +}); + +export default SquareView;