1#"We're going to build a wall"
2class Material:
3 def __init__(self, mass):
4 if not isinstance(mass, int):
5 raise ValueError("Ти олигофрен ли си, трябва да е цяло число")
6 self.mass = mass
7 self._used = False
8
9 @property
10 def volume(self):
11 return self.mass / self.density
12
13 def mark_as_used(self):
14 if self._used:
15 raise AssertionError("Даже не се и учудвам, че слагаш нещо което е вече сложено")
16 self._used = True
17
18
19class Concrete(Material):
20 density = 2500
21
22
23class Brick(Material):
24 density = 2000
25
26
27class Stone(Material):
28 density = 1600
29
30
31class Wood(Material):
32 density = 600
33
34
35class Steel(Material):
36 density = 7700 #Стоманата не е по-плътна от един венест сникерс
37
38material_classes = {
39 "Concrete": Concrete,
40 "Brick": Brick,
41 "Stone": Stone,
42 "Wood": Wood,
43 "Steel": Steel
44}
45
46class Factory:
47 all_factories = []
48 dynamic_classes = {}
49
50 def __init__(self):
51 self.created_materials = []
52 Factory.all_factories.append(self)
53
54 def __call__(self, *args, **kwargs):
55 if (not args and not kwargs) or (args and kwargs):
56 raise ValueError("Как изобщо се стигна до тук???")
57
58 if kwargs:
59 return self.for_kwargs(kwargs)
60 if args:
61 return self.for_args(args)
62
63 def for_kwargs(self, kwargs):
64 materials = []
65 for name, mass in kwargs.items():
66 if name in material_classes:
67 material_class = material_classes[name]
68 elif name in Factory.dynamic_classes:
69 material_class = Factory.dynamic_classes[name]
70 else:
71 raise ValueError(f"Материал с име '{name}' още не измислен глупчо")
72
73 material_instance = material_class(mass)
74 materials.append(material_instance)
75 self.created_materials.append(material_instance)
76
77 return tuple(materials)
78
79 def for_args(self, args):
80 def extract_base_names(materials):
81 base_names = []
82
83 for material in materials:
84 if "_" in type(material).__name__:
85 base_names.extend(type(material).__name__.split("_"))
86 else:
87 base_names.append(type(material).__name__)
88
89 return sorted(base_names)
90
91 materials = []
92 for material in args:
93 if material._used:
94 raise AssertionError(f"{material} вече е използван да не казвам къде")
95 material.mark_as_used()
96 materials.append(material)
97
98 class_name = "_".join(extract_base_names(materials))
99
100 if class_name not in Factory.dynamic_classes:
101 density = sum(type(current_material).density for current_material in materials) / len(materials)
102
103 class Alloy(Material):
104 pass
105
106 Alloy.density = density
107 Alloy.__name__ = class_name
108 Factory.dynamic_classes[class_name] = Alloy
109
110 alloy_class = Factory.dynamic_classes[class_name]
111 total_mass = sum(material.mass for material in materials)
112 alloy_instance = alloy_class(total_mass)
113
114 self.created_materials.append(alloy_instance)
115 return alloy_instance
116
117 def can_build(self, required_volume):
118
119 total_volume = sum(material.volume for material in self.created_materials if not material._used)
120 return total_volume >= required_volume
121
122 @classmethod
123 def can_build_together(cls, required_volume):
124
125 total_volume = 0
126 for factory in cls.all_factories:
127 total_volume += sum(material.volume for material in factory.created_materials if not material._used)
128
129 return total_volume >= required_volume
.....FFF..
======================================================================
FAIL: test_positional_arguments_multiple_argument_from_initial_set (test.TestFactory.test_positional_arguments_multiple_argument_from_initial_set)
Test calling a factory using multiple positional arguments.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 116, in test_positional_arguments_multiple_argument_from_initial_set
concrete_wood = self.factory1(concrete, wood)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 61, in __call__
return self.for_args(args)
^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 94, in for_args
raise AssertionError(f"{material} вече е използван да не казвам къде")
AssertionError: <solution.Concrete object at 0x792c38ada690> вече е използван да не казвам къде
======================================================================
FAIL: test_positional_arguments_multiple_argument_with_dynamics (test.TestFactory.test_positional_arguments_multiple_argument_with_dynamics)
Test calling a factory using multiple positional arguments.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 130, in test_positional_arguments_multiple_argument_with_dynamics
self.assertAlmostEqual(mega_material.volume, 6.77, places=2) # mass=19500, density=2880
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 5.661290322580645 != 6.77 within 2 places (1.1087096774193546 difference)
======================================================================
FAIL: test_positional_arguments_single_argument (test.TestFactory.test_positional_arguments_single_argument)
Test calling a factory using a sigle positional argument.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 80, in test_positional_arguments_single_argument
self.assertIs(type(concrete2), solution.Concrete)
AssertionError: <class 'solution.Factory.for_args.<locals>.Alloy'> is not <class 'solution.Concrete'>
----------------------------------------------------------------------
Ran 10 tests in 0.011s
FAILED (failures=3)
26.11.2024 17:32
26.11.2024 17:33
26.11.2024 17:33
26.11.2024 17:34