first iteration new rate v2

This commit is contained in:
nad 2019-03-13 13:06:58 +01:00
parent 4bfadae267
commit 40a2ed3916
5 changed files with 87 additions and 254 deletions

View File

@ -40,7 +40,9 @@ There are three types of rating a device, depend on the aspect you are focusing
2. `Functionality Rate` 2. `Functionality Rate`
3. `Appearance Rate` 3. `Appearance Rate`
4. `Final Rate` 4. `Final Rate`
1. ComputerRate
2. MobileRate
3. ManualRate
To structure device events information, create two different main class Benchmark and Test. To structure device events information, create two different main class Benchmark and Test.
Benchmark class is part of the **quality rate** and Test class is part of the **functionality rate**. Benchmark class is part of the **quality rate** and Test class is part of the **functionality rate**.
@ -51,63 +53,17 @@ The following will explain in more detail the three types of rate. Rate class is
**1. Quality Rate** **1. Quality Rate**
Device components immutable characteristics list: Device components immutable characteristics and Benchmark, the act of gauging the performance of a device.
* Display (screen):
- Size (inch)
- Resolution (pixels)
- Density (ppi)
* Processor:
- Number of cores (Natural)
- Speed (GHz)
* RAM:
- Size (GB)
- Speed (MHz)
* Data Storage:
- Size (GB)
* Battery:
- Size (mAh)
- Voltage (V)
* Camera:
- Resolution (MP)
* Benchmark:
The act of gauging the performance of a device.
This subclasses define which functionality aspects take into account in score.
- Benchmark DataStorage
- Benchmark RamSysbench
- Benchmark Processor
- Benchmark Graphic Card (TODO)
-
** Natural: a positive number that does not have decimals.
**2. Functionality Rate** **2. Functionality Rate**
* Test: Test, the act of testing usage condition of a device and its functionality aspects/characteristics. Following standard R2 specification*.
The act of testing usage condition of a device and its functionality aspects/characteristics.
Following standard R2 specification*:
- Test DataStorage (SMART Test) //TODO which SMART test vars important for func aspect??
- Test Processor (Stress Test) //TODO which SMART test vars important for func aspect??
- Test Bios (Manual Test)
- Test Audio (Manual Test)
- Test Battery
- Test Connectivity
-
**3. Appearance Rate** **3. Appearance Rate**
* Visual Test: Mainly is compute using the results of a visual Test, it is a test of appearance that its aspects are represented with grade.
It is a test of appearance that its aspects are represented with grade. It focuses mainly on the aesthetic or cosmetic defects of important parts of the device, such as the chassis, display (screen) and cameras.
It focuses mainly on the aesthetic or cosmetic defects of important parts of the device,
such as the chassis, display (screen) and cameras.
Below is explained in more detail how the calculations and formulas that are used to compute the score of a device. Below is explained in more detail how the calculations and formulas that are used to compute the score of a device.

View File

