Merge branch 'zinch-lab4'
This commit is contained in:
commit
74ebac6de5
148
README.md
148
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 {
|
||||
<<enumeration>>
|
||||
+ SAD
|
||||
+ ANGRY
|
||||
+ SCARY
|
||||
+ RAGE
|
||||
+ NORMAL
|
||||
- String feel
|
||||
+ values() Feels[]
|
||||
+ toString() String
|
||||
+ valueOf(String) Feels
|
||||
}
|
||||
|
||||
class Gender {
|
||||
<<enumeration>>
|
||||
- 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 {
|
||||
<<interface>>
|
||||
+ grab(Item) void
|
||||
}
|
||||
|
||||
class IMovable {
|
||||
<<interface>>
|
||||
+ moveTo(Entity) void
|
||||
}
|
||||
|
||||
class IFeelable {
|
||||
<<interface>>
|
||||
+ setFeel(Feels) void
|
||||
}
|
||||
|
||||
class IGrabbable {
|
||||
<<interface>>
|
||||
+ 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
|
||||
```
|
||||
Есть вложенный статический класс `Engin` у Карлсона, отвечающий за его движок. В нём есть локальный класс `Path`, хранящий
|
||||
в себе дистанцию полёта и формулу расчёта расхода. Для формулы используются анонимные классы интерфейса `IntFormula`.
|
||||
Есть вложенный не статический класс `Mouth` у Малыша, который отвечает за его речь.
|
||||
@ -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;
|
||||
|
||||
7
src/Characters/ExitFuelException.java
Normal file
7
src/Characters/ExitFuelException.java
Normal file
@ -0,0 +1,7 @@
|
||||
package Characters;
|
||||
|
||||
public class ExitFuelException extends RuntimeException {
|
||||
public ExitFuelException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,12 @@
|
||||
package Characters;
|
||||
|
||||
public enum Feels {
|
||||
ANGRY("злиться"),
|
||||
ANGRY("злой как чёрт"),
|
||||
SCARY("дрогнул губой"),
|
||||
SAD("надулся"),
|
||||
RAGE("взревела от бешенства"),
|
||||
NORMAL("Нормально");
|
||||
NORMAL("нормально"),
|
||||
DEAD_INSIDE("был просто в отчаянии");
|
||||
|
||||
private final String feel;
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -3,5 +3,5 @@ package Characters;
|
||||
import Items.Item;
|
||||
|
||||
interface ICanTake {
|
||||
void grab(Item obj);
|
||||
void grab(Item obj) throws OwnershipException;
|
||||
}
|
||||
|
||||
7
src/Characters/IFlyable.java
Normal file
7
src/Characters/IFlyable.java
Normal file
@ -0,0 +1,7 @@
|
||||
package Characters;
|
||||
|
||||
import Entity.*;
|
||||
|
||||
public interface IFlyable {
|
||||
void flyTo(Entity obj);
|
||||
}
|
||||
@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
35
src/Characters/Malysh.java
Normal file
35
src/Characters/Malysh.java
Normal file
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
7
src/Characters/OwnershipException.java
Normal file
7
src/Characters/OwnershipException.java
Normal file
@ -0,0 +1,7 @@
|
||||
package Characters;
|
||||
|
||||
public class OwnershipException extends Exception {
|
||||
public OwnershipException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
18
src/Items/Door.java
Normal file
18
src/Items/Door.java
Normal file
@ -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("Дверь распахнулась");
|
||||
}
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user