Skip to content

Commit

Permalink
Merge branch 'develop' into feature/#56-banks-board
Browse files Browse the repository at this point in the history
  • Loading branch information
Enessetere committed Feb 5, 2021
2 parents c9f4227 + aa62f6a commit 0cc7b44
Show file tree
Hide file tree
Showing 13 changed files with 547 additions and 76 deletions.
100 changes: 56 additions & 44 deletions src/app/GameController.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,77 @@
// import { time } from 'console';
import { AnimalNames } from '../Enums/AnimalNamesEnum';
import { Player } from '../Player';
import { BreedProcessor } from './BreedProcessor';
import { Bank } from './logic/Bank';
import { Timer } from './Timer';
import { GameProcessor } from './logic/GameProcessor';
import { View } from './View';
import { Game } from './logic/Game';
import { defaultGameConfiguration } from './logic/defaultGameConfiguration';

export class GameController {
private currentPlayer: Player | undefined;
private player: Player | undefined;
private timer: Timer;
private breedProcessor: BreedProcessor;
private game: Game;
private gameProcessor: GameProcessor;
constructor(private view: View) {
this.timer = new Timer();
this.breedProcessor = new BreedProcessor(new Bank());
this.game = new Game(defaultGameConfiguration);
this.gameProcessor = new GameProcessor(this.game);
}

get theCurrentPlayer(): Player {
return this.currentPlayer as Player;
get theGame(): Game {
return this.game;
}

get theTimer(): Timer {
return this.timer;
/**
* Starts the turn for the current player.
* Displays alert when the time is over.
* Updates the remaining time on the View.
*/
startTurn(): void {
this.gameProcessor.startTurn(
(currentPlayer) => {
this.view.displayAlert(currentPlayer?.theName as string);
},
(remainingTime) => {
this.view.updateRemainingTime(remainingTime);
},
);
}

startTurn(): void {
this.timer.countdown();
const turnTimer = setInterval(() => {
if (!this.timer.running) {
clearInterval(turnTimer);
if (Math.ceil(this.timer.theTurnTimeLeft) === 0) {
this.view.displayAlert(
this.currentPlayer?.theName as string,
);
this.nextPlayer();
this.startTurn();
}
}
this.view.updateRemainingTime(
Math.round(this.timer.theTurnTimeLeft),
);
}, 10);
stopTurn(): void {
this.gameProcessor.stopTurn();
}

breed(): [AnimalNames, AnimalNames] | undefined {
if (this.timer.theTurnTimeLeft === 0) {
return;
/**
* Executes trade proposed by the player and checks win condition.
* If player wins the game after the trade, stops the timer and tells the View to display the WinModal.
* @param offer made by the player
* @param target desired by the player
* @returns true if the trade was sucessful, false otherwise
*/
trade(
offer: [AnimalNames, number],
target: [AnimalNames, number],
): boolean {
const tradeResult = this.gameProcessor.trade(offer, target);
if (this.gameProcessor.checkWin()) {
this.gameProcessor.stopTurn();
this.view.displayWinModal(this.game.theCurrentPlayer);
}
const rollResult = this.breedProcessor.processBreedPhase(
this.currentPlayer as Player,
);
return rollResult;
return tradeResult;
}

stopTurn(): void {
this.timer.resetTurn();
/**
* Rolls the dice for the player and updates their Herd.
* If player wins the game after the breed, stops the timer and tells the View to display the WinModal.
*/
breed(): [AnimalNames, AnimalNames] | undefined {
const diceResult = this.gameProcessor.breed();
if (this.gameProcessor.checkWin()) {
this.gameProcessor.stopTurn();
this.view.displayWinModal(this.game.theCurrentPlayer);
}
return diceResult;
}

/**
* Sets the current player to the next player in order.
*/
nextPlayer(): void {
//TODO multiplayer logic
this.currentPlayer = this.player;
this.timer.resetTurn();
this.gameProcessor.nextPlayer();
}
}
32 changes: 19 additions & 13 deletions src/app/Trade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ import { multiply } from 'lodash';
import { Player } from '../Player';
import { Herd } from './logic/Herd';

export type Offer = [AnimalNames, number];

export class Trade {
constructor(private bank: Player) {}
get thisBank(): Player {
return this.bank;
}
/**
* Gets an offer from player and returns true or false if transaction can be made processed and process it if possible
* @param offer accepts tuple with offer containing animal name and quantity to be sold
Expand All @@ -14,13 +19,17 @@ export class Trade {
* @returns true if transaction will be processed, and false otherwise
*/
processOffer(
offer: [AnimalNames, number],
offer: Offer,
{ theHerd: playerHerd }: Player,
target: [AnimalNames, number],
target: Offer,
): boolean {
const [offeredAnimal, offeredAnimalCount] = offer;
const [targetAnimal, targetAnimalCount] = target;
if (
playerHerd.getAnimalNumber(offer[0]) < offer[1] ||
this.bank.theHerd.getAnimalNumber(target[0]) < target[1]
playerHerd.getAnimalNumber(offeredAnimal) <
offeredAnimalCount ||
this.bank.theHerd.getAnimalNumber(targetAnimal) <
targetAnimalCount
) {
return false;
}
Expand All @@ -35,17 +44,14 @@ export class Trade {
: this.disposeResult(offer, playerHerd, target);
}

private calculateValue(offer: [AnimalNames, number]): number {
private calculateValue([animal, count]: Offer): number {
return multiply(
ConvertToAnimalObject.convertToAnimalObject(offer[0]).theValue,
offer[1],
ConvertToAnimalObject.convertToAnimalObject(animal).theValue,
count,
);
}

private adjustOffer(
offer: [AnimalNames, number],
target: [AnimalNames, number],
): void {
private adjustOffer(offer: Offer, target: Offer): void {
offer[1] -= 1;
if (this.calculateValue(offer) <= this.calculateValue(target)) {
return;
Expand All @@ -57,9 +63,9 @@ export class Trade {
* updates players and banks herd
*/
private disposeResult(
[animalSold, quantitySold]: [AnimalNames, number],
[animalSold, quantitySold]: Offer,
playerHerd: Herd,
[animalBought, quantityBought]: [AnimalNames, number],
[animalBought, quantityBought]: Offer,
): boolean {
playerHerd.addAnimalsToHerd(animalSold, -quantitySold);
playerHerd.addAnimalsToHerd(animalBought, quantityBought);
Expand Down
15 changes: 10 additions & 5 deletions src/app/View.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Render } from './utils/Render';
import { AnimalNames } from '../Enums/AnimalNamesEnum';
import { GameController } from './GameController';
import { Game } from './logic/Game';
import { defaultGameConfiguration } from './logic/defaultGameConfiguration';
import { Player } from '../Player';
import { WinModal } from './components/WinModal';

export class View {
renderMenuView(): void {
Expand Down Expand Up @@ -60,8 +60,6 @@ export class View {
: playersChosenAvatarPath;

Render.removeAllChildren('#sf-app');
new Game(defaultGameConfiguration);

this.renderGameView(inputValue, playersChosenAvatarPath);
};
startGameButton.addEventListener('click', handleClick);
Expand Down Expand Up @@ -116,7 +114,7 @@ export class View {
rollADiceButton.addEventListener('click', () => {
const rollResult = gameController.breed();
herdView.innerText = JSON.stringify(
gameController.theCurrentPlayer.theHerd.theAnimals.map(
gameController.theGame.theCurrentPlayer.theHerd.theAnimals.map(
([animal, count]) => [animal.theName, count],
),
);
Expand Down Expand Up @@ -161,6 +159,13 @@ export class View {
alert(`${name}'s turn has passed!`);
}

displayWinModal(player: Player): void {
const modal = new WinModal();
modal.create(player);
modal.addButton();
Render.render('#sf-app', modal.modal);
}

handleTrade(): void {
console.log('handle trade');
}
Expand Down
31 changes: 31 additions & 0 deletions src/app/components/EmptyModal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Render } from '../utils/Render';
import { pull } from 'lodash';

export abstract class EmptyModal {
modal: HTMLElement;
modalContainer: HTMLElement;
constructor() {
this.modalContainer = Render.elementFactory('div', {
className: 'modal__container',
});
this.modal = Render.elementFactory(
'div',
{ className: 'modal' },
this.modalContainer,
);
}

/**
* Hides modal - adds class with display:none
*/
protected hideModal(): void {
this.modal.classList.add('modal--hidden');
}

/**
* Shows modal - removes class with display:none
*/
protected showModal(): void {
this.modal.classList.remove('modal--hidden');
}
}
16 changes: 2 additions & 14 deletions src/app/components/ModalBasic.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,8 @@
import { Render } from '../utils/Render';
import { Button } from './Button';
import { EmptyModal } from './EmptyModal';

export class ModalBasic {
modal: HTMLElement;
modalContainer: HTMLElement;
constructor() {
this.modalContainer = Render.elementFactory('div', {
className: 'modal__container',
});
this.modal = Render.elementFactory(
'div',
{ className: 'modal' },
this.modalContainer,
);
}

export class ModalBasic extends EmptyModal {
/**
* Creates and appends the main modal structure.
* @param {string} heading Heading to be render inside the modal.
Expand Down
Loading

0 comments on commit 0cc7b44

Please sign in to comment.