1MATERIALS_DENSITIES = {"Concrete" : 2500, "Brick" : 2000, "Stone" : 1600, "Wood" : 600, "Steel" : 7700}
2
3class Material:
4
5 def __init__(self, weight):
6 self.name = type(self).__name__
7 self.weight = weight
8 self.used = False
9 if self.name in MATERIALS_DENSITIES:
10 self.density = MATERIALS_DENSITIES[self.name]
11
12
13 @property
14 def volume(self):
15 if self.used:
16 return 0
17 return float(self.weight / self.density)
18
19 def mark_as_used(self):
20 self.used = True
21
22
23class Concrete(Material):
24 pass
25
26
27class Brick(Material):
28 pass
29
30
31class Stone(Material):
32 pass
33
34
35class Wood(Material):
36 pass
37
38
39class Steel(Material):
40 pass
41
42
43class Factory():
44 MATERIALS = {"Concrete" : Concrete, "Brick" : Brick, "Stone" : Stone, "Wood" : Wood, "Steel" : Steel}
45 dynamicly_created_materials = {}
46 all_instances = []
47
48 def __init__(self):
49 self.current_factory_instances = []
50
51 def __call__(self, *args, **kwargs):
52 if (args and kwargs) or (not args and not kwargs):
53 raise ValueError("Invalid arguments.")
54
55 elif args:
56 return self._create_dynamic_material(*args)
57
58 elif kwargs:
59 result_tuple = ()
60 for name, weight in kwargs.items():
61 if name in self.MATERIALS:
62 material_class = self.MATERIALS[name]
63 elif name in self.dynamicly_created_materials:
64 material_class = self.dynamicly_created_materials[name]
65 else:
66 raise ValueError("Invalid material.")
67 result_tuple += (material_class(weight), )
68 self.current_factory_instances += list(result_tuple)
69 return result_tuple
70
71
72 def _create_dynamic_material(self, *args):
73 for curr_material in args:
74 if not isinstance(curr_material, Material):
75 raise ValueError("Invalid material.")
76 if curr_material.used:
77 raise AssertionError("This material has been used already.")
78 for curr_material in args:
79 curr_material.mark_as_used()
80
81 all_names = [material.name for material in args]
82 split_elements = [name for element in all_names for name in element.split("_")]
83 elements = sorted(split_elements)
84 new_class_name = "_".join(elements)
85 new_weight = sum(material.weight for material in args )
86
87 if new_class_name not in self.dynamicly_created_materials:
88
89 class DynamicMaterial(Material):
90
91 def __init__(self, weight):
92 super().__init__(weight)
93 self.density = sum(MATERIALS_DENSITIES[curr_class_name] for curr_class_name in elements) / len(elements)
94 self.name = new_class_name
95
96 self.dynamicly_created_materials[new_class_name] = DynamicMaterial
97
98 curr_instance = self.dynamicly_created_materials[new_class_name](new_weight)
99 if not curr_instance in Factory.all_instances:
100 Factory.all_instances.append(curr_instance)
101 if not curr_instance in self.current_factory_instances:
102 self.current_factory_instances.append(curr_instance)
103 return curr_instance
104
105 def can_build(self, value):
106 return sum(material.volume for material in self.current_factory_instances) >= value
107
108 @classmethod
109 def can_build_together(cls, value):
110 return sum(material.volume for material in cls.all_instances) >= value
111
112
.F..FFFF..
======================================================================
FAIL: test_can_build (test.TestFactory.test_can_build)
Test can_build methods.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 178, in test_can_build
self.assertTrue(self.factory2.can_build_together(6.0))
AssertionError: False is not true
======================================================================
FAIL: 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 146, in test_named_arguments_with_dynamically_created_classes
self.assertEqual(result1.__class__.__name__,
AssertionError: 'DynamicMaterial' != 'Brick_Concrete_Steel_Stone_Wood'
- DynamicMaterial
+ 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 94, in test_positional_arguments_multiple_argument_from_initial_set
self.assertEqual(result.__class__.__name__, 'Brick_Concrete_Wood')
AssertionError: 'DynamicMaterial' != 'Brick_Concrete_Wood'
- DynamicMaterial
+ Brick_Concrete_Wood
======================================================================
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: 'DynamicMaterial' != 'Brick_Concrete_Steel_Stone_Wood'
- DynamicMaterial
+ Brick_Concrete_Steel_Stone_Wood
======================================================================
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._create_dynamic_material.<locals>.DynamicMaterial'> is not <class 'solution.Concrete'>
----------------------------------------------------------------------
Ran 10 tests in 0.015s
FAILED (failures=5)
26.11.2024 12:57
26.11.2024 12:59
26.11.2024 12:58
26.11.2024 13:00
26.11.2024 13:01
26.11.2024 13:01
26.11.2024 13:02