From 0f508a1d59e723926f588059543b1fa47745c8d1 Mon Sep 17 00:00:00 2001 From: nad Date: Thu, 7 Mar 2019 17:07:59 +0100 Subject: [PATCH] first iteration models ratev2 --- ereuse_devicehub/resources/event/models.py | 526 +++++++++--------- .../resources/event/rate/workbench/v2_0.py | 290 +++++++++- 2 files changed, 552 insertions(+), 264 deletions(-) diff --git a/ereuse_devicehub/resources/event/models.py b/ereuse_devicehub/resources/event/models.py index bce40332..4f85ee28 100644 --- a/ereuse_devicehub/resources/event/models.py +++ b/ereuse_devicehub/resources/event/models.py @@ -651,7 +651,7 @@ class ManualRate(IndividualRate): raise NotImplementedError() -class WorkbenchComputerRate(ManualRate): +class ComputerRate(ManualRate): id = Column(UUID(as_uuid=True), ForeignKey(ManualRate.id), primary_key=True) processor = Column(Float(decimal_return_scale=2), check_range('processor', *RATE_POSITIVE)) ram = Column(Float(decimal_return_scale=2), check_range('ram', *RATE_POSITIVE)) @@ -697,172 +697,6 @@ class WorkbenchComputerRate(ManualRate): return RatingRange.from_score(self.graphic_card) -""" QUALITY RATE CODE START HERE """ - - -class QualityRate(Rate): - id = Column(UUID(as_uuid=True), ForeignKey(Rate.id), primary_key=True) - processor = Column(Float(decimal_return_scale=2), check_range('processor', *RATE_POSITIVE), - comment='Is a test explain cpu component.') - ram = Column(Float(decimal_return_scale=2), check_range('ram', *RATE_POSITIVE), - comment='RAM memory rate.') - data_storage = Column(Float(decimal_return_scale=2), check_range('data_storage', *RATE_POSITIVE), - comment='Data storage rate, like HHD, SSD.') - - @property - def ram_range(self): - return self.workbench.ram_range - - @property - def processor_range(self): - return self.workbench.processor_range - - @property - def display_range(self): - return self.workbench.data_storage_range - - @property - def data_storage_range(self): - return self.workbench.data_storage_range - - @property - def battery_range(self): - return self.workbench.ram_range - - @property - def camera_range(self): - return self.workbench_mobile.camera_range - - @property - def graphic_card_range(self): - return self.workbench_mobil.graphic_card_range - - -class QualityRateComputer(QualityRate): - id = Column(UUID(as_uuid=True), ForeignKey(QualityRate.id), primary_key=True) - processor = Column(Float(decimal_return_scale=2), check_range('processor', *RATE_POSITIVE), - comment='Is a test explain cpu component.') - ram = Column(Float(decimal_return_scale=2), check_range('ram', *RATE_POSITIVE), - comment='RAM memory rate.') - data_storage = Column(Float(decimal_return_scale=2), check_range('data_storage', *RATE_POSITIVE), - comment='Data storage rate, like HHD, SSD.') - - graphic_card = Column(Float(decimal_return_scale=2), check_range('graphic_card', *RATE_POSITIVE), - comment='Graphic card score in performance, amount of memory and benchmark result') - network_adapter = Column(Float(decimal_return_scale=2), check_range('network_adapter', *RATE_POSITIVE), - comment='Network adapter rate, take it speed limit') - - bios = Column(Float(decimal_return_scale=2), check_range('bios', *RATE_POSITIVE)) - bios_range = Column(DBEnum(Bios)) - bios_range.comment = Bios.__doc__ - - # todo ensure for WorkbenchRate version and software are not None when inserting them - - def ratings(self): - """ - #Computes all the possible rates taking this rating as a model. - - #Returns a set of ratings, including this one, which is mutated, - #and the final :class:`.AggregateRate`. - """ - from ereuse_devicehub.resources.event.rate.main import main - return main(self, **app.config.get_namespace('WORKBENCH_RATE_')) - - @property - def graphic_card_range(self): - if self.graphic_card: - return RatingRange.from_score(self.graphic_card) - - @property - def network_adapter_range(self): - return self.workbench_mobil.network_adapter_range - - @property - def bios_range(self): - return self.workbench_mobil.bios_range - - -class QualityRateMobile(QualityRate): - id = Column(UUID(as_uuid=True), ForeignKey(QualityRate.id), primary_key=True) - display = Column(Float(decimal_return_scale=2), check_range('display', *RATE_POSITIVE)) - display.comment = 'Display rate, screen resolution and size to calculate PPI and convert in score' - battery = Column(Float(decimal_return_scale=2), check_range('battery', *RATE_POSITIVE), - comment='Battery rate is related with capacity and its health') - camera = Column(Float(decimal_return_scale=2), check_range('camera', *RATE_POSITIVE), - comment='Camera rate take into account resolution') - - graphic_card = Column(Float(decimal_return_scale=2), check_range('graphic_card', *RATE_POSITIVE), - comment='Graphic card score in performance, amount of memory and benchmark result') - network_adapter = Column(Float(decimal_return_scale=2), check_range('network_adapter', *RATE_POSITIVE), - comment='Network adapter rate, take it speed limit') - - bios = Column(Float(decimal_return_scale=2), check_range('bios', *RATE_POSITIVE)) - bios_range = Column(DBEnum(Bios)) - bios_range.comment = Bios.__doc__ - - # todo ensure for WorkbenchRate version and software are not None when inserting them - - def ratings(self): - """ - #Computes all the possible rates taking this rating as a model. - """ - from ereuse_devicehub.resources.event.rate.main import main - return main(self, **app.config.get_namespace('WORKBENCH_RATE_')) - - @property - def display_range(self): - if self.data_storage: - return RatingRange.from_score(self.data_storage) - - @property - def battery_range(self): - if self.ram: - return RatingRange.from_score(self.ram) - - @property - def camera_range(self): - if self.processor: - return RatingRange.from_score(self.processor) - - @property - def graphic_card_range(self): - if self.graphic_card: - return RatingRange.from_score(self.graphic_card) - - -class FunctionalityRate(Rate): - id = Column(UUID(as_uuid=True), ForeignKey(Rate.id), primary_key=True) - functionality = Column(Float(decimal_return_scale=2), check_range('functionality', *FUNCTIONALITY_RANGE)) - functionality.comment = 'Functionality rate of a device' - - functionality_range = Column(DBEnum(FunctionalityRangev2)) - functionality_range.comment = FunctionalityRangev2.__doc__ - - connectivity = Column(Float(decimal_return_scale=2), - comment='This punctuation covers a series of aspects related to connectivity.') - audio = Column(Float(decimal_return_scale=2), comment='Take into account loudspeaker and microphone') - - @property - def connectivity_rate(self): - yield - - @property - def audio_rate(self): - yield - - @property - def test_buttonse(self): - yield - - @classmethod - def test_camera_defects(self): - yield - - -class FinalRate(Rate): - id = Column(UUID(as_uuid=True), ForeignKey(Rate.id), primary_key=True) - - class AggregateRate(Rate): id = Column(UUID(as_uuid=True), ForeignKey(Rate.id), primary_key=True) manual_id = Column(UUID(as_uuid=True), ForeignKey(ManualRate.id)) @@ -959,7 +793,186 @@ class AggregateRate(Rate): return aggregate -#################################################################################### +class EreusePrice(Price): + """The act of setting a price by guessing it using the eReuse.org + algorithm. + + This algorithm states that the price is the use value of the device + (represented by its last :class:`.Rate`) multiplied by a constants + value agreed by a circuit or platform. + """ + MULTIPLIER = { + Desktop: 20, + Laptop: 30 + } + + class Type: + def __init__(self, percentage: float, price: Decimal) -> None: + # see https://stackoverflow.com/a/29651462 for the - 0.005 + self.amount = EreusePrice.to_price(price * Decimal(percentage)) + self.percentage = EreusePrice.to_price(price * Decimal(percentage)) + self.percentage = round(percentage - 0.005, 2) + + class Service: + REFURBISHER, PLATFORM, RETAILER = 0, 1, 2 + STANDARD, WARRANTY2 = 'STD', 'WR2' + SCHEMA = { + Desktop: { + RatingRange.HIGH: { + STANDARD: (0.35125, 0.204375, 0.444375), + WARRANTY2: (0.47425, 0.275875, 0.599875) + }, + RatingRange.MEDIUM: { + STANDARD: (0.385, 0.2558333333, 0.3591666667), + WARRANTY2: (0.539, 0.3581666667, 0.5028333333) + }, + RatingRange.LOW: { + STANDARD: (0.5025, 0.30875, 0.18875), + }, + }, + Laptop: { + RatingRange.HIGH: { + STANDARD: (0.3469230769, 0.195, 0.4580769231), + WARRANTY2: (0.4522307692, 0.2632307692, 0.6345384615) + }, + RatingRange.MEDIUM: { + STANDARD: (0.382, 0.1735, 0.4445), + WARRANTY2: (0.5108, 0.2429, 0.6463) + }, + RatingRange.LOW: { + STANDARD: (0.4528571429, 0.2264285714, 0.3207142857), + } + } + } + SCHEMA[Server] = SCHEMA[Desktop] + + def __init__(self, device, rating_range, role, price: Decimal) -> None: + cls = device.__class__ if device.__class__ != Server else Desktop + rate = self.SCHEMA[cls][rating_range] + self.standard = EreusePrice.Type(rate[self.STANDARD][role], price) + if self.WARRANTY2 in rate: + self.warranty2 = EreusePrice.Type(rate[self.WARRANTY2][role], price) + + def __init__(self, rating: AggregateRate, **kwargs) -> None: + if rating.rating_range == RatingRange.VERY_LOW: + raise ValueError('Cannot compute price for Range.VERY_LOW') + # We pass ROUND_UP strategy so price is always greater than what refurbisher... amounts + price = self.to_price(rating.rating * self.MULTIPLIER[rating.device.__class__], ROUND_UP) + super().__init__(rating=rating, + device=rating.device, + price=price, + software=kwargs.pop('software', app.config['PRICE_SOFTWARE']), + version=kwargs.pop('version', app.config['PRICE_VERSION']), + **kwargs) + self._compute() + + @orm.reconstructor + def _compute(self): + """ + Calculates eReuse.org prices when initializing the + instance from the price and other properties. + """ + self.refurbisher = self._service(self.Service.REFURBISHER) + self.retailer = self._service(self.Service.RETAILER) + self.platform = self._service(self.Service.PLATFORM) + if hasattr(self.refurbisher, 'warranty2'): + self.warranty2 = round(self.refurbisher.warranty2.amount + + self.retailer.warranty2.amount + + self.platform.warranty2.amount, 2) + + def _service(self, role): + return self.Service(self.device, self.rating.rating_range, role, self.price) + + +class EreusePrice(Price): + """The act of setting a price by guessing it using the eReuse.org + algorithm. + + This algorithm states that the price is the use value of the device + (represented by its last :class:`.Rate`) multiplied by a constants + value agreed by a circuit or platform. + """ + MULTIPLIER = { + Desktop: 20, + Laptop: 30 + } + + class Type: + def __init__(self, percentage: float, price: Decimal) -> None: + # see https://stackoverflow.com/a/29651462 for the - 0.005 + self.amount = EreusePrice.to_price(price * Decimal(percentage)) + self.percentage = EreusePrice.to_price(price * Decimal(percentage)) + self.percentage = round(percentage - 0.005, 2) + + class Service: + REFURBISHER, PLATFORM, RETAILER = 0, 1, 2 + STANDARD, WARRANTY2 = 'STD', 'WR2' + SCHEMA = { + Desktop: { + RatingRange.HIGH: { + STANDARD: (0.35125, 0.204375, 0.444375), + WARRANTY2: (0.47425, 0.275875, 0.599875) + }, + RatingRange.MEDIUM: { + STANDARD: (0.385, 0.2558333333, 0.3591666667), + WARRANTY2: (0.539, 0.3581666667, 0.5028333333) + }, + RatingRange.LOW: { + STANDARD: (0.5025, 0.30875, 0.18875), + }, + }, + Laptop: { + RatingRange.HIGH: { + STANDARD: (0.3469230769, 0.195, 0.4580769231), + WARRANTY2: (0.4522307692, 0.2632307692, 0.6345384615) + }, + RatingRange.MEDIUM: { + STANDARD: (0.382, 0.1735, 0.4445), + WARRANTY2: (0.5108, 0.2429, 0.6463) + }, + RatingRange.LOW: { + STANDARD: (0.4528571429, 0.2264285714, 0.3207142857), + } + } + } + SCHEMA[Server] = SCHEMA[Desktop] + + def __init__(self, device, rating_range, role, price: Decimal) -> None: + cls = device.__class__ if device.__class__ != Server else Desktop + rate = self.SCHEMA[cls][rating_range] + self.standard = EreusePrice.Type(rate[self.STANDARD][role], price) + if self.WARRANTY2 in rate: + self.warranty2 = EreusePrice.Type(rate[self.WARRANTY2][role], price) + + def __init__(self, rating: AggregateRate, **kwargs) -> None: + if rating.rating_range == RatingRange.VERY_LOW: + raise ValueError('Cannot compute price for Range.VERY_LOW') + # We pass ROUND_UP strategy so price is always greater than what refurbisher... amounts + price = self.to_price(rating.rating * self.MULTIPLIER[rating.device.__class__], ROUND_UP) + super().__init__(rating=rating, + device=rating.device, + price=price, + software=kwargs.pop('software', app.config['PRICE_SOFTWARE']), + version=kwargs.pop('version', app.config['PRICE_VERSION']), + **kwargs) + self._compute() + + @orm.reconstructor + def _compute(self): + """ + Calculates eReuse.org prices when initializing the + instance from the price and other properties. + """ + self.refurbisher = self._service(self.Service.REFURBISHER) + self.retailer = self._service(self.Service.RETAILER) + self.platform = self._service(self.Service.PLATFORM) + if hasattr(self.refurbisher, 'warranty2'): + self.warranty2 = round(self.refurbisher.warranty2.amount + + self.retailer.warranty2.amount + + self.platform.warranty2.amount, 2) + + def _service(self, role): + return self.Service(self.device, self.rating.rating_range, role, self.price) class ResultRate(Rate): @@ -1150,6 +1163,92 @@ class ResultRate(Rate): return aggregate +class BenchmarkRate: + """ + Common class to group by benchmark rate classes + """ + + +class BenchmarkQuality(BenchmarkRate): + """ + Computes quality benchmarks results to aggregate in result rate + """ + cpu_sysbench = Column(Float(decimal_return_scale=2)) + cpu_sysbench.comment = 'Benchmark processor component with sysbench tool' + ram_sysbench = Column(Float(decimal_return_scale=2)) + ram_sysbench.comment = 'Benchmark RAM component' + # gpu_sysbench = Column(Float(decimal_return_scale=2)) todo how to do? + data_storage_sysbench = Column(Float(decimal_return_scale=2)) + data_storage_sysbench.comment = 'Benchmark data storage component with sysbench tool' + data_storage_smart = Column(Float(decimal_return_scale=2)) + data_storage_smart.comment = 'Benchmark data storage component with SMART tool' + + +class FunctionalityTest(Test): + """ + Class where are generic devices functionality aspects + """ + + +class TestAudio(FunctionalityTest): + """ + Test to check all this aspects related with audio fucntions + """ + loudspeaker = Column(BDEnum(LoudspeakerRange)) + loudspeaker.comment = 'Range to determine if the speaker is working properly and what sound quality it has.' + microphone = Column(Boolean) + microphone.comment = 'This evaluate if microphone works correctly' + + +class TestConnectivity(FunctionalityTest): + """ + Test to check all this aspects related with functionality connections in devices + """ + + SIM = Column(Boolean) + SIM.comment = 'Evaluate if SIM works' + wifi = Column(Boolean) + wifi.comment = 'Evaluate if wifi connection works correctly' + bluetooth = Column(Boolean) + bluetooth.comment = 'Evaluate if bluetooth works' + usb = Column(DBEnum()) + usb.comment = 'Evaluate if usb port was detected and charger plug works' + + +class TestBattery(FunctionalityTest): + """ + Test of length of charge. Source R2: Minimum X minutes discharging the device + """ + battery_duration = Column(Boolean()) + battery_duration.comment = '' + + +class TestBios(FunctionalityTest): + """ + Test that determinate if is difficult to access BIOS, like need password, are protected.. + """ + bios_range = Column(DBEnum()) + bios_range.comment = 'Range of difficult to acces BIOS' + + +class TestApperance(): + """ + Class with appearance characteristics + """ + chassis_defects_range = Column(BDEnum(ChassisRange)) + chassis_defects_range.comment = 'Range to determinate cosmetic defects on chassis like scratches' + + +class TestVisual(TestAppearance): + """ + Check aesthetics or cosmetic aspects. Like defects on chassis, display, .. + """ + camera_defects_range = Column(BDEnum(CameraRange)) + camera_defects_range = 'Range to determinate cosmetic defects on camera' + display_defects_range = Column(BDEnum(DisplayRange)) + display_defects_range = 'Range to determinate cosmetic defects on display' + + class Price(JoinedWithOneDeviceMixin, EventWithOneDevice): """The act of setting a trading price for the device. @@ -1217,97 +1316,6 @@ class Price(JoinedWithOneDeviceMixin, EventWithOneDevice): return '{0:0.2f} {1}'.format(self.price, self.currency) -class EreusePrice(Price): - """The act of setting a price by guessing it using the eReuse.org - algorithm. - - This algorithm states that the price is the use value of the device - (represented by its last :class:`.Rate`) multiplied by a constants - value agreed by a circuit or platform. - """ - MULTIPLIER = { - Desktop: 20, - Laptop: 30 - } - - class Type: - def __init__(self, percentage: float, price: Decimal) -> None: - # see https://stackoverflow.com/a/29651462 for the - 0.005 - self.amount = EreusePrice.to_price(price * Decimal(percentage)) - self.percentage = EreusePrice.to_price(price * Decimal(percentage)) - self.percentage = round(percentage - 0.005, 2) - - class Service: - REFURBISHER, PLATFORM, RETAILER = 0, 1, 2 - STANDARD, WARRANTY2 = 'STD', 'WR2' - SCHEMA = { - Desktop: { - RatingRange.HIGH: { - STANDARD: (0.35125, 0.204375, 0.444375), - WARRANTY2: (0.47425, 0.275875, 0.599875) - }, - RatingRange.MEDIUM: { - STANDARD: (0.385, 0.2558333333, 0.3591666667), - WARRANTY2: (0.539, 0.3581666667, 0.5028333333) - }, - RatingRange.LOW: { - STANDARD: (0.5025, 0.30875, 0.18875), - }, - }, - Laptop: { - RatingRange.HIGH: { - STANDARD: (0.3469230769, 0.195, 0.4580769231), - WARRANTY2: (0.4522307692, 0.2632307692, 0.6345384615) - }, - RatingRange.MEDIUM: { - STANDARD: (0.382, 0.1735, 0.4445), - WARRANTY2: (0.5108, 0.2429, 0.6463) - }, - RatingRange.LOW: { - STANDARD: (0.4528571429, 0.2264285714, 0.3207142857), - } - } - } - SCHEMA[Server] = SCHEMA[Desktop] - - def __init__(self, device, rating_range, role, price: Decimal) -> None: - cls = device.__class__ if device.__class__ != Server else Desktop - rate = self.SCHEMA[cls][rating_range] - self.standard = EreusePrice.Type(rate[self.STANDARD][role], price) - if self.WARRANTY2 in rate: - self.warranty2 = EreusePrice.Type(rate[self.WARRANTY2][role], price) - - def __init__(self, rating: AggregateRate, **kwargs) -> None: - if rating.rating_range == RatingRange.VERY_LOW: - raise ValueError('Cannot compute price for Range.VERY_LOW') - # We pass ROUND_UP strategy so price is always greater than what refurbisher... amounts - price = self.to_price(rating.rating * self.MULTIPLIER[rating.device.__class__], ROUND_UP) - super().__init__(rating=rating, - device=rating.device, - price=price, - software=kwargs.pop('software', app.config['PRICE_SOFTWARE']), - version=kwargs.pop('version', app.config['PRICE_VERSION']), - **kwargs) - self._compute() - - @orm.reconstructor - def _compute(self): - """ - Calculates eReuse.org prices when initializing the - instance from the price and other properties. - """ - self.refurbisher = self._service(self.Service.REFURBISHER) - self.retailer = self._service(self.Service.RETAILER) - self.platform = self._service(self.Service.PLATFORM) - if hasattr(self.refurbisher, 'warranty2'): - self.warranty2 = round(self.refurbisher.warranty2.amount - + self.retailer.warranty2.amount - + self.platform.warranty2.amount, 2) - - def _service(self, role): - return self.Service(self.device, self.rating.rating_range, role, self.price) - - class Test(JoinedWithOneDeviceMixin, EventWithOneDevice): """The act of testing the physical condition of a device and its components. diff --git a/ereuse_devicehub/resources/event/rate/workbench/v2_0.py b/ereuse_devicehub/resources/event/rate/workbench/v2_0.py index 5f4be16e..9fc392b0 100644 --- a/ereuse_devicehub/resources/event/rate/workbench/v2_0.py +++ b/ereuse_devicehub/resources/event/rate/workbench/v2_0.py @@ -1,10 +1,9 @@ from enum import Enum from typing import Iterable -from ereuse_devicehub.resources.device.models import Computer, DataStorage, Desktop, Laptop, \ - Processor, RamModule, Server, Device -from ereuse_devicehub.resources.event.models import BenchmarkDataStorage, BenchmarkProcessor, \ - WorkbenchRate +from ereuse_devicehub.resources.device.models import DataStorage, Processor, RamModule, Device +from ereuse_devicehub.resources.enums import RatingRange +from ereuse_devicehub.resources.event.models import BenchmarkDataStorage, WorkbenchRate from ereuse_devicehub.resources.event.rate.rate import BaseRate @@ -128,6 +127,288 @@ class Appearance(Range): NONE = -0.3 +class QualityRate(Rate): + id = Column(UUID(as_uuid=True), ForeignKey(Rate.id), primary_key=True) + processor = Column(Float(decimal_return_scale=2), check_range('processor', *RATE_POSITIVE), + comment='Is a test explain cpu component.') + ram = Column(Float(decimal_return_scale=2), check_range('ram', *RATE_POSITIVE), + comment='RAM memory rate.') + data_storage = Column(Float(decimal_return_scale=2), check_range('data_storage', *RATE_POSITIVE), + comment='Data storage rate, like HHD, SSD.') + + @property + def ram_range(self): + return self.workbench.ram_range + + @property + def processor_range(self): + return self.workbench.processor_range + + @property + def display_range(self): + return self.workbench.data_storage_range + + @property + def data_storage_range(self): + return self.workbench.data_storage_range + + @property + def battery_range(self): + return self.workbench.ram_range + + @property + def camera_range(self): + return self.workbench_mobile.camera_range + + @property + def graphic_card_range(self): + return self.workbench_mobil.graphic_card_range + + +class QualityRateComputer(QualityRate): + id = Column(UUID(as_uuid=True), ForeignKey(QualityRate.id), primary_key=True) + processor = Column(Float(decimal_return_scale=2), check_range('processor', *RATE_POSITIVE), + comment='Is a test explain cpu component.') + ram = Column(Float(decimal_return_scale=2), check_range('ram', *RATE_POSITIVE), + comment='RAM memory rate.') + data_storage = Column(Float(decimal_return_scale=2), check_range('data_storage', *RATE_POSITIVE), + comment='Data storage rate, like HHD, SSD.') + + graphic_card = Column(Float(decimal_return_scale=2), check_range('graphic_card', *RATE_POSITIVE), + comment='Graphic card score in performance, amount of memory and benchmark result') + network_adapter = Column(Float(decimal_return_scale=2), check_range('network_adapter', *RATE_POSITIVE), + comment='Network adapter rate, take it speed limit') + + bios = Column(Float(decimal_return_scale=2), check_range('bios', *RATE_POSITIVE)) + bios_range = Column(DBEnum(Bios)) + bios_range.comment = Bios.__doc__ + + # todo ensure for WorkbenchRate version and software are not None when inserting them + + def ratings(self): + """ + #Computes all the possible rates taking this rating as a model. + + #Returns a set of ratings, including this one, which is mutated, + #and the final :class:`.AggregateRate`. + """ + from ereuse_devicehub.resources.event.rate.main import main + return main(self, **app.config.get_namespace('WORKBENCH_RATE_')) + + @property + def graphic_card_range(self): + if self.graphic_card: + return RatingRange.from_score(self.graphic_card) + + @property + def network_adapter_range(self): + return self.workbench_mobil.network_adapter_range + + @property + def bios_range(self): + return self.workbench_mobil.bios_range + + +class QualityRateMobile(QualityRate): + id = Column(UUID(as_uuid=True), ForeignKey(QualityRate.id), primary_key=True) + display = Column(Float(decimal_return_scale=2), check_range('display', *RATE_POSITIVE)) + display.comment = 'Display rate, screen resolution and size to calculate PPI and convert in score' + battery = Column(Float(decimal_return_scale=2), check_range('battery', *RATE_POSITIVE), + comment='Battery rate is related with capacity and its health') + camera = Column(Float(decimal_return_scale=2), check_range('camera', *RATE_POSITIVE), + comment='Camera rate take into account resolution') + + graphic_card = Column(Float(decimal_return_scale=2), check_range('graphic_card', *RATE_POSITIVE), + comment='Graphic card score in performance, amount of memory and benchmark result') + network_adapter = Column(Float(decimal_return_scale=2), check_range('network_adapter', *RATE_POSITIVE), + comment='Network adapter rate, take it speed limit') + + bios = Column(Float(decimal_return_scale=2), check_range('bios', *RATE_POSITIVE)) + bios_range = Column(DBEnum(Bios)) + bios_range.comment = Bios.__doc__ + + # todo ensure for WorkbenchRate version and software are not None when inserting them + + def ratings(self): + """ + #Computes all the possible rates taking this rating as a model. + """ + from ereuse_devicehub.resources.event.rate.main import main + return main(self, **app.config.get_namespace('WORKBENCH_RATE_')) + + @property + def display_range(self): + if self.data_storage: + return RatingRange.from_score(self.data_storage) + + @property + def battery_range(self): + if self.ram: + return RatingRange.from_score(self.ram) + + @property + def camera_range(self): + if self.processor: + return RatingRange.from_score(self.processor) + + @property + def graphic_card_range(self): + if self.graphic_card: + return RatingRange.from_score(self.graphic_card) + + +class FunctionalityRate(Rate): + id = Column(UUID(as_uuid=True), ForeignKey(Rate.id), primary_key=True) + functionality = Column(Float(decimal_return_scale=2), check_range('functionality', *FUNCTIONALITY_RANGE)) + functionality.comment = 'Functionality rate of a device' + + functionality_range = Column(DBEnum(FunctionalityRangev2)) + functionality_range.comment = FunctionalityRangev2.__doc__ + + connectivity = Column(Float(decimal_return_scale=2), + comment='This punctuation covers a series of aspects related to connectivity.') + audio = Column(Float(decimal_return_scale=2), comment='Take into account loudspeaker and microphone') + + @property + def connectivity_rate(self): + yield + + @property + def audio_rate(self): + yield + + @property + def test_buttonse(self): + yield + + @classmethod + def test_camera_defects(self): + yield + + +class ResultRate(Rate): + """The act of grading the appearance, quality (performance), and functionality + of a device. + + There are five categories of ``Rate``: + 1. ``Quality``. How good is the machine, in terms of performance. + 2. ``Functionality``. + 3. ``Appearance``. + 4. ``Market value``. + 5. ``Cost of repair``. + + + There are types of rating a device: + + 1. Rate Quality + 2. Rate Functionality + 3. Rate Final + + + List of source where can input information of rating a device: + + 1. When processing the device with Workbench Computer/Mobile. + 2. Using the Android App (through Scan). + 3. + 4. Anytime after manually written in a form in the website. + """ + + id = Column(UUID(as_uuid=True), ForeignKey(Rate.id), primary_key=True) + quality_id = Column(UUID(as_uuid=True), ForeignKey(ManualRate.id)) + quality_id.comment = """The Quality Rate used to generate this + aggregation, or None if none used. + """ + + func_id = Column(UUID(as_uuid=True), ForeignKey(ManualRate.id)) + func_id.comment = """The Functionality Rate used to generate this + aggregation, or None if none used. + """ + + final_id = Column(UUID(as_uuid=True), ForeignKey(ManualRate.id)) + final_id.comment = """The Final Rate used to generate this + aggregation, or None if none used. + """ + + """ MANUAL INPUT """ + manual_id = Column(UUID(as_uuid=True), ForeignKey(ManualRate.id)) + manual_id.comment = """The ManualEvent used to generate this + aggregation, or None if none used. + + An example of ManualEvent is using the web or the Android app + to rate a device. + """ + manual = relationship(ManualRate, + backref=backref('aggregate_rate_manual', + lazy=True, + order_by=lambda: ResultRate.created, + collection_class=OrderedSet), + primaryjoin=manual_id == ManualRate.id) + + """ WORKBENCH COMPUTER """ + workbench_computer_id = Column(UUID(as_uuid=True), ForeignKey(QualityRateComputer.id)) + workbench_computer_id.comment = """The WorkbenchRate used to generate + this aggregation, or None if none used. + """ + workbench_computer = relationship(QualityRateComputer, + backref=backref('aggregate_rate_workbench', + lazy=True, + order_by=lambda: ResultRate.created, + collection_class=OrderedSet), + primaryjoin=workbench_computer_id == QualityRateComputer.id) + + """ WORKBENCH MOBILE """ + + workbench_mobile_id = Column(UUID(as_uuid=True), ForeignKey(QualityRateMobile.id)) + workbench_mobile_id.comment = """The WorkbenchRate used to generate + this aggregation, or None if none used. + """ + workbench_mobile = relationship(QualityRateMobile, + backref=backref('aggregate_rate_workbench', + lazy=True, + order_by=lambda: ResultRate.created, + collection_class=OrderedSet), + primaryjoin=workbench_mobile_id == QualityRateMobile.id) + + def __init__(self, *args, **kwargs) -> None: + kwargs.setdefault('version', StrictVersion('1.0')) + super().__init__(*args, **kwargs) + + @classmethod + def quality_rate(cls, quality: QualityRate): + pass + + @classmethod + def functionality_rate(cls, func: FunctionalityRate): + pass + + @classmethod + def final_rate(cls, rate: Rate): + pass + + # Categories + + @classmethod + def quality_category(cls, quality: QualityRate): + pass + + @classmethod + def functionality_category(cls, quality: QualityRate): + pass + + @classmethod + def appearance_category(cls, quality: QualityRate): + pass + + @classmethod + def maket_value_category(cls, quality: QualityRate): + pass + + @classmethod + def cost_of_repair_category(cls, quality: QualityRate): + pass + + + class DisplayRate(QualityRate): """ Calculate a DisplayRate @@ -156,7 +437,6 @@ class DisplayRate(QualityRate): # TODO quality components rate qualityrate class?? - class ProcessorRate(QualityRate): """ Calculate a ProcessorRate