]> Untitled Git - axy/ft/python01.git/commitdiff
Simple things done complexly i love this subject
authorAxy <gilliardmarthey.axel@gmail.com>
Wed, 7 Jan 2026 15:28:47 +0000 (16:28 +0100)
committerAxy <gilliardmarthey.axel@gmail.com>
Wed, 7 Jan 2026 15:28:47 +0000 (16:28 +0100)
ex2/ft_plant_growth.py
ex3/ft_plant_factory.py
ex4/ft_garden_security.py
ex5/ft_plant_types.py
ex6/ft_garden_analytics.py [new file with mode: 0644]

index 576959505fedb019cf26eab20e63f5199b2f9532..62e44fc8c746a4542bee5c81d9755e43e46d701c 100644 (file)
@@ -15,10 +15,10 @@ class Plant:
             + f"{self.age_days} days old"
         )
 
-    def grow(self, by_cm: int):
+    def grow(self, by_cm: int) -> None:
         self.height_cm += by_cm
 
-    def age(self, by_days: int):
+    def age(self, by_days: int) -> None:
         # We assume a growth rate of 1cm per day
         self.grow(by_days)
         self.age_days += by_days
index f64a217a29cd05b49824d29a430e95a5378801ed..fa1628921f9ec4af71195f99e74713a02b165021 100644 (file)
@@ -15,20 +15,17 @@ class Plant:
             + f"{self.age_days} days old"
         )
 
-    def grow(self, by_cm: int):
+    def grow(self, by_cm: int) -> None:
         self.height_cm += by_cm
 
-    def age(self, by_days: int):
+    def age(self, by_days: int) -> None:
         # We assume a growth rate of 1cm per day
         self.grow(by_days)
         self.age_days += by_days
 
 
 class PlantFactory:
-    plants: list[Plant]
-
-    def __init__(self):
-        self.plants = []
+    plants: list[Plant] = []
 
     def create(self, name: str, height_cm: int, age_days: int) -> Plant:
         plant = Plant(name, height_cm, age_days)
index ae69fb56df4741375bba40267d26e42f50d64f59..a908d95491e50ea47acb4e0d9d05c3626ff932a0 100644 (file)
@@ -13,15 +13,15 @@ class SecurePlant:
         return f"{self.__name}: ({self.__height_cm}cm, {self.__age_days} days)"
 
     @staticmethod
-    def __reject_with_message(operation: str, msg: str):
+    def __reject_with_message(operation: str, msg: str) -> None:
         print(f"\nInvalid operation attempted: {operation} [REJECTED]")
         print(f"Security: {msg}")
 
     @staticmethod
-    def __accept_update(field: str, value: str):
+    def __accept_update(field: str, value: str) -> None:
         print(f"{field} updated: {value} [OK]")
 
-    def set_height(self, height_cm: int):
+    def set_height(self, height_cm: int) -> None:
         if height_cm < 0:
             self.__reject_with_message(
                 f"height {height_cm}cm", "Negative height rejected"
@@ -30,7 +30,7 @@ class SecurePlant:
             self.__accept_update("Height", f"{height_cm}cm")
             self.__height_cm = height_cm
 
-    def set_age(self, age_days: int):
+    def set_age(self, age_days: int) -> None:
         if age_days < 0:
             self.__reject_with_message(
                 f"age {age_days} days", "Negative age rejected"
index d94d822c1225c8b4dd2b48915d05debfeb90e245..a1448c0a2d8b740bf41c974602308acd034d720c 100644 (file)
@@ -30,7 +30,7 @@ class Plant:
             ", ", self.get_attributes()
         )
 
-    def action(self):
+    def action(self) -> None:
         pass
 
 
@@ -47,10 +47,10 @@ class Flower(Plant):
     def get_attributes(self) -> list[str]:
         return super().get_attributes() + [f"{self.color} color"]
 
-    def bloom(self):
+    def bloom(self) -> None:
         print(f"{self.name} is blooming beautifully!")
 
-    def action(self):
+    def action(self) -> None:
         self.bloom()
 
 
@@ -59,7 +59,7 @@ class Tree(Plant):
 
     def __init__(
         self, name: str, height_cm: int, age_days: int, trunk_diameter_cm: int
-    ):
+    ) -> None:
         super().__init__(name, height_cm, age_days)
         self.trunk_diameter_cm = trunk_diameter_cm
 
