diff --git a/README.md b/README.md index f07ca4a..d25d464 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Chrome уже поддерживает использование модулей Инструктаж окончен. Твоя задача - создавать новые типы карт, наследующиеся от Card. Можешь приступать к решению задачи! -1. «Классы» ++++1. «Классы» Во всем коде типы определены по-старому, через прототипы. Изоляция кода при этом обеспечивает за счет техники IIFE: https://developer.mozilla.org/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/IIFE @@ -53,10 +53,10 @@ Chrome уже поддерживает использование модулей Результат будет тот же, но запись будет более лаконичной. Чтобы лучше понять разницу между старым и новым синтаксисом перепиши `TaskQueue` с использованием `class` и без IIFE: -- Убери обрамляющую определение `TaskQueue` самовызывающуюся функцию. -- Перенеси вверх функцию `runNextTask`, потому что это не метод `TaskQueue`. -- Объяви тип `TaskQueue` с помощью инструкции `class`, определи constructor и все методы. -- `export default` поставь сразу перед инструкции `class`. +++- Убери обрамляющую определение `TaskQueue` самовызывающуюся функцию. +++- Перенеси вверх функцию `runNextTask`, потому что это не метод `TaskQueue`. +++- Объяви тип `TaskQueue` с помощью инструкции `class`, определи constructor и все методы. +++- `export default` поставь сразу перед инструкции `class`. Пример перехода от старого синтаксиса к новому: @@ -98,7 +98,7 @@ function secret(value) { ``` -2. «Утки против собак» ++++2. «Утки против собак» Создай в `index.js` две новые карты, используй `class` и унаследовав их от `Card`: - `Duck` с именем «Мирная утка» и силой 2 - `Dog` с именем «Пес-бандит» и силой 3 @@ -111,11 +111,11 @@ https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Classes#%D0%9D%D0 Не забудь вызвать базовый конструктор `Card` с помощью `super`! -- Новые карты должны создаваться, даже если им не передать параметров: `new Duck()` и `new Dog()`. -- Методы `quacks` и `swims` утки должны создаваться на уровне класса, а не добавляться в конструкторе. -- После добавления новых типов замени карты в колоде шерифа на уток, а в колоде бандита - на собак. -- Функция `isDuck` должна возвращать `true` для утки, а функция `isDog` — для собаки. -- Если все сделано правильно, то внизу карты утки должен быть текст Duck➔ Card, а у собаки Dog➔ Card. +++- Новые карты должны создаваться, даже если им не передать параметров: `new Duck()` и `new Dog()`. +++- Методы `quacks` и `swims` утки должны создаваться на уровне класса, а не добавляться в конструкторе. +++ После добавления новых типов замени карты в колоде шерифа на уток, а в колоде бандита - на собак. +++- Функция `isDuck` должна возвращать `true` для утки, а функция `isDog` — для собаки. +++- Если все сделано правильно, то внизу карты утки должен быть текст Duck➔ Card, а у собаки Dog➔ Card. Колоды для проверки: ```js @@ -130,12 +130,12 @@ const banditStartDeck = [ ``` -3. «Утка или собака?» ++++3. «Утка или собака?» Метод `getDescriptions` в `Card` создан для того, чтобы на картах появлялась дополнительная информация. Его функционал хочется расширить. Причем так, чтобы это работало и для уток, и для собак, и для всех остальных существ, которые будут добавляться. -- Создай новый тип `Creature` и унаследуй его от `Card`. +++- Создай новый тип `Creature` и унаследуй его от `Card`. - Сделай так, чтобы `Duck` и `Dog` наследовались от `Creature`. - Переопредели в классе `Creature` реализацию `getDescriptions` на новую. Теперь в ней должны возвращаться две строки описания в виде массива. @@ -157,7 +157,7 @@ const banditStartDeck = [ а у собак надпись «Собака» над цепочкой наследования. -4. «Громила» ++++4. «Громила» Для уток все становится плохо, когда в рядах бандитов появляется Громила. Добавь карту `Trasher`: @@ -192,7 +192,7 @@ const banditStartDeck = [ ``` -5. «Гатлинг» ++++5. «Гатлинг» Нехорошо нападать на мирных жителей. Это еще может быть опасно, если в сарае припрятан Гатлинг. Добавь карту `Gatling`: @@ -222,7 +222,7 @@ const banditStartDeck = [ ``` -6. «Братки» ++++6. «Братки» Чем их больше, тем они сильнее. Добавь карту `Lad`: diff --git a/src/TaskQueue.js b/src/TaskQueue.js index f3a9c6a..098d4fc 100644 --- a/src/TaskQueue.js +++ b/src/TaskQueue.js @@ -1,10 +1,34 @@ -const TaskQueue = function() { - function TaskQueue() { +function runNextTask(taskQueue) { + if (taskQueue.running || taskQueue.tasks.length === 0) { + return; + } + taskQueue.running = true; + const task = taskQueue.tasks.shift(); + + if (task.runAndContinue) { + setTimeout(() => { + task.runAndContinue(() => { + task.dispose && task.dispose(); + taskQueue.running = false; + + setTimeout(() => { + runNextTask(taskQueue); + }); + }); + }, 0); + } + else { + runNextTask(taskQueue); + } +} + +export default class TaskQueue { + constructor() { this.tasks = []; this.running = false; } - TaskQueue.prototype.push = function(run, dispose, duration) { + push(run, dispose, duration) { if (duration === undefined || duration === null) { this.tasks.push({runAndContinue: run, dispose}); } else { @@ -19,37 +43,10 @@ const TaskQueue = function() { }); } runNextTask(this); - }; + } - TaskQueue.prototype.continueWith = function(action) { + continueWith(action) { this.push(action, null, 0); - }; - - function runNextTask(taskQueue) { - if (taskQueue.running || taskQueue.tasks.length === 0) { - return; - } - taskQueue.running = true; - const task = taskQueue.tasks.shift(); - - if (task.runAndContinue) { - setTimeout(() => { - task.runAndContinue(() => { - task.dispose && task.dispose(); - taskQueue.running = false; - - setTimeout(() => { - runNextTask(taskQueue); - }); - }); - }, 0); - } - else { - runNextTask(taskQueue); - } } +} - return TaskQueue; -}(); - -export default TaskQueue; diff --git a/src/index.js b/src/index.js index a01f912..ef13850 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,7 @@ import SpeedRate from './SpeedRate.js'; // Отвечает является ли карта уткой. function isDuck(card) { - return card && card.quacks && card.swims; + return card instanceof Duck; } // Отвечает является ли карта собакой. @@ -27,30 +27,156 @@ function getCreatureDescription(card) { return 'Существо'; } - +class Creature extends Card { + constructor(name, maxPower) { + super(name, maxPower) + } + getDescriptions() { + let res = []; + res.push(getCreatureDescription(this)); + res.push(super.getDescriptions()) + return res; + } +} // Основа для утки. -function Duck() { - this.quacks = function () { console.log('quack') }; - this.swims = function () { console.log('float: both;') }; -} +class Duck extends Creature{ + constructor(name = 'Мирная утка', maxPower = 2) { + super(name, maxPower); + } + quacks() { + console.log('quack') + } + + swims() { + console.log('float: both;') + } +} // Основа для собаки. -function Dog() { +class Dog extends Creature { + constructor(name = 'Пес-бандит', maxPower = 3) { + super(name, maxPower); + } +} + +class Trasher extends Dog { + constructor() { + super('Громила', 5); + } + + + modifyTakenDamage(value, fromCard, gameContext, continuation) { + if (value > 1) { + this.view.signalAbility(() => super.modifyTakenDamage(value - 1, fromCard, gameContext, continuation)); + } else { + this.view.signalAbility(continuation); + } + } + + getDescriptions() { + return [ + "Громила получает на 1 меньше урона", + ...super.getDescriptions(), + ]; + } +} + +class Gatling extends Creature{ + constructor() { + super('Гатлинг', 6); + } + + attack(gameContext, continuation) { + const taskQueue = new TaskQueue(); + + const {currentPlayer, oppositePlayer, position, updateView} = gameContext; + for(let e of oppositePlayer.table) { + if(e) { + taskQueue.push(onDone => this.view.showAttack(onDone)); + taskQueue.push(onDone => this.dealDamageToCreature(2, e, gameContext, onDone)); + } + } + taskQueue.continueWith(continuation); + console.log(Lad.countLad) + } +} + +class Lad extends Dog { + constructor() { + super('Браток', 2); + } + + static get InGameCount() { return this.inGameCount || 0; } + + static set InGameCount(value) { this.inGameCount = value; } + + static getBonus() { + return this.InGameCount * (this.InGameCount + 1) / 2; + } + + doAfterComingIntoPlay(gameContext, continuation) { + Lad.InGameCount++; + continuation(); + } + + doBeforeRemoving(continuation) { + Lad.InGameCount--; + continuation(); + } + + modifyDealedDamageToCreature(value, toCard, gameContext, continuation) { + this.view.signalAbility(() => { + continuation(value + Lad.getBonus()); + }) + } + + modifyTakenDamage(value, fromCard, gameContext, continuation) { + this.view.signalAbility(() => { + continuation(value - Lad.getBonus()); + }) + } + + getDescriptions() { + let description = super.getDescriptions(); + if (Lad.prototype.hasOwnProperty('modifyDealedDamageToCreature') && Lad.prototype.hasOwnProperty('modifyTakenDamage')) { + description.unshift('Чем больше братков находится в игре, тем больше урона без потерь поглощается' + + ' и больше урона по картам наносится каждым из них'); + } + return description; + } +} + +class Rogue extends Creature { + constructor() { + super('Изгой', 2); + } } +class Brewer extends Duck { + constructor() { + super('Пивозавр', 2); + } + + +} + + + // Колода Шерифа, нижнего игрока. const seriffStartDeck = [ - new Card('Мирный житель', 2), - new Card('Мирный житель', 2), - new Card('Мирный житель', 2), + new Duck(), + new Duck(), + new Duck(), + ]; // Колода Бандита, верхнего игрока. const banditStartDeck = [ - new Card('Бандит', 3), + new Lad(), + new Lad(), ];