1class Material:
2 DENSITY = 0
3
4 def __init__(self, mass):
5 self.mass = mass
6 self.valid = True
7
8 @property
9 def volume(self):
10 return self.mass / self.DENCITY
11
12 def invalidate(self):
13 if self.valid:
14 self.valid = False
15 return True
16 return False
17
18
19class Concrete(Material):
20 DENCITY = 2500
21
22
23class Brick(Material):
24 DENCITY = 2000
25
26
27class Stone(Material):
28 DENCITY = 1600
29
30
31class Wood(Material):
32 DENCITY = 600
33
34
35class Steel(Material):
36 DENCITY = 7700
37
38
39CLASS_REGISTER = {'Concrete' : Concrete, 'Brick' : Brick, 'Stone' : Stone, 'Wood' : Wood, 'Steel' : Steel}
40
41
42class Factory:
43 all_materials = []
44
45 def __init__(self):
46 self.materials = []
47
48 def help_generate_class(self, *args):
49 new_args = []
50 dencity = 0
51 count = 0
52 mass = 0
53 for item in list(*args):
54 if not item.invalidate():
55 raise AssertionError
56 self.remove_material(item)
57 args_name = item.__class__.__name__.split('_')
58 for element in args_name:
59 dencity += CLASS_REGISTER[element].DENCITY
60 count += 1
61 new_args.extend(args_name)
62 mass += item.mass
63 return '_'.join(str(item).capitalize() for item in sorted(new_args)), dencity // count, mass
64
65 def add_instance(self, material, value):
66 material_instance = CLASS_REGISTER[material](value)
67 self.materials.append(material_instance)
68 return material_instance
69
70 def call_with_kwargs(self, **kwargs):
71 res = []
72 for material, value in kwargs.items():
73 if material not in CLASS_REGISTER:
74 raise ValueError
75 res.append(self.add_instance(material, value))
76 self.all_materials.extend(self.materials)
77 return tuple(res)
78
79 def call_with_args(self, *args):
80 name, dencity, mass = self.help_generate_class(args)
81 if name in CLASS_REGISTER:
82 material_instance = self.add_instance(name, mass)
83 self.all_materials.extend(self.materials)
84 return material_instance
85 else:
86 DynamicClass = type(name, (Material,), {'DENCITY' : dencity})
87 CLASS_REGISTER[name] = DynamicClass
88 material_instance = self.add_instance(name, mass)
89 self.all_materials.extend(self.materials)
90 return material_instance
91
92 def __call__(self, *args, **kwargs):
93 if args and kwargs or not args and not kwargs:
94 raise ValueError
95 if kwargs:
96 return self.call_with_kwargs(**kwargs)
97 return self.call_with_args(*args)
98
99 def remove_material(self, material):
100 if material in self.materials:
101 self.materials.remove(material)
102 self.all_materials.remove(material)
103
104 @property
105 def volume(self):
106 volume_sum = sum(item.volume for item in self.materials)
107 return volume_sum
108
109 def can_build(self, desired_volume):
110 return desired_volume <= self.volume
111
112 @classmethod
113 def can_build_together(cls, desired_volume):
114 volume = 0
115 for item in cls.all_materials:
116 volume += item.volume
117 return desired_volume <= volume
.....FF...
======================================================================
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 97, in __call__
return self.call_with_args(*args)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 80, in call_with_args
name, dencity, mass = self.help_generate_class(args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 55, in help_generate_class
raise AssertionError
AssertionError
======================================================================
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 125, in test_positional_arguments_multiple_argument_with_dynamics
self.assertAlmostEqual(brick_concrete_stone.volume, 5.2131, places=4)
AssertionError: 5.213969503197245 != 5.2131 within 4 places (0.0008695031972454359 difference)
----------------------------------------------------------------------
Ran 10 tests in 0.010s
FAILED (failures=2)
| f | 1 | class Material: | f | 1 | class Material: |
| n | 2 | DENCITY = 0 | n | 2 | DENSITY = 0 |
| 3 | 3 | ||||
| 4 | def __init__(self, mass): | 4 | def __init__(self, mass): | ||
| 5 | self.mass = mass | 5 | self.mass = mass | ||
| 6 | self.valid = True | 6 | self.valid = True | ||
| 7 | 7 | ||||
| 8 | @property | 8 | @property | ||
| 9 | def volume(self): | 9 | def volume(self): | ||
| 10 | return self.mass / self.DENCITY | 10 | return self.mass / self.DENCITY | ||
| 11 | 11 | ||||
| 12 | def invalidate(self): | 12 | def invalidate(self): | ||
| 13 | if self.valid: | 13 | if self.valid: | ||
| 14 | self.valid = False | 14 | self.valid = False | ||
| 15 | return True | 15 | return True | ||
| 16 | return False | 16 | return False | ||
| 17 | 17 | ||||
| 18 | 18 | ||||
| 19 | class Concrete(Material): | 19 | class Concrete(Material): | ||
| 20 | DENCITY = 2500 | 20 | DENCITY = 2500 | ||
| 21 | 21 | ||||
| 22 | 22 | ||||
| 23 | class Brick(Material): | 23 | class Brick(Material): | ||
| 24 | DENCITY = 2000 | 24 | DENCITY = 2000 | ||
| 25 | 25 | ||||
| 26 | 26 | ||||
| 27 | class Stone(Material): | 27 | class Stone(Material): | ||
| 28 | DENCITY = 1600 | 28 | DENCITY = 1600 | ||
| 29 | 29 | ||||
| 30 | 30 | ||||
| 31 | class Wood(Material): | 31 | class Wood(Material): | ||
| 32 | DENCITY = 600 | 32 | DENCITY = 600 | ||
| 33 | 33 | ||||
| 34 | 34 | ||||
| 35 | class Steel(Material): | 35 | class Steel(Material): | ||
| 36 | DENCITY = 7700 | 36 | DENCITY = 7700 | ||
| 37 | 37 | ||||
| 38 | 38 | ||||
| n | 39 | class_register = {'Concrete' : Concrete, 'Brick' : Brick, 'Stone' : Stone, 'Wood' : Wood, 'Steel' : Steel} | n | 39 | CLASS_REGISTER = {'Concrete' : Concrete, 'Brick' : Brick, 'Stone' : Stone, 'Wood' : Wood, 'Steel' : Steel} |
| 40 | |||||
| 41 | |||||
| 42 | def help_generate_class(fact, *args): | ||||
| 43 | newArgs = [] | ||||
| 44 | dencity = 0 | ||||
| 45 | count = 0 | ||||
| 46 | mass = 0 | ||||
| 47 | for item in list(*args): | ||||
| 48 | if not item.invalidate(): | ||||
| 49 | raise AssertionError | ||||
| 50 | fact.remove_material(item) | ||||
| 51 | curr_class = item.__class__ | ||||
| 52 | args_name = [] | ||||
| 53 | args_name.extend(curr_class.__name__.split('_')) | ||||
| 54 | for element in args_name: | ||||
| 55 | dencity += class_register[element].DENCITY | ||||
| 56 | count += 1 | ||||
| 57 | newArgs.extend(args_name) | ||||
| 58 | mass += item.mass | ||||
| 59 | return ('_'.join(f"{str(item).capitalize()}" for item in sorted(newArgs)), dencity // count, mass) | ||||
| 60 | 40 | ||||
| 61 | 41 | ||||
| 62 | class Factory: | 42 | class Factory: | ||
| 63 | all_materials = [] | 43 | all_materials = [] | ||
| 64 | 44 | ||||
| 65 | def __init__(self): | 45 | def __init__(self): | ||
| 66 | self.materials = [] | 46 | self.materials = [] | ||
| 67 | 47 | ||||
| n | n | 48 | def help_generate_class(self, *args): | ||
| 49 | new_args = [] | ||||
| 50 | dencity = 0 | ||||
| 51 | count = 0 | ||||
| 52 | mass = 0 | ||||
| 53 | for item in list(*args): | ||||
| 54 | if not item.invalidate(): | ||||
| 55 | raise AssertionError | ||||
| 56 | self.remove_material(item) | ||||
| 57 | args_name = item.__class__.__name__.split('_') | ||||
| 58 | for element in args_name: | ||||
| 59 | dencity += CLASS_REGISTER[element].DENCITY | ||||
| 60 | count += 1 | ||||
| 61 | new_args.extend(args_name) | ||||
| 62 | mass += item.mass | ||||
| 63 | return '_'.join(str(item).capitalize() for item in sorted(new_args)), dencity // count, mass | ||||
| 64 | |||||
| 65 | def add_instance(self, material, value): | ||||
| 66 | material_instance = CLASS_REGISTER[material](value) | ||||
| 67 | self.materials.append(material_instance) | ||||
| 68 | return material_instance | ||||
| 69 | |||||
| 70 | def call_with_kwargs(self, **kwargs): | ||||
| 71 | res = [] | ||||
| 72 | for material, value in kwargs.items(): | ||||
| 73 | if material not in CLASS_REGISTER: | ||||
| 74 | raise ValueError | ||||
| 75 | res.append(self.add_instance(material, value)) | ||||
| 76 | self.all_materials.extend(self.materials) | ||||
| 77 | return tuple(res) | ||||
| 78 | |||||
| 79 | def call_with_args(self, *args): | ||||
| 80 | name, dencity, mass = self.help_generate_class(args) | ||||
| 81 | if name in CLASS_REGISTER: | ||||
| 82 | material_instance = self.add_instance(name, mass) | ||||
| 83 | self.all_materials.extend(self.materials) | ||||
| 84 | return material_instance | ||||
| 85 | else: | ||||
| 86 | DynamicClass = type(name, (Material,), {'DENCITY' : dencity}) | ||||
| 87 | CLASS_REGISTER[name] = DynamicClass | ||||
| 88 | material_instance = self.add_instance(name, mass) | ||||
| 89 | self.all_materials.extend(self.materials) | ||||
| 90 | return material_instance | ||||
| 91 | |||||
| 68 | def __call__(self, *args, **kwargs): | 92 | def __call__(self, *args, **kwargs): | ||
| n | 69 | if len(args) and len(kwargs) or not len(args) and not len(kwargs): | n | 93 | if args and kwargs or not args and not kwargs: |
| 70 | raise ValueError | 94 | raise ValueError | ||
| n | 71 | if len(kwargs): | n | 95 | if kwargs: |
| 72 | res = [] | 96 | return self.call_with_kwargs(**kwargs) | ||
| 73 | for material, value in kwargs.items(): | 97 | return self.call_with_args(*args) | ||
| 74 | if material not in class_register.keys(): | ||||
| 75 | raise ValueError | ||||
| 76 | material_instance = class_register[material](value) | ||||
| 77 | res.append(material_instance) | ||||
| 78 | self.materials.append(material_instance) | ||||
| 79 | self.__class__.all_materials.extend(self.materials) | ||||
| 80 | return tuple(res) | ||||
| 81 | if len(args): | ||||
| 82 | name, dencity, mass = help_generate_class(self, args) | ||||
| 83 | if name in class_register: | ||||
| 84 | #the class already exists | ||||
| 85 | material_instance = class_register[name](mass) | ||||
| 86 | |||||
| 87 | self.materials.append(material_instance) | ||||
| 88 | self.__class__.all_materials.extend(self.materials) | ||||
| 89 | return material_instance | ||||
| 90 | else: | ||||
| 91 | #creating new class | ||||
| 92 | Dynamic_class = type(name, (Material,), {'DENCITY' : dencity}) | ||||
| 93 | class_register[name] = Dynamic_class | ||||
| 94 | material_instance = Dynamic_class(mass) | ||||
| 95 | self.materials.append(material_instance) | ||||
| 96 | self.__class__.all_materials.extend(self.materials) | ||||
| 97 | return material_instance | ||||
| 98 | 98 | ||||
| 99 | def remove_material(self, material): | 99 | def remove_material(self, material): | ||
| 100 | if material in self.materials: | 100 | if material in self.materials: | ||
| 101 | self.materials.remove(material) | 101 | self.materials.remove(material) | ||
| n | 102 | self.__class__.all_materials.remove(material) | n | 102 | self.all_materials.remove(material) |
| 103 | 103 | ||||
| 104 | @property | 104 | @property | ||
| 105 | def volume(self): | 105 | def volume(self): | ||
| t | 106 | volume = 0 | t | 106 | volume_sum = sum(item.volume for item in self.materials) |
| 107 | for item in self.materials: | ||||
| 108 | volume += item.volume | ||||
| 109 | return volume | 107 | return volume_sum | ||
| 110 | 108 | ||||
| 111 | def can_build(self, desired_volume): | 109 | def can_build(self, desired_volume): | ||
| 112 | return desired_volume <= self.volume | 110 | return desired_volume <= self.volume | ||
| 113 | 111 | ||||
| 114 | @classmethod | 112 | @classmethod | ||
| 115 | def can_build_together(cls, desired_volume): | 113 | def can_build_together(cls, desired_volume): | ||
| 116 | volume = 0 | 114 | volume = 0 | ||
| 117 | for item in cls.all_materials: | 115 | for item in cls.all_materials: | ||
| 118 | volume += item.volume | 116 | volume += item.volume | ||
| 119 | return desired_volume <= volume | 117 | return desired_volume <= volume |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
| f | 1 | class Material: | f | 1 | class Material: |
| 2 | DENCITY = 0 | 2 | DENCITY = 0 | ||
| 3 | 3 | ||||
| 4 | def __init__(self, mass): | 4 | def __init__(self, mass): | ||
| 5 | self.mass = mass | 5 | self.mass = mass | ||
| 6 | self.valid = True | 6 | self.valid = True | ||
| 7 | 7 | ||||
| 8 | @property | 8 | @property | ||
| 9 | def volume(self): | 9 | def volume(self): | ||
| 10 | return self.mass / self.DENCITY | 10 | return self.mass / self.DENCITY | ||
| 11 | 11 | ||||
| 12 | def invalidate(self): | 12 | def invalidate(self): | ||
| 13 | if self.valid: | 13 | if self.valid: | ||
| 14 | self.valid = False | 14 | self.valid = False | ||
| 15 | return True | 15 | return True | ||
| 16 | return False | 16 | return False | ||
| 17 | 17 | ||||
| 18 | 18 | ||||
| 19 | class Concrete(Material): | 19 | class Concrete(Material): | ||
| 20 | DENCITY = 2500 | 20 | DENCITY = 2500 | ||
| 21 | 21 | ||||
| 22 | 22 | ||||
| 23 | class Brick(Material): | 23 | class Brick(Material): | ||
| 24 | DENCITY = 2000 | 24 | DENCITY = 2000 | ||
| 25 | 25 | ||||
| 26 | 26 | ||||
| 27 | class Stone(Material): | 27 | class Stone(Material): | ||
| 28 | DENCITY = 1600 | 28 | DENCITY = 1600 | ||
| 29 | 29 | ||||
| 30 | 30 | ||||
| 31 | class Wood(Material): | 31 | class Wood(Material): | ||
| 32 | DENCITY = 600 | 32 | DENCITY = 600 | ||
| 33 | 33 | ||||
| 34 | 34 | ||||
| 35 | class Steel(Material): | 35 | class Steel(Material): | ||
| 36 | DENCITY = 7700 | 36 | DENCITY = 7700 | ||
| 37 | 37 | ||||
| 38 | 38 | ||||
| 39 | class_register = {'Concrete' : Concrete, 'Brick' : Brick, 'Stone' : Stone, 'Wood' : Wood, 'Steel' : Steel} | 39 | class_register = {'Concrete' : Concrete, 'Brick' : Brick, 'Stone' : Stone, 'Wood' : Wood, 'Steel' : Steel} | ||
| 40 | 40 | ||||
| 41 | 41 | ||||
| t | 42 | def help_generate_class(fact, *args): # a ako se hvurli greshka i nqkopi sa invalidirani drugi ne? | t | 42 | def help_generate_class(fact, *args): |
| 43 | newArgs = [] | 43 | newArgs = [] | ||
| 44 | dencity = 0 | 44 | dencity = 0 | ||
| 45 | count = 0 | 45 | count = 0 | ||
| 46 | mass = 0 | 46 | mass = 0 | ||
| 47 | for item in list(*args): | 47 | for item in list(*args): | ||
| 48 | if not item.invalidate(): | 48 | if not item.invalidate(): | ||
| 49 | raise AssertionError | 49 | raise AssertionError | ||
| 50 | fact.remove_material(item) | 50 | fact.remove_material(item) | ||
| 51 | curr_class = item.__class__ | 51 | curr_class = item.__class__ | ||
| 52 | args_name = [] | 52 | args_name = [] | ||
| 53 | args_name.extend(curr_class.__name__.split('_')) | 53 | args_name.extend(curr_class.__name__.split('_')) | ||
| 54 | for element in args_name: | 54 | for element in args_name: | ||
| 55 | dencity += class_register[element].DENCITY | 55 | dencity += class_register[element].DENCITY | ||
| 56 | count += 1 | 56 | count += 1 | ||
| 57 | newArgs.extend(args_name) | 57 | newArgs.extend(args_name) | ||
| 58 | mass += item.mass | 58 | mass += item.mass | ||
| 59 | return ('_'.join(f"{str(item).capitalize()}" for item in sorted(newArgs)), dencity // count, mass) | 59 | return ('_'.join(f"{str(item).capitalize()}" for item in sorted(newArgs)), dencity // count, mass) | ||
| 60 | 60 | ||||
| 61 | 61 | ||||
| 62 | class Factory: | 62 | class Factory: | ||
| 63 | all_materials = [] | 63 | all_materials = [] | ||
| 64 | 64 | ||||
| 65 | def __init__(self): | 65 | def __init__(self): | ||
| 66 | self.materials = [] | 66 | self.materials = [] | ||
| 67 | 67 | ||||
| 68 | def __call__(self, *args, **kwargs): | 68 | def __call__(self, *args, **kwargs): | ||
| 69 | if len(args) and len(kwargs) or not len(args) and not len(kwargs): | 69 | if len(args) and len(kwargs) or not len(args) and not len(kwargs): | ||
| 70 | raise ValueError | 70 | raise ValueError | ||
| 71 | if len(kwargs): | 71 | if len(kwargs): | ||
| 72 | res = [] | 72 | res = [] | ||
| 73 | for material, value in kwargs.items(): | 73 | for material, value in kwargs.items(): | ||
| 74 | if material not in class_register.keys(): | 74 | if material not in class_register.keys(): | ||
| 75 | raise ValueError | 75 | raise ValueError | ||
| 76 | material_instance = class_register[material](value) | 76 | material_instance = class_register[material](value) | ||
| 77 | res.append(material_instance) | 77 | res.append(material_instance) | ||
| 78 | self.materials.append(material_instance) | 78 | self.materials.append(material_instance) | ||
| 79 | self.__class__.all_materials.extend(self.materials) | 79 | self.__class__.all_materials.extend(self.materials) | ||
| 80 | return tuple(res) | 80 | return tuple(res) | ||
| 81 | if len(args): | 81 | if len(args): | ||
| 82 | name, dencity, mass = help_generate_class(self, args) | 82 | name, dencity, mass = help_generate_class(self, args) | ||
| 83 | if name in class_register: | 83 | if name in class_register: | ||
| 84 | #the class already exists | 84 | #the class already exists | ||
| 85 | material_instance = class_register[name](mass) | 85 | material_instance = class_register[name](mass) | ||
| 86 | 86 | ||||
| 87 | self.materials.append(material_instance) | 87 | self.materials.append(material_instance) | ||
| 88 | self.__class__.all_materials.extend(self.materials) | 88 | self.__class__.all_materials.extend(self.materials) | ||
| 89 | return material_instance | 89 | return material_instance | ||
| 90 | else: | 90 | else: | ||
| 91 | #creating new class | 91 | #creating new class | ||
| 92 | Dynamic_class = type(name, (Material,), {'DENCITY' : dencity}) | 92 | Dynamic_class = type(name, (Material,), {'DENCITY' : dencity}) | ||
| 93 | class_register[name] = Dynamic_class | 93 | class_register[name] = Dynamic_class | ||
| 94 | material_instance = Dynamic_class(mass) | 94 | material_instance = Dynamic_class(mass) | ||
| 95 | self.materials.append(material_instance) | 95 | self.materials.append(material_instance) | ||
| 96 | self.__class__.all_materials.extend(self.materials) | 96 | self.__class__.all_materials.extend(self.materials) | ||
| 97 | return material_instance | 97 | return material_instance | ||
| 98 | 98 | ||||
| 99 | def remove_material(self, material): | 99 | def remove_material(self, material): | ||
| 100 | if material in self.materials: | 100 | if material in self.materials: | ||
| 101 | self.materials.remove(material) | 101 | self.materials.remove(material) | ||
| 102 | self.__class__.all_materials.remove(material) | 102 | self.__class__.all_materials.remove(material) | ||
| 103 | 103 | ||||
| 104 | @property | 104 | @property | ||
| 105 | def volume(self): | 105 | def volume(self): | ||
| 106 | volume = 0 | 106 | volume = 0 | ||
| 107 | for item in self.materials: | 107 | for item in self.materials: | ||
| 108 | volume += item.volume | 108 | volume += item.volume | ||
| 109 | return volume | 109 | return volume | ||
| 110 | 110 | ||||
| 111 | def can_build(self, desired_volume): | 111 | def can_build(self, desired_volume): | ||
| 112 | return desired_volume <= self.volume | 112 | return desired_volume <= self.volume | ||
| 113 | 113 | ||||
| 114 | @classmethod | 114 | @classmethod | ||
| 115 | def can_build_together(cls, desired_volume): | 115 | def can_build_together(cls, desired_volume): | ||
| 116 | volume = 0 | 116 | volume = 0 | ||
| 117 | for item in cls.all_materials: | 117 | for item in cls.all_materials: | ||
| 118 | volume += item.volume | 118 | volume += item.volume | ||
| 119 | return desired_volume <= volume | 119 | return desired_volume <= volume |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||