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 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|