1class Concrete:
2 density = 2500
3
4 def __init__(self, mass):
5 self.mass = mass
6
7 @property
8 def volume(self):
9 return self.mass / self.density
10
11
12class Brick:
13 density = 2000
14
15 def __init__(self, mass):
16 self.mass = mass
17
18 @property
19 def volume(self):
20 return self.mass / self.density
21
22
23class Stone:
24 density = 1600
25
26 def __init__(self, mass):
27 self.mass = mass
28
29 @property
30 def volume(self):
31 return self.mass / self.density
32
33
34class Wood:
35 density = 600
36
37 def __init__(self, mass):
38 self.mass = mass
39
40 @property
41 def volume(self):
42 return self.mass / self.density
43
44
45class Steel:
46 density = 7700
47
48 def __init__(self, mass):
49 self.mass = mass
50
51 @property
52 def volume(self):
53 return self.mass / self.density
54
55
56class Factory:
57 global_materials_dict = {cls.__name__: cls for cls in [Concrete, Brick, Stone, Wood, Steel]}
58 all_created_objects = []
59
60 def __init__(self):
61 self.materials_dict = Factory.global_materials_dict.copy()
62
63 self.used_objects = set()
64
65 self.created_objects = []
66
67 Factory.all_created_objects.append(self.created_objects)
68
69 def __call__(self, *args, **kwargs):
70 if args and kwargs:
71 raise ValueError("Do not mix positional and keyword arguments.")
72
73 if not args and not kwargs:
74 raise ValueError("Must be called with arguments.")
75
76 if kwargs:
77 result = []
78
79 for name, mass in kwargs.items():
80 if name not in self.materials_dict:
81 raise ValueError(f"Unknown material: {name}")
82
83 material_class = self.materials_dict[name]
84
85 obj = material_class(mass)
86
87 self.created_objects.append(obj)
88 result.append(obj)
89
90 return tuple(result)
91
92 if args:
93 base_materials = set()
94 total_mass = 0
95
96 for material in args:
97 if material in self.used_objects:
98 raise AssertionError("Material has already been used.")
99
100 arg_class_name = material.__class__.__name__
101
102 base_materials.add(arg_class_name)
103
104 total_mass += material.mass
105
106 self.used_objects.update(args)
107
108 class_name = "_".join(sorted(base_materials))
109
110 if class_name not in Factory.global_materials_dict:
111 if arg_class_name not in self.materials_dict:
112 return
113
114 average_density = sum(self.materials_dict[name].density for name in base_materials) / len(base_materials)
115
116 new_class = type(
117 class_name,
118 (object,),
119 {
120 "density": average_density,
121 "__init__": lambda self, mass: setattr(self, "mass", mass),
122 "volume": property(lambda self: self.mass / self.density),
123 },
124 )
125
126 Factory.global_materials_dict[class_name] = new_class
127
128 self.materials_dict[class_name] = new_class
129
130 obj = self.materials_dict[class_name](total_mass)
131
132 self.created_objects.append(obj)
133
134 return obj
135
136 def can_build(self, required_volume):
137 total_volume = sum(obj.volume for obj in self.created_objects)
138
139 return total_volume >= required_volume
140
141 @classmethod
142 def can_build_together(cls, required_volume):
143 total_volume = sum(obj.volume for created_objects in cls.all_created_objects for obj in created_objects)
144
145 return total_volume >= required_volume
.FE...F...
======================================================================
ERROR: test_materials_between_factories (test.TestFactory.test_materials_between_factories)
Test materials sharing.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 156, in test_materials_between_factories
result2, = self.factory2(Brick_Concrete_Steel_Stone_Wood=2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 81, in __call__
raise ValueError(f"Unknown material: {name}")
ValueError: Unknown material: Brick_Concrete_Steel_Stone_Wood
======================================================================
FAIL: test_can_build (test.TestFactory.test_can_build)
Test can_build methods.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 175, in test_can_build
self.assertFalse(self.factory2.can_build(4.0001))
AssertionError: True is not false
======================================================================
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 128, in test_positional_arguments_multiple_argument_with_dynamics
self.assertEqual(mega_material.__class__.__name__,
AssertionError: 'Brick_Concrete_Stone_Steel_Wood' != 'Brick_Concrete_Steel_Stone_Wood'
- Brick_Concrete_Stone_Steel_Wood
? ------
+ Brick_Concrete_Steel_Stone_Wood
? ++++++
----------------------------------------------------------------------
Ran 10 tests in 0.010s
FAILED (failures=2, errors=1)
24.11.2024 17:08
24.11.2024 17:07
24.11.2024 17:16
24.11.2024 17:22
24.11.2024 17:07