1class Material:
2 def __init__(self, mass: int):
3 self.mass = mass
4 self.__used = False
5
6 @property
7 def volume(self) -> float:
8 return self.mass / self.density
9
10 def mark_as_used(self):
11 self.__used = True
12
13 def is_used(self):
14 return self.__used
15
16
17class Concrete(Material):
18 density = 2500
19
20
21class Brick(Material):
22 density = 2000
23
24
25class Stone(Material):
26 density = 1600
27
28
29class Wood(Material):
30 density = 600
31
32
33class Steel(Material):
34 density = 7700
35
36
37class Factory:
38 def __init__(self):
39 self._existing_classes = {
40 'Concrete': Concrete,
41 'Brick': Brick,
42 'Stone': Stone,
43 'Wood': Wood,
44 'Steel': Steel,
45 }
46 self._created_instances = []
47 self._dynamic_classes = {}
48
49 def __call__(self, *args, **kwargs):
50 if kwargs and args:
51 raise ValueError("ValueError с произволен текст.")
52
53 if kwargs:
54 return self._create_materials_by_name(kwargs)
55
56 if args:
57 return self._create_materials_by_instance(args)
58
59 raise ValueError("ValueError с произволен текст.")
60
61 def _create_materials_by_name(self, materials: dict):
62 result = []
63 for name, mass in materials.items():
64 if name not in self._existing_classes:
65 raise ValueError("ValueError с произволен текст.")
66
67 material_class = self._existing_classes[name]
68 instance = material_class(mass)
69 result.append(instance)
70 self._created_instances.append(instance)
71
72 return tuple(result)
73
74 def _create_materials_by_instance(self, materials: tuple):
75 self._validate_materials(materials)
76 self._mark_materials_as_used(materials)
77 class_name = self._generate_class_name(materials)
78 alloy_class = self._get_or_create_alloy_class(class_name, materials)
79 total_mass = self._calculate_total_mass(materials)
80 instance = alloy_class(total_mass)
81 self._created_instances.append(instance)
82 return instance
83
84 def _validate_materials(self, materials):
85 for material in materials:
86 if material.is_used():
87 raise AssertionError("Material вече е използван.")
88 if not isinstance(material, Material):
89 raise ValueError("ValueError с произволен текст.")
90
91 def _mark_materials_as_used(self, materials):
92 for material in materials:
93 material.mark_as_used()
94
95 def _generate_class_name(self, materials):
96 return "_".join(sorted(material.__class__.__name__ for material in materials))
97
98 def _get_or_create_alloy_class(self, class_name, materials):
99 if class_name in self._dynamic_classes:
100 return self._dynamic_classes[class_name]
101
102 avg_density = self._calculate_average_density(materials)
103 alloy_class = type(
104 class_name,
105 (Material,),
106 {
107 'density': avg_density,
108 },
109 )
110 self._dynamic_classes[class_name] = alloy_class
111 return alloy_class
112
113 def _calculate_average_density(self, materials):
114 return sum(material.density for material in materials) / len(materials)
115
116 def _calculate_total_mass(self, materials):
117 return sum(material.mass for material in materials)
118
119 def can_build(self, volume_needed: float) -> bool:
120 total_volume = sum(material.volume for material in self._created_instances if not material.is_used())
121 print(f"Total unused volume: {total_volume}, Required volume: {volume_needed}")
122 return total_volume >= volume_needed
.E
Stdout:
Total unused volume: 2.0, Required volume: 2.000001
Total unused volume: 2.0, Required volume: 2.0
Total unused volume: 4.0, Required volume: 4.0001
Total unused volume: 4.0, Required volume: 4.0
E.E.FF..
======================================================================
ERROR: test_can_build (test.TestFactory.test_can_build)
Test can_build methods.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 177, in test_can_build
self.assertFalse(solution.Factory.can_build_together(6.0001))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: type object 'Factory' has no attribute 'can_build_together'
Stdout:
Total unused volume: 2.0, Required volume: 2.000001
Total unused volume: 2.0, Required volume: 2.0
Total unused volume: 4.0, Required volume: 4.0001
Total unused volume: 4.0, Required volume: 4.0
======================================================================
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 54, in __call__
return self._create_materials_by_name(kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 65, in _create_materials_by_name
raise ValueError("ValueError с произволен текст.")
ValueError: ValueError с произволен текст.
======================================================================
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 54, in __call__
return self._create_materials_by_name(kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 65, in _create_materials_by_name
raise ValueError("ValueError с произволен текст.")
ValueError: ValueError с произволен текст.
======================================================================
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
? ++++++
======================================================================
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.Concrete'> is not <class 'solution.Concrete'>
----------------------------------------------------------------------
Ran 10 tests in 0.017s
FAILED (failures=2, errors=3)
Виктор Бечев
26.11.2024 16:34Решението изглежда прилично разбито и спретнато, но надявам се знаеш, че ти липсва един от методите по условие - `can_build_together`.
|
26.11.2024 16:32