Files
pf2015/js/pexeso-controller.js
2014-12-28 21:49:10 +00:00

375 lines
10 KiB
JavaScript

angular.module('app', ['angular-flippy', 'level-selector', 'level-complete'])
.controller('PexesoController', function($scope, $timeout, $rootScope) {
$scope.isLevelVisible = false;
$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
* - "languageCode" - display text in specified language
* - oneLanguage - pickup one language for each card on the beginning of game
* - randomLanguage - each turn of card selects different language for the same item
*/
$scope.levels = [
{
levelName: "01: 2x2 Picture",
totalCards: 2*2,
cardsPerRow: 2,
chainLength: 2,
cardTypes: ['picture', 'picture']
},
{
levelName: "02: 3x3 Picture",
totalCards: 3*3,
cardsPerRow: 3,
chainLength: 3,
cardTypes: ['picture', 'picture', 'picture']
},
{
levelName: "03: 4x4 Picture",
totalCards: 4*4,
cardsPerRow: 4,
chainLength: 4,
cardTypes: ['picture', 'picture', 'picture', 'picture']
}, {
totalCards: 4*4,
cardsPerRow: 4,
chainLength: 2,
cardTypes: ['picture', 'picture']
}, {
totalCards: 4*4,
cardsPerRow: 4,
chainLength: 2,
cardTypes: ['picture', 'en-US']
}, {
totalCards: 4*4,
cardsPerRow: 4,
chainLength: 2,
cardTypes: ['picture', 'oneLanguage']
}, {
totalCards: 4*4,
cardsPerRow: 4,
chainLength: 2,
cardTypes: ['picture', 'randomLanguage']
}, {
totalCards: 3*3,
cardsPerRow: 3,
chainLength: 3,
cardTypes: ['picture', 'picture', 'picture']
}, {
totalCards: 3*3,
cardsPerRow: 3,
chainLength: 3,
cardTypes: ['picture', 'randomLanguage', 'randomLanguage']
}, {
totalCards: 4*4,
cardsPerRow: 4,
chainLength: 4,
cardTypes: ['picture', 'randomLanguage', 'randomLanguage', 'randomLanguage']
}
];
$scope.currentLevel = $scope.levels[0];
$scope.languages = {
'cs-CZ': {
title: 'Čeština'
},
'en-US': {
title: 'English'
},
'sk-SK': {
title: 'Slovenčina'
}
};
$scope.basicCards = {
'cherry' : {
'cs-CZ': 'třešnička',
'en-US': 'cherry',
'sk-SK': 'čerešňa'
},
'cheese' : {
'cs-CZ': 'sýr',
'en-US': 'cheese',
'sk-SK': 'syr'
},
'carrot' : {
'cs-CZ': 'mrkev',
'en-US': 'carrot',
'sk-SK': 'mrkva'
},
'dwarf': {
'cs-CZ': 'trpaslík',
'en-US': 'dwarf',
'sk-SK': 'trpaslík'
},
'barrel': {
'cs-CZ': 'sud',
'en-US': 'barrel',
'sk-SK': 'sud'
},
'butterfly': {
'cs-CZ': 'motýl',
'en-US': 'butterfly',
'sk-SK': 'motýľ'
},
'ghost': {
'cs-CZ': 'duch',
'en-US': 'ghost',
'sk-SK': 'duch'
},
'rose': {
'cs-CZ': 'růže',
'en-US': 'rose',
'sk-SK': 'ruža'
},
'sun': {
'cs-CZ': 'slunce',
'en-US': 'sun',
'sk-SK': 'slnko'
},
'cloud': {
'cs-CZ': 'oblak',
'en-US': 'cloud',
'sk-SK': 'oblak'
}
};
$scope.cards = $scope.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: ''
};
};
/**
* Generate game board.
*/
$scope.generateBoard = function(totalCount) {
$scope.board = [];
var fullStack = []
var stack = [];
angular.forEach($scope.basicCards, 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];
stack.push(tempCard);
}
}
for (var index = 0; index < totalCount; index++) {
var 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, 1000);
}
} 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;
$scope.cardStyle = {
width: cardSize + "px",
height: cardSize + "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",
"padding-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.chainLength = $scope.currentLevel.chainLength;
$scope.computeCardSize($scope.currentLevel.cardsPerRow);
$scope.generateBoard($scope.currentLevel.totalCards);
$scope.isLevelVisible = true;
};
/**
* Level complete - display level outro screen.
*/
$scope.completeLevel = function() {
var args = {
levelIndex: $scope.levelIndex
};
$rootScope.$emit('completeLevel', args);
};
/**
* Return to level selection screen
*/
$scope.cancelLevel = function() {
$scope.isLevelVisible = false;
$rootScope.$emit('cancelLevel', {});
};
$rootScope.$on('startLevel', $scope.initLevel);
});