@ -374,7 +374,8 @@ class Computer(Device):
1. The max Ethernet speed of the computer, 0 if ethernet 1. The max Ethernet speed of the computer, 0 if ethernet
adaptor exists but its speed is unknown, None if no eth adaptor exists but its speed is unknown, None if no eth
adaptor exists. adaptor exists.# TODO add all grade tables (chassis defects, camera defects, buttons test, connectivity, ..)
2. The max WiFi speed of the computer, 0 if computer has 2. The max WiFi speed of the computer, 0 if computer has
WiFi but its speed is unknown, None if no WiFi adaptor WiFi but its speed is unknown, None if no WiFi adaptor
exists. exists.
@ -452,14 +453,6 @@ class Mobile(Device):
The Mobile Equipment Identifier as a hexadecimal string. The Mobile Equipment Identifier as a hexadecimal string.
""" """
# TODO Add more characteristics, like display resolution, battery health, graphic card, ...
display_size = Column(Float(decimal_return_scale=2))
display_size.comment = 'Display size; Units: inches;'
battery_size = Column(Float(decimal_return_scale=2))
battery_size.comment = 'Battery size; Units: mAh'
camera_resolution = Column(Float(decimal_return_scale=2))
camera_resolution.comment = 'Camera resolution; Units: Megapixels'
@validates('imei') @validates('imei')
def validate_imei(self, _, value: int): def validate_imei(self, _, value: int):
if not imei.is_valid(str(value)): if not imei.is_valid(str(value)):
@ -763,3 +756,32 @@ class Manufacturer(db.Model):
'COPY common.manufacturer FROM STDIN (FORMAT csv)', 'COPY common.manufacturer FROM STDIN (FORMAT csv)',
f f
) )
class Battery(Component):
"""
Battery component, mobile device
"""
size = Column(Float(decimal_return_scale=2))
size.comment = 'Battery size; Units: 2000 mAh'
voltage = Column()
voltage.comment = 'Battery voltage; Units: 3,5 V'
technology = Column()
technology.comment = 'Battery technology used; Ex: Li-Ti'
charge_counter = Column()
charge_counter.comment = 'Number of time that battery has been charged'
wireless = Column(Boolean, nullable=False, default=False)
wireless.comment = 'If battery can charging wireless'
health = Column(DBEnum)
health.comment = 'Battery health indicator'
status = Column(DBEnum)
status.comment = 'Battery status indicator'
class Camera(Component):
"""
Component camera in mobile devices
"""
resolution = Column(Float(decimal_return_scale=2))
resolution.comment = 'Camera resolution; Units: Megapixels'

View File

@ -94,20 +94,6 @@ class AggregateRatingVersions(Enum):
@unique @unique
class AppearanceRange(Enum): class AppearanceRange(Enum):
"""Grades the imperfections that aesthetically affect the device, but not its usage."""
Z = '0. The device is new.'
A = 'A. Is like new (without visual damage)'
B = 'B. Is in really good condition (small visual damage in difficult places to spot)'
C = 'C. Is in good condition (small visual damage in parts that are easy to spot, not screens)'
D = 'D. Is acceptable (visual damage in visible parts, not screens)'
E = 'E. Is unacceptable (considerable visual damage that can affect usage)'
def __str__(self):
return self.name
@unique
class AppearanceRangev2(Enum):
"""Based on usage condition of a device and its functionality aspects/characteristics.""" """Based on usage condition of a device and its functionality aspects/characteristics."""
Z = 'Z. The device is new' Z = 'Z. The device is new'
A = 'A. Is like new; without visual damage' A = 'A. Is like new; without visual damage'
@ -126,22 +112,6 @@ APPEARANCE_RANGE = 0.5, -0.3
@unique @unique
class FunctionalityRange(Enum): class FunctionalityRange(Enum):
"""Grades the defects of a device that affect its usage."""
# todo sync with https://github.com/ereuse/rdevicescore#input
A = 'A. Everything works perfectly (buttons, and in case of screens there are no scratches)'
B = 'B. There is a button difficult to press or a small scratch in an edge of a screen'
C = 'C. A non-important button (or similar) doesn\'t work; screen has multiple scratches in edges'
D = 'D. Multiple buttons don\'t work; screen has visual damage resulting in uncomfortable usage'
def __str__(self):
return self.name
FUNCTIONALITY_RANGE = -0.25, 0.5
@unique
class FunctionalityRangev2(Enum):
"""Grade the buttons and chassis that affect its usage, like screen defect or camera defects""" """Grade the buttons and chassis that affect its usage, like screen defect or camera defects"""
A = 'A. All the buttons works perfectly, no screen/camera defects and chassis without issues' A = 'A. All the buttons works perfectly, no screen/camera defects and chassis without issues'
B = 'B. There is a button difficult to press or unstable it, a screen/camera defect or chassis problem' B = 'B. There is a button difficult to press or unstable it, a screen/camera defect or chassis problem'
@ -153,6 +123,9 @@ class FunctionalityRangev2(Enum):
return self.name return self.name
FUNCTIONALITY_RANGE = -0.25, 0.5
@unique @unique
class BatteryHealthRange(Enum): class BatteryHealthRange(Enum):
"""Grade the battery health status, depending on self report Android system""" """Grade the battery health status, depending on self report Android system"""

