From 53e534f08b377dad018f7ee78a9b75ae540fa839 Mon Sep 17 00:00:00 2001 From: Dominik Date: Tue, 2 Feb 2021 04:37:44 +0100 Subject: [PATCH 01/27] split ModalBasic into EmptyModal --- src/app/components/EmptyModal.ts | 16 ++++++++++++++++ src/app/components/ModalBasic.ts | 16 ++-------------- 2 files changed, 18 insertions(+), 14 deletions(-) create mode 100644 src/app/components/EmptyModal.ts diff --git a/src/app/components/EmptyModal.ts b/src/app/components/EmptyModal.ts new file mode 100644 index 0000000..f15f191 --- /dev/null +++ b/src/app/components/EmptyModal.ts @@ -0,0 +1,16 @@ +import { Render } from '../utils/Render'; + +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, + ); + } +} diff --git a/src/app/components/ModalBasic.ts b/src/app/components/ModalBasic.ts index ce3060d..0fc28c1 100644 --- a/src/app/components/ModalBasic.ts +++ b/src/app/components/ModalBasic.ts @@ -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. From e19b069bdfe5fa354a0b510cd8d12ecd7caaab69 Mon Sep 17 00:00:00 2001 From: Dominik Date: Tue, 2 Feb 2021 04:38:39 +0100 Subject: [PATCH 02/27] create TradeModal --- src/app/components/TradeModal.ts | 76 ++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/app/components/TradeModal.ts diff --git a/src/app/components/TradeModal.ts b/src/app/components/TradeModal.ts new file mode 100644 index 0000000..7e7cba8 --- /dev/null +++ b/src/app/components/TradeModal.ts @@ -0,0 +1,76 @@ +import { Player } from '~src/Player'; +import { Herd } from '../logic/Herd'; +import { Trade } from '../Trade'; +import { Render } from '../utils/Render'; +import { EmptyModal } from './EmptyModal'; + +export class TradeModal extends EmptyModal { + tradeWrapper: HTMLElement; + playerView: HTMLElement; + bankView: HTMLElement; + constructor(private trade: Trade) { + super(); + this.playerView = Render.elementFactory('div', { + className: 'trade-player__herd', + }); + this.bankView = Render.elementFactory('div', { + className: 'trade-player__herd', + }); + this.tradeWrapper = Render.elementFactory( + 'div', + { + className: 'trade__wrapper', + }, + this.playerView, + this.bankView, + ); + } + + createModal(): HTMLElement { + Render.childrenInjector( + this.modalContainer, + this.createHerdView(new Player('Johny')), + ); + return this.modal; + } + + createHerdView(player: Player): HTMLElement { + const herd = Render.elementFactory( + 'div', + { + className: 'trade-player__herd', + }, + ...this.generateAnimalRows(player.theHerd), + ); + const container = Render.elementFactory( + 'div', + { + className: 'trade-player', + }, + Render.elementFactory( + 'H2', + { className: 'trade-player__header' }, + `${player.theName}`, + ), + herd, + ); + return container; + } + + private generateAnimalRows(herd: Herd): HTMLElement[] { + const animalsRows: HTMLElement[] = herd.theAnimals.reduce( + (animalsElements: HTMLElement[], [animal, count]) => { + animalsElements.push( + Render.elementFactory( + 'p', + {}, + `${animal.theName}: ${count}`, + ), + ); + return animalsElements; + }, + [], + ); + return animalsRows; + } +} From a09fcce26747745c5a1db6f3e5edf867393b817d Mon Sep 17 00:00:00 2001 From: Dominik Date: Tue, 2 Feb 2021 04:40:05 +0100 Subject: [PATCH 03/27] add TradeModalDemo --- src/app/manuals/TradeModalDemo.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/app/manuals/TradeModalDemo.ts diff --git a/src/app/manuals/TradeModalDemo.ts b/src/app/manuals/TradeModalDemo.ts new file mode 100644 index 0000000..1c4b772 --- /dev/null +++ b/src/app/manuals/TradeModalDemo.ts @@ -0,0 +1,17 @@ +import { Player } from '~src/Player'; +import { TradeModal } from '../components/TradeModal'; +import { Bank } from '../logic/Bank'; +import { Trade } from '../Trade'; +import { Render } from '../utils/Render'; + +export class TradeModalDemo { + static playDemo(): void { + const trade = new Trade(new Bank()); + const modal = new TradeModal(trade); + const player = new Player( + 'player', + './static/images/avatars/dog.png', + ); + Render.render('#sf-app', modal.createModal()); + } +} From c9dba28de4a3825e4772b4d2ce1d67fa33b80843 Mon Sep 17 00:00:00 2001 From: Dominik Date: Tue, 2 Feb 2021 04:41:14 +0100 Subject: [PATCH 04/27] format WinModal --- src/app/components/WinModal.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/components/WinModal.ts b/src/app/components/WinModal.ts index d366501..a59d83f 100644 --- a/src/app/components/WinModal.ts +++ b/src/app/components/WinModal.ts @@ -25,4 +25,4 @@ export class WinModal extends ModalBasic { alt: `${theName}-avatar`, }); } -} \ No newline at end of file +} From 31860c34099341877b99f3b0ecb1919bb80f042d Mon Sep 17 00:00:00 2001 From: Aleksandra Pawlak Date: Sun, 31 Jan 2021 23:06:52 +0100 Subject: [PATCH 05/27] Implement checkWin method --- src/app/logic/Game.ts | 6 ++++++ src/app/logic/GameProcessor.ts | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/app/logic/GameProcessor.ts diff --git a/src/app/logic/Game.ts b/src/app/logic/Game.ts index 8b7d12e..be178a0 100644 --- a/src/app/logic/Game.ts +++ b/src/app/logic/Game.ts @@ -27,6 +27,7 @@ export class Game { timer: Timer; breedProcessor: BreedProcessor; trade: Trade; + private currentPlayerNumber: number; constructor({ mode, roundTimeInSeconds, @@ -57,6 +58,7 @@ export class Game { this.playersHerdConfig, ), ); + this.currentPlayerNumber = 0; this.bank = new Bank(this.banksHerdConfig); // TODO: GET DICE DATA FROM CONFIG AFTER/ IF DICE REFACTOR // TODO: CHECK IF NEEDED SINCE THEY ARE CALLED IN BREEDPROCESSOR @@ -75,6 +77,10 @@ export class Game { return this.players; } + get theCurrentPlayer(): Player { + return this.players[this.currentPlayerNumber]; + } + get theBank(): Bank { return this.bank; } diff --git a/src/app/logic/GameProcessor.ts b/src/app/logic/GameProcessor.ts new file mode 100644 index 0000000..0e070d0 --- /dev/null +++ b/src/app/logic/GameProcessor.ts @@ -0,0 +1,34 @@ +import { AnimalNames } from '~src/Enums/AnimalNamesEnum'; +import { Game } from './Game'; + +export class GameProcessor { + constructor(private game: Game) {} + + // TODO implement when Trade is merged + // trade() {} + + checkWin(): void { + this.game.theCurrentPlayer; + const animalsRequiredToWin: AnimalNames[] = [ + AnimalNames.RABBIT, + AnimalNames.SHEEP, + AnimalNames.PIG, + AnimalNames.COW, + AnimalNames.HORSE, + ]; + for (const animal in animalsRequiredToWin) { + if ( + this.game.theCurrentPlayer.theHerd.getAnimalNumber( + animal as AnimalNames, + ) === 0 + ) { + return; + } + } + //TODO winner + } + + // breed() {} + + // nextPlayer() {} +} From 38d6474151d104f28ac678f2f17134524683fb17 Mon Sep 17 00:00:00 2001 From: Aleksandra Pawlak Date: Mon, 1 Feb 2021 18:15:58 +0100 Subject: [PATCH 06/27] Implement more logic in GameProcessor --- src/app/GameController.ts | 71 +++++++++++++--------------------- src/app/View.ts | 4 -- src/app/logic/Game.ts | 5 +++ src/app/logic/GameProcessor.ts | 50 +++++++++++++++++++++--- 4 files changed, 75 insertions(+), 55 deletions(-) diff --git a/src/app/GameController.ts b/src/app/GameController.ts index c04a913..2ec9b1e 100644 --- a/src/app/GameController.ts +++ b/src/app/GameController.ts @@ -1,65 +1,46 @@ // 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 gameProcessor: GameProcessor; constructor(private view: View) { - this.timer = new Timer(); - this.breedProcessor = new BreedProcessor(new Bank()); + this.gameProcessor = new GameProcessor( + new Game(defaultGameConfiguration), + ); } - get theCurrentPlayer(): Player { - return this.currentPlayer as Player; + startTurn(): void { + this.gameProcessor.startTurn( + (currentPlayer) => { + this.view.displayAlert(currentPlayer?.theName as string); + }, + (remainingTime) => { + this.view.updateRemainingTime(remainingTime); + }, + ); } - get theTimer(): Timer { - return this.timer; + stopTurn(): void { + this.gameProcessor.stopTurn(); } - 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); - } + // TODO when Trade is done + // trade(); breed(): [AnimalNames, AnimalNames] | undefined { - if (this.timer.theTurnTimeLeft === 0) { - return; + const diceResult = this.gameProcessor.breed(); + if (this.gameProcessor.checkWin()) { + this.gameProcessor.stopTurn(); + //TODO winModal from View } - const rollResult = this.breedProcessor.processBreedPhase( - this.currentPlayer as Player, - ); - return rollResult; - } - - stopTurn(): void { - this.timer.resetTurn(); + return diceResult; } nextPlayer(): void { - //TODO multiplayer logic - this.currentPlayer = this.player; - this.timer.resetTurn(); + this.gameProcessor.nextPlayer(); } } diff --git a/src/app/View.ts b/src/app/View.ts index efa47e7..70d8ac1 100644 --- a/src/app/View.ts +++ b/src/app/View.ts @@ -1,8 +1,6 @@ import { Render } from './utils/Render'; import { AnimalNames } from '../Enums/AnimalNamesEnum'; import { GameController } from './GameController'; -import { Game } from './logic/Game'; -import { defaultGameConfiguration } from './logic/defaultGameConfiguration'; export class View { renderMenuView(): void { @@ -60,8 +58,6 @@ export class View { : playersChosenAvatarPath; Render.removeAllChildren('#sf-app'); - new Game(defaultGameConfiguration); - this.renderGameView(inputValue, playersChosenAvatarPath); }; startGameButton.addEventListener('click', handleClick); diff --git a/src/app/logic/Game.ts b/src/app/logic/Game.ts index be178a0..fe4384a 100644 --- a/src/app/logic/Game.ts +++ b/src/app/logic/Game.ts @@ -69,6 +69,11 @@ export class Game { this.trade = new Trade(this.bank); } + nextPlayer(): void { + this.currentPlayerNumber = + (this.currentPlayerNumber + 1) % this.players.length; + } + get theMode(): GameModes { return this.mode; } diff --git a/src/app/logic/GameProcessor.ts b/src/app/logic/GameProcessor.ts index 0e070d0..10c0909 100644 --- a/src/app/logic/GameProcessor.ts +++ b/src/app/logic/GameProcessor.ts @@ -1,14 +1,41 @@ import { AnimalNames } from '~src/Enums/AnimalNamesEnum'; +import { Player } from '~src/Player'; import { Game } from './Game'; export class GameProcessor { constructor(private game: Game) {} + startTurn( + turnTimeOverCallback: (currentPlayer: Player) => void, + updateRemainingTimeCallback: (remainingTime: number) => void, + ): void { + this.game.theTimer.countdown(); + const turnTimer = setInterval(() => { + if (!this.game.theTimer.running) { + clearInterval(turnTimer); + if (Math.ceil(this.game.theTimer.theTurnTimeLeft) === 0) { + turnTimeOverCallback(this.game.theCurrentPlayer); + + this.nextPlayer(); + this.startTurn( + turnTimeOverCallback, + updateRemainingTimeCallback, + ); + } + } + updateRemainingTimeCallback( + Math.round(this.game.theTimer.theTurnTimeLeft), + ); + }, 10); + } + + stopTurn(): void { + this.game.theTimer.resetTurn(); + } // TODO implement when Trade is merged // trade() {} - checkWin(): void { - this.game.theCurrentPlayer; + checkWin(): boolean { const animalsRequiredToWin: AnimalNames[] = [ AnimalNames.RABBIT, AnimalNames.SHEEP, @@ -22,13 +49,24 @@ export class GameProcessor { animal as AnimalNames, ) === 0 ) { - return; + return false; } } - //TODO winner + return true; } - // breed() {} + breed(): [AnimalNames, AnimalNames] | undefined { + if (this.game.theTimer.theTurnTimeLeft === 0) { + return; + } + const rollResult = this.game.theBreedProcessor.processBreedPhase( + this.game.theCurrentPlayer, + ); + return rollResult; + } - // nextPlayer() {} + nextPlayer(): void { + this.game.nextPlayer(); + this.game.theTimer.resetTurn(); + } } From 4117131c068c9f04f190b8ea08891526b520ba5c Mon Sep 17 00:00:00 2001 From: Aleksandra Pawlak Date: Tue, 2 Feb 2021 17:58:53 +0100 Subject: [PATCH 07/27] Implement Trade processing and WinModal displaying closes #77 --- src/app/GameController.ts | 25 +++++++++++++++++++------ src/app/View.ts | 11 ++++++++++- src/app/logic/GameProcessor.ts | 17 +++++++++++++++-- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/app/GameController.ts b/src/app/GameController.ts index 2ec9b1e..a0db37b 100644 --- a/src/app/GameController.ts +++ b/src/app/GameController.ts @@ -6,11 +6,15 @@ import { Game } from './logic/Game'; import { defaultGameConfiguration } from './logic/defaultGameConfiguration'; export class GameController { + private game: Game; private gameProcessor: GameProcessor; constructor(private view: View) { - this.gameProcessor = new GameProcessor( - new Game(defaultGameConfiguration), - ); + this.game = new Game(defaultGameConfiguration); + this.gameProcessor = new GameProcessor(this.game); + } + + get theGame(): Game { + return this.game; } startTurn(): void { @@ -28,14 +32,23 @@ export class GameController { this.gameProcessor.stopTurn(); } - // TODO when Trade is done - // trade(); + 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); + } + return tradeResult; + } breed(): [AnimalNames, AnimalNames] | undefined { const diceResult = this.gameProcessor.breed(); if (this.gameProcessor.checkWin()) { this.gameProcessor.stopTurn(); - //TODO winModal from View + this.view.displayWinModal(this.game.theCurrentPlayer); } return diceResult; } diff --git a/src/app/View.ts b/src/app/View.ts index 70d8ac1..48c31c9 100644 --- a/src/app/View.ts +++ b/src/app/View.ts @@ -1,6 +1,8 @@ import { Render } from './utils/Render'; import { AnimalNames } from '../Enums/AnimalNamesEnum'; import { GameController } from './GameController'; +import { Player } from '../Player'; +import { WinModal } from './components/WinModal'; export class View { renderMenuView(): void { @@ -112,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], ), ); @@ -156,4 +158,11 @@ export class View { displayAlert(name: string): void { 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); + } } diff --git a/src/app/logic/GameProcessor.ts b/src/app/logic/GameProcessor.ts index 10c0909..50b2660 100644 --- a/src/app/logic/GameProcessor.ts +++ b/src/app/logic/GameProcessor.ts @@ -32,8 +32,21 @@ export class GameProcessor { stopTurn(): void { this.game.theTimer.resetTurn(); } - // TODO implement when Trade is merged - // trade() {} + + trade( + offer: [AnimalNames, number], + target: [AnimalNames, number], + ): boolean { + if (this.game.theTimer.theTurnTimeLeft === 0) { + return false; + } + const tradeResult = this.game.theTrade.processOffer( + offer, + this.game.theCurrentPlayer, + target, + ); + return tradeResult; + } checkWin(): boolean { const animalsRequiredToWin: AnimalNames[] = [ From d67b4d53ff479c973da73b429cb9208dfdfbc2f3 Mon Sep 17 00:00:00 2001 From: Aleksandra Pawlak Date: Tue, 2 Feb 2021 18:24:37 +0100 Subject: [PATCH 08/27] Add documentation for GameController and GameProcessor methods --- src/app/GameController.ts | 20 +++++++++++++++++++- src/app/logic/GameProcessor.ts | 25 +++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/app/GameController.ts b/src/app/GameController.ts index a0db37b..73417ec 100644 --- a/src/app/GameController.ts +++ b/src/app/GameController.ts @@ -1,4 +1,3 @@ -// import { time } from 'console'; import { AnimalNames } from '../Enums/AnimalNamesEnum'; import { GameProcessor } from './logic/GameProcessor'; import { View } from './View'; @@ -17,6 +16,11 @@ export class GameController { return this.game; } + /** + * 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) => { @@ -32,6 +36,13 @@ export class GameController { this.gameProcessor.stopTurn(); } + /** + * 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], @@ -44,6 +55,10 @@ export class GameController { return tradeResult; } + /** + * 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()) { @@ -53,6 +68,9 @@ export class GameController { return diceResult; } + /** + * Sets the current player to the next player in order. + */ nextPlayer(): void { this.gameProcessor.nextPlayer(); } diff --git a/src/app/logic/GameProcessor.ts b/src/app/logic/GameProcessor.ts index 50b2660..313cb3f 100644 --- a/src/app/logic/GameProcessor.ts +++ b/src/app/logic/GameProcessor.ts @@ -5,6 +5,12 @@ import { Game } from './Game'; export class GameProcessor { constructor(private game: Game) {} + /** + * Starts the timer for current players turn. + * When the time is over, resets the timer, sets current player to the next player and starts the timer. + * @param turnTimeOverCallback to be executed when the time is over + * @param updateRemainingTimeCallback to be executed when the remaining time changes + */ startTurn( turnTimeOverCallback: (currentPlayer: Player) => void, updateRemainingTimeCallback: (remainingTime: number) => void, @@ -29,10 +35,19 @@ export class GameProcessor { }, 10); } + /** + * Stops the timer for the current player. + */ stopTurn(): void { this.game.theTimer.resetTurn(); } + /** + * Executes trade proposed by the player and checks win condition. + * @param offer made by the player + * @param target desired by the player + * @returns true if the trade was sucessful, false if the trade was not sucessful or the player run out of time + */ trade( offer: [AnimalNames, number], target: [AnimalNames, number], @@ -48,6 +63,9 @@ export class GameProcessor { return tradeResult; } + /** + * @returns true if current player wins the game, false otherwise + */ checkWin(): boolean { const animalsRequiredToWin: AnimalNames[] = [ AnimalNames.RABBIT, @@ -68,6 +86,10 @@ export class GameProcessor { return true; } + /** + * Rolls the dice for the player and updates their Herd. + * @returns the result of the current players roll + */ breed(): [AnimalNames, AnimalNames] | undefined { if (this.game.theTimer.theTurnTimeLeft === 0) { return; @@ -78,6 +100,9 @@ export class GameProcessor { return rollResult; } + /** + * Sets the current player to the next player in order and resets the timer. + */ nextPlayer(): void { this.game.nextPlayer(); this.game.theTimer.resetTurn(); From 2f3cca630364a4b892daa78d9b6a35d7b3bba9b0 Mon Sep 17 00:00:00 2001 From: Dominik Date: Thu, 4 Feb 2021 01:55:01 +0100 Subject: [PATCH 09/27] add 'dom.iterable' to tsconfig lib to allow use FormData's entries --- tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/tsconfig.json b/tsconfig.json index 0801227..3a6dde5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,6 +8,7 @@ "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, "lib": [ "es6", + "dom.iterable", "DOM" ] /* Specify library files to be included in the compilation. */, "allowJs": true /* Allow javascript files to be compiled. */, From 8ffc05d0f900bdf2300e043c1aae94aeb592c265 Mon Sep 17 00:00:00 2001 From: Dominik Date: Thu, 4 Feb 2021 02:03:50 +0100 Subject: [PATCH 10/27] add getter to the bank in Trade --- src/app/Trade.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/Trade.ts b/src/app/Trade.ts index 3a4551a..00f96ea 100644 --- a/src/app/Trade.ts +++ b/src/app/Trade.ts @@ -6,6 +6,9 @@ import { Herd } from './logic/Herd'; 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 From 86c214333b9df31361633d3c2f9160d41dcf5921 Mon Sep 17 00:00:00 2001 From: Dominik Date: Thu, 4 Feb 2021 06:06:17 +0100 Subject: [PATCH 11/27] add type Offer in class Trade --- src/app/Trade.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/app/Trade.ts b/src/app/Trade.ts index 00f96ea..f3875d7 100644 --- a/src/app/Trade.ts +++ b/src/app/Trade.ts @@ -4,6 +4,8 @@ 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 { @@ -17,9 +19,9 @@ 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 { if ( playerHerd.getAnimalNumber(offer[0]) < offer[1] || @@ -38,17 +40,14 @@ export class Trade { : this.disposeResult(offer, playerHerd, target); } - private calculateValue(offer: [AnimalNames, number]): number { + private calculateValue(offer: Offer): number { return multiply( ConvertToAnimalObject.convertToAnimalObject(offer[0]).theValue, offer[1], ); } - 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; From 4aa0b97467ef1527289ce1da4d6665ce4fdcb77a Mon Sep 17 00:00:00 2001 From: Dominik Date: Thu, 4 Feb 2021 06:10:54 +0100 Subject: [PATCH 12/27] continuation of work on TradeModal --- src/app/components/TradeModal.ts | 121 +++++++++++++++++++++++++------ 1 file changed, 99 insertions(+), 22 deletions(-) diff --git a/src/app/components/TradeModal.ts b/src/app/components/TradeModal.ts index 7e7cba8..694f84d 100644 --- a/src/app/components/TradeModal.ts +++ b/src/app/components/TradeModal.ts @@ -1,70 +1,113 @@ +import { AnimalNames } from '~src/Enums/AnimalNamesEnum'; import { Player } from '~src/Player'; import { Herd } from '../logic/Herd'; -import { Trade } from '../Trade'; +import { Offer, Trade } from '../Trade'; import { Render } from '../utils/Render'; import { EmptyModal } from './EmptyModal'; export class TradeModal extends EmptyModal { - tradeWrapper: HTMLElement; + tradeForm: HTMLElement; playerView: HTMLElement; bankView: HTMLElement; - constructor(private trade: Trade) { + + constructor(private trade: Trade, private player: Player) { super(); this.playerView = Render.elementFactory('div', { - className: 'trade-player__herd', + className: 'trade__player-wrapper', }); this.bankView = Render.elementFactory('div', { - className: 'trade-player__herd', + className: 'trade__player-wrapper', }); - this.tradeWrapper = Render.elementFactory( - 'div', + this.tradeForm = Render.elementFactory( + 'form', { - className: 'trade__wrapper', + action: '', + method: 'get', + className: 'trade', }, this.playerView, + Render.elementFactory('input', { + type: 'submit', + value: 'Trade', + className: 'trade__submit', + }), this.bankView, ); + this.modalContainer.appendChild(this.tradeForm); } createModal(): HTMLElement { Render.childrenInjector( - this.modalContainer, - this.createHerdView(new Player('Johny')), + this.bankView, + this.createHerdView(this.trade.thisBank, true), ); + this.tradeForm.addEventListener('submit', this.handleSubmit); return this.modal; } - createHerdView(player: Player): HTMLElement { - const herd = Render.elementFactory( + setPlayer(player: Player): void { + Render.removeAllChildren(this.playerView); + this.playerView.appendChild(this.createHerdView(player)); + } + + refreshHerdViews(player: Player, bank: Player): void { + this.setPlayer(player); + Render.removeAllChildren(this.bankView); + this.bankView.appendChild(this.createHerdView(bank, true)); + } + + private createHerdView( + { theHerd: herd, theName: name }: Player, + isBank = false, + ): HTMLElement { + const herdElement = Render.elementFactory( 'div', { - className: 'trade-player__herd', + className: 'trade__player-herd', }, - ...this.generateAnimalRows(player.theHerd), + ...this.generateAnimalRows(herd, isBank), ); const container = Render.elementFactory( 'div', { - className: 'trade-player', + className: 'trade__player', }, Render.elementFactory( 'H2', - { className: 'trade-player__header' }, - `${player.theName}`, + { className: 'trade__player-heading' }, + `${name}`, ), - herd, + herdElement, ); return container; } - private generateAnimalRows(herd: Herd): HTMLElement[] { + private generateAnimalRows( + herd: Herd, + isBank: boolean, + ): HTMLElement[] { const animalsRows: HTMLElement[] = herd.theAnimals.reduce( (animalsElements: HTMLElement[], [animal, count]) => { animalsElements.push( Render.elementFactory( - 'p', - {}, - `${animal.theName}: ${count}`, + 'div', + { className: 'trade__row' }, + Render.elementFactory( + 'label', + { + for: `${isBank ? 'bank' : 'player'}_${ + animal.theName + }`, + }, + `${animal.theName}: ${count}`, + ), + Render.elementFactory('input', { + type: 'number', + id: `${isBank ? 'bank' : 'player'}_${animal.theName}`, + name: `${isBank ? 'bank' : 'player'}_${animal.theName}`, + min: '0', + max: `${count}`, + }), ), ); return animalsElements; @@ -73,4 +116,38 @@ export class TradeModal extends EmptyModal { ); return animalsRows; } + + private formDataIntoTuples(formData: FormData): [Offer, Offer] { + const offer: Offer[] = []; + const target: Offer[] = []; + for (const [key, value] of formData.entries()) { + const numberOfAnimals = parseInt(value.toString()); + const [player, animal] = key.split('_'); + if (numberOfAnimals > 0) { + switch (player) { + case 'player': { + offer.push([animal as AnimalNames, numberOfAnimals]); + break; + } + case 'bank': { + target.push([animal as AnimalNames, numberOfAnimals]); + break; + } + } + } + } + if (offer.length !== 1 || target.length !== 1) { + console.log('Za dużo zwiemrzątek'); + } + return [offer[0], target[0]]; + } + + private handleSubmit = (event: Event): void => { + event.preventDefault(); + const formData = new FormData(event.target as HTMLFormElement); + const [offer, target] = this.formDataIntoTuples(formData); + if (this.trade.processOffer(offer, this.player, target)) { + this.refreshHerdViews(this.player, this.trade.thisBank); + } + }; } From 43497b75f699283d5ed7e45e1df8bbe7ba6e7e5b Mon Sep 17 00:00:00 2001 From: Dominik Date: Thu, 4 Feb 2021 06:14:06 +0100 Subject: [PATCH 13/27] update TradeModalDemo --- src/app/manuals/TradeModalDemo.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/app/manuals/TradeModalDemo.ts b/src/app/manuals/TradeModalDemo.ts index 1c4b772..40776dd 100644 --- a/src/app/manuals/TradeModalDemo.ts +++ b/src/app/manuals/TradeModalDemo.ts @@ -1,3 +1,4 @@ +import { AnimalNames } from '~src/Enums/AnimalNamesEnum'; import { Player } from '~src/Player'; import { TradeModal } from '../components/TradeModal'; import { Bank } from '../logic/Bank'; @@ -7,11 +8,17 @@ import { Render } from '../utils/Render'; export class TradeModalDemo { static playDemo(): void { const trade = new Trade(new Bank()); - const modal = new TradeModal(trade); const player = new Player( 'player', './static/images/avatars/dog.png', ); + player.theHerd.addAnimalsToHerd(AnimalNames.RABBIT, 20); + player.theHerd.addAnimalsToHerd(AnimalNames.SHEEP, 5); + player.theHerd.addAnimalsToHerd(AnimalNames.PIG, 5); + player.theHerd.addAnimalsToHerd(AnimalNames.COW, 2); + player.theHerd.addAnimalsToHerd(AnimalNames.HORSE, 1); + const modal = new TradeModal(trade, player); Render.render('#sf-app', modal.createModal()); + modal.setPlayer(player); } } From e46a2eca7c4fb4f88358802e8bd036e02018ed1d Mon Sep 17 00:00:00 2001 From: Dominik Date: Thu, 4 Feb 2021 06:16:54 +0100 Subject: [PATCH 14/27] add basic styles --- styles/components/_components.scss | 1 + styles/components/_tradeModal.scss | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 styles/components/_tradeModal.scss diff --git a/styles/components/_components.scss b/styles/components/_components.scss index ecd618a..f7b3e39 100644 --- a/styles/components/_components.scss +++ b/styles/components/_components.scss @@ -2,3 +2,4 @@ @import './components/button'; @import './components/modal'; @import './menu'; +@import './tradeModal'; diff --git a/styles/components/_tradeModal.scss b/styles/components/_tradeModal.scss new file mode 100644 index 0000000..e712358 --- /dev/null +++ b/styles/components/_tradeModal.scss @@ -0,0 +1,24 @@ +.trade { + display: grid; + height: 100%; + grid-template-columns: 2fr 1fr 2fr; + + &__player-herd { + display: flex; + flex-direction: column; + row-gap: 1em; + } + + &__row { + display: grid; + } + + &__player-heading { + padding-bottom: 1em; + text-transform: uppercase; + } + + &__submit { + height: 4em; + } +} From 761069728a3d644c5ff82e4a23a0aaf963665fc4 Mon Sep 17 00:00:00 2001 From: Dominik Date: Thu, 4 Feb 2021 06:48:37 +0100 Subject: [PATCH 15/27] add comments and few tweaks --- src/app/components/TradeModal.ts | 73 ++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/src/app/components/TradeModal.ts b/src/app/components/TradeModal.ts index 694f84d..02ef9b3 100644 --- a/src/app/components/TradeModal.ts +++ b/src/app/components/TradeModal.ts @@ -9,9 +9,11 @@ export class TradeModal extends EmptyModal { tradeForm: HTMLElement; playerView: HTMLElement; bankView: HTMLElement; + player: Player; - constructor(private trade: Trade, private player: Player) { + constructor(private trade: Trade, firstPlayer: Player) { super(); + this.player = firstPlayer; this.playerView = Render.elementFactory('div', { className: 'trade__player-wrapper', }); @@ -36,24 +38,33 @@ export class TradeModal extends EmptyModal { this.modalContainer.appendChild(this.tradeForm); } + /** + * Creates TradeModal and returns it as HTMLElement. + */ createModal(): HTMLElement { Render.childrenInjector( this.bankView, this.createHerdView(this.trade.thisBank, true), ); + Render.childrenInjector( + this.playerView, + this.createHerdView(this.player), + ); this.tradeForm.addEventListener('submit', this.handleSubmit); return this.modal; } - setPlayer(player: Player): void { + /** + * Sets next player and his herd in the TradeModal. + */ + setNextPlayer(player: Player): void { + this.player = player; Render.removeAllChildren(this.playerView); - this.playerView.appendChild(this.createHerdView(player)); - } - - refreshHerdViews(player: Player, bank: Player): void { - this.setPlayer(player); + this.playerView.appendChild(this.createHerdView(this.player)); Render.removeAllChildren(this.bankView); - this.bankView.appendChild(this.createHerdView(bank, true)); + this.bankView.appendChild( + this.createHerdView(this.trade.thisBank, true), + ); } private createHerdView( @@ -88,35 +99,41 @@ export class TradeModal extends EmptyModal { ): HTMLElement[] { const animalsRows: HTMLElement[] = herd.theAnimals.reduce( (animalsElements: HTMLElement[], [animal, count]) => { - animalsElements.push( - Render.elementFactory( - 'div', - { className: 'trade__row' }, + if (count > 0) { + animalsElements.push( Render.elementFactory( - 'label', - { - for: `${isBank ? 'bank' : 'player'}_${ + 'div', + { className: 'trade__row' }, + Render.elementFactory( + 'label', + { + for: `${isBank ? 'bank' : 'player'}_${ + animal.theName + }`, + }, + `${animal.theName}: ${count}`, + ), + Render.elementFactory('input', { + type: 'number', + id: `${isBank ? 'bank' : 'player'}_${animal.theName}`, + name: `${isBank ? 'bank' : 'player'}_${ animal.theName }`, - }, - `${animal.theName}: ${count}`, + min: '0', + max: `${count}`, + }), ), - Render.elementFactory('input', { - type: 'number', - id: `${isBank ? 'bank' : 'player'}_${animal.theName}`, - name: `${isBank ? 'bank' : 'player'}_${animal.theName}`, - min: '0', - max: `${count}`, - }), - ), - ); + ); + } return animalsElements; }, [], ); + return animalsRows; } + //TODO: refactor private formDataIntoTuples(formData: FormData): [Offer, Offer] { const offer: Offer[] = []; const target: Offer[] = []; @@ -136,6 +153,8 @@ export class TradeModal extends EmptyModal { } } } + + //TODO: add display warning when more or less than needed if (offer.length !== 1 || target.length !== 1) { console.log('Za dużo zwiemrzątek'); } @@ -147,7 +166,7 @@ export class TradeModal extends EmptyModal { const formData = new FormData(event.target as HTMLFormElement); const [offer, target] = this.formDataIntoTuples(formData); if (this.trade.processOffer(offer, this.player, target)) { - this.refreshHerdViews(this.player, this.trade.thisBank); + this.setNextPlayer(this.player); } }; } From 8983b3bf8c2c10dfbdf68d5b055432f96d53b022 Mon Sep 17 00:00:00 2001 From: Dominik Date: Thu, 4 Feb 2021 06:52:09 +0100 Subject: [PATCH 16/27] add change players after timeout in TradeModalDemo --- src/app/manuals/TradeModalDemo.ts | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/app/manuals/TradeModalDemo.ts b/src/app/manuals/TradeModalDemo.ts index 40776dd..8a69cb2 100644 --- a/src/app/manuals/TradeModalDemo.ts +++ b/src/app/manuals/TradeModalDemo.ts @@ -5,11 +5,12 @@ import { Bank } from '../logic/Bank'; import { Trade } from '../Trade'; import { Render } from '../utils/Render'; +//type TradeModalDemo.playDemo() in init in App.ts export class TradeModalDemo { static playDemo(): void { const trade = new Trade(new Bank()); const player = new Player( - 'player', + 'Donald', './static/images/avatars/dog.png', ); player.theHerd.addAnimalsToHerd(AnimalNames.RABBIT, 20); @@ -19,6 +20,29 @@ export class TradeModalDemo { player.theHerd.addAnimalsToHerd(AnimalNames.HORSE, 1); const modal = new TradeModal(trade, player); Render.render('#sf-app', modal.createModal()); - modal.setPlayer(player); + + const player2 = new Player( + 'Gerwazy', + './static/images/avatars/dog.png', + ); + player2.theHerd.addAnimalsToHerd(AnimalNames.RABBIT, 6); + player2.theHerd.addAnimalsToHerd(AnimalNames.SHEEP, 1); + player2.theHerd.addAnimalsToHerd(AnimalNames.PIG, 2); + player2.theHerd.addAnimalsToHerd(AnimalNames.COW, 1); + player2.theHerd.addAnimalsToHerd(AnimalNames.HORSE, 1); + + setTimeout(() => modal.setNextPlayer(player2), 15000); + + const player3 = new Player( + 'Eustachy', + './static/images/avatars/dog.png', + ); + player3.theHerd.addAnimalsToHerd(AnimalNames.RABBIT, 8); + player3.theHerd.addAnimalsToHerd(AnimalNames.SHEEP, 3); + player3.theHerd.addAnimalsToHerd(AnimalNames.PIG, 1); + player3.theHerd.addAnimalsToHerd(AnimalNames.COW, 2); + player3.theHerd.addAnimalsToHerd(AnimalNames.HORSE, 0); + + setTimeout(() => modal.setNextPlayer(player3), 15000); } } From 92ece73aa03d812f206cd322080d69f0594bfbae Mon Sep 17 00:00:00 2001 From: Aleksandra Pawlak Date: Thu, 4 Feb 2021 14:16:02 +0100 Subject: [PATCH 17/27] Adress CR feedback --- src/app/logic/GameProcessor.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/app/logic/GameProcessor.ts b/src/app/logic/GameProcessor.ts index 313cb3f..533d6d9 100644 --- a/src/app/logic/GameProcessor.ts +++ b/src/app/logic/GameProcessor.ts @@ -52,7 +52,7 @@ export class GameProcessor { offer: [AnimalNames, number], target: [AnimalNames, number], ): boolean { - if (this.game.theTimer.theTurnTimeLeft === 0) { + if (!this.hasTimeLeft()) { return false; } const tradeResult = this.game.theTrade.processOffer( @@ -91,7 +91,7 @@ export class GameProcessor { * @returns the result of the current players roll */ breed(): [AnimalNames, AnimalNames] | undefined { - if (this.game.theTimer.theTurnTimeLeft === 0) { + if (!this.hasTimeLeft()) { return; } const rollResult = this.game.theBreedProcessor.processBreedPhase( @@ -107,4 +107,8 @@ export class GameProcessor { this.game.nextPlayer(); this.game.theTimer.resetTurn(); } + + private hasTimeLeft(): boolean { + return this.game.theTimer.theTurnTimeLeft === 0; + } } From 8f0ab9105b937365fd9aefc35d2fa6e5ec91766b Mon Sep 17 00:00:00 2001 From: Dominik Date: Fri, 5 Feb 2021 04:23:16 +0100 Subject: [PATCH 18/27] change types in disposeResult in Trade --- src/app/Trade.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/Trade.ts b/src/app/Trade.ts index f3875d7..f199ae3 100644 --- a/src/app/Trade.ts +++ b/src/app/Trade.ts @@ -59,9 +59,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); From 97bc557fb61c465328f9c52177bea3966193464c Mon Sep 17 00:00:00 2001 From: Dominik Date: Fri, 5 Feb 2021 06:02:48 +0100 Subject: [PATCH 19/27] add processTrade method --- src/app/components/TradeModal.ts | 38 +++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/app/components/TradeModal.ts b/src/app/components/TradeModal.ts index 02ef9b3..0297978 100644 --- a/src/app/components/TradeModal.ts +++ b/src/app/components/TradeModal.ts @@ -24,7 +24,7 @@ export class TradeModal extends EmptyModal { 'form', { action: '', - method: 'get', + method: 'post', className: 'trade', }, this.playerView, @@ -35,7 +35,7 @@ export class TradeModal extends EmptyModal { }), this.bankView, ); - this.modalContainer.appendChild(this.tradeForm); + Render.childrenInjector(this.modalContainer, this.tradeForm); } /** @@ -133,8 +133,7 @@ export class TradeModal extends EmptyModal { return animalsRows; } - //TODO: refactor - private formDataIntoTuples(formData: FormData): [Offer, Offer] { + private formDataIntoTuples(formData: FormData): [Offer[], Offer[]] { const offer: Offer[] = []; const target: Offer[] = []; for (const [key, value] of formData.entries()) { @@ -153,19 +152,38 @@ export class TradeModal extends EmptyModal { } } } + return [offer, target]; + } - //TODO: add display warning when more or less than needed - if (offer.length !== 1 || target.length !== 1) { - console.log('Za dużo zwiemrzątek'); + private processTrade([offer, target]: [Offer[], Offer[]]): boolean { + if (offer.length === 1 && target.length === 1) { + const [[offeredAnimal]] = offer; + const [[targetAnimal]] = target; + if (this.trade.processOffer(offer[0], this.player, target[0])) { + return true; + } + console.log( + `The ratio of the ${offeredAnimal}s to ${targetAnimal} is not correct`, + ); + } + if (offer.length > 1 || target.length > 1) { + console.log( + 'To much types of animals, allowed one type for one type', + ); + } + if (offer.length <= 0 || target.length <= 0) { + console.log( + 'There need to be at least one animal on both sides', + ); } - return [offer[0], target[0]]; + return false; } private handleSubmit = (event: Event): void => { event.preventDefault(); const formData = new FormData(event.target as HTMLFormElement); - const [offer, target] = this.formDataIntoTuples(formData); - if (this.trade.processOffer(offer, this.player, target)) { + const data = this.formDataIntoTuples(formData); + if (this.processTrade(data)) { this.setNextPlayer(this.player); } }; From 25f3191d49acd11bae197ec41fcb114ef9f88f52 Mon Sep 17 00:00:00 2001 From: Dominik Date: Fri, 5 Feb 2021 06:53:18 +0100 Subject: [PATCH 20/27] destructurize in Trade --- src/app/Trade.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/app/Trade.ts b/src/app/Trade.ts index f199ae3..0a38773 100644 --- a/src/app/Trade.ts +++ b/src/app/Trade.ts @@ -23,9 +23,13 @@ export class Trade { { theHerd: playerHerd }: Player, 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; } @@ -40,10 +44,10 @@ export class Trade { : this.disposeResult(offer, playerHerd, target); } - private calculateValue(offer: Offer): number { + private calculateValue([animal, count]: Offer): number { return multiply( - ConvertToAnimalObject.convertToAnimalObject(offer[0]).theValue, - offer[1], + ConvertToAnimalObject.convertToAnimalObject(animal).theValue, + count, ); } From 4ef1c48898dba819de73947ee52ffa481049467c Mon Sep 17 00:00:00 2001 From: Dominik Date: Fri, 5 Feb 2021 07:13:52 +0100 Subject: [PATCH 21/27] add warning in TradeModal --- src/app/components/TradeModal.ts | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/app/components/TradeModal.ts b/src/app/components/TradeModal.ts index 0297978..54d3726 100644 --- a/src/app/components/TradeModal.ts +++ b/src/app/components/TradeModal.ts @@ -9,6 +9,7 @@ export class TradeModal extends EmptyModal { tradeForm: HTMLElement; playerView: HTMLElement; bankView: HTMLElement; + warning: HTMLElement; player: Player; constructor(private trade: Trade, firstPlayer: Player) { @@ -35,7 +36,14 @@ export class TradeModal extends EmptyModal { }), this.bankView, ); - Render.childrenInjector(this.modalContainer, this.tradeForm); + this.warning = Render.elementFactory('p', { + className: 'warning', + }); + Render.childrenInjector( + this.modalContainer, + this.tradeForm, + this.warning, + ); } /** @@ -51,6 +59,8 @@ export class TradeModal extends EmptyModal { this.createHerdView(this.player), ); this.tradeForm.addEventListener('submit', this.handleSubmit); + this.modal.addEventListener('keydown', this.clearWarning); + this.modal.addEventListener('click', this.clearWarning); return this.modal; } @@ -160,25 +170,33 @@ export class TradeModal extends EmptyModal { const [[offeredAnimal]] = offer; const [[targetAnimal]] = target; if (this.trade.processOffer(offer[0], this.player, target[0])) { + console.log('poszło'); return true; } - console.log( - `The ratio of the ${offeredAnimal}s to ${targetAnimal} is not correct`, + this.displayWarning( + `The value ratio of the ${offeredAnimal}s to ${targetAnimal}s is not correct`, ); + return false; } if (offer.length > 1 || target.length > 1) { - console.log( + this.displayWarning( 'To much types of animals, allowed one type for one type', ); + return false; } if (offer.length <= 0 || target.length <= 0) { - console.log( + this.displayWarning( 'There need to be at least one animal on both sides', ); + return false; } return false; } + private displayWarning(message: string): void { + this.warning.textContent = message; + } + private handleSubmit = (event: Event): void => { event.preventDefault(); const formData = new FormData(event.target as HTMLFormElement); @@ -187,4 +205,8 @@ export class TradeModal extends EmptyModal { this.setNextPlayer(this.player); } }; + + private clearWarning = (): void => { + this.warning.textContent = ''; + }; } From d617cd308bb76746ce7f0966feddc35d8608f9f8 Mon Sep 17 00:00:00 2001 From: Dominik Date: Fri, 5 Feb 2021 07:16:55 +0100 Subject: [PATCH 22/27] add style to warning --- styles/components/_tradeModal.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/styles/components/_tradeModal.scss b/styles/components/_tradeModal.scss index e712358..a127deb 100644 --- a/styles/components/_tradeModal.scss +++ b/styles/components/_tradeModal.scss @@ -22,3 +22,8 @@ height: 4em; } } + +.warning { + background-color: yellow; + font-size: 26px; +} From f970767f228bf9dbb10781d5f193642e98eff95b Mon Sep 17 00:00:00 2001 From: Dominik Date: Fri, 5 Feb 2021 07:40:57 +0100 Subject: [PATCH 23/27] add hideModal and showModal methods to EmptyModal.ts --- src/app/components/EmptyModal.ts | 15 +++++++++++++++ styles/components/_modal.scss | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/src/app/components/EmptyModal.ts b/src/app/components/EmptyModal.ts index f15f191..df6de9a 100644 --- a/src/app/components/EmptyModal.ts +++ b/src/app/components/EmptyModal.ts @@ -1,4 +1,5 @@ import { Render } from '../utils/Render'; +import { pull } from 'lodash'; export abstract class EmptyModal { modal: HTMLElement; @@ -13,4 +14,18 @@ export abstract class EmptyModal { 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'); + } } diff --git a/styles/components/_modal.scss b/styles/components/_modal.scss index 9a7ab06..c817f93 100644 --- a/styles/components/_modal.scss +++ b/styles/components/_modal.scss @@ -39,4 +39,8 @@ } &__button { } + + &--hidden { + display: none; + } } From d016f1f1cd53584470dd740f012420076d76a9c1 Mon Sep 17 00:00:00 2001 From: Dominik Date: Fri, 5 Feb 2021 07:42:34 +0100 Subject: [PATCH 24/27] implement hiding/showing TradeModal --- src/app/components/TradeModal.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/components/TradeModal.ts b/src/app/components/TradeModal.ts index 54d3726..2bd5f38 100644 --- a/src/app/components/TradeModal.ts +++ b/src/app/components/TradeModal.ts @@ -75,6 +75,7 @@ export class TradeModal extends EmptyModal { this.bankView.appendChild( this.createHerdView(this.trade.thisBank, true), ); + this.showModal(); } private createHerdView( @@ -202,7 +203,7 @@ export class TradeModal extends EmptyModal { const formData = new FormData(event.target as HTMLFormElement); const data = this.formDataIntoTuples(formData); if (this.processTrade(data)) { - this.setNextPlayer(this.player); + this.hideModal(); } }; From eeabd24a45409b66893da028f26dc6aa2344ab2f Mon Sep 17 00:00:00 2001 From: Dominik Date: Fri, 5 Feb 2021 07:55:13 +0100 Subject: [PATCH 25/27] add backButton to TradeModal --- src/app/components/TradeModal.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/components/TradeModal.ts b/src/app/components/TradeModal.ts index 2bd5f38..6f7eb0b 100644 --- a/src/app/components/TradeModal.ts +++ b/src/app/components/TradeModal.ts @@ -10,6 +10,7 @@ export class TradeModal extends EmptyModal { playerView: HTMLElement; bankView: HTMLElement; warning: HTMLElement; + backButton: HTMLElement; player: Player; constructor(private trade: Trade, firstPlayer: Player) { @@ -39,10 +40,12 @@ export class TradeModal extends EmptyModal { this.warning = Render.elementFactory('p', { className: 'warning', }); + this.backButton = Render.elementFactory('button', {}, 'back'); Render.childrenInjector( this.modalContainer, this.tradeForm, this.warning, + this.backButton, ); } @@ -61,6 +64,7 @@ export class TradeModal extends EmptyModal { this.tradeForm.addEventListener('submit', this.handleSubmit); this.modal.addEventListener('keydown', this.clearWarning); this.modal.addEventListener('click', this.clearWarning); + this.backButton.addEventListener('click', () => this.hideModal()); return this.modal; } @@ -171,7 +175,6 @@ export class TradeModal extends EmptyModal { const [[offeredAnimal]] = offer; const [[targetAnimal]] = target; if (this.trade.processOffer(offer[0], this.player, target[0])) { - console.log('poszło'); return true; } this.displayWarning( From e525bd5b17417d4a39f8ed119c46a24e12fb02b4 Mon Sep 17 00:00:00 2001 From: Dominik Date: Fri, 5 Feb 2021 08:16:05 +0100 Subject: [PATCH 26/27] extract updating bank to the separate method --- src/app/components/TradeModal.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/components/TradeModal.ts b/src/app/components/TradeModal.ts index 6f7eb0b..432844d 100644 --- a/src/app/components/TradeModal.ts +++ b/src/app/components/TradeModal.ts @@ -75,11 +75,15 @@ export class TradeModal extends EmptyModal { this.player = player; Render.removeAllChildren(this.playerView); this.playerView.appendChild(this.createHerdView(this.player)); + this.updateBank(); + this.showModal(); + } + + private updateBank(): void { Render.removeAllChildren(this.bankView); this.bankView.appendChild( this.createHerdView(this.trade.thisBank, true), ); - this.showModal(); } private createHerdView( From a1908e9c6b83cbc34d046e36e440654d2c3be6db Mon Sep 17 00:00:00 2001 From: Dominik Date: Fri, 5 Feb 2021 08:17:06 +0100 Subject: [PATCH 27/27] fix bug in TradeModalDemo --- src/app/manuals/TradeModalDemo.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/manuals/TradeModalDemo.ts b/src/app/manuals/TradeModalDemo.ts index 8a69cb2..b5dc6dc 100644 --- a/src/app/manuals/TradeModalDemo.ts +++ b/src/app/manuals/TradeModalDemo.ts @@ -31,8 +31,6 @@ export class TradeModalDemo { player2.theHerd.addAnimalsToHerd(AnimalNames.COW, 1); player2.theHerd.addAnimalsToHerd(AnimalNames.HORSE, 1); - setTimeout(() => modal.setNextPlayer(player2), 15000); - const player3 = new Player( 'Eustachy', './static/images/avatars/dog.png', @@ -43,6 +41,9 @@ export class TradeModalDemo { player3.theHerd.addAnimalsToHerd(AnimalNames.COW, 2); player3.theHerd.addAnimalsToHerd(AnimalNames.HORSE, 0); - setTimeout(() => modal.setNextPlayer(player3), 15000); + setTimeout(() => { + modal.setNextPlayer(player2); + setTimeout(() => modal.setNextPlayer(player3), 15000); + }, 15000); } }