Домашни > Another brick in the wall > Решения > Решението на Христо Исов

Резултати
5 точки от тестове
0 точки от учител

5 точки общо

5 успешни теста
5 неуспешни теста
Код
Скрий всички коментари

  1class Material:
  2    def __init__(self, mass: int):
  3        self.mass = mass
  4        self.__used = False
  5
  6    @property
  7    def volume(self) -> float:
  8        return self.mass / self.density
  9
 10    def mark_as_used(self):
 11        self.__used = True
 12
 13    def is_used(self):
 14        return self.__used
 15
 16
 17class Concrete(Material):
 18    density = 2500
 19
 20
 21class Brick(Material):
 22    density = 2000
 23
 24
 25class Stone(Material):
 26    density = 1600
 27
 28
 29class Wood(Material):
 30    density = 600
 31
 32
 33class Steel(Material):
 34    density = 7700
 35
 36
 37class Factory:
 38    def __init__(self):
 39        self._existing_classes = {
 40            'Concrete': Concrete,
 41            'Brick': Brick,
 42            'Stone': Stone,
 43            'Wood': Wood,
 44            'Steel': Steel,
 45        }
 46        self._created_instances = []
 47        self._dynamic_classes = {}
 48
 49    def __call__(self, *args, **kwargs):
 50        if kwargs and args:
 51            raise ValueError("ValueError с произволен текст.")
 52
 53        if kwargs:
 54            return self._create_materials_by_name(kwargs)
 55
 56        if args:
 57            return self._create_materials_by_instance(args)
 58
 59        raise ValueError("ValueError с произволен текст.")
 60
 61    def _create_materials_by_name(self, materials: dict):
 62        result = []
 63        for name, mass in materials.items():
 64            if name not in self._existing_classes:
 65                raise ValueError("ValueError с произволен текст.")
 66
 67            material_class = self._existing_classes[name]
 68            instance = material_class(mass)
 69            result.append(instance)
 70            self._created_instances.append(instance)
 71
 72        return tuple(result)
 73
 74    def _create_materials_by_instance(self, materials: tuple):
 75        self._validate_materials(materials)
 76        self._mark_materials_as_used(materials)
 77        class_name = self._generate_class_name(materials)
 78        alloy_class = self._get_or_create_alloy_class(class_name, materials)
 79        total_mass = self._calculate_total_mass(materials)
 80        instance = alloy_class(total_mass)
 81        self._created_instances.append(instance)
 82        return instance
 83
 84    def _validate_materials(self, materials):
 85        for material in materials:
 86            if material.is_used():
 87                raise AssertionError("Material вече е използван.")
 88            if not isinstance(material, Material):
 89                raise ValueError("ValueError с произволен текст.")
 90
 91    def _mark_materials_as_used(self, materials):
 92        for material in materials:
 93            material.mark_as_used()
 94
 95    def _generate_class_name(self, materials):
 96        return "_".join(sorted(material.__class__.__name__ for material in materials))
 97
 98    def _get_or_create_alloy_class(self, class_name, materials):
 99        if class_name in self._dynamic_classes:
100            return self._dynamic_classes[class_name]
101
102        avg_density = self._calculate_average_density(materials)
103        alloy_class = type(
104            class_name,
105            (Material,),
106            {
107                'density': avg_density,
108            },
109        )
110        self._dynamic_classes[class_name] = alloy_class
111        return alloy_class
112
113    def _calculate_average_density(self, materials):
114        return sum(material.density for material in materials) / len(materials)
115
116    def _calculate_total_mass(self, materials):
117        return sum(material.mass for material in materials)
118
119    def can_build(self, volume_needed: float) -> bool:
120        total_volume = sum(material.volume for material in self._created_instances if not material.is_used())
121        print(f"Total unused volume: {total_volume}, Required volume: {volume_needed}")
122        return total_volume >= volume_needed

.E
Stdout:
Total unused volume: 2.0, Required volume: 2.000001
Total unused volume: 2.0, Required volume: 2.0
Total unused volume: 4.0, Required volume: 4.0001
Total unused volume: 4.0, Required volume: 4.0
E.E.FF..
======================================================================
ERROR: test_can_build (test.TestFactory.test_can_build)
Test can_build methods.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 177, in test_can_build
self.assertFalse(solution.Factory.can_build_together(6.0001))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: type object 'Factory' has no attribute 'can_build_together'

Stdout:
Total unused volume: 2.0, Required volume: 2.000001
Total unused volume: 2.0, Required volume: 2.0
Total unused volume: 4.0, Required volume: 4.0001
Total unused volume: 4.0, Required volume: 4.0

======================================================================
ERROR: test_materials_between_factories (test.TestFactory.test_materials_between_factories)
Test materials sharing.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 156, in test_materials_between_factories
result2, = self.factory2(Brick_Concrete_Steel_Stone_Wood=2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 54, in __call__
return self._create_materials_by_name(kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 65, in _create_materials_by_name
raise ValueError("ValueError с произволен текст.")
ValueError: ValueError с произволен текст.

======================================================================
ERROR: test_named_arguments_with_dynamically_created_classes (test.TestFactory.test_named_arguments_with_dynamically_created_classes)
Test dynamically created classes uniqueness.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 145, in test_named_arguments_with_dynamically_created_classes
result2, = self.factory1(Brick_Concrete_Steel_Stone_Wood=2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 54, in __call__
return self._create_materials_by_name(kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 65, in _create_materials_by_name
raise ValueError("ValueError с произволен текст.")
ValueError: ValueError с произволен текст.

======================================================================
FAIL: test_positional_arguments_multiple_argument_with_dynamics (test.TestFactory.test_positional_arguments_multiple_argument_with_dynamics)
Test calling a factory using multiple positional arguments.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 128, in test_positional_arguments_multiple_argument_with_dynamics
self.assertEqual(mega_material.__class__.__name__,
AssertionError: 'Brick_Concrete_Stone_Steel_Wood' != 'Brick_Concrete_Steel_Stone_Wood'
- Brick_Concrete_Stone_Steel_Wood
? ------
+ Brick_Concrete_Steel_Stone_Wood
? ++++++

======================================================================
FAIL: test_positional_arguments_single_argument (test.TestFactory.test_positional_arguments_single_argument)
Test calling a factory using a sigle positional argument.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 80, in test_positional_arguments_single_argument
self.assertIs(type(concrete2), solution.Concrete)
AssertionError: <class 'solution.Concrete'> is not <class 'solution.Concrete'>

----------------------------------------------------------------------
Ran 10 tests in 0.017s

FAILED (failures=2, errors=3)

Дискусия
Виктор Бечев
26.11.2024 16:34

Решението изглежда прилично разбито и спретнато, но надявам се знаеш, че ти липсва един от методите по условие - `can_build_together`.
История
Това решение има само една версия.