View File

@ -31,8 +31,7 @@ from ereuse_devicehub.resources.device.models import Component, Computer, DataSt
from ereuse_devicehub.resources.enums import AppearanceRange, Bios, ErasureStandards, \ from ereuse_devicehub.resources.enums import AppearanceRange, Bios, ErasureStandards, \
FunctionalityRange, PhysicalErasureMethod, PriceSoftware, RATE_NEGATIVE, RATE_POSITIVE, \ FunctionalityRange, PhysicalErasureMethod, PriceSoftware, RATE_NEGATIVE, RATE_POSITIVE, \
RatingRange, RatingSoftware, ReceiverRole, Severity, SnapshotExpectedEvents, SnapshotSoftware, \ RatingRange, RatingSoftware, ReceiverRole, Severity, SnapshotExpectedEvents, SnapshotSoftware, \
TestDataStorageLength, FUNCTIONALITY_RANGE, FunctionalityRangev2, AppearanceRangev2, BatteryHealthRange TestDataStorageLength, FUNCTIONALITY_RANGE, FunctionalityRange, AppearanceRange, BatteryHealthRange
from ereuse_devicehub.resources.event.rate.workbench.v2_0 import QualityRate, FunctionalityRate
from ereuse_devicehub.resources.models import STR_SM_SIZE, Thing from ereuse_devicehub.resources.models import STR_SM_SIZE, Thing
from ereuse_devicehub.resources.user.models import User from ereuse_devicehub.resources.user.models import User
@ -718,15 +717,15 @@ class TestConnectivity(Test):
""" """
Test to check all this aspects related with functionality connections in devices Test to check all this aspects related with functionality connections in devices
""" """
# TODO name for SIM (3G)
SIM = Column(Boolean) celular_network = Column(Boolean)
SIM.comment = 'Evaluate if SIM works' SIM.comment = 'Evaluate if SIM works'
wifi = Column(Boolean) wifi = Column(Boolean)
wifi.comment = 'Evaluate if wifi connection works correctly' wifi.comment = 'Evaluate if wifi connection works correctly'
bluetooth = Column(Boolean) bluetooth = Column(Boolean)
bluetooth.comment = 'Evaluate if bluetooth works' bluetooth.comment = 'Evaluate if bluetooth works'
usb = Column(DBEnum(USBPortRange)) usb_port = Column(DBEnum(USBPortRange))
usb.comment = 'Evaluate if usb port was detected and charger plug works' usb_port.comment = 'Evaluate if usb port was detected and charger plug works'
class TestBattery(Test): class TestBattery(Test):
@ -744,13 +743,18 @@ class TestBattery(Test):
class TestBios(Test): class TestBios(Test):
""" """
Test that determinate motherboard no beeps, codes or errors when power on, Test that determinate motherboard no beeps, codes or errors when power on
and a grade to reflect some possibles difficult to access or modify setting in the BIOS, like password protection..
""" """
bios_power_on = Column(Boolean()) bios_power_on = Column(Boolean())
bios_power_on.comment = """ bios_power_on.comment = """
Motherboards do a self check when powering up (R2 p.23), test PASS if no beeps, codes, or errors appears. Motherboards do a self check when powering up (R2 p.23), test PASS if no beeps, codes, or errors appears.
""" """
class TestBiosDifficulty:
"""
Test to determinate a grade to reflect some possibles difficult to access or modify setting in the BIOS, like password protection..
"""
# TODO Eum(BiosAccesRange) # TODO Eum(BiosAccesRange)
bios_access_range = Column(BDEnum(BiosAccessRange)) bios_access_range = Column(BDEnum(BiosAccessRange))
bios_access_range.comment = 'Range of difficult to acces BIOS' bios_access_range.comment = 'Range of difficult to acces BIOS'
@ -763,8 +767,8 @@ class TestVisual(ManualRate):
Like defects on chassis, display, .. Like defects on chassis, display, ..
""" """
# TODO Consider if add some new var in appearance aspect?? # TODO Consider if add some new var in appearance aspect??
appearance_range = Column(DBEnum(AppearanceRangev2)) appearance_range = Column(DBEnum(AppearanceRange))
appearance_range.comment = AppearanceRangev2.__doc__ appearance_range.comment = AppearanceRange.__doc__
class Rate(JoinedWithOneDeviceMixin, EventWithOneDevice): class Rate(JoinedWithOneDeviceMixin, EventWithOneDevice):
@ -844,7 +848,7 @@ class IndividualRate(Rate):
pass pass
class ManualRate(IndividualRate): class RateManual(IndividualRate):
id = Column(UUID(as_uuid=True), ForeignKey(Rate.id), primary_key=True) id = Column(UUID(as_uuid=True), ForeignKey(Rate.id), primary_key=True)
labelling = Column(Boolean) labelling = Column(Boolean)
labelling.comment = """Sets if there are labels stuck that should labelling.comment = """Sets if there are labels stuck that should
@ -865,111 +869,18 @@ class ManualRate(IndividualRate):
raise NotImplementedError() raise NotImplementedError()
# TODO is necessary? class RateComputer(IndividualRate):
class WorkbenchComputer(ManualRate): """
"""
pass pass
class WorkbenchMobile(ManualRate): class RateMobile(IndividualRate):
"""
"""
pass pass
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))
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: AggregateRate.created,
collection_class=OrderedSet),
primaryjoin=manual_id == ManualRate.id)
workbench_id = Column(UUID(as_uuid=True), ForeignKey(QualityRateComputer.id))
workbench_id.comment = """The WorkbenchRate used to generate
this aggregation, or None if none used.
"""
workbench = relationship(QualityRateComputer,
backref=backref('aggregate_rate_workbench',
lazy=True,
order_by=lambda: AggregateRate.created,
collection_class=OrderedSet),
primaryjoin=workbench_id == QualityRateComputer.id)
def __init__(self, *args, **kwargs) -> None:
kwargs.setdefault('version', StrictVersion('1.0'))
super().__init__(*args, **kwargs)
# todo take value from LAST event (manual or workbench)
@property
def processor(self):
return self.workbench.processor
@property
def ram(self):
return self.workbench.ram
@property
def data_storage(self):
return self.workbench.data_storage
@property
def graphic_card(self):
return self.workbench.graphic_card
@property
def data_storage_range(self):
return self.workbench.data_storage_range
@property
def ram_range(self):
return self.workbench.ram_range
@property
def processor_range(self):
return self.workbench.processor_range
@property
def graphic_card_range(self):
return self.workbench.graphic_card_range
@property
def bios(self):
return self.workbench.bios
@property
def functionality_range(self):
return self.workbench.functionality_range
@property
def appearance_range(self):
return self.workbench.appearance_range
@property
def bios_range(self):
return self.workbench.bios_range
@property
def labelling(self):
return self.workbench.labelling
@classmethod
def from_workbench_rate(cls, rate: QualityRate):
aggregate = cls()
aggregate.rating = rate.rating
aggregate.software = rate.software
aggregate.appearance = rate.appearance
aggregate.functionality = rate.functionality
aggregate.device = rate.device
aggregate.workbench = rate
return aggregate
class QualityRate(Rate): class QualityRate(Rate):
""" """
The act of compute performance (quality) a device The act of compute performance (quality) a device
@ -982,7 +893,6 @@ class QualityRate(Rate):
data_storage = Column(Float(decimal_return_scale=2), check_range('data_storage', *RATE_POSITIVE), data_storage = Column(Float(decimal_return_scale=2), check_range('data_storage', *RATE_POSITIVE),
comment='Data storage rate, like HHD, SSD.') comment='Data storage rate, like HHD, SSD.')
""" MOBILE QUALITY RATE """
display = Column(Float(decimal_return_scale=2), check_range('display', *RATE_POSITIVE)) 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' 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), battery = Column(Float(decimal_return_scale=2), check_range('battery', *RATE_POSITIVE),
@ -990,7 +900,6 @@ class QualityRate(Rate):
camera = Column(Float(decimal_return_scale=2), check_range('camera', *RATE_POSITIVE), camera = Column(Float(decimal_return_scale=2), check_range('camera', *RATE_POSITIVE),
comment='Camera rate take into account resolution') comment='Camera rate take into account resolution')
""" COMPUTER QUALITY RATE """
graphic_card = Column(Float(decimal_return_scale=2), check_range('graphic_card', *RATE_POSITIVE), 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') 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), network_adapter = Column(Float(decimal_return_scale=2), check_range('network_adapter', *RATE_POSITIVE),
@ -1047,8 +956,8 @@ class FunctionalityRate(Rate):
functionality = Column(Float(decimal_return_scale=2), check_range('functionality', *FUNCTIONALITY_RANGE)) functionality = Column(Float(decimal_return_scale=2), check_range('functionality', *FUNCTIONALITY_RANGE))
functionality.comment = 'Functionality rate of a device' functionality.comment = 'Functionality rate of a device'
functionality_range = Column(DBEnum(FunctionalityRangev2)) functionality_range = Column(DBEnum(FunctionalityRange))
functionality_range.comment = FunctionalityRangev2.__doc__ functionality_range.comment = FunctionalityRange.__doc__
class FinalRate(Rate): class FinalRate(Rate):
@ -1062,20 +971,27 @@ class FinalRate(Rate):
4. ``Market value``. 4. ``Market value``.
5. ``Cost of repair``. 5. ``Cost of repair``.
We define 5 categories to measure:
There are different types of rating a device: Functionality (F). Answers to does the machine work well? Condition tests fall in here.
Appearance (A). Aesthetic evaluation, surface deterioration.
1. Rate Quality Quality (Q). How good is the machine, in terms of performance. Benchmarks, power, and characteristics fall here. The quality score, that represents the performance of the device, the functionality score, that based on the correct working of the buttons, audio and connectivity aspects, and the appaerance score, that focused on the aesthetics and cosmetics aspects like visual damage on screen, buttons or cabinet.
2. Rate Functionality Market value (MV). Perceived value, brand recognition, selling value.
3. Rate Final Cost of repair, refurbish and manufacture. ( C )
List of source where can input information of rating a device: List of source where can input information of rating a device:
1. When processing the device with Workbench Computer/Mobile. 1. When processing the device with Workbench Computer or WB Mobile.
2. Using the Android App (through Scan). 2. Using the Android App (through Scan).
3. 3. ...
4. Anytime after manually written in a form in the website. 4. Anytime after manually written in a form in the website.
There are three types of rating a device, depend on the aspect you are focusing on:
1. `Quality Rate`
2. `Functionality Rate`
3. `Appearance Rate`
4. `Final Rate`
""" """
id = Column(UUID(as_uuid=True), ForeignKey(Rate.id), primary_key=True) id = Column(UUID(as_uuid=True), ForeignKey(Rate.id), primary_key=True)
@ -1179,7 +1095,6 @@ class FinalRate(Rate):
def cost_of_repair_category(cls, quality: QualityRate): def cost_of_repair_category(cls, quality: QualityRate):
pass pass
# todo take value from LAST event (manual or workbench) # todo take value from LAST event (manual or workbench)
@property @property

View File

@ -14,7 +14,7 @@ from ereuse_devicehub.resources.agent import schemas as s_agent
from ereuse_devicehub.resources.device import schemas as s_device from ereuse_devicehub.resources.device import schemas as s_device
from ereuse_devicehub.resources.enums import AppearanceRange, Bios, FunctionalityRange, \ from ereuse_devicehub.resources.enums import AppearanceRange, Bios, FunctionalityRange, \
PhysicalErasureMethod, PriceSoftware, RATE_POSITIVE, RatingRange, RatingSoftware, ReceiverRole, \ PhysicalErasureMethod, PriceSoftware, RATE_POSITIVE, RatingRange, RatingSoftware, ReceiverRole, \
Severity, SnapshotExpectedEvents, SnapshotSoftware, TestDataStorageLength, FunctionalityRangev2 Severity, SnapshotExpectedEvents, SnapshotSoftware, TestDataStorageLength, FunctionalityRange
from ereuse_devicehub.resources.event import models as m from ereuse_devicehub.resources.event import models as m
from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE
from ereuse_devicehub.resources.schemas import Thing from ereuse_devicehub.resources.schemas import Thing
@ -213,7 +213,7 @@ class ManualRate(IndividualRate):
labelling = Boolean(description=m.ManualRate.labelling.comment) labelling = Boolean(description=m.ManualRate.labelling.comment)
class WorkbencComputer(ManualRate): class RateComputer(ManualRate):
__doc__ = m.WorkbenchRate.__doc__ __doc__ = m.WorkbenchRate.__doc__
processor = Float() processor = Float()
ram = Float() ram = Float()
@ -229,43 +229,10 @@ class WorkbencComputer(ManualRate):
graphic_card_range = EnumField(RatingRange, dump_only=True, data_key='graphicCardRange') graphic_card_range = EnumField(RatingRange, dump_only=True, data_key='graphicCardRange')
class WorkbenchMobile(ManualRate): class RateMobile(ManualRate):
pass pass
class AggregateRate(Rate):
__doc__ = m.AggregateRate.__doc__
workbench = NestedOn(WorkbenchRate, dump_only=True,
description=m.AggregateRate.workbench_id.comment)
manual = NestedOn(ManualRate,
dump_only=True,
description=m.AggregateRate.manual_id.comment)
processor = Float(dump_only=True)
ram = Float(dump_only=True)
data_storage = Float(dump_only=True)
graphic_card = Float(dump_only=True)
bios = EnumField(Bios, dump_only=True)
bios_range = EnumField(Bios,
description=m.WorkbenchRate.bios_range.comment,
data_key='biosRange')
appearance_range = EnumField(AppearanceRange,
required=True,
data_key='appearanceRange',
description=m.ManualRate.appearance_range.comment)
functionality_range = EnumField(FunctionalityRange,
required=True,
data_key='functionalityRange',
description=m.ManualRate.functionality_range.comment)
labelling = Boolean(description=m.ManualRate.labelling.comment)
data_storage_range = EnumField(RatingRange, dump_only=True, data_key='dataStorageRange')
ram_range = EnumField(RatingRange, dump_only=True, data_key='ramRange')
processor_range = EnumField(RatingRange, dump_only=True, data_key='processorRange')
graphic_card_range = EnumField(RatingRange, dump_only=True, data_key='graphicCardRange')
""" RATE v2 CODE"""
class QualityRate(Rate): class QualityRate(Rate):
__doc__ = m.QualityRate.__doc__ __doc__ = m.QualityRate.__doc__
@ -310,7 +277,7 @@ class FinalRate(Rate):
required=True, required=True,
data_key='appearanceRangev2', data_key='appearanceRangev2',
description=m.ManualRate.appearance_range.comment) description=m.ManualRate.appearance_range.comment)
functionality_range = EnumField(FunctionalityRangev2, functionality_range = EnumField(FunctionalityRange,
required=True, required=True,
data_key='functionalityRangev2', data_key='functionalityRangev2',
description=m.ManualRate.functionality_range.comment) description=m.ManualRate.functionality_range.comment)