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`
3. `Appearance Rate`
4. `Final Rate`
1. ComputerRate
2. MobileRate
3. ManualRate
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**.
@ -51,63 +53,17 @@ The following will explain in more detail the three types of rate. Rate class is
**1. Quality Rate**
Device components immutable characteristics list:
* 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.
Device components immutable characteristics and Benchmark, the act of gauging the performance of a device.
**2. Functionality Rate**
* Test:
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
-
Test, the act of testing usage condition of a device and its functionality aspects/characteristics. Following standard R2 specification*.
**3. Appearance Rate**
* Visual Test:
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.
Mainly is compute using the results of a visual Test, 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.
Below is explained in more detail how the calculations and formulas that are used to compute the score of a device.
@ -121,7 +77,7 @@ Explication of how to compute score of a device, step by step:
Normalized the characteristics of the components between 0 and 1 using the theoretical norms table**
with xMin and xMax and standardize the values applying the following formula:
**Normalization characteristic value = (x xMin)/(xMax xMin)**
**Normalization characteristic value = (x xMin)/(xMax xMin)**
2. Merge the characteristics of every component in one score.
Carry out the harmonic mean weighted by the weight of each characteristic.

View file

@ -374,7 +374,8 @@ class Computer(Device):
1. The max Ethernet speed of the computer, 0 if ethernet
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
WiFi but its speed is unknown, None if no WiFi adaptor
exists.
@ -452,14 +453,6 @@ class Mobile(Device):
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')
def validate_imei(self, _, value: int):
if not imei.is_valid(str(value)):
@ -763,3 +756,32 @@ class Manufacturer(db.Model):
'COPY common.manufacturer FROM STDIN (FORMAT csv)',
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
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."""
Z = 'Z. The device is new'
A = 'A. Is like new; without visual damage'
@ -126,22 +112,6 @@ APPEARANCE_RANGE = 0.5, -0.3
@unique
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"""
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'
@ -153,6 +123,9 @@ class FunctionalityRangev2(Enum):
return self.name
FUNCTIONALITY_RANGE = -0.25, 0.5
@unique
class BatteryHealthRange(Enum):
"""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, \
FunctionalityRange, PhysicalErasureMethod, PriceSoftware, RATE_NEGATIVE, RATE_POSITIVE, \
RatingRange, RatingSoftware, ReceiverRole, Severity, SnapshotExpectedEvents, SnapshotSoftware, \
TestDataStorageLength, FUNCTIONALITY_RANGE, FunctionalityRangev2, AppearanceRangev2, BatteryHealthRange
from ereuse_devicehub.resources.event.rate.workbench.v2_0 import QualityRate, FunctionalityRate
TestDataStorageLength, FUNCTIONALITY_RANGE, FunctionalityRange, AppearanceRange, BatteryHealthRange
from ereuse_devicehub.resources.models import STR_SM_SIZE, Thing
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
"""
SIM = Column(Boolean)
# TODO name for SIM (3G)
celular_network = 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(USBPortRange))
usb.comment = 'Evaluate if usb port was detected and charger plug works'
usb_port = Column(DBEnum(USBPortRange))
usb_port.comment = 'Evaluate if usb port was detected and charger plug works'
class TestBattery(Test):
@ -744,13 +743,18 @@ class TestBattery(Test):
class TestBios(Test):
"""
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..
Test that determinate motherboard no beeps, codes or errors when power on
"""
bios_power_on = Column(Boolean())
bios_power_on.comment = """
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)
bios_access_range = Column(BDEnum(BiosAccessRange))
bios_access_range.comment = 'Range of difficult to acces BIOS'
@ -763,8 +767,8 @@ class TestVisual(ManualRate):
Like defects on chassis, display, ..
"""
# TODO Consider if add some new var in appearance aspect??
appearance_range = Column(DBEnum(AppearanceRangev2))
appearance_range.comment = AppearanceRangev2.__doc__
appearance_range = Column(DBEnum(AppearanceRange))
appearance_range.comment = AppearanceRange.__doc__
class Rate(JoinedWithOneDeviceMixin, EventWithOneDevice):
@ -844,7 +848,7 @@ class IndividualRate(Rate):
pass
class ManualRate(IndividualRate):
class RateManual(IndividualRate):
id = Column(UUID(as_uuid=True), ForeignKey(Rate.id), primary_key=True)
labelling = Column(Boolean)
labelling.comment = """Sets if there are labels stuck that should
@ -865,111 +869,18 @@ class ManualRate(IndividualRate):
raise NotImplementedError()
# TODO is necessary?
class WorkbenchComputer(ManualRate):
class RateComputer(IndividualRate):
"""
"""
pass
class WorkbenchMobile(ManualRate):
class RateMobile(IndividualRate):
"""
"""
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):
"""
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),
comment='Data storage rate, like HHD, SSD.')
""" MOBILE QUALITY RATE """
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),
@ -990,7 +900,6 @@ class QualityRate(Rate):
camera = Column(Float(decimal_return_scale=2), check_range('camera', *RATE_POSITIVE),
comment='Camera rate take into account resolution')
""" COMPUTER QUALITY RATE """
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),
@ -1047,8 +956,8 @@ class FunctionalityRate(Rate):
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__
functionality_range = Column(DBEnum(FunctionalityRange))
functionality_range.comment = FunctionalityRange.__doc__
class FinalRate(Rate):
@ -1062,21 +971,28 @@ class FinalRate(Rate):
4. ``Market value``.
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.
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.
Market value (MV). Perceived value, brand recognition, selling value.
Cost of repair, refurbish and manufacture. ( C )
1. Rate Quality
2. Rate Functionality
3. Rate Final
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).
3.
3. ...
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)
quality_id = Column(UUID(as_uuid=True), ForeignKey(QualityRate.id))
@ -1179,7 +1095,6 @@ class FinalRate(Rate):
def cost_of_repair_category(cls, quality: QualityRate):
pass
# todo take value from LAST event (manual or workbench)
@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.enums import AppearanceRange, Bios, FunctionalityRange, \
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.models import STR_BIG_SIZE, STR_SIZE
from ereuse_devicehub.resources.schemas import Thing
@ -213,7 +213,7 @@ class ManualRate(IndividualRate):
labelling = Boolean(description=m.ManualRate.labelling.comment)
class WorkbencComputer(ManualRate):
class RateComputer(ManualRate):
__doc__ = m.WorkbenchRate.__doc__
processor = Float()
ram = Float()
@ -229,43 +229,10 @@ class WorkbencComputer(ManualRate):
graphic_card_range = EnumField(RatingRange, dump_only=True, data_key='graphicCardRange')
class WorkbenchMobile(ManualRate):
class RateMobile(ManualRate):
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):
__doc__ = m.QualityRate.__doc__
@ -310,7 +277,7 @@ class FinalRate(Rate):
required=True,
data_key='appearanceRangev2',
description=m.ManualRate.appearance_range.comment)
functionality_range = EnumField(FunctionalityRangev2,
functionality_range = EnumField(FunctionalityRange,
required=True,
data_key='functionalityRangev2',
description=m.ManualRate.functionality_range.comment)