1class Material:
2 def __init__(self, mass):
3 self.mass = mass
4 self.used = False
5
6 @property
7 def volume(self):
8 return self.mass / self.density
9
10
11class Concrete(Material):
12 density = 2500
13
14
15class Brick(Material):
16 density = 2000
17
18
19class Stone(Material):
20 density = 1600
21
22
23class Wood(Material):
24 density = 600
25
26
27class Steel(Material):
28 density = 7700
29
30
31class Factory:
32 all_factories = []
33
34 known_materials = {
35 'Concrete': Concrete,
36 'Brick': Brick,
37 'Stone': Stone,
38 'Wood': Wood,
39 'Steel': Steel
40 }
41
42 def __init__(self):
43 self.created = []
44 Factory.all_factories.append(self)
45
46 def __call__(self, *args, **kargs):
47 """This method is not long, it's monumental."""
48 if args and kargs or not args and not kargs:
49 raise ValueError
50
51 if kargs:
52 result = []
53 for material_name, mass in kargs.items():
54 if material_name not in Factory.known_materials:
55 raise ValueError(f"Unknown material: {material_name}")
56
57 material = Factory.known_materials[material_name]
58 self.created.append(Factory.known_materials[material_name](mass))
59 result.append(material(mass))
60
61 return tuple(result)
62
63 if args:
64 for material in args:
65 if material.__class__.__name__ not in Factory.known_materials:
66 raise ValueError(f"Unknown material: {material_name}")
67
68 for material in args:
69 if material.used:
70 raise AssertionError
71
72 for material in args:
73 material.used = True
74
75 for material in self.created:
76 for names in args:
77 if material.__class__.__name__ is names.__class__.__name__:
78 material.used = True
79
80 material_name = []
81
82 for material in args:
83 material_name.append(material.__class__.__name__)
84
85 new_material_name = '_'.join(material_name)
86
87 material_mass = sum(material.mass for material in args)
88
89 if new_material_name in Factory.known_materials:
90 self.created.append(Factory.known_materials[new_material_name](material_mass))
91 return Factory.known_materials[new_material_name](material_mass)
92
93 original_materials_names = new_material_name.split('_')
94
95 material_density = 0
96 for material in original_materials_names:
97 material_density += Factory.known_materials[material].density
98
99 material_density /= len(original_materials_names)
100
101 new_material = type(new_material_name, (Material,), {
102 'density': material_density,
103 })
104
105 Factory.known_materials[new_material_name] = new_material
106 self.created.append(Factory.known_materials[new_material_name](material_mass))
107
108 return new_material(material_mass)
109
110 def get_total_volume(self):
111 total_volume = 0
112 for materials in self.created:
113 if materials.used is False:
114 total_volume += materials.volume
115 return total_volume
116
117 def can_build(self, volume_needed):
118 return self.get_total_volume() >= volume_needed
119
120 @classmethod
121 def can_build_together(cls, volume_needed):
122 total_volume = 0
123
124 for factories in cls.all_factories:
125 total_volume += factories.get_total_volume()
126 return total_volume >= volume_needed
..E.EFF...
======================================================================
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 55, in __call__
raise ValueError(f"Unknown material: {material_name}")
ValueError: Unknown material: 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 55, in __call__
raise ValueError(f"Unknown material: {material_name}")
ValueError: Unknown material: 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: 'Wood_Brick_Concrete' != 'Brick_Concrete_Wood'
- Wood_Brick_Concrete
? -----
+ 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: 'Steel_Stone_Concrete_Brick_Wood' != 'Brick_Concrete_Steel_Stone_Wood'
- Steel_Stone_Concrete_Brick_Wood
+ Brick_Concrete_Steel_Stone_Wood
----------------------------------------------------------------------
Ran 10 tests in 0.010s
FAILED (failures=2, errors=2)
| f | 1 | class Material: | f | 1 | class Material: |
| 2 | def __init__(self, mass): | 2 | def __init__(self, mass): | ||
| 3 | self.mass = mass | 3 | self.mass = mass | ||
| 4 | self.used = False | 4 | self.used = False | ||
| 5 | 5 | ||||
| 6 | @property | 6 | @property | ||
| 7 | def volume(self): | 7 | def volume(self): | ||
| 8 | return self.mass / self.density | 8 | return self.mass / self.density | ||
| 9 | 9 | ||||
| 10 | 10 | ||||
| 11 | class Concrete(Material): | 11 | class Concrete(Material): | ||
| 12 | density = 2500 | 12 | density = 2500 | ||
| 13 | 13 | ||||
| 14 | 14 | ||||
| 15 | class Brick(Material): | 15 | class Brick(Material): | ||
| 16 | density = 2000 | 16 | density = 2000 | ||
| 17 | 17 | ||||
| 18 | 18 | ||||
| 19 | class Stone(Material): | 19 | class Stone(Material): | ||
| 20 | density = 1600 | 20 | density = 1600 | ||
| 21 | 21 | ||||
| 22 | 22 | ||||
| 23 | class Wood(Material): | 23 | class Wood(Material): | ||
| 24 | density = 600 | 24 | density = 600 | ||
| 25 | 25 | ||||
| 26 | 26 | ||||
| 27 | class Steel(Material): | 27 | class Steel(Material): | ||
| 28 | density = 7700 | 28 | density = 7700 | ||
| 29 | 29 | ||||
| 30 | 30 | ||||
| 31 | class Factory: | 31 | class Factory: | ||
| 32 | all_factories = [] | 32 | all_factories = [] | ||
| 33 | 33 | ||||
| 34 | known_materials = { | 34 | known_materials = { | ||
| 35 | 'Concrete': Concrete, | 35 | 'Concrete': Concrete, | ||
| 36 | 'Brick': Brick, | 36 | 'Brick': Brick, | ||
| 37 | 'Stone': Stone, | 37 | 'Stone': Stone, | ||
| 38 | 'Wood': Wood, | 38 | 'Wood': Wood, | ||
| 39 | 'Steel': Steel | 39 | 'Steel': Steel | ||
| 40 | } | 40 | } | ||
| 41 | 41 | ||||
| 42 | def __init__(self): | 42 | def __init__(self): | ||
| 43 | self.created = [] | 43 | self.created = [] | ||
| 44 | Factory.all_factories.append(self) | 44 | Factory.all_factories.append(self) | ||
| 45 | 45 | ||||
| 46 | def __call__(self, *args, **kargs): | 46 | def __call__(self, *args, **kargs): | ||
| 47 | """This method is not long, it's monumental.""" | 47 | """This method is not long, it's monumental.""" | ||
| 48 | if args and kargs or not args and not kargs: | 48 | if args and kargs or not args and not kargs: | ||
| 49 | raise ValueError | 49 | raise ValueError | ||
| 50 | 50 | ||||
| 51 | if kargs: | 51 | if kargs: | ||
| 52 | result = [] | 52 | result = [] | ||
| 53 | for material_name, mass in kargs.items(): | 53 | for material_name, mass in kargs.items(): | ||
| 54 | if material_name not in Factory.known_materials: | 54 | if material_name not in Factory.known_materials: | ||
| 55 | raise ValueError(f"Unknown material: {material_name}") | 55 | raise ValueError(f"Unknown material: {material_name}") | ||
| 56 | 56 | ||||
| 57 | material = Factory.known_materials[material_name] | 57 | material = Factory.known_materials[material_name] | ||
| 58 | self.created.append(Factory.known_materials[material_name](mass)) | 58 | self.created.append(Factory.known_materials[material_name](mass)) | ||
| 59 | result.append(material(mass)) | 59 | result.append(material(mass)) | ||
| 60 | 60 | ||||
| 61 | return tuple(result) | 61 | return tuple(result) | ||
| 62 | 62 | ||||
| 63 | if args: | 63 | if args: | ||
| 64 | for material in args: | 64 | for material in args: | ||
| 65 | if material.__class__.__name__ not in Factory.known_materials: | 65 | if material.__class__.__name__ not in Factory.known_materials: | ||
| 66 | raise ValueError(f"Unknown material: {material_name}") | 66 | raise ValueError(f"Unknown material: {material_name}") | ||
| 67 | 67 | ||||
| 68 | for material in args: | 68 | for material in args: | ||
| 69 | if material.used: | 69 | if material.used: | ||
| 70 | raise AssertionError | 70 | raise AssertionError | ||
| 71 | 71 | ||||
| 72 | for material in args: | 72 | for material in args: | ||
| 73 | material.used = True | 73 | material.used = True | ||
| 74 | 74 | ||||
| 75 | for material in self.created: | 75 | for material in self.created: | ||
| 76 | for names in args: | 76 | for names in args: | ||
| 77 | if material.__class__.__name__ is names.__class__.__name__: | 77 | if material.__class__.__name__ is names.__class__.__name__: | ||
| 78 | material.used = True | 78 | material.used = True | ||
| 79 | 79 | ||||
| 80 | material_name = [] | 80 | material_name = [] | ||
| 81 | 81 | ||||
| 82 | for material in args: | 82 | for material in args: | ||
| 83 | material_name.append(material.__class__.__name__) | 83 | material_name.append(material.__class__.__name__) | ||
| 84 | 84 | ||||
| 85 | new_material_name = '_'.join(material_name) | 85 | new_material_name = '_'.join(material_name) | ||
| 86 | 86 | ||||
| 87 | material_mass = sum(material.mass for material in args) | 87 | material_mass = sum(material.mass for material in args) | ||
| 88 | 88 | ||||
| 89 | if new_material_name in Factory.known_materials: | 89 | if new_material_name in Factory.known_materials: | ||
| 90 | self.created.append(Factory.known_materials[new_material_name](material_mass)) | 90 | self.created.append(Factory.known_materials[new_material_name](material_mass)) | ||
| 91 | return Factory.known_materials[new_material_name](material_mass) | 91 | return Factory.known_materials[new_material_name](material_mass) | ||
| 92 | 92 | ||||
| 93 | original_materials_names = new_material_name.split('_') | 93 | original_materials_names = new_material_name.split('_') | ||
| 94 | 94 | ||||
| 95 | material_density = 0 | 95 | material_density = 0 | ||
| 96 | for material in original_materials_names: | 96 | for material in original_materials_names: | ||
| 97 | material_density += Factory.known_materials[material].density | 97 | material_density += Factory.known_materials[material].density | ||
| 98 | 98 | ||||
| 99 | material_density /= len(original_materials_names) | 99 | material_density /= len(original_materials_names) | ||
| 100 | 100 | ||||
| 101 | new_material = type(new_material_name, (Material,), { | 101 | new_material = type(new_material_name, (Material,), { | ||
| 102 | 'density': material_density, | 102 | 'density': material_density, | ||
| 103 | }) | 103 | }) | ||
| 104 | 104 | ||||
| 105 | Factory.known_materials[new_material_name] = new_material | 105 | Factory.known_materials[new_material_name] = new_material | ||
| 106 | self.created.append(Factory.known_materials[new_material_name](material_mass)) | 106 | self.created.append(Factory.known_materials[new_material_name](material_mass)) | ||
| 107 | 107 | ||||
| 108 | return new_material(material_mass) | 108 | return new_material(material_mass) | ||
| 109 | 109 | ||||
| 110 | def get_total_volume(self): | 110 | def get_total_volume(self): | ||
| 111 | total_volume = 0 | 111 | total_volume = 0 | ||
| 112 | for materials in self.created: | 112 | for materials in self.created: | ||
| 113 | if materials.used is False: | 113 | if materials.used is False: | ||
| 114 | total_volume += materials.volume | 114 | total_volume += materials.volume | ||
| 115 | return total_volume | 115 | return total_volume | ||
| 116 | 116 | ||||
| 117 | def can_build(self, volume_needed): | 117 | def can_build(self, volume_needed): | ||
| 118 | return self.get_total_volume() >= volume_needed | 118 | return self.get_total_volume() >= volume_needed | ||
| 119 | 119 | ||||
| 120 | @classmethod | 120 | @classmethod | ||
| 121 | def can_build_together(cls, volume_needed): | 121 | def can_build_together(cls, volume_needed): | ||
| 122 | total_volume = 0 | 122 | total_volume = 0 | ||
| 123 | 123 | ||||
| t | 124 | for cur in range(0, len(cls.all_factories)): | t | 124 | for factories in cls.all_factories: |
| 125 | total_volume += cls.all_factories[cur].get_total_volume() | 125 | total_volume += factories.get_total_volume() | ||
| 126 | return total_volume >= volume_needed | 126 | return total_volume >= volume_needed |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
| f | 1 | class Material: | f | 1 | class Material: |
| 2 | def __init__(self, mass): | 2 | def __init__(self, mass): | ||
| 3 | self.mass = mass | 3 | self.mass = mass | ||
| 4 | self.used = False | 4 | self.used = False | ||
| 5 | 5 | ||||
| 6 | @property | 6 | @property | ||
| 7 | def volume(self): | 7 | def volume(self): | ||
| 8 | return self.mass / self.density | 8 | return self.mass / self.density | ||
| 9 | 9 | ||||
| 10 | 10 | ||||
| 11 | class Concrete(Material): | 11 | class Concrete(Material): | ||
| 12 | density = 2500 | 12 | density = 2500 | ||
| 13 | 13 | ||||
| 14 | 14 | ||||
| 15 | class Brick(Material): | 15 | class Brick(Material): | ||
| 16 | density = 2000 | 16 | density = 2000 | ||
| 17 | 17 | ||||
| 18 | 18 | ||||
| 19 | class Stone(Material): | 19 | class Stone(Material): | ||
| 20 | density = 1600 | 20 | density = 1600 | ||
| 21 | 21 | ||||
| 22 | 22 | ||||
| 23 | class Wood(Material): | 23 | class Wood(Material): | ||
| 24 | density = 600 | 24 | density = 600 | ||
| 25 | 25 | ||||
| 26 | 26 | ||||
| 27 | class Steel(Material): | 27 | class Steel(Material): | ||
| 28 | density = 7700 | 28 | density = 7700 | ||
| 29 | 29 | ||||
| 30 | 30 | ||||
| 31 | class Factory: | 31 | class Factory: | ||
| 32 | all_factories = [] | 32 | all_factories = [] | ||
| 33 | 33 | ||||
| 34 | known_materials = { | 34 | known_materials = { | ||
| 35 | 'Concrete': Concrete, | 35 | 'Concrete': Concrete, | ||
| 36 | 'Brick': Brick, | 36 | 'Brick': Brick, | ||
| 37 | 'Stone': Stone, | 37 | 'Stone': Stone, | ||
| 38 | 'Wood': Wood, | 38 | 'Wood': Wood, | ||
| 39 | 'Steel': Steel | 39 | 'Steel': Steel | ||
| 40 | } | 40 | } | ||
| 41 | 41 | ||||
| 42 | def __init__(self): | 42 | def __init__(self): | ||
| 43 | self.created = [] | 43 | self.created = [] | ||
| 44 | Factory.all_factories.append(self) | 44 | Factory.all_factories.append(self) | ||
| 45 | 45 | ||||
| 46 | def __call__(self, *args, **kargs): | 46 | def __call__(self, *args, **kargs): | ||
| n | n | 47 | """This method is not long, it's monumental.""" | ||
| 47 | if args and kargs or not args and not kargs: | 48 | if args and kargs or not args and not kargs: | ||
| 48 | raise ValueError | 49 | raise ValueError | ||
| 49 | 50 | ||||
| 50 | if kargs: | 51 | if kargs: | ||
| 51 | result = [] | 52 | result = [] | ||
| 52 | for material_name, mass in kargs.items(): | 53 | for material_name, mass in kargs.items(): | ||
| 53 | if material_name not in Factory.known_materials: | 54 | if material_name not in Factory.known_materials: | ||
| 54 | raise ValueError(f"Unknown material: {material_name}") | 55 | raise ValueError(f"Unknown material: {material_name}") | ||
| 55 | 56 | ||||
| 56 | material = Factory.known_materials[material_name] | 57 | material = Factory.known_materials[material_name] | ||
| 57 | self.created.append(Factory.known_materials[material_name](mass)) | 58 | self.created.append(Factory.known_materials[material_name](mass)) | ||
| 58 | result.append(material(mass)) | 59 | result.append(material(mass)) | ||
| 59 | 60 | ||||
| 60 | return tuple(result) | 61 | return tuple(result) | ||
| 61 | 62 | ||||
| 62 | if args: | 63 | if args: | ||
| 63 | for material in args: | 64 | for material in args: | ||
| 64 | if material.__class__.__name__ not in Factory.known_materials: | 65 | if material.__class__.__name__ not in Factory.known_materials: | ||
| 65 | raise ValueError(f"Unknown material: {material_name}") | 66 | raise ValueError(f"Unknown material: {material_name}") | ||
| 66 | 67 | ||||
| 67 | for material in args: | 68 | for material in args: | ||
| 68 | if material.used: | 69 | if material.used: | ||
| 69 | raise AssertionError | 70 | raise AssertionError | ||
| 70 | 71 | ||||
| 71 | for material in args: | 72 | for material in args: | ||
| 72 | material.used = True | 73 | material.used = True | ||
| 73 | 74 | ||||
| 74 | for material in self.created: | 75 | for material in self.created: | ||
| 75 | for names in args: | 76 | for names in args: | ||
| 76 | if material.__class__.__name__ is names.__class__.__name__: | 77 | if material.__class__.__name__ is names.__class__.__name__: | ||
| 77 | material.used = True | 78 | material.used = True | ||
| 78 | 79 | ||||
| 79 | material_name = [] | 80 | material_name = [] | ||
| 80 | 81 | ||||
| 81 | for material in args: | 82 | for material in args: | ||
| 82 | material_name.append(material.__class__.__name__) | 83 | material_name.append(material.__class__.__name__) | ||
| 83 | 84 | ||||
| 84 | new_material_name = '_'.join(material_name) | 85 | new_material_name = '_'.join(material_name) | ||
| 85 | 86 | ||||
| 86 | material_mass = sum(material.mass for material in args) | 87 | material_mass = sum(material.mass for material in args) | ||
| 87 | 88 | ||||
| 88 | if new_material_name in Factory.known_materials: | 89 | if new_material_name in Factory.known_materials: | ||
| 89 | self.created.append(Factory.known_materials[new_material_name](material_mass)) | 90 | self.created.append(Factory.known_materials[new_material_name](material_mass)) | ||
| 90 | return Factory.known_materials[new_material_name](material_mass) | 91 | return Factory.known_materials[new_material_name](material_mass) | ||
| 91 | 92 | ||||
| 92 | original_materials_names = new_material_name.split('_') | 93 | original_materials_names = new_material_name.split('_') | ||
| 93 | 94 | ||||
| 94 | material_density = 0 | 95 | material_density = 0 | ||
| 95 | for material in original_materials_names: | 96 | for material in original_materials_names: | ||
| 96 | material_density += Factory.known_materials[material].density | 97 | material_density += Factory.known_materials[material].density | ||
| 97 | 98 | ||||
| 98 | material_density /= len(original_materials_names) | 99 | material_density /= len(original_materials_names) | ||
| 99 | 100 | ||||
| 100 | new_material = type(new_material_name, (Material,), { | 101 | new_material = type(new_material_name, (Material,), { | ||
| 101 | 'density': material_density, | 102 | 'density': material_density, | ||
| t | 102 | '__init__': lambda self, mass: Material.__init__(self, mass), | t | ||
| 103 | 'volume': property(lambda self: self.mass / self.density), | ||||
| 104 | 'used': False, | ||||
| 105 | }) | 103 | }) | ||
| 106 | 104 | ||||
| 107 | Factory.known_materials[new_material_name] = new_material | 105 | Factory.known_materials[new_material_name] = new_material | ||
| 108 | self.created.append(Factory.known_materials[new_material_name](material_mass)) | 106 | self.created.append(Factory.known_materials[new_material_name](material_mass)) | ||
| 109 | 107 | ||||
| 110 | return new_material(material_mass) | 108 | return new_material(material_mass) | ||
| 111 | 109 | ||||
| 112 | def get_total_volume(self): | 110 | def get_total_volume(self): | ||
| 113 | total_volume = 0 | 111 | total_volume = 0 | ||
| 114 | for materials in self.created: | 112 | for materials in self.created: | ||
| 115 | if materials.used is False: | 113 | if materials.used is False: | ||
| 116 | total_volume += materials.volume | 114 | total_volume += materials.volume | ||
| 117 | return total_volume | 115 | return total_volume | ||
| 118 | 116 | ||||
| 119 | def can_build(self, volume_needed): | 117 | def can_build(self, volume_needed): | ||
| 120 | return self.get_total_volume() >= volume_needed | 118 | return self.get_total_volume() >= volume_needed | ||
| 121 | 119 | ||||
| 122 | @classmethod | 120 | @classmethod | ||
| 123 | def can_build_together(cls, volume_needed): | 121 | def can_build_together(cls, volume_needed): | ||
| 124 | total_volume = 0 | 122 | total_volume = 0 | ||
| 125 | 123 | ||||
| 126 | for cur in range(0, len(cls.all_factories)): | 124 | for cur in range(0, len(cls.all_factories)): | ||
| 127 | total_volume += cls.all_factories[cur].get_total_volume() | 125 | total_volume += cls.all_factories[cur].get_total_volume() | ||
| 128 | return total_volume >= volume_needed | 126 | return total_volume >= volume_needed |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
| f | 1 | class Material: | f | 1 | class Material: |
| 2 | def __init__(self, mass): | 2 | def __init__(self, mass): | ||
| 3 | self.mass = mass | 3 | self.mass = mass | ||
| 4 | self.used = False | 4 | self.used = False | ||
| 5 | 5 | ||||
| 6 | @property | 6 | @property | ||
| 7 | def volume(self): | 7 | def volume(self): | ||
| 8 | return self.mass / self.density | 8 | return self.mass / self.density | ||
| 9 | 9 | ||||
| n | n | 10 | |||
| 10 | class Concrete(Material): | 11 | class Concrete(Material): | ||
| n | 11 | density = 2500 | n | 12 | density = 2500 |
| 13 | |||||
| 12 | 14 | ||||
| 13 | class Brick(Material): | 15 | class Brick(Material): | ||
| n | 14 | density = 2000 | n | 16 | density = 2000 |
| 17 | |||||
| 15 | 18 | ||||
| 16 | class Stone(Material): | 19 | class Stone(Material): | ||
| n | 17 | density = 1600 | n | 20 | density = 1600 |
| 21 | |||||
| 18 | 22 | ||||
| 19 | class Wood(Material): | 23 | class Wood(Material): | ||
| 20 | density = 600 | 24 | density = 600 | ||
| 21 | 25 | ||||
| n | n | 26 | |||
| 22 | class Steel(Material): | 27 | class Steel(Material): | ||
| 23 | density = 7700 | 28 | density = 7700 | ||
| n | n | 29 | |||
| 24 | 30 | ||||
| 25 | class Factory: | 31 | class Factory: | ||
| 26 | all_factories = [] | 32 | all_factories = [] | ||
| 27 | 33 | ||||
| 28 | known_materials = { | 34 | known_materials = { | ||
| 29 | 'Concrete': Concrete, | 35 | 'Concrete': Concrete, | ||
| 30 | 'Brick': Brick, | 36 | 'Brick': Brick, | ||
| 31 | 'Stone': Stone, | 37 | 'Stone': Stone, | ||
| 32 | 'Wood': Wood, | 38 | 'Wood': Wood, | ||
| 33 | 'Steel': Steel | 39 | 'Steel': Steel | ||
| 34 | } | 40 | } | ||
| 35 | 41 | ||||
| 36 | def __init__(self): | 42 | def __init__(self): | ||
| 37 | self.created = [] | 43 | self.created = [] | ||
| 38 | Factory.all_factories.append(self) | 44 | Factory.all_factories.append(self) | ||
| 39 | 45 | ||||
| 40 | def __call__(self, *args, **kargs): | 46 | def __call__(self, *args, **kargs): | ||
| 41 | if args and kargs or not args and not kargs: | 47 | if args and kargs or not args and not kargs: | ||
| 42 | raise ValueError | 48 | raise ValueError | ||
| 43 | 49 | ||||
| 44 | if kargs: | 50 | if kargs: | ||
| 45 | result = [] | 51 | result = [] | ||
| 46 | for material_name, mass in kargs.items(): | 52 | for material_name, mass in kargs.items(): | ||
| 47 | if material_name not in Factory.known_materials: | 53 | if material_name not in Factory.known_materials: | ||
| 48 | raise ValueError(f"Unknown material: {material_name}") | 54 | raise ValueError(f"Unknown material: {material_name}") | ||
| 49 | 55 | ||||
| 50 | material = Factory.known_materials[material_name] | 56 | material = Factory.known_materials[material_name] | ||
| 51 | self.created.append(Factory.known_materials[material_name](mass)) | 57 | self.created.append(Factory.known_materials[material_name](mass)) | ||
| 52 | result.append(material(mass)) | 58 | result.append(material(mass)) | ||
| n | 53 | n | 59 | ||
| 54 | return tuple(result) | 60 | return tuple(result) | ||
| 55 | 61 | ||||
| 56 | if args: | 62 | if args: | ||
| 57 | for material in args: | 63 | for material in args: | ||
| 58 | if material.__class__.__name__ not in Factory.known_materials: | 64 | if material.__class__.__name__ not in Factory.known_materials: | ||
| n | 59 | raise ValueError(f"Unknown material") | n | 65 | raise ValueError(f"Unknown material: {material_name}") |
| 60 | 66 | ||||
| 61 | for material in args: | 67 | for material in args: | ||
| 62 | if material.used: | 68 | if material.used: | ||
| 63 | raise AssertionError | 69 | raise AssertionError | ||
| n | 64 | n | 70 | ||
| 65 | for material in args: | 71 | for material in args: | ||
| 66 | material.used = True | 72 | material.used = True | ||
| n | 67 | n | 73 | ||
| 68 | for material in self.created: | 74 | for material in self.created: | ||
| 69 | for names in args: | 75 | for names in args: | ||
| 70 | if material.__class__.__name__ is names.__class__.__name__: | 76 | if material.__class__.__name__ is names.__class__.__name__: | ||
| 71 | material.used = True | 77 | material.used = True | ||
| 72 | 78 | ||||
| 73 | material_name = [] | 79 | material_name = [] | ||
| 74 | 80 | ||||
| 75 | for material in args: | 81 | for material in args: | ||
| 76 | material_name.append(material.__class__.__name__) | 82 | material_name.append(material.__class__.__name__) | ||
| 77 | 83 | ||||
| 78 | new_material_name = '_'.join(material_name) | 84 | new_material_name = '_'.join(material_name) | ||
| 79 | 85 | ||||
| 80 | material_mass = sum(material.mass for material in args) | 86 | material_mass = sum(material.mass for material in args) | ||
| 81 | 87 | ||||
| 82 | if new_material_name in Factory.known_materials: | 88 | if new_material_name in Factory.known_materials: | ||
| 83 | self.created.append(Factory.known_materials[new_material_name](material_mass)) | 89 | self.created.append(Factory.known_materials[new_material_name](material_mass)) | ||
| 84 | return Factory.known_materials[new_material_name](material_mass) | 90 | return Factory.known_materials[new_material_name](material_mass) | ||
| 85 | 91 | ||||
| 86 | original_materials_names = new_material_name.split('_') | 92 | original_materials_names = new_material_name.split('_') | ||
| 87 | 93 | ||||
| 88 | material_density = 0 | 94 | material_density = 0 | ||
| 89 | for material in original_materials_names: | 95 | for material in original_materials_names: | ||
| 90 | material_density += Factory.known_materials[material].density | 96 | material_density += Factory.known_materials[material].density | ||
| 91 | 97 | ||||
| n | 92 | material_density/= len(original_materials_names) | n | 98 | material_density /= len(original_materials_names) |
| 93 | 99 | ||||
| 94 | new_material = type(new_material_name, (Material,), { | 100 | new_material = type(new_material_name, (Material,), { | ||
| 95 | 'density': material_density, | 101 | 'density': material_density, | ||
| n | 96 | '__init__': lambda self, mass: Material.__init__(self, mass), | n | 102 | '__init__': lambda self, mass: Material.__init__(self, mass), |
| 97 | 'volume': property(lambda self: self.mass / self.density), | 103 | 'volume': property(lambda self: self.mass / self.density), | ||
| 98 | 'used': False, | 104 | 'used': False, | ||
| 99 | }) | 105 | }) | ||
| n | 100 | n | 106 | ||
| 101 | Factory.known_materials[new_material_name] = new_material | 107 | Factory.known_materials[new_material_name] = new_material | ||
| 102 | self.created.append(Factory.known_materials[new_material_name](material_mass)) | 108 | self.created.append(Factory.known_materials[new_material_name](material_mass)) | ||
| 103 | 109 | ||||
| 104 | return new_material(material_mass) | 110 | return new_material(material_mass) | ||
| 105 | 111 | ||||
| 106 | def get_total_volume(self): | 112 | def get_total_volume(self): | ||
| 107 | total_volume = 0 | 113 | total_volume = 0 | ||
| 108 | for materials in self.created: | 114 | for materials in self.created: | ||
| 109 | if materials.used is False: | 115 | if materials.used is False: | ||
| 110 | total_volume += materials.volume | 116 | total_volume += materials.volume | ||
| 111 | return total_volume | 117 | return total_volume | ||
| n | 112 | n | 118 | ||
| 113 | def can_build(self, volume_needed): | 119 | def can_build(self, volume_needed): | ||
| 114 | return self.get_total_volume() >= volume_needed | 120 | return self.get_total_volume() >= volume_needed | ||
| 115 | 121 | ||||
| 116 | @classmethod | 122 | @classmethod | ||
| 117 | def can_build_together(cls, volume_needed): | 123 | def can_build_together(cls, volume_needed): | ||
| 118 | total_volume = 0 | 124 | total_volume = 0 | ||
| 119 | 125 | ||||
| 120 | for cur in range(0, len(cls.all_factories)): | 126 | for cur in range(0, len(cls.all_factories)): | ||
| n | 121 | total_volume += cls.all_factories[cur].get_total_volume() | n | 127 | total_volume += cls.all_factories[cur].get_total_volume() |
| 122 | print(total_volume) | ||||
| 123 | return total_volume >= volume_needed | 128 | return total_volume >= volume_needed | ||
| t | 124 | t | |||
| 125 | factory1 = Factory() | ||||
| 126 | brick1, wood1 = factory1(Brick=2000, Wood=1200) | ||||
| 127 | print(brick1.volume) # 1.0 | ||||
| 128 | print(wood1.volume) # 2.0 | ||||
| 129 | brick_wood1 = factory1(brick1, wood1) | ||||
| 130 | print(brick_wood1.volume) # 2.46... | ||||
| 131 | print(factory1.can_build(3)) # False | ||||
| 132 | |||||
| 133 | factory2 = Factory() | ||||
| 134 | brick2, wood2 = factory2(Brick=2000, Wood=1200) | ||||
| 135 | print(brick2.volume) # 1.0 | ||||
| 136 | print(wood2.volume) # 2.0 | ||||
| 137 | brick_wood2 = factory2(brick2, wood2) | ||||
| 138 | print(brick_wood2.volume) # 2.46... | ||||
| 139 | print(factory2.can_build(3)) # False | ||||
| 140 | |||||
| 141 | print(Factory.can_build_together(3)) # True |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||