angular.module('app', ['angular-flippy', 'level-selector', 'level-complete']) .controller('PexesoController', function($scope, $timeout, $rootScope) { $scope.isLevelVisible = false; // Is start information with confirmation visible $scope.isStartConfirmation = true; $scope.instructions = []; $scope.levelIndex = 0; // How many cards must be found as the same. $scope.chainLength = 2; // Which card types are active $scope.currentCardTypes = [ 'picture', 'picture' ]; // Fit defined number of items on screen $scope.containerStyle = { "max-width": "280px" }; // Card style - define dimensions $scope.cardStyle = { width: "60px", height: "60px" }; /** * Level descriptor: * * totalCards - How many cards are on the board * chainLength - How many cards must be found from the same kind * cardType - Define type of game * - picture - display image of item * - key - display ID as text * - "name" - use text field from card set */ $scope.levels = [ { levelName: "01: 2 Pictures", instructions: ['fa-picture-o', 'fa-plus', 'fa-picture-o'], totalCards: 2*2, cardsPerRow: 2, chainLength: 2, cardSet: basicCards, cardTypes: ['picture', 'picture'] }, { levelName: "02: 3 Pictures", instructions: ['fa-picture-o', 'fa-plus', 'fa-picture-o', 'fa-plus', 'fa-picture-o'], totalCards: 3*3, cardsPerRow: 3, chainLength: 3, cardSet: basicCards, cardTypes: ['picture', 'picture', 'picture'] }, { levelName: "03: 4 Pictures", instructions: ['fa-picture-o', 'fa-plus', 'fa-picture-o', 'fa-plus', 'fa-picture-o', 'fa-plus', 'fa-picture-o'], totalCards: 4*4, cardsPerRow: 4, chainLength: 4, cardSet: basicCards, cardTypes: ['picture', 'picture', 'picture', 'picture'] }, { levelName: "04: Math", instructions: ['fa-circle-o', 'fa-plus', 'fa-calculator'], totalCards: 4*4, cardsPerRow: 4, chainLength: 2, cardSet: mathCards, cardTypes: ['arabic', 'math'] }, { levelName: "05: Roman", instructions: ['fa-circle-o', 'fa-plus', 'fa-file-excel-o'], totalCards: 4*4, cardsPerRow: 4, chainLength: 2, cardSet: mathCards, cardTypes: ['arabic', 'roman'] }, { levelName: "06: Japanese", instructions: ['fa-circle-o', 'fa-plus', 'fa-jpy'], totalCards: 4*4, cardsPerRow: 4, chainLength: 2, cardSet: mathCards, cardTypes: ['arabic', 'japanese'] }, { levelName: "07: 4x MIX", instructions: ['fa-circle-o', 'fa-plus', 'fa-calculator', 'fa-plus', 'fa-file-excel-o', 'fa-plus', 'fa-jpy'], totalCards: 4*4, cardsPerRow: 4, chainLength: 4, cardSet: mathCards, cardTypes: ['arabic', 'math', 'roman', 'japanese'] },{ levelName: "08: Morse", instructions: ['fa-font', 'fa-plus', 'fa-circle', 'fa-minus'], totalCards: 4*4, cardsPerRow: 4, chainLength: 2, cardSet: alphabetCards, cardTypes: ['key', 'morse'] }, { levelName: "Finale", instructions: ['fa-smile-o'], totalCards: 7*1, cardsPerRow: 7, chainLength: 7, cardSet: finaleCards, cardTypes: ['1','2','3','4','5','6','7'] } ]; $scope.currentLevel = $scope.levels[0]; $scope.cards = basicCards; $scope.board = []; /** * Generate playing card object. */ $scope.getCard = function(card, cardId, index) { return { cardId: cardId, card: card, cardType: 'picture', index: index, state: 'mystery', flipState: '' }; }; $scope.isFinallevel = function() { return ($scope.levelIndex == $scope.levels.length - 1); }; /** * Generate game board. */ $scope.generateBoard = function(totalCount) { $scope.board = []; var fullStack = [] var stack = []; angular.forEach($scope.currentLevel.cardSet, function(card, cardId) { fullStack.push($scope.getCard(card, cardId, 1)); }); for (var groupIndex = 0; groupIndex < totalCount / $scope.chainLength; groupIndex++) { var cardIndex = Math.floor((Math.random() * fullStack.length)); var card = fullStack[cardIndex]; fullStack.splice(cardIndex, 1); for (var instanceIndex = 0; instanceIndex < $scope.chainLength; instanceIndex++) { var tempCard = $scope.getCard(card, card.cardId, instanceIndex + 1); tempCard.cardType = $scope.currentCardTypes[instanceIndex]; if (tempCard.cardType == 'picture') { tempCard.image = tempCard.cardId; tempCard.label = ""; } else { tempCard.image = 'question'; if (tempCard.cardType == 'key') { tempCard.label = tempCard.cardId; } else { tempCard.label = tempCard.card.card[tempCard.cardType]; } } stack.push(tempCard); } } var isFinalLevel = $scope.isFinallevel(); for (var index = 0; index < totalCount; index++) { var coordinate = 0; if (!isFinalLevel) { coordinate = Math.floor((Math.random()* stack.length)); } $scope.board.push(stack[coordinate]); stack.splice(coordinate, 1); } }; $scope.selectionCounter = 0; $scope.selectedCards = []; /** * Set state of all selected cards to defined state. */ $scope.setSelectionState = function(state) { $scope.selectionCounter = 0; angular.forEach($scope.selectedCards, function(card) { card.state = state; if (state == "mystery") { card.flipState = ''; } else { card.flipState = 'flipped'; } }); $scope.selectedCards = []; }; /** * Check whether all cards were selected. */ $scope.areAllSelectedSame = function() { var previous = null; // At least n-cards must match if ($scope.selectedCards.length < $scope.chainLength) { return false; } for (var index=0; index<$scope.selectedCards.length; index++) { var card = $scope.selectedCards[index]; if (previous === null) { previous = card; } else { if (previous.cardId != card.cardId) { return false; } } } return true; }; /** * Check whether all items on the board are solved. */ $scope.isLevelComplete = function() { for (var index=0; index < $scope.board.length; index++) { var item = $scope.board[index]; if (item.state != "solved") { return false; } } return true; }; /** * Reset selection of current cards */ $scope.resetSelection = function() { $scope.setSelectionState('mystery'); }; /** * Click handler to select card. */ $scope.selectCard = function(card) { // only mystery cards are processed if (card.state != 'mystery') { return; } $scope.selectionCounter += 1; if ($scope.selectionCounter == $scope.chainLength + 1) { $scope.resetSelection(); return; } else { $scope.selectedCards.push(card); } if (card.state == 'mystery') { card.state = 'selected' + $scope.selectionCounter; card.flipState = 'flipped'; } if ($scope.areAllSelectedSame()) { $scope.setSelectionState('solved'); if ($scope.isLevelComplete()) { $timeout($scope.completeLevel, 2000); } } else if ($scope.selectionCounter == $scope.chainLength) { $timeout($scope.resetSelection, 1000); } }; /** * Adjust size of card */ $scope.computeCardSize = function(cardsPerRow) { var cardSize = Math.floor(Math.min(window.innerWidth, window.innerHeight) / cardsPerRow) - 20; if (cardSize < 14) { cardSize = 14; } var fontSize = Math.floor(cardSize * 0.6); if (fontSize < 12) { fontSize = 12; } $scope.cardStyle = { width: cardSize + "px", height: cardSize + "px", "font-size": fontSize + "px" }; var paddingLeft = Math.floor((window.innerWidth - (cardSize + 10) * cardsPerRow) / 2); var paddingTop = Math.floor((window.innerHeight - (cardSize + 10) * cardsPerRow) / 2) - 32; if (paddingLeft < 0) { paddingLeft = 0; } if (paddingTop < 0) { paddingTop = 0; } $scope.containerStyle = { "max-width": (cardSize + 20) * cardsPerRow + "px", "padding-left": paddingLeft + "px", "margin-top": paddingTop + "px" }; }; /** * Start Level */ $scope.initLevel = function(event, args) { $scope.levelIndex = args.levelIndex; $scope.currentLevel = $scope.levels[$scope.levelIndex]; $scope.currentCardTypes = $scope.currentLevel.cardTypes; $scope.instructions = $scope.currentLevel.instructions; $scope.chainLength = $scope.currentLevel.chainLength; $scope.computeCardSize($scope.currentLevel.cardsPerRow); $scope.generateBoard($scope.currentLevel.totalCards); $scope.isLevelVisible = true; $scope.isStartConfirmation= true; }; $scope.playLevel = function() { $scope.isStartConfirmation = false; } /** * Level complete - display level outro screen. */ $scope.completeLevel = function() { var args = { levelIndex: $scope.levelIndex, isFinalLevel: $scope.isFinallevel() }; $rootScope.$emit('completeLevel', args); }; /** * Return to level selection screen */ $scope.cancelLevel = function() { $scope.isLevelVisible = false; $rootScope.$emit('cancelLevel', {}); }; $rootScope.$on('startLevel', $scope.initLevel); });