1class Material:
2 density: float
3 def __init__(self, mass):
4 self.mass = mass
5 self.volume = float(mass / self.density)
6 self.valid = True
7
8
9
10class Concrete(Material):
11 density = 2500
12
13class Brick(Material):
14 density = 2000
15
16class Stone(Material):
17 density = 1600
18
19class Wood(Material):
20 density = 600
21
22class Steel(Material):
23 density = 7700
24
25material_classes={"Concrete": Concrete, "Brick": Brick, "Stone": Stone, "Wood": Wood, "Steel": Steel}
26
27class Factory:
28 _total_volume = 0.0
29
30 def __init__(self):
31 self.volume = 0.0
32
33 def __create_materials(self, kwds):
34 try:
35 materials = [material_classes[name](val) for name, val in kwds.items()]
36 if not all(isinstance(obj, Material) for obj in materials):
37 raise ValueError("Factory instance cannot be called with parameter names which are not materials!")
38 self.volume += sum([material.volume for material in materials])
39 type(self)._total_volume += sum([material.volume for material in materials])
40 return tuple(materials)
41 except:
42 raise ValueError("Factory instance cannot be called with parameter names which are not materials!")
43
44 def __make_alloy(self, result_class, result_mass, volume_to_erase):
45 result_material = material_classes[result_class](result_mass)
46 self.volume -= volume_to_erase
47 self.volume += result_material.volume
48 type(self)._total_volume -= volume_to_erase
49 type(self)._total_volume += result_material.volume
50 return result_material
51
52 def __create_new_material(self, args):
53 if any(not material.valid for material in args):
54 raise AssertionError("Factory instance cannot take already used materials!")
55 for material in args:
56 material.valid = False
57 volume_to_erase = sum([material.volume for material in args])
58 arg_material_names = [material.__class__.__name__ for material in args]
59 arg_material_names = [material for combination in arg_material_names for material in combination.split("_")]
60 arg_material_names.sort()
61 result_class = "_".join(arg_material_names)
62 result_mass = sum([material.mass for material in args ])
63 try:
64 return self.__make_alloy(result_class, result_mass, volume_to_erase)
65 except:
66 new_density: float = sum(material_classes[material].density for material in arg_material_names) / len(arg_material_names)
67 material_classes[result_class] = type(result_class,(Material, ),{'density': new_density,})
68 return self.__make_alloy(result_class, result_mass, volume_to_erase)
69
70 def __call__(self, *args, **kwds):
71 if not args and not kwds:
72 raise ValueError("Factory instance cannot be called without parameters!")
73 if args and kwds:
74 raise ValueError("Factory instance cannot be called with both positional and named parameters!")
75 if kwds:
76 return self.__create_materials(kwds)
77 if args:
78 return self.__create_new_material(args)
79
80 def can_build(self, required_volume):
81 return self.volume >= required_volume
82
83 @classmethod
84 def can_build_together(cls, required_volume):
85 return cls._total_volume >= required_volume
86
..........
----------------------------------------------------------------------
Ran 10 tests in 0.012s
OK
Виктор Бечев
22.11.2024 14:04Не пречи, но не го прави по-добър вариант. Design decision е, няма някакво еднозначно предимство да "забраняваш" външния достъп, в крайна сметка е напълно окей дизайнът ти да дава правото на външни за класът обекти да четат класовите атрибути.
|
Дейвид Барух
22.11.2024 09:52ем правя го само заради ооп концепцията, да няма външен достъп до промяна на density за материал, предполагам че не пречи 😅
|
Виктор Бечев
22.11.2024 02:09Мммм, добре, gotcha, не го догледах. Щом държиш `_density` да е protected - ще трябва да е така, съгласен, другите варианти са езотерични. Then again, няма много смисъл да е protected, не печелиш нищо.
|
Дейвид Барух
21.11.2024 22:28нее тва нарочно е клас метод за да може да го достъпвам от класа без да има инстанция : @classmethod
def get_density(cls): , може би по-удачно ще е да му сменя името
|
Дейвид Барух
21.11.2024 19:47този метод да не го променям :
``` @classmethod
def can_build_together(cls, required_volume):
return cls._total_volume >= required_volume``` `
имам предвид си го оставя class method
|
Дейвид Барух
20.11.2024 13:48Да на използваните трябва да се извадят
|
Виктор Бечев
20.11.2024 13:46Всъщност си разбрал правилно, методите следва да проверяват за индивидуална фабрика и за всички фабрики взети заедно, дали обемите на произведените, но не преизползвани материали, стигат за изработването на стена с даден размер.
|
Дейвид Барух
20.11.2024 13:38can_build не разбрах много какво трябва да прави. Трябва да събираме volume-а на всички създадени от фабриката материали и да се гледа дали входния параметър на can_build функцията е по- малък от volume-ма на текущата инстация на Factory?
|
f | 1 | class Material: | f | 1 | class Material: |
2 | density: float | 2 | density: float | ||
3 | def __init__(self, mass): | 3 | def __init__(self, mass): | ||
4 | self.mass = mass | 4 | self.mass = mass | ||
5 | self.volume = float(mass / self.density) | 5 | self.volume = float(mass / self.density) | ||
6 | self.valid = True | 6 | self.valid = True | ||
7 | 7 | ||||
8 | 8 | ||||
9 | 9 | ||||
10 | class Concrete(Material): | 10 | class Concrete(Material): | ||
11 | density = 2500 | 11 | density = 2500 | ||
12 | 12 | ||||
13 | class Brick(Material): | 13 | class Brick(Material): | ||
14 | density = 2000 | 14 | density = 2000 | ||
15 | 15 | ||||
16 | class Stone(Material): | 16 | class Stone(Material): | ||
17 | density = 1600 | 17 | density = 1600 | ||
18 | 18 | ||||
19 | class Wood(Material): | 19 | class Wood(Material): | ||
20 | density = 600 | 20 | density = 600 | ||
21 | 21 | ||||
22 | class Steel(Material): | 22 | class Steel(Material): | ||
23 | density = 7700 | 23 | density = 7700 | ||
24 | 24 | ||||
25 | material_classes={"Concrete": Concrete, "Brick": Brick, "Stone": Stone, "Wood": Wood, "Steel": Steel} | 25 | material_classes={"Concrete": Concrete, "Brick": Brick, "Stone": Stone, "Wood": Wood, "Steel": Steel} | ||
26 | 26 | ||||
27 | class Factory: | 27 | class Factory: | ||
28 | _total_volume = 0.0 | 28 | _total_volume = 0.0 | ||
29 | 29 | ||||
30 | def __init__(self): | 30 | def __init__(self): | ||
31 | self.volume = 0.0 | 31 | self.volume = 0.0 | ||
32 | 32 | ||||
33 | def __create_materials(self, kwds): | 33 | def __create_materials(self, kwds): | ||
34 | try: | 34 | try: | ||
35 | materials = [material_classes[name](val) for name, val in kwds.items()] | 35 | materials = [material_classes[name](val) for name, val in kwds.items()] | ||
36 | if not all(isinstance(obj, Material) for obj in materials): | 36 | if not all(isinstance(obj, Material) for obj in materials): | ||
37 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | 37 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | ||
38 | self.volume += sum([material.volume for material in materials]) | 38 | self.volume += sum([material.volume for material in materials]) | ||
39 | type(self)._total_volume += sum([material.volume for material in materials]) | 39 | type(self)._total_volume += sum([material.volume for material in materials]) | ||
40 | return tuple(materials) | 40 | return tuple(materials) | ||
41 | except: | 41 | except: | ||
42 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | 42 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | ||
43 | 43 | ||||
44 | def __make_alloy(self, result_class, result_mass, volume_to_erase): | 44 | def __make_alloy(self, result_class, result_mass, volume_to_erase): | ||
45 | result_material = material_classes[result_class](result_mass) | 45 | result_material = material_classes[result_class](result_mass) | ||
46 | self.volume -= volume_to_erase | 46 | self.volume -= volume_to_erase | ||
47 | self.volume += result_material.volume | 47 | self.volume += result_material.volume | ||
48 | type(self)._total_volume -= volume_to_erase | 48 | type(self)._total_volume -= volume_to_erase | ||
49 | type(self)._total_volume += result_material.volume | 49 | type(self)._total_volume += result_material.volume | ||
50 | return result_material | 50 | return result_material | ||
51 | 51 | ||||
52 | def __create_new_material(self, args): | 52 | def __create_new_material(self, args): | ||
53 | if any(not material.valid for material in args): | 53 | if any(not material.valid for material in args): | ||
54 | raise AssertionError("Factory instance cannot take already used materials!") | 54 | raise AssertionError("Factory instance cannot take already used materials!") | ||
55 | for material in args: | 55 | for material in args: | ||
56 | material.valid = False | 56 | material.valid = False | ||
57 | volume_to_erase = sum([material.volume for material in args]) | 57 | volume_to_erase = sum([material.volume for material in args]) | ||
58 | arg_material_names = [material.__class__.__name__ for material in args] | 58 | arg_material_names = [material.__class__.__name__ for material in args] | ||
59 | arg_material_names = [material for combination in arg_material_names for material in combination.split("_")] | 59 | arg_material_names = [material for combination in arg_material_names for material in combination.split("_")] | ||
60 | arg_material_names.sort() | 60 | arg_material_names.sort() | ||
61 | result_class = "_".join(arg_material_names) | 61 | result_class = "_".join(arg_material_names) | ||
62 | result_mass = sum([material.mass for material in args ]) | 62 | result_mass = sum([material.mass for material in args ]) | ||
63 | try: | 63 | try: | ||
64 | return self.__make_alloy(result_class, result_mass, volume_to_erase) | 64 | return self.__make_alloy(result_class, result_mass, volume_to_erase) | ||
65 | except: | 65 | except: | ||
66 | new_density: float = sum(material_classes[material].density for material in arg_material_names) / len(arg_material_names) | 66 | new_density: float = sum(material_classes[material].density for material in arg_material_names) / len(arg_material_names) | ||
67 | material_classes[result_class] = type(result_class,(Material, ),{'density': new_density,}) | 67 | material_classes[result_class] = type(result_class,(Material, ),{'density': new_density,}) | ||
68 | return self.__make_alloy(result_class, result_mass, volume_to_erase) | 68 | return self.__make_alloy(result_class, result_mass, volume_to_erase) | ||
69 | 69 | ||||
70 | def __call__(self, *args, **kwds): | 70 | def __call__(self, *args, **kwds): | ||
71 | if not args and not kwds: | 71 | if not args and not kwds: | ||
72 | raise ValueError("Factory instance cannot be called without parameters!") | 72 | raise ValueError("Factory instance cannot be called without parameters!") | ||
73 | if args and kwds: | 73 | if args and kwds: | ||
74 | raise ValueError("Factory instance cannot be called with both positional and named parameters!") | 74 | raise ValueError("Factory instance cannot be called with both positional and named parameters!") | ||
75 | if kwds: | 75 | if kwds: | ||
76 | return self.__create_materials(kwds) | 76 | return self.__create_materials(kwds) | ||
77 | if args: | 77 | if args: | ||
78 | return self.__create_new_material(args) | 78 | return self.__create_new_material(args) | ||
79 | 79 | ||||
80 | def can_build(self, required_volume): | 80 | def can_build(self, required_volume): | ||
81 | return self.volume >= required_volume | 81 | return self.volume >= required_volume | ||
82 | 82 | ||||
83 | @classmethod | 83 | @classmethod | ||
84 | def can_build_together(cls, required_volume): | 84 | def can_build_together(cls, required_volume): | ||
85 | return cls._total_volume >= required_volume | 85 | return cls._total_volume >= required_volume | ||
86 | 86 | ||||
87 | 87 | ||||
t | 88 | factory1 = Factory() | t | ||
89 | brick1, wood1 = factory1(Brick=2000, Wood=1200) | ||||
90 | print(brick1.volume) # 1.0 | ||||
91 | print(wood1.volume) # 2.0 | ||||
92 | brick_wood1 = factory1(brick1, wood1) | ||||
93 | print(brick_wood1.volume) # 2.46... | ||||
94 | print(factory1.can_build(3)) # False | ||||
95 | |||||
96 | factory2 = Factory() | ||||
97 | brick2, wood2 = factory2(Brick=2000, Wood=1200) | ||||
98 | print(brick2.volume) # 1.0 | ||||
99 | print(wood2.volume) # 2.0 | ||||
100 | brick_wood2 = factory2(brick2, wood2) | ||||
101 | print(brick_wood2.volume) # 2.46... | ||||
102 | print(factory2.can_build(3)) # False | ||||
103 | |||||
104 | print(Factory.can_build_together(3)) # True |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | class Material: | f | 1 | class Material: |
n | 2 | _density: float | n | 2 | density: float |
3 | def __init__(self, mass): | 3 | def __init__(self, mass): | ||
4 | self.mass = mass | 4 | self.mass = mass | ||
n | 5 | self.volume = float(mass / self._density) | n | 5 | self.volume = float(mass / self.density) |
6 | self.valid = True | 6 | self.valid = True | ||
7 | 7 | ||||
n | 8 | @classmethod | n | 8 | |
9 | def density(cls): | ||||
10 | return cls._density | ||||
11 | 9 | ||||
12 | class Concrete(Material): | 10 | class Concrete(Material): | ||
n | 13 | _density = 2500 | n | 11 | density = 2500 |
14 | 12 | ||||
15 | class Brick(Material): | 13 | class Brick(Material): | ||
n | 16 | _density = 2000 | n | 14 | density = 2000 |
17 | 15 | ||||
18 | class Stone(Material): | 16 | class Stone(Material): | ||
n | 19 | _density = 1600 | n | 17 | density = 1600 |
20 | 18 | ||||
21 | class Wood(Material): | 19 | class Wood(Material): | ||
n | 22 | _density = 600 | n | 20 | density = 600 |
23 | 21 | ||||
24 | class Steel(Material): | 22 | class Steel(Material): | ||
n | 25 | _density = 7700 | n | 23 | density = 7700 |
26 | 24 | ||||
27 | material_classes={"Concrete": Concrete, "Brick": Brick, "Stone": Stone, "Wood": Wood, "Steel": Steel} | 25 | material_classes={"Concrete": Concrete, "Brick": Brick, "Stone": Stone, "Wood": Wood, "Steel": Steel} | ||
28 | 26 | ||||
29 | class Factory: | 27 | class Factory: | ||
30 | _total_volume = 0.0 | 28 | _total_volume = 0.0 | ||
31 | 29 | ||||
32 | def __init__(self): | 30 | def __init__(self): | ||
33 | self.volume = 0.0 | 31 | self.volume = 0.0 | ||
34 | 32 | ||||
35 | def __create_materials(self, kwds): | 33 | def __create_materials(self, kwds): | ||
36 | try: | 34 | try: | ||
37 | materials = [material_classes[name](val) for name, val in kwds.items()] | 35 | materials = [material_classes[name](val) for name, val in kwds.items()] | ||
38 | if not all(isinstance(obj, Material) for obj in materials): | 36 | if not all(isinstance(obj, Material) for obj in materials): | ||
39 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | 37 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | ||
40 | self.volume += sum([material.volume for material in materials]) | 38 | self.volume += sum([material.volume for material in materials]) | ||
41 | type(self)._total_volume += sum([material.volume for material in materials]) | 39 | type(self)._total_volume += sum([material.volume for material in materials]) | ||
42 | return tuple(materials) | 40 | return tuple(materials) | ||
43 | except: | 41 | except: | ||
44 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | 42 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | ||
45 | 43 | ||||
46 | def __make_alloy(self, result_class, result_mass, volume_to_erase): | 44 | def __make_alloy(self, result_class, result_mass, volume_to_erase): | ||
47 | result_material = material_classes[result_class](result_mass) | 45 | result_material = material_classes[result_class](result_mass) | ||
48 | self.volume -= volume_to_erase | 46 | self.volume -= volume_to_erase | ||
49 | self.volume += result_material.volume | 47 | self.volume += result_material.volume | ||
50 | type(self)._total_volume -= volume_to_erase | 48 | type(self)._total_volume -= volume_to_erase | ||
51 | type(self)._total_volume += result_material.volume | 49 | type(self)._total_volume += result_material.volume | ||
52 | return result_material | 50 | return result_material | ||
53 | 51 | ||||
54 | def __create_new_material(self, args): | 52 | def __create_new_material(self, args): | ||
55 | if any(not material.valid for material in args): | 53 | if any(not material.valid for material in args): | ||
56 | raise AssertionError("Factory instance cannot take already used materials!") | 54 | raise AssertionError("Factory instance cannot take already used materials!") | ||
57 | for material in args: | 55 | for material in args: | ||
58 | material.valid = False | 56 | material.valid = False | ||
59 | volume_to_erase = sum([material.volume for material in args]) | 57 | volume_to_erase = sum([material.volume for material in args]) | ||
60 | arg_material_names = [material.__class__.__name__ for material in args] | 58 | arg_material_names = [material.__class__.__name__ for material in args] | ||
61 | arg_material_names = [material for combination in arg_material_names for material in combination.split("_")] | 59 | arg_material_names = [material for combination in arg_material_names for material in combination.split("_")] | ||
62 | arg_material_names.sort() | 60 | arg_material_names.sort() | ||
63 | result_class = "_".join(arg_material_names) | 61 | result_class = "_".join(arg_material_names) | ||
64 | result_mass = sum([material.mass for material in args ]) | 62 | result_mass = sum([material.mass for material in args ]) | ||
65 | try: | 63 | try: | ||
66 | return self.__make_alloy(result_class, result_mass, volume_to_erase) | 64 | return self.__make_alloy(result_class, result_mass, volume_to_erase) | ||
67 | except: | 65 | except: | ||
n | 68 | new_density: float = sum(material_classes[material].density() for material in arg_material_names) / len(arg_material_names) | n | 66 | new_density: float = sum(material_classes[material].density for material in arg_material_names) / len(arg_material_names) |
69 | material_classes[result_class] = type(result_class,(Material, ),{'_density': new_density,}) | 67 | material_classes[result_class] = type(result_class,(Material, ),{'density': new_density,}) | ||
70 | return self.__make_alloy(result_class, result_mass, volume_to_erase) | 68 | return self.__make_alloy(result_class, result_mass, volume_to_erase) | ||
71 | 69 | ||||
72 | def __call__(self, *args, **kwds): | 70 | def __call__(self, *args, **kwds): | ||
73 | if not args and not kwds: | 71 | if not args and not kwds: | ||
74 | raise ValueError("Factory instance cannot be called without parameters!") | 72 | raise ValueError("Factory instance cannot be called without parameters!") | ||
75 | if args and kwds: | 73 | if args and kwds: | ||
76 | raise ValueError("Factory instance cannot be called with both positional and named parameters!") | 74 | raise ValueError("Factory instance cannot be called with both positional and named parameters!") | ||
77 | if kwds: | 75 | if kwds: | ||
78 | return self.__create_materials(kwds) | 76 | return self.__create_materials(kwds) | ||
79 | if args: | 77 | if args: | ||
80 | return self.__create_new_material(args) | 78 | return self.__create_new_material(args) | ||
81 | 79 | ||||
82 | def can_build(self, required_volume): | 80 | def can_build(self, required_volume): | ||
n | 83 | print("self.volume :",self.volume) | n | ||
84 | return self.volume >= required_volume | 81 | return self.volume >= required_volume | ||
85 | 82 | ||||
86 | @classmethod | 83 | @classmethod | ||
87 | def can_build_together(cls, required_volume): | 84 | def can_build_together(cls, required_volume): | ||
88 | return cls._total_volume >= required_volume | 85 | return cls._total_volume >= required_volume | ||
89 | 86 | ||||
90 | 87 | ||||
t | t | 88 | factory1 = Factory() | ||
89 | brick1, wood1 = factory1(Brick=2000, Wood=1200) | ||||
90 | print(brick1.volume) # 1.0 | ||||
91 | print(wood1.volume) # 2.0 | ||||
92 | brick_wood1 = factory1(brick1, wood1) | ||||
93 | print(brick_wood1.volume) # 2.46... | ||||
94 | print(factory1.can_build(3)) # False | ||||
95 | |||||
96 | factory2 = Factory() | ||||
97 | brick2, wood2 = factory2(Brick=2000, Wood=1200) | ||||
98 | print(brick2.volume) # 1.0 | ||||
99 | print(wood2.volume) # 2.0 | ||||
100 | brick_wood2 = factory2(brick2, wood2) | ||||
101 | print(brick_wood2.volume) # 2.46... | ||||
102 | print(factory2.can_build(3)) # False | ||||
103 | |||||
104 | print(Factory.can_build_together(3)) # True |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | class Material: | f | 1 | class Material: |
2 | _density: float | 2 | _density: float | ||
3 | def __init__(self, mass): | 3 | def __init__(self, mass): | ||
4 | self.mass = mass | 4 | self.mass = mass | ||
5 | self.volume = float(mass / self._density) | 5 | self.volume = float(mass / self._density) | ||
6 | self.valid = True | 6 | self.valid = True | ||
n | n | 7 | |||
7 | @classmethod | 8 | @classmethod | ||
n | 8 | def get_density(cls): | n | 9 | def density(cls): |
9 | return cls._density | 10 | return cls._density | ||
10 | 11 | ||||
11 | class Concrete(Material): | 12 | class Concrete(Material): | ||
12 | _density = 2500 | 13 | _density = 2500 | ||
13 | 14 | ||||
14 | class Brick(Material): | 15 | class Brick(Material): | ||
15 | _density = 2000 | 16 | _density = 2000 | ||
16 | 17 | ||||
17 | class Stone(Material): | 18 | class Stone(Material): | ||
18 | _density = 1600 | 19 | _density = 1600 | ||
19 | 20 | ||||
20 | class Wood(Material): | 21 | class Wood(Material): | ||
21 | _density = 600 | 22 | _density = 600 | ||
22 | 23 | ||||
23 | class Steel(Material): | 24 | class Steel(Material): | ||
24 | _density = 7700 | 25 | _density = 7700 | ||
25 | 26 | ||||
n | n | 27 | material_classes={"Concrete": Concrete, "Brick": Brick, "Stone": Stone, "Wood": Wood, "Steel": Steel} | ||
28 | |||||
26 | class Factory: | 29 | class Factory: | ||
27 | _total_volume = 0.0 | 30 | _total_volume = 0.0 | ||
28 | 31 | ||||
29 | def __init__(self): | 32 | def __init__(self): | ||
30 | self.volume = 0.0 | 33 | self.volume = 0.0 | ||
31 | 34 | ||||
n | n | 35 | def __create_materials(self, kwds): | ||
36 | try: | ||||
37 | materials = [material_classes[name](val) for name, val in kwds.items()] | ||||
38 | if not all(isinstance(obj, Material) for obj in materials): | ||||
39 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | ||||
40 | self.volume += sum([material.volume for material in materials]) | ||||
41 | type(self)._total_volume += sum([material.volume for material in materials]) | ||||
42 | return tuple(materials) | ||||
43 | except: | ||||
44 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | ||||
45 | |||||
46 | def __make_alloy(self, result_class, result_mass, volume_to_erase): | ||||
47 | result_material = material_classes[result_class](result_mass) | ||||
48 | self.volume -= volume_to_erase | ||||
49 | self.volume += result_material.volume | ||||
50 | type(self)._total_volume -= volume_to_erase | ||||
51 | type(self)._total_volume += result_material.volume | ||||
52 | return result_material | ||||
53 | |||||
54 | def __create_new_material(self, args): | ||||
55 | if any(not material.valid for material in args): | ||||
56 | raise AssertionError("Factory instance cannot take already used materials!") | ||||
57 | for material in args: | ||||
58 | material.valid = False | ||||
59 | volume_to_erase = sum([material.volume for material in args]) | ||||
60 | arg_material_names = [material.__class__.__name__ for material in args] | ||||
61 | arg_material_names = [material for combination in arg_material_names for material in combination.split("_")] | ||||
62 | arg_material_names.sort() | ||||
63 | result_class = "_".join(arg_material_names) | ||||
64 | result_mass = sum([material.mass for material in args ]) | ||||
65 | try: | ||||
66 | return self.__make_alloy(result_class, result_mass, volume_to_erase) | ||||
67 | except: | ||||
68 | new_density: float = sum(material_classes[material].density() for material in arg_material_names) / len(arg_material_names) | ||||
69 | material_classes[result_class] = type(result_class,(Material, ),{'_density': new_density,}) | ||||
70 | return self.__make_alloy(result_class, result_mass, volume_to_erase) | ||||
71 | |||||
32 | def __call__(self, *args, **kwds): | 72 | def __call__(self, *args, **kwds): | ||
33 | if not args and not kwds: | 73 | if not args and not kwds: | ||
34 | raise ValueError("Factory instance cannot be called without parameters!") | 74 | raise ValueError("Factory instance cannot be called without parameters!") | ||
35 | if args and kwds: | 75 | if args and kwds: | ||
36 | raise ValueError("Factory instance cannot be called with both positional and named parameters!") | 76 | raise ValueError("Factory instance cannot be called with both positional and named parameters!") | ||
37 | if kwds: | 77 | if kwds: | ||
n | 38 | try: | n | 78 | return self.__create_materials(kwds) |
39 | materials = [globals()[name](val) for name, val in kwds.items()] | ||||
40 | if not all(isinstance(obj, Material) for obj in materials): | ||||
41 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | ||||
42 | self.volume += sum([material.volume for material in materials]) | ||||
43 | type(self)._total_volume += sum([material.volume for material in materials]) | ||||
44 | return tuple(materials) | ||||
45 | except: | ||||
46 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | ||||
47 | if args: | 79 | if args: | ||
n | 48 | if any(not material.valid for material in args): | n | 80 | return self.__create_new_material(args) |
49 | raise AssertionError("Factory instance cannot take already used materials!") | ||||
50 | for material in args: | ||||
51 | material.valid = False | ||||
52 | volume_to_erase = sum([material.volume for material in args]) | ||||
53 | arg_material_names = [material.__class__.__name__ for material in args] | ||||
54 | arg_material_names = [material for combination in arg_material_names for material in combination.split("_")] | ||||
55 | arg_material_names.sort() | ||||
56 | result_class = "_".join(arg_material_names) | ||||
57 | result_mass = sum([material.mass for material in args ]) | ||||
58 | try: | ||||
59 | result_material = globals()[result_class](result_mass) | ||||
60 | self.volume -= volume_to_erase | ||||
61 | self.volume += result_material.volume | ||||
62 | type(self)._total_volume -= volume_to_erase | ||||
63 | type(self)._total_volume += result_material.volume | ||||
64 | return result_material | ||||
65 | except: | ||||
66 | new_density: float = sum(globals()[material].get_density() for material in arg_material_names) / len(arg_material_names) | ||||
67 | globals()[result_class] = type(result_class,(Material, ),{'_density': new_density,}) | ||||
68 | result_material = globals()[result_class](result_mass) | ||||
69 | self.volume -= volume_to_erase | ||||
70 | self.volume += result_material.volume | ||||
71 | type(self)._total_volume -= volume_to_erase | ||||
72 | type(self)._total_volume += result_material.volume | ||||
73 | return result_material | ||||
74 | 81 | ||||
75 | def can_build(self, required_volume): | 82 | def can_build(self, required_volume): | ||
76 | print("self.volume :",self.volume) | 83 | print("self.volume :",self.volume) | ||
77 | return self.volume >= required_volume | 84 | return self.volume >= required_volume | ||
78 | 85 | ||||
79 | @classmethod | 86 | @classmethod | ||
80 | def can_build_together(cls, required_volume): | 87 | def can_build_together(cls, required_volume): | ||
81 | return cls._total_volume >= required_volume | 88 | return cls._total_volume >= required_volume | ||
n | n | 89 | |||
82 | 90 | ||||
t | 83 | t | |||
84 | |||||
85 | |||||
86 |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | class Material: | f | 1 | class Material: |
2 | _density: float | 2 | _density: float | ||
3 | def __init__(self, mass): | 3 | def __init__(self, mass): | ||
4 | self.mass = mass | 4 | self.mass = mass | ||
5 | self.volume = float(mass / self._density) | 5 | self.volume = float(mass / self._density) | ||
6 | self.valid = True | 6 | self.valid = True | ||
7 | @classmethod | 7 | @classmethod | ||
8 | def get_density(cls): | 8 | def get_density(cls): | ||
9 | return cls._density | 9 | return cls._density | ||
10 | 10 | ||||
11 | class Concrete(Material): | 11 | class Concrete(Material): | ||
12 | _density = 2500 | 12 | _density = 2500 | ||
13 | 13 | ||||
14 | class Brick(Material): | 14 | class Brick(Material): | ||
15 | _density = 2000 | 15 | _density = 2000 | ||
16 | 16 | ||||
17 | class Stone(Material): | 17 | class Stone(Material): | ||
18 | _density = 1600 | 18 | _density = 1600 | ||
19 | 19 | ||||
20 | class Wood(Material): | 20 | class Wood(Material): | ||
21 | _density = 600 | 21 | _density = 600 | ||
22 | 22 | ||||
23 | class Steel(Material): | 23 | class Steel(Material): | ||
24 | _density = 7700 | 24 | _density = 7700 | ||
25 | 25 | ||||
26 | class Factory: | 26 | class Factory: | ||
27 | _total_volume = 0.0 | 27 | _total_volume = 0.0 | ||
28 | 28 | ||||
29 | def __init__(self): | 29 | def __init__(self): | ||
30 | self.volume = 0.0 | 30 | self.volume = 0.0 | ||
31 | 31 | ||||
32 | def __call__(self, *args, **kwds): | 32 | def __call__(self, *args, **kwds): | ||
33 | if not args and not kwds: | 33 | if not args and not kwds: | ||
34 | raise ValueError("Factory instance cannot be called without parameters!") | 34 | raise ValueError("Factory instance cannot be called without parameters!") | ||
35 | if args and kwds: | 35 | if args and kwds: | ||
36 | raise ValueError("Factory instance cannot be called with both positional and named parameters!") | 36 | raise ValueError("Factory instance cannot be called with both positional and named parameters!") | ||
37 | if kwds: | 37 | if kwds: | ||
38 | try: | 38 | try: | ||
39 | materials = [globals()[name](val) for name, val in kwds.items()] | 39 | materials = [globals()[name](val) for name, val in kwds.items()] | ||
40 | if not all(isinstance(obj, Material) for obj in materials): | 40 | if not all(isinstance(obj, Material) for obj in materials): | ||
41 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | 41 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | ||
42 | self.volume += sum([material.volume for material in materials]) | 42 | self.volume += sum([material.volume for material in materials]) | ||
43 | type(self)._total_volume += sum([material.volume for material in materials]) | 43 | type(self)._total_volume += sum([material.volume for material in materials]) | ||
44 | return tuple(materials) | 44 | return tuple(materials) | ||
45 | except: | 45 | except: | ||
46 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | 46 | raise ValueError("Factory instance cannot be called with parameter names which are not materials!") | ||
47 | if args: | 47 | if args: | ||
48 | if any(not material.valid for material in args): | 48 | if any(not material.valid for material in args): | ||
49 | raise AssertionError("Factory instance cannot take already used materials!") | 49 | raise AssertionError("Factory instance cannot take already used materials!") | ||
50 | for material in args: | 50 | for material in args: | ||
51 | material.valid = False | 51 | material.valid = False | ||
n | n | 52 | volume_to_erase = sum([material.volume for material in args]) | ||
52 | arg_material_names = [material.__class__.__name__ for material in args] | 53 | arg_material_names = [material.__class__.__name__ for material in args] | ||
53 | arg_material_names = [material for combination in arg_material_names for material in combination.split("_")] | 54 | arg_material_names = [material for combination in arg_material_names for material in combination.split("_")] | ||
54 | arg_material_names.sort() | 55 | arg_material_names.sort() | ||
55 | result_class = "_".join(arg_material_names) | 56 | result_class = "_".join(arg_material_names) | ||
56 | result_mass = sum([material.mass for material in args ]) | 57 | result_mass = sum([material.mass for material in args ]) | ||
57 | try: | 58 | try: | ||
58 | result_material = globals()[result_class](result_mass) | 59 | result_material = globals()[result_class](result_mass) | ||
n | n | 60 | self.volume -= volume_to_erase | ||
59 | self.volume += result_material.volume | 61 | self.volume += result_material.volume | ||
n | n | 62 | type(self)._total_volume -= volume_to_erase | ||
60 | type(self)._total_volume += result_material.volume | 63 | type(self)._total_volume += result_material.volume | ||
61 | return result_material | 64 | return result_material | ||
62 | except: | 65 | except: | ||
63 | new_density: float = sum(globals()[material].get_density() for material in arg_material_names) / len(arg_material_names) | 66 | new_density: float = sum(globals()[material].get_density() for material in arg_material_names) / len(arg_material_names) | ||
64 | globals()[result_class] = type(result_class,(Material, ),{'_density': new_density,}) | 67 | globals()[result_class] = type(result_class,(Material, ),{'_density': new_density,}) | ||
65 | result_material = globals()[result_class](result_mass) | 68 | result_material = globals()[result_class](result_mass) | ||
n | n | 69 | self.volume -= volume_to_erase | ||
66 | self.volume += result_material.volume | 70 | self.volume += result_material.volume | ||
n | n | 71 | type(self)._total_volume -= volume_to_erase | ||
67 | type(self)._total_volume += result_material.volume | 72 | type(self)._total_volume += result_material.volume | ||
68 | return result_material | 73 | return result_material | ||
69 | 74 | ||||
70 | def can_build(self, required_volume): | 75 | def can_build(self, required_volume): | ||
71 | print("self.volume :",self.volume) | 76 | print("self.volume :",self.volume) | ||
72 | return self.volume >= required_volume | 77 | return self.volume >= required_volume | ||
73 | 78 | ||||
74 | @classmethod | 79 | @classmethod | ||
75 | def can_build_together(cls, required_volume): | 80 | def can_build_together(cls, required_volume): | ||
76 | return cls._total_volume >= required_volume | 81 | return cls._total_volume >= required_volume | ||
77 | 82 | ||||
n | 78 | n | |||
79 | 83 | ||||
80 | 84 | ||||
81 | 85 | ||||
t | t | 86 |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|