Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solution #1362

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 44 additions & 1 deletion app/main.py
Original file line number Diff line number Diff line change
@@ -1 +1,44 @@
# write your code here
from app.players.elves.elf_ranges import ElfRanger
from app.players.elves.druid import Druid
from app.players.dwarves.dwarf_warrior import DwarfWarrior
from app.players.dwarves.dwarf_blacksmith import DwarfBlacksmith

def calculate_team_total_rating(team):
return sum(player.get_rating() for player in team)

def elves_concert(elves):
for elf in elves:
elf.play_elf_song()

def feast_of_the_dwarves(dwarves):
for dwarf in dwarves:
dwarf.eat_favourite_dish()

# Testing the implementation
ranger = ElfRanger(nickname="Nardual Chaekian", musical_instrument="flute", bow_level=7)
print(ranger.get_rating()) # 21
print(ranger.player_info()) # "Elf ranger Nardual Chaekian. Nardual Chaekian has bow of the 7 level"
ranger.play_elf_song() # "Nardual Chaekian is playing a song on the flute"

warrior = DwarfWarrior(nickname="Thiddeal", favourite_dish="French Fries", hummer_level=7)
print(warrior.get_rating()) # 11
print(warrior.player_info()) # "Dwarf warrior Thiddeal. Thiddeal has a hummer of the 7 level"
warrior.eat_favourite_dish() # "Thiddeal is eating French Fries"

team = [
Druid(nickname="Druid", musical_instrument="flute", favourite_spell="ABC"),
ElfRanger(nickname="Ranger", musical_instrument="trumpet", bow_level=33),
]
print(calculate_team_total_rating(team)) # 102

elves = [
Druid(nickname="Nardual", musical_instrument="flute", favourite_spell="aaa"),
ElfRanger(nickname="Rothilion", musical_instrument="trumpet", bow_level=33),
]
elves_concert(elves) # "Nardual is playing a song on the flute" "Rothilion is playing a song on the trumpet"

dwarves = [
DwarfWarrior(nickname="Thiddeal", favourite_dish="French Fries", hummer_level=3),
DwarfWarrior(nickname="Dwarf", favourite_dish="Caesar Salad", hummer_level=3),
]
feast_of_the_dwarves(dwarves) # "Thiddeal is eating French Fries" "Dwarf is eating Caesar Salad"
9 changes: 9 additions & 0 deletions app/players/dwarves/dwarf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from app.players.player import Player

class Dwarf(Player):
def __init__(self, nickname, favourite_dish):
super().__init__(nickname)
self._favourite_dish = favourite_dish

def eat_favourite_dish(self):
print(f"{self.nickname} is eating {self._favourite_dish}")
12 changes: 12 additions & 0 deletions app/players/dwarves/dwarf_blacksmith.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from app.players.dwarves.dwarf import Dwarf

class DwarfBlacksmith(Dwarf):
def __init__(self, nickname, favourite_dish, skill_level):
super().__init__(nickname, favourite_dish)
self._skill_level = skill_level

def get_rating(self):
return self._skill_level

def player_info(self):
return f"Dwarf blacksmith {self.nickname} with skill of the {self._skill_level} level"
12 changes: 12 additions & 0 deletions app/players/dwarves/dwarf_warrior.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from app.players.dwarves.dwarf import Dwarf

class DwarfWarrior(Dwarf):
def __init__(self, nickname, favourite_dish, hummer_level):
super().__init__(nickname, favourite_dish)
self._hummer_level = hummer_level

def get_rating(self):
return self._hummer_level + 4

def player_info(self):
return f"Dwarf warrior {self.nickname}. {self.nickname} has a hummer of the {self._hummer_level} level"
12 changes: 12 additions & 0 deletions app/players/elves/druid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from app.players.elves.elf import Elf

class Druid(Elf):
def __init__(self, nickname, musical_instrument, favourite_spell):
super().__init__(nickname, musical_instrument)
self._favourite_spell = favourite_spell

def get_rating(self):
return len(self._favourite_spell)

def player_info(self):
return f"Druid {self.nickname}. {self.nickname} has a favourite spell: {self._favourite_spell}"
9 changes: 9 additions & 0 deletions app/players/elves/elf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from app.players.player import Player