@@ -71,11 +71,11 @@ class Tree(Plant):
             f"{self.trunk_diameter_cm}cm diameter"
         ]
 
-    def produce_shade(self):
+    def produce_shade(self) -> None:
         shade = round(self.trunk_diameter_cm * self.height_cm / 3.2 / 100)
         print(f"{self.name} provides {shade} square meters of shade")
 
-    def action(self):
+    def action(self) -> None:
         self.produce_shade()
 
 
@@ -90,7 +90,7 @@ class Vegetable(Plant):
         age_days: int,
         harvest_season: str,
         nutritional_value: str,
-    ):
+    ) -> None:
         super().__init__(name, height_cm, age_days)
         self.harvest_season = harvest_season
         self.nutritional_value = nutritional_value
@@ -101,10 +101,10 @@ class Vegetable(Plant):
     def get_attributes(self) -> list[str]:
         return super().get_attributes() + [f"{self.harvest_season} harvest"]
 
-    def nutritional_info(self):
+    def nutritional_info(self) -> None:
         print(f"{self.name} is rich in {self.nutritional_value}")
 
-    def action(self):
+    def action(self) -> None:
         self.nutritional_info()
 
 
diff --git a/ex6/ft_garden_analytics.py b/ex6/ft_garden_analytics.py
new file mode 100644 (file)
index 0000000..5f704d2
--- /dev/null
@@ -0,0 +1,213 @@
+def join(sep: str, elements: list[str]) -> str:
+    res: str | None = None
+    for s in elements:
+        if res is None:
+            res = s
+        else:
+            res += sep + s
+    if res is not None:
+        return res
+    return ""
+
+
+class Plant:
+    __name: str
+    __height_cm: int = 0
+
+    def __init__(self, name: str, height_cm: int) -> None:
+        self.__name = name.capitalize()
+        if height_cm >= 0:
+            self.__height_cm = height_cm
+        else:
+            print("[Warning] attempted to instantiate plant with bad height")
+            print("[Warning] defaulting to 0")
+
+    def get_attributes(self) -> list[str]:
+        return [f"{self.__height_cm}cm"]
+
+    def get_type(self) -> str:
+        return "regular"
+
+    def __repr__(self) -> str:
+
+        return f"{self.__name}: " + join(", ", self.get_attributes())
+
+    def get_name(self) -> str:
+        return self.__name
+
+    def get_height(self) -> int:
+        return self.__height_cm
+
+    def grow(self) -> int:
+        """returns the number of centimeters gained"""
+        self.__height_cm += 1
+        print(f"{self.get_name()} grew 1cm")
+        return 1
+
+
+class FloweringPlant(Plant):
+    color: str
+
+    def __init__(self, name: str, height_cm: int, color: str) -> None:
+        super().__init__(name, height_cm)
+        self.color = color
+
+    def get_attributes(self) -> list[str]:
+        return super().get_attributes() + [f"{self.color} flowers (blooming)"]
+
+    def get_type(self) -> str:
+        return "flowering"
+
+
+class PrizeFlower(FloweringPlant):
+    __prize_points: int
+
+    def __init__(
+        self, name: str, height_cm: int, color: str, prize_points: int
+    ) -> None:
+        super().__init__(name, height_cm, color)
+        self.__prize_points = prize_points
+
+    def get_attributes(self) -> list[str]:
+        return super().get_attributes() + [
+            f"Prize points: {self.__prize_points}"
+        ]
+
+    def get_prize_points(self) -> int:
+        return self.__prize_points
+
+    def get_type(self) -> str:
+        return "prize flowers"
+
+
+class Garden:
+    class GardenReport:
+        new_plants: int = 0
+        growth: int = 0
+
+        @staticmethod
+        def count_types(plants: list[Plant]) -> dict[str, int]:
+            res = {}
+            for plant in plants:
+                if plant.get_type() in res:
+                    res[plant.get_type()] += 1
+                else:
+                    res[plant.get_type()] = 1
+            return res
+
+        def update_growth(self, growth: int) -> None:
+            self.growth += growth
+
+        def update_plant_count(self, count: int) -> None:
+            self.new_plants += count
+
+        def finish(self, plants: list[Plant]) -> str:
+            types = join(
+                ", ",
+                [
+                    f"{n} {kind}"
+                    for (kind, n) in self.count_types(plants).items()
+                ],
+            )
+            return (
+                f"Plants added: {self.new_plants}, "
+                + f"Total growth: {self.growth}cm\n"
+                + f"Plant types: {types}"
+            )
+
+    plants: list[Plant]
+    report: GardenReport
+
+    def __init__(self) -> None:
+        self.plants = []
+        self.report = self.GardenReport()
+
+    def add_plant(self, plant: Plant) -> None:
+        self.plants += [plant]
+        self.report.update_plant_count(1)
+
+    def grow_all(self) -> None:
+        for plant in self.plants:
+            self.report.update_growth(plant.grow())
+
+    def next_report(self) -> str:
+        report = self.report.finish(self.plants)
+        self.report = self.GardenReport()
+        return (
+            f"Plants in garden:\n"
+            + join("", [f"- {plant}\n" for plant in self.plants])
+            + f"\n{report}"
+        )
+
+
+class GardenManager:
+    class GardenStats:
+        @staticmethod
+        def compute_scores(gardens: dict[str, Garden]) -> dict[str, int]:
+            def compute_score(garden: Garden) -> int:
+                res = 0
+                for plant in garden.plants:
+                    if type(plant) is PrizeFlower:
+                        res += plant.get_prize_points()
+                return res
+
+            res = {}
+            for k, v in gardens.items():
+                res[k] = compute_score(v)
+            return res
+
+        @staticmethod
+        def format_scores(scores: dict[str, int]) -> str:
+            return "Garden scores - " + join(
+                ", ", [f"{owner}: {n}" for (owner, n) in scores.items()]
+            )
+
+    __gardens: dict[str, Garden] = {}
+
+    def grow_garden(self, owner: str) -> None:
+        print(f"\n{owner} is helping all plants grow...")
+        self.__gardens[owner].grow_all()
+
+    def add_plant(self, owner: str, plant: Plant) -> None:
+        if owner not in self.__gardens:
+            self.__gardens[owner] = Garden()
+        self.__gardens[owner].add_plant(plant)
+        print(f"Added {plant.get_name()} to {owner}'s garden")
+
+    def print_report(self, owner: str) -> None:
+        print(
+            f"\n=== {owner}'s Garden Report ===\n"
+            + self.__gardens[owner].next_report()
+        )
+
+    @staticmethod
+    def create_garden_network(gardens: dict[str, Garden]):
+        res = GardenManager()
+        res.__gardens = gardens
+        for garden in res.__gardens.values():
+            garden.next_report()
+        return res
+
+    def print_stats(self) -> None:
+        scores = self.GardenStats.compute_scores(self.__gardens)
+        print()
+        print(self.GardenStats.format_scores(scores))
+        print(f"Total gardens managed: {len(self.__gardens)}")
+
+
+if __name__ == "__main__":
+    print("=== Garden Management System Demo ===\n")
+
+    manager = GardenManager.create_garden_network({"Alice": Garden()})
+
+    manager.add_plant("Alice", PrizeFlower("sunflower", 80, "yellow", 12))
+    manager.add_plant("Alice", FloweringPlant("violet", 8, "blue"))
+    manager.add_plant("Alice", Plant("oak tree", 410))
+    manager.add_plant("Bob", PrizeFlower("rose", 40, "red", 18))
+
+    manager.grow_garden("Alice")
+    manager.print_report("Alice")
+    manager.print_report("Bob")
+
+    print("=== Garden Network Stats ===")
+    manager.print_stats()