diff --git a/README.md b/README.md index 5ef5c79..41cfbaf 100644 --- a/README.md +++ b/README.md @@ -3,24 +3,35 @@ **ИСУ:** 408657 -**Вариант:** 528475 +**Вариант:** ~528475.3 + +_Так как на se.ifmo сбросились варианты я взял текст напрямую из сказки._ ## Задание -> У Карлсона дрогнули губы, и он надулся. Он сделал шаг к плите и взял со сковородки одну тефтельку. Вот этого ему не следовало делать. Фрекен Бок взревела от бешенства и кинулась на Карлсона, схватила его за шиворот и вытолкнула за дверь. +> У Карлсона дрогнули губы, и он надулся. Он сделал шаг к плите и взял со сковородки одну тефтельку. +> Вот этого ему не следовало делать. Фрекен Бок взревела от бешенства и кинулась на Карлсона, схватила его за шиворот +> и вытолкнула за дверь. Малыш был просто в отчаянии. Больше он ничего не успел сказать, потому что дверь кухни +> распахнулась и ворвался Карлсон, тоже злой как чёрт. Он подлетел к Фрекен Бок и топнул ногой об пол. ## Вывод программы - ``` Кралсон дрогнул губой Кралсон надулся Он сделал шаг к плита -Кралсон взял одну тефтелька из сковородка +Предмет тефтелька принадлежит Фрекен Бок, а не Кралсон Вот этого ему не следовало делать Фрекен Бок взревела от бешенства Она кинулась к Кралсон Она схватила Кралсон за шиворот -Она вытолкнула Кралсон за дверь +Она вытолкнула Кралсон за Дверь +Малыш был просто в отчаянии +Он ничего не сказал +Дверь распахнулась +Он сделал шаг к Дверь +Кралсон злой как чёрт +Он подлетел к Фрекен Бок +Кралсон топнул ногой ``` ## Структура проекта @@ -32,125 +43,16 @@ graph TD; Entity-->Item; Item-->Container; ``` -Главный абстрактный класс - Entity, который имеет только имя. От него наследуются предметы и персонажи. Персонажи могут чувствовать *(IFeelabe)*, двигаться *(IMovable)* и брать вещи *(ITakeable)*. Также персонажи имеют гендер *(enum Feels)*. +Главный абстрактный класс - Entity, который имеет только имя. От него наследуются предметы и персонажи. +Персонажи могут чувствовать *(IFeelabe)*, двигаться *(IMovable)* и брать вещи *(ITakeable)*. +Также персонажи имеют гендер *(enum Feels)*. За историю отвечает класс *StoryTeller*. Он меняет состояние персонажей и отображает их состояние. -## UML Диаграмма -```mermaid -classDiagram -class Entity { - # String name - + getName() String -} -class Character { - # Item itemInHand - # Feels feel - - String currentState - - Gender gender - - Entity position - + setFeel(Feels)* void - + moveTo(Entity)* void - + grab(Item)* void - + getItemInHand() Item - + getPosition() Entity - + getGender() String - + getState() String - # setState(String) void - # setPosition(Entity) void -} -class FrenBok { - - IGrabbable characterInHand - + grabCharacter(IGrabbable) void - + setFeel(Feels) void - + moveTo(Entity) void - + grab(Item) void - + pushCharacterBehindItem(Item) void -} -class Karlson { - + grab(Item) void - + setFeel(Feels) void - + moveTo(Entity) void - + grabFrom(Container) void - + getGrabbablePart() String -} +## Особенности 4 лабы +Есть два исключения: `OwnershipException` и `ExitFuelException`. `OwnershipException` - исключение при взятии чужой вещи. +`ExitFuelException` возникает, когда у Карлсона кончается топливо. -class Item { - - Character owner - + getOwner() Character - + setOwner(Character) void -} -class Container { - - Item innerItem - + getInnerItem() Item -} - -class Feels { -<> - + SAD - + ANGRY - + SCARY - + RAGE - + NORMAL - - String feel - + values() Feels[] - + toString() String - + valueOf(String) Feels -} - -class Gender { -<> - - String gender - + MAN - + WOMAN - + valueOf(String) Gender - + toString() String - + values() Gender[] -} - -class StoryTeller { - - Item door - - Item meatball - - Container fryingPan - - FrenBok frenBok - - Karlson karlson - - Item kitchenHob - + play() void -} - -class ICanTake { - <> - + grab(Item) void -} - -class IMovable { - <> - + moveTo(Entity) void -} - -class IFeelable { - <> - + setFeel(Feels) void -} - -class IGrabbable { - <> - + getGrabbablePart() String -} - -IGrabbable --|> IMovable - -Character --|> Entity -Container --|> Item -FrenBok --|> Character -Item --|> Entity -Karlson --|> Character - -Character ..|> IFeelable -Character ..|> IMovable -Character ..|> ICanTake -Karlson ..|> IGrabbable - -Character --> Feels -Character --> Gender -``` \ No newline at end of file +Есть вложенный статический класс `Engin` у Карлсона, отвечающий за его движок. В нём есть локальный класс `Path`, хранящий +в себе дистанцию полёта и формулу расчёта расхода. Для формулы используются анонимные классы интерфейса `IntFormula`. +Есть вложенный не статический класс `Mouth` у Малыша, который отвечает за его речь. \ No newline at end of file diff --git a/src/Characters/Character.java b/src/Characters/Character.java index 2ce18e5..6ebba26 100644 --- a/src/Characters/Character.java +++ b/src/Characters/Character.java @@ -6,6 +6,23 @@ import Items.Item; import java.util.Objects; public abstract class Character extends Entity implements IMovable, IFeelable, ICanTake { + + public enum Gender { + MAN("Он"), + WOMAN("Она"); + + private final String gender; + + Gender(String gender) { + this.gender = gender; + } + + @Override + public String toString() { + return gender; + } + } + private final Gender gender; private Entity position; private String currentState = ""; @@ -26,29 +43,32 @@ public abstract class Character extends Entity implements IMovable, IFeelable, I return this.gender.toString(); } - public abstract void setFeel(Feels feel); + public final void setFeel(Feels feel) { + this.feel = feel; + this.setState(String.format("%s %s", this.getName(), feel)); + } public abstract void moveTo(Entity obj); - public abstract void grab(Item obj); + public abstract void grab(Item obj) throws OwnershipException; - public Item getItemInHand() { + public final Item getItemInHand() { return this.itemInHand; } - public Entity getPosition() { + public final Entity getPosition() { return this.position; } - protected void setPosition(Entity obj) { + protected final void setPosition(Entity obj) { this.position = obj; } - public String getState() { + public final String getState() { return this.currentState; } - protected void setState(String state) { + protected final void setState(String state) { this.currentState = state; } @@ -57,7 +77,6 @@ public abstract class Character extends Entity implements IMovable, IFeelable, I return this.getName(); } - @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/Characters/ExitFuelException.java b/src/Characters/ExitFuelException.java new file mode 100644 index 0000000..29b11eb --- /dev/null +++ b/src/Characters/ExitFuelException.java @@ -0,0 +1,7 @@ +package Characters; + +public class ExitFuelException extends RuntimeException { + public ExitFuelException(String message) { + super(message); + } +} diff --git a/src/Characters/Feels.java b/src/Characters/Feels.java index 1fc9b8d..4a0d236 100644 --- a/src/Characters/Feels.java +++ b/src/Characters/Feels.java @@ -1,11 +1,12 @@ package Characters; public enum Feels { - ANGRY("злиться"), + ANGRY("злой как чёрт"), SCARY("дрогнул губой"), SAD("надулся"), RAGE("взревела от бешенства"), - NORMAL("Нормально"); + NORMAL("нормально"), + DEAD_INSIDE("был просто в отчаянии"); private final String feel; diff --git a/src/Characters/FrenBok.java b/src/Characters/FrenBok.java index 349ec87..fb35296 100644 --- a/src/Characters/FrenBok.java +++ b/src/Characters/FrenBok.java @@ -10,12 +10,6 @@ public class FrenBok extends Character { super("Фрекен Бок", Gender.WOMAN); } - @Override - public void setFeel(Feels feel) { - this.feel = feel; - this.setState(String.format("%s %s", this.getName(), feel)); - } - @Override public void moveTo(Entity obj) { this.setPosition(obj); @@ -23,9 +17,12 @@ public class FrenBok extends Character { } @Override - public void grab(Item obj) { + public void grab(Item obj) throws OwnershipException { this.itemInHand = obj; - this.setState(String.format("%s взяла %s", this.getGender(), obj.getName())); + this.setState(String.format("%s взяла %s", this.getGender(), obj)); + if (obj.getOwner() != this && obj.getOwner() != null) { + throw new OwnershipException(String.format("Предмет %s принадлежит %s, а не %s", obj.getName(), obj.getOwner().getName(), this.getName())); + } } public void grabCharacter(IGrabbable character) { diff --git a/src/Characters/Gender.java b/src/Characters/Gender.java deleted file mode 100644 index ecae76d..0000000 --- a/src/Characters/Gender.java +++ /dev/null @@ -1,17 +0,0 @@ -package Characters; - -public enum Gender { - MAN("Он"), - WOMAN("Она"); - - private final String gender; - - Gender(String gender) { - this.gender = gender; - } - - @Override - public String toString() { - return gender; - } -} diff --git a/src/Characters/ICanTake.java b/src/Characters/ICanTake.java index b98ba29..207cbd7 100644 --- a/src/Characters/ICanTake.java +++ b/src/Characters/ICanTake.java @@ -3,5 +3,5 @@ package Characters; import Items.Item; interface ICanTake { - void grab(Item obj); + void grab(Item obj) throws OwnershipException; } diff --git a/src/Characters/IFlyable.java b/src/Characters/IFlyable.java new file mode 100644 index 0000000..2467ed0 --- /dev/null +++ b/src/Characters/IFlyable.java @@ -0,0 +1,7 @@ +package Characters; + +import Entity.*; + +public interface IFlyable { + void flyTo(Entity obj); +} diff --git a/src/Characters/Karlson.java b/src/Characters/Karlson.java index 965c3cc..f473b6f 100644 --- a/src/Characters/Karlson.java +++ b/src/Characters/Karlson.java @@ -4,7 +4,13 @@ import Entity.Entity; import Items.Container; import Items.Item; -public class Karlson extends Character implements IGrabbable { +import java.util.Arrays; +import java.util.function.IntFunction; +import java.util.function.IntSupplier; + +public class Karlson extends Character implements IGrabbable, IFlyable { + private final Engine engine = new Engine(); + public Karlson() { super("Кралсон", Gender.MAN); } @@ -14,10 +20,83 @@ public class Karlson extends Character implements IGrabbable { this.feel = feel; } - @Override - public void setFeel(Feels feel) { - this.feel = feel; - this.setState(String.format("%s %s", this.getName(), feel)); + private static class Engine { + private int fuel = 13; + + public Engine() {} + public boolean canFly() { + return fuel > 0; + } + + public void startFly() { + this.fuel -= this.countMinPath(); + if (fuel < 0) { + throw new ExitFuelException("У двигателя кончилось топливо"); + } + } + + public int countMinPath() { + interface IntFormula { + int getResult(int x); + int getAbs(int x); + } + class Path { + private final int distance; + private final IntFormula formula; + + Path (int distance, IntFormula formula) { + this.distance = distance; + this.formula = formula; + } + + public int getResult() { + return formula.getAbs(distance); + } + } + + Path[] paths = { + new Path(4, new IntFormula() { + @Override + public int getResult(int x) { + return x*3; + } + + @Override + public int getAbs(int x) { + return Math.abs(getResult(x)); + } + }), + new Path(7, new IntFormula() { + @Override + public int getResult(int x) { + return x*6; + } + + @Override + public int getAbs(int x) { + return Math.abs(getResult(x)); + } + }), + new Path(1, new IntFormula() { + @Override + public int getResult(int x) { + return x*x-2; + } + + @Override + public int getAbs(int x) { + return Math.abs(getResult(x)); + } + }) + }; + + int minPath = Integer.MAX_VALUE; + for (Path path: paths) { + minPath = Math.min(path.getResult(), minPath); + } + + return minPath; + } } @Override @@ -26,13 +105,26 @@ public class Karlson extends Character implements IGrabbable { this.setState(String.format("%s сделал шаг к %s", this.getGender(), obj)); } - @Override - public void grab(Item obj) { - this.itemInHand = obj; - this.setState(String.format("%s взял %s", this.getGender(), obj)); + public void flyTo(Entity obj) { + if (engine.canFly()) { + this.moveTo(obj); + this.engine.startFly(); + this.setState(String.format("%s подлетел к %s", this.getGender(), obj)); + return; + } + this.setState("%s пытался взлететь, но у него не получилось"); } - public void grabFrom(Container container) { + @Override + public void grab(Item obj) throws OwnershipException { + this.itemInHand = obj; + this.setState(String.format("%s взял %s", this.getGender(), obj)); + if (obj.getOwner() != this && obj.getOwner() != null) { + throw new OwnershipException(String.format("Предмет %s принадлежит %s, а не %s", obj.getName(), obj.getOwner().getName(), this.getName())); + } + } + + public void grabFrom(Container container) throws OwnershipException { this.grab(container.getInnerItem()); this.setState(String.format("%s взял одну %s из %s", this.getName(), container.getInnerItem(), container)); } @@ -41,4 +133,8 @@ public class Karlson extends Character implements IGrabbable { public String getGrabbablePart() { return "шиворот"; } + + public void stomp() { + this.setState(String.format("%s топнул ногой", this.getName())); + } } diff --git a/src/Characters/Malysh.java b/src/Characters/Malysh.java new file mode 100644 index 0000000..526e26f --- /dev/null +++ b/src/Characters/Malysh.java @@ -0,0 +1,35 @@ +package Characters; + +import Entity.Entity; +import Items.Item; + +public class Malysh extends Character { + public Mouth mouth = new Mouth(); + public Malysh() { + super("Малыш", Gender.MAN ,Feels.NORMAL); + } + public class Mouth { + public void speak(String speech) { + if (speech == null) { + Malysh.this.setState(String.format("%s ничего не сказал", Malysh.this.getGender())); + return; + } + Malysh.this.setState(String.format("%s сказал: \"%s\"", Malysh.this.getName(), speech)); + } + } + + @Override + public void moveTo(Entity obj) { + this.setPosition(obj); + this.setState(String.format("%s подошёл к %s", this.getGender(), obj)); + } + + @Override + public void grab(Item obj) throws OwnershipException { + this.itemInHand = obj; + this.setState(String.format("%s присвоил себе %s", this.getGender(), obj)); + if (obj.getOwner() != this && obj.getOwner() != null) { + throw new OwnershipException(String.format("Предмет %s принадлежит %s, а не %s", obj.getName(), obj.getOwner().getName(), this.getName())); + } + } +} diff --git a/src/Characters/OwnershipException.java b/src/Characters/OwnershipException.java new file mode 100644 index 0000000..f8cc1ed --- /dev/null +++ b/src/Characters/OwnershipException.java @@ -0,0 +1,7 @@ +package Characters; + +public class OwnershipException extends Exception { + public OwnershipException(String message) { + super(message); + } +} diff --git a/src/Items/Door.java b/src/Items/Door.java new file mode 100644 index 0000000..977d7ac --- /dev/null +++ b/src/Items/Door.java @@ -0,0 +1,18 @@ +package Items; + +public class Door extends Item { + private boolean isOpen = false; + + public Door() { + super("Дверь"); + } + + public void openDoor() { + this.isOpen = true; + System.out.println("Дверь закрылась"); + } + public void closeDoor() { + this.isOpen = false; + System.out.println("Дверь распахнулась"); + } +} diff --git a/src/StoryTeller/StoryTeller.java b/src/StoryTeller/StoryTeller.java index a47f25f..188dd45 100644 --- a/src/StoryTeller/StoryTeller.java +++ b/src/StoryTeller/StoryTeller.java @@ -1,21 +1,22 @@ package StoryTeller; -import Characters.Feels; -import Characters.FrenBok; -import Characters.Karlson; +import Characters.*; +import Characters.Character; import Items.Container; +import Items.Door; import Items.Item; public class StoryTeller { // Персонажи private final Karlson karlson = new Karlson(); private final FrenBok frenBok = new FrenBok(); + private final Malysh malysh = new Malysh(); // Предметы private final Item kitchenHob = new Item("плита"); private final Item meatball = new Item("тефтелька"); private final Container fryingPan = new Container("сковородка", meatball, frenBok); - private final Item door = new Item("дверь"); + private final Door door = new Door(); public void play() { karlson.setFeel(Feels.SCARY); @@ -24,9 +25,13 @@ public class StoryTeller { System.out.println(karlson.getState()); karlson.moveTo(kitchenHob); System.out.println(karlson.getState()); - karlson.grabFrom(fryingPan); - System.out.println(karlson.getState()); - if (fryingPan.getOwner() == frenBok) { + try { + karlson.grabFrom(fryingPan); + System.out.println(karlson.getState()); + frenBok.setFeel(Feels.NORMAL); + System.out.println(frenBok.getState()); + } catch (OwnershipException e) { + System.out.println(e.getMessage()); System.out.println("Вот этого ему не следовало делать"); frenBok.setFeel(Feels.RAGE); System.out.println(frenBok.getState()); @@ -36,9 +41,19 @@ public class StoryTeller { System.out.println(frenBok.getState()); frenBok.pushCharacterBehindItem(door); System.out.println(frenBok.getState()); - } else { - frenBok.setFeel(Feels.NORMAL); - System.out.println(frenBok); + malysh.setFeel(Feels.DEAD_INSIDE); + System.out.println(malysh.getState()); + malysh.mouth.speak(null); + System.out.println(malysh.getState()); + door.closeDoor(); + karlson.moveTo(door); + System.out.println(karlson.getState()); + karlson.setFeel(Feels.ANGRY); + System.out.println(karlson.getState()); + karlson.flyTo(frenBok); + System.out.println(karlson.getState()); + karlson.stomp(); + System.out.println(karlson.getState()); } } }