class Elf(Player):
def __init__(self, nickname, musical_instrument):
super().__init__(nickname)
self._musical_instrument = musical_instrument

def play_elf_song(self):
print(f"{self.nickname} is playing a song on the {self._musical_instrument}")
12 changes: 12 additions & 0 deletions app/players/elves/elf_ranges.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from app.players.elves.elf import Elf

class ElfRanger(Elf):
def __init__(self, nickname, musical_instrument, bow_level):
super().__init__(nickname, musical_instrument)
self._bow_level = bow_level

def get_rating(self):
return self._bow_level * 3

def player_info(self):
return f"Elf ranger {self.nickname}. {self.nickname} has bow of the {self._bow_level} level"
13 changes: 13 additions & 0 deletions app/players/player.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from abc import ABC, abstractmethod

class Player(ABC):
def __init__(self, nickname):
self.nickname = nickname

@abstractmethod
def get_rating(self):
pass

@abstractmethod
def player_info(self):
pass
151 changes: 17 additions & 134 deletions tests/test_main.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,27 @@
import inspect
import io
from contextlib import redirect_stdout

import pytest
from contextlib import redirect_stdout
import inspect

from app import main
from app.main import calculate_team_total_rating, elves_concert, feast_of_the_dwarves
from app.players.dwarves.dwarf import Dwarf
from app.players.dwarves.dwarf_blacksmith import DwarfBlacksmith
from app.players.dwarves.dwarf_warrior import DwarfWarrior
from app.players.dwarves.dwarf_blacksmith import DwarfBlacksmith
from app.players.elves.druid import Druid
from app.players.elves.elf import Elf
from app.players.elves.elf_ranger import ElfRanger
from app.players.player import Player
from app.players.elves.elf_ranges import ElfRanger


@pytest.mark.parametrize(
"class_,methods",
[
(Player, ["get_rating", "player_info"]),
(Elf, ["get_rating", "player_info", "play_elf_song"]),
(ElfRanger, ["get_rating", "player_info", "play_elf_song"]),
(Druid, ["get_rating", "player_info", "play_elf_song"]),
(Dwarf, ["get_rating", "player_info", "eat_favourite_dish"]),
(DwarfWarrior, ["get_rating", "player_info", "eat_favourite_dish"]),
(DwarfBlacksmith, ["get_rating", "player_info", "eat_favourite_dish"]),
],
)
def test_classes_should_have_corresponding_methods(class_, methods):
def test_classes_should_have_methods(class_, methods):
for method in methods:
assert (
hasattr(class_, method)
), f"Class '{class_.__name__}' should have method {method}"


@pytest.mark.parametrize(
"class_",
[
Player, Elf, Dwarf,
]
)
def test_classes_should_be_abstract(class_):
assert inspect.isabstract(class_), (
f"Class '{class_.__name__}' should be abstract"
)
assert hasattr(class_, method), f"Class '{class_.__name__}' should have method {method}"


@pytest.mark.parametrize(
Expand All @@ -58,21 +36,6 @@ def test_classes_should_not_be_abstract(class_):
)


@pytest.mark.parametrize(
"class_,methods",
[
(Elf, ["get_rating", "player_info"]),
(Dwarf, ["get_rating", "player_info"]),
],
)
def test_abstract_methods_should_not_be_redefined(class_, methods):
for method in methods:
assert (
getattr(class_, method) is getattr(Player, method)
), f"Class '{class_.__name__}' should not redefine " \
f"abstract method '{method}'"


