Skip to content
Snippets Groups Projects
Commit 11a86cfd authored by Thomas Röck's avatar Thomas Röck
Browse files

v_3_2

parent e7ced56e
No related branches found
No related tags found
No related merge requests found
from exceptions import DeadPlantError
from plant import Plant
class Bed:
_WATERING_THRESHOLD = 5
def __init__(self, location: str) -> None:
self.location = location
self._plants = []
self.water_level = 0
def __repr__(self) -> str:
return f"Bed {self.location}"
def __str__(self) -> str:
return (f"{self!r}\n"
f"Water level: {self.water_level}\n"
f"{len(self.plants)} plants: {[p.species for p in self.plants]}")
@property
def water_level(self) -> int:
return self._water_level
@water_level.setter
def water_level(self, water_level: int):
if water_level < 0:
raise ValueError(f"No more water in {self!r}.")
self._water_level = water_level
@property
def plants(self) -> list:
return self._plants
@plants.deleter
def plants(self):
self._plants.clear()
@property
def needs_water(self) -> bool:
return self.water_level < self._WATERING_THRESHOLD
def plant_plant(self, plant: Plant) -> None:
self.plants.append(plant)
def water(self, added_water: int = 1) -> None:
self.water_level += added_water
def update(self) -> None:
for plant in self.plants:
try:
self.water_level -= 1
plant.grow()
except ValueError:
print(f"{self!r} is out of water, plants can't grow")
return
except DeadPlantError:
print(f"{plant!r} in {self!r} is dead and should be removed quickly!")
def harvest(self) -> list:
harvested = []
for plant in self.plants:
harvested.extend(plant.harvest())
return harvested
class NoMoreFruitsError(Exception):
pass
class DeadPlantError(Exception):
pass
from dataclasses import dataclass
@dataclass
class Fruit:
name: str
calories: int
# %% Imports
from bed import Bed
from fruit import Fruit
from plant import FruitBearingPlant, RootVegetable
# from root import Root
# %% Create objects
plants = [FruitBearingPlant("strawberry", 3, Fruit("strawberry", 33)),
FruitBearingPlant("tomato", 4, Fruit("tomato", 16))]
bed = Bed("in the garden")
# Let's call some methods
c = " >" # cursor
# Method: __str__
print(" Bed Methods ".center(79, "-"))
print(c, "Print informal string representation of <bed>\n")
print(bed, end="\n\n")
# Property: needs_water
print(c, "<bed> needs water?\n")
print(bed.needs_water, end='\n\n')
# Method: water
amount = 9
print(c, f"Water <bed> (amount={amount})\n")
bed.water(amount)
print(bed, end="\n\n")
# Method: plant_plant
print(c, f"Plant plants {plants}\n") # For every plant in the list, the formal string repr. is called (__repr__)
for plant in plants:
bed.plant_plant(plant)
print(f"Planting {plant}") # this calls the informal string representation of the plant
print(f"\n{bed}")
# %%
# bed.water(amount - bed.water_level)
# Method: update
periods = amount // len(plants) # this is the operator for a floor division
print(c, f"Update bed for {periods} periods\n")
for _ in range(periods):
bed.update()
print(f"Plants: {[str(plant) for plant in bed.plants]}\n")
print(bed, end="\n\n")
# Property: water_level.setter
print(c, "Update <bed> and check water_level\n")
bed.update()
print(f"Plants: {[str(plant) for plant in bed.plants]}\n")
# Method: harvest
print(c, "Harvest <bed>\n")
bed_yield = bed.harvest()
print(f"yield: {bed_yield}\n")
print(bed, end="\n\n")
# %%
# Same as above without prints
plants = [FruitBearingPlant("strawberry", 3, Fruit("strawberry", 33)),
FruitBearingPlant("tomato", 4, Fruit("tomato", 16)),
RootVegetable("carrot", 1.2, 77, 2)]
bed = Bed("in the garden")
amount = 20
bed.water(amount)
for plant in plants:
bed.plant_plant(plant)
periods = amount // len(plants)
for _ in range(periods):
bed.update()
bed.update()
bed_yield = bed.harvest()
# %%
bed_yield
# %%
import random
from abc import ABC, abstractmethod
from copy import copy
from exceptions import DeadPlantError, NoMoreFruitsError
from fruit import Fruit
from root import Root
class Plant(ABC):
def __init__(self, species: str, growth_factor: float):
self.species = species
self.growth_factor = growth_factor
self._size = 1
self.dead = False
def __repr__(self):
return f"{self.species}"
def __str__(self):
return f"{self.species} of size {self.size:.1f}"
@property
def growth_factor(self):
return self._growth_factor
@growth_factor.setter
def growth_factor(self, growth_factor: float):
if growth_factor <= 1:
raise ValueError(f"Invalid growth_factor: {growth_factor} (>1 required)")
self._growth_factor = growth_factor
@property
def size(self):
return self._size
def grow(self) -> None:
if self.dead:
raise DeadPlantError("{self} is dead, it can't grow")
self._size *= self.growth_factor
@abstractmethod
def harvest(self) -> list:
raise NotImplementedError
class FruitBearingPlant(Plant):
def __init__(self, species: str, growth_factor: float, fruit_template: Fruit):
super().__init__(species, growth_factor)
self.fruit_template = fruit_template
self._fruits = []
def __str__(self):
return f"{self.species} of size {self.size:.1f} with {len(self.fruits)} fruits"
@property
def fruits(self):
return self._fruits
@fruits.deleter
def fruits(self):
self._fruits.clear()
def grow(self) -> None:
super().grow()
if random.randrange(100) < self.size:
self.fruits.append(copy(self.fruit_template))
def pick(self) -> Fruit:
if not self.fruits:
raise NoMoreFruitsError(f"{self} is empty, you can't pick any more fruits :(")
return self.fruits.pop()
def harvest(self) -> list:
harvested = []
while True:
try:
harvested.append(self.pick())
except NoMoreFruitsError:
return harvested
class RootVegetable(Plant):
def __init__(self,
species: str,
growth_factor: float,
calories_per_root_length: int,
plant_size_to_root_length_factor: float):
super().__init__(species, growth_factor)
self._root = Root(self.species, calories_per_root_length)
self._plant_size_to_root_length_factor = plant_size_to_root_length_factor
def grow(self):
super().grow()
self._root.length = self._size * self._plant_size_to_root_length_factor
def harvest(self) -> list:
self.dead = True
if self._root is None:
return []
harvested = [self._root]
self._root = None
return harvested
from dataclasses import dataclass
@dataclass
class Root:
name: str
calories_per_length: int
length: float = 0.0
@property
def calories(self) -> float:
return self.calories_per_length * self.length
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment