1class Material:
2 def __init__(self, mass: int):
3 self.mass = mass
4
5 @property
6 def volume(self):
7 return self.mass / self.density
8
9
10class Concrete(Material):
11 density = 2500
12
13
14class Brick(Material):
15 density = 2000
16
17
18class Stone(Material):
19 density = 1600
20
21
22class Wood(Material):
23 density = 600
24
25
26class Steel(Material):
27 density = 7700
28
29
30class Factory:
31 all_factories = []
32 used_instances = []
33
34 dynamic_classes = {
35 "Concrete": Concrete,
36 "Brick": Brick,
37 "Stone": Stone,
38 "Wood": Wood,
39 "Steel": Steel
40 }
41
42 def __init__(self):
43 self.created_instances = []
44 Factory.all_factories.append(self)
45
46 def __call__(self, *args, **kwargs):
47 if args and kwargs:
48 raise ValueError("Cannot mix positional and keyword arguments.")
49 if not args and not kwargs:
50 raise ValueError("Factory requires arguments.")
51
52 if kwargs:
53 return self._create_named_materials(**kwargs)
54 return self._create_alloy(*args)
55
56 def _create_named_materials(self, **kwargs):
57 results = []
58 for name, mass in kwargs.items():
59 cls = globals().get(name)
60 if cls is None or not issubclass(cls, Material):
61 raise ValueError(f"Invalid material name: {name}")
62
63 instance = cls(mass)
64 self.created_instances.append(instance)
65 results.append(instance)
66
67 return tuple(results)
68
69 def _create_alloy(self, *args):
70 for instance in args:
71 if instance in self.used_instances:
72 raise AssertionError("This material instance has already been used.")
73 self.used_instances.append(instance)
74
75 materials = []
76 for base in args:
77 arr = type(base).__name__.split("_")
78 materials.extend(arr)
79
80 base_classes = sorted(set(self.dynamic_classes[material] for material in materials), key=lambda cls: cls.__name__)
81 class_name = "_".join(base.__name__ for base in base_classes)
82
83 if class_name not in self.dynamic_classes:
84 density = sum(cls.density for cls in base_classes) / len(base_classes)
85 new_class = type(
86 class_name,
87 (Material,),
88 {"density": density}
89 )
90 self.dynamic_classes[class_name] = new_class
91
92 total_mass = sum(instance.mass for instance in args)
93 new_instance = self.dynamic_classes[class_name](total_mass)
94 self.created_instances.append(new_instance)
95 return new_instance
96
97 def can_build(self, target_volume):
98 total_volume = sum(instance.volume for instance in self.created_instances if instance not in self.used_instances)
99 return total_volume >= target_volume
100
101 @classmethod
102 def can_build_together(cls, target_volume):
103 total_volume = 0
104 for factory in cls.all_factories:
105 total_volume += sum(
106 instance.volume for instance in factory.created_instances if instance not in factory.used_instances
107 )
108
109 return total_volume >= target_volume
..E.EF....
======================================================================
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 53, in __call__
return self._create_named_materials(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 61, in _create_named_materials
raise ValueError(f"Invalid material name: {name}")
ValueError: Invalid material name: Brick_Concrete_Steel_Stone_Wood
======================================================================
ERROR: test_named_arguments_with_dynamically_created_classes (test.TestFactory.test_named_arguments_with_dynamically_created_classes)
Test dynamically created classes uniqueness.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 145, in test_named_arguments_with_dynamically_created_classes
result2, = self.factory1(Brick_Concrete_Steel_Stone_Wood=2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 53, in __call__
return self._create_named_materials(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 61, in _create_named_materials
raise ValueError(f"Invalid material name: {name}")
ValueError: Invalid material name: Brick_Concrete_Steel_Stone_Wood
======================================================================
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 54, in __call__
return self._create_alloy(*args)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 72, in _create_alloy
raise AssertionError("This material instance has already been used.")
AssertionError: This material instance has already been used.
----------------------------------------------------------------------
Ran 10 tests in 0.012s
FAILED (failures=1, errors=2)
26.11.2024 14:07
26.11.2024 14:08