@pytest.mark.parametrize(
"nickname,musical_instrument,bow_level,rating,song,player_info",
[
Expand All @@ -94,14 +57,7 @@ def test_abstract_methods_should_not_be_redefined(class_, methods):
),
]
)
def test_elf_ranger_class(
nickname,
musical_instrument,
bow_level,
rating,
song,
player_info,
):
def test_elf_ranger_class(nickname, musical_instrument, bow_level, rating, song, player_info):
ranger = ElfRanger(
nickname=nickname,
musical_instrument=musical_instrument,
Expand Down Expand Up @@ -136,24 +92,17 @@ def test_elf_ranger_class(
),
]
)
def test_druid_class(
nickname,
musical_instrument,
favourite_spell,
rating,
song,
player_info,
):
ranger = Druid(
def test_druid_class(nickname, musical_instrument, favourite_spell, rating, song, player_info):
druid = Druid(
nickname=nickname,
musical_instrument=musical_instrument,
favourite_spell=favourite_spell
)
assert ranger.get_rating() == rating
assert ranger.player_info() == player_info
assert druid.get_rating() == rating
assert druid.player_info() == player_info
f = io.StringIO()
with redirect_stdout(f):
ranger.play_elf_song()
druid.play_elf_song()
assert f.getvalue() == song


Expand All @@ -178,14 +127,7 @@ def test_druid_class(
),
]
)
def test_dwarf_warrior_class(
nickname,
favourite_dish,
hummer_level,
rating,
eating_message,
player_info,
):
def test_dwarf_warrior_class(nickname, favourite_dish, hummer_level, rating, eating_message, player_info):
warrior = DwarfWarrior(
nickname=nickname,
favourite_dish=favourite_dish,
Expand Down Expand Up @@ -220,14 +162,7 @@ def test_dwarf_warrior_class(
),
]
)
def test_dwarf_blacksmith_class(
nickname,
favourite_dish,
skill_level,
rating,
eating_message,
player_info,
):
def test_dwarf_blacksmith_class(nickname, favourite_dish, skill_level, rating, eating_message, player_info):
blacksmith = DwarfBlacksmith(
nickname=nickname,
favourite_dish=favourite_dish,
Expand All @@ -244,11 +179,8 @@ def test_dwarf_blacksmith_class(
@pytest.mark.parametrize(
"team,rating",
[
([], 0),
(
[Druid(nickname="Druid", musical_instrument="", favourite_spell="aaa")],
3
),
([], 0),
([Druid(nickname="Druid", musical_instrument="", favourite_spell="aaa")], 3),
(
[
Druid(nickname="Druid", musical_instrument="", favourite_spell="aaa"),
Expand All @@ -263,15 +195,6 @@ def test_dwarf_blacksmith_class(
],
16
),
(
[
DwarfWarrior(nickname="Dwarf", favourite_dish="", hummer_level=6),
ElfRanger(nickname="Ranger1", musical_instrument="", bow_level=2),
ElfRanger(nickname="Ranger2", musical_instrument="", bow_level=6),
DwarfBlacksmith(nickname="DwarfBlacksmith", favourite_dish="", skill_level=10),
],
44
),
]
)
def test_calculate_team_total_rating(team, rating):
Expand All @@ -291,18 +214,6 @@ def test_calculate_team_total_rating(team, rating):
"Rothilion is playing a song on the trumpet\n"
)
),
(
[
Druid(nickname="Nardual", musical_instrument="flute", favourite_spell="aaa"),
ElfRanger(nickname="Rothilion", musical_instrument="trumpet", bow_level=33),
Druid(nickname="Faridal", musical_instrument="flute", favourite_spell="aaa"),
],
(
"Nardual is playing a song on the flute\n"
"Rothilion is playing a song on the trumpet\n"
"Faridal is playing a song on the flute\n"
)
),
]
)
def test_elves_concert(elves, songs):
Expand All @@ -325,38 +236,10 @@ def test_elves_concert(elves, songs):
"Dwarf is eating Caesar Salad\n"
)
),
(
[
DwarfWarrior(nickname="Thiddeal", favourite_dish="French Fries", hummer_level=3),
DwarfWarrior(nickname="Dwarf", favourite_dish="Caesar Salad", hummer_level=3),
DwarfWarrior(nickname="Dwarf2", favourite_dish="French Fries", hummer_level=3),
],
(
"Thiddeal is eating French Fries\n"
"Dwarf is eating Caesar Salad\n"
"Dwarf2 is eating French Fries\n"
)
)
]
)
def test_feast_of_the_dwarves(dwarves, feast_output):
f = io.StringIO()
with redirect_stdout(f):
feast_of_the_dwarves(dwarves)
assert f.getvalue() == feast_output


@pytest.mark.parametrize(
"class_",
[
ElfRanger, Druid, DwarfWarrior, DwarfBlacksmith
],
)
def test_some_classes_not_subclass_of_abc(class_):
lines = inspect.getsource(class_)
assert "ABC" not in lines


def test_comment_deleted():
lines = inspect.getsource(main)
assert "# write your code here" not in lines
assert f.getvalue() == feast_output
Loading