adding comments about rate algorithm
This commit is contained in:
parent
61f4c127d4
commit
c19783954e
|
@ -1,5 +1,6 @@
|
||||||
"""
|
"""
|
||||||
This file contains all actions can apply to a device and is sorted according to a structure based on:
|
This file contains all actions can apply to a device and is sorted according
|
||||||
|
to a structure based on:
|
||||||
|
|
||||||
* Generic Actions
|
* Generic Actions
|
||||||
* Benchmarks
|
* Benchmarks
|
||||||
|
@ -647,6 +648,12 @@ class Test(JoinedWithOneDeviceMixin, ActionWithOneDevice):
|
||||||
"""The act of testing the physical condition of a device and its
|
"""The act of testing the physical condition of a device and its
|
||||||
components.
|
components.
|
||||||
|
|
||||||
|
Ref in R2 Provision 6 pag.19:
|
||||||
|
Records of test results are imperative to documenting
|
||||||
|
the functionality of each device.
|
||||||
|
Pass or fail results for each test in the process must be recorded
|
||||||
|
either manually or through software automation.
|
||||||
|
|
||||||
Testing errors and warnings are easily taken in
|
Testing errors and warnings are easily taken in
|
||||||
:attr:`ereuse_devicehub.resources.device.models.Device.working`.
|
:attr:`ereuse_devicehub.resources.device.models.Device.working`.
|
||||||
"""
|
"""
|
||||||
|
@ -674,10 +681,23 @@ class TestMixin:
|
||||||
|
|
||||||
|
|
||||||
class MeasureBattery(TestMixin, Test):
|
class MeasureBattery(TestMixin, Test):
|
||||||
"""A sample of the status of the battery.
|
"""
|
||||||
|
A sample of the status of the battery.
|
||||||
|
Ref in R2 Provision 6 pag.22 Example:
|
||||||
|
Length of charge; Expected results: Minimum 40 minutes.
|
||||||
|
|
||||||
Operative Systems keep a record of several aspects of a battery.
|
Operative Systems keep a record of several aspects of a battery.
|
||||||
This is a sample of those.
|
This is a sample of those.
|
||||||
|
|
||||||
|
:class: 'Severtity'
|
||||||
|
Info/Pass(0):
|
||||||
|
|
||||||
|
Notice(1):
|
||||||
|
|
||||||
|
Warning(2):
|
||||||
|
|
||||||
|
Error/Fail(3):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
size = db.Column(db.Integer, nullable=False)
|
size = db.Column(db.Integer, nullable=False)
|
||||||
size.comment = """Maximum battery capacity, in mAh."""
|
size.comment = """Maximum battery capacity, in mAh."""
|
||||||
|
@ -704,6 +724,16 @@ class TestDataStorage(TestMixin, Test):
|
||||||
|
|
||||||
The test takes to other SMART values indicators of the overall health
|
The test takes to other SMART values indicators of the overall health
|
||||||
of the data storage.
|
of the data storage.
|
||||||
|
|
||||||
|
:class: 'Severtity'
|
||||||
|
Info/Pass(0):
|
||||||
|
|
||||||
|
Notice(1):
|
||||||
|
|
||||||
|
Warning(2):
|
||||||
|
|
||||||
|
Error/Fail(3):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
length = Column(DBEnum(TestDataStorageLength), nullable=False) # todo from type
|
length = Column(DBEnum(TestDataStorageLength), nullable=False) # todo from type
|
||||||
status = Column(Unicode(), check_lower('status'), nullable=False)
|
status = Column(Unicode(), check_lower('status'), nullable=False)
|
||||||
|
@ -771,7 +801,18 @@ class StressTest(TestMixin, Test):
|
||||||
|
|
||||||
class TestAudio(TestMixin, Test):
|
class TestAudio(TestMixin, Test):
|
||||||
"""
|
"""
|
||||||
Test to check all this aspects related with audio functions, Manual Tests??
|
Test to check audio device aspects, focus on speaker sounds correctly
|
||||||
|
and microphone record sounds good
|
||||||
|
|
||||||
|
:class: 'Severtity'
|
||||||
|
Info/Pass(0):
|
||||||
|
|
||||||
|
Notice(1):
|
||||||
|
|
||||||
|
Warning(2):
|
||||||
|
|
||||||
|
Error/Fail(3):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
_speaker = Column('speaker', Boolean)
|
_speaker = Column('speaker', Boolean)
|
||||||
_speaker.comment = """Whether the speaker works as expected."""
|
_speaker.comment = """Whether the speaker works as expected."""
|
||||||
|
@ -803,35 +844,87 @@ class TestAudio(TestMixin, Test):
|
||||||
|
|
||||||
|
|
||||||
class TestConnectivity(TestMixin, Test):
|
class TestConnectivity(TestMixin, Test):
|
||||||
"""Tests that the device can connect both physically and
|
"""
|
||||||
wirelessly.
|
Tests that the device can connect both physically and wirelessly.
|
||||||
|
|
||||||
A failing test means that at least one connection of the device
|
A failing test means that at least one connection of the device
|
||||||
is not working well. A comment should get into more detail.
|
is not working well. A comment should get into more detail.
|
||||||
|
|
||||||
|
:class: 'Severtity'
|
||||||
|
Info/Pass(0):
|
||||||
|
|
||||||
|
Notice(1):
|
||||||
|
|
||||||
|
Warning(2):
|
||||||
|
|
||||||
|
Error/Fail(3):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class TestCamera(TestMixin, Test):
|
class TestCamera(TestMixin, Test):
|
||||||
"""Tests the working conditions of the camera of the device,
|
"""
|
||||||
|
Tests the working conditions of the camera of the device,
|
||||||
specially when taking pictures or recording video.
|
specially when taking pictures or recording video.
|
||||||
|
Fail when camera can't take pictures.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class TestKeyboard(TestMixin, Test):
|
class TestKeyboard(TestMixin, Test):
|
||||||
"""Whether the keyboard works correctly."""
|
"""
|
||||||
|
Whether the keyboard works correctly.
|
||||||
|
|
||||||
|
Ref in R2 Provision 6 pag.22 example:
|
||||||
|
PASS when each key produces character on the screen
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class TestTrackpad(TestMixin, Test):
|
class TestTrackpad(TestMixin, Test):
|
||||||
"""Whether the trackpad works correctly."""
|
"""
|
||||||
|
Whether the trackpad works correctly.
|
||||||
|
|
||||||
|
Ref in R2 Provision 6 pag.22 example:
|
||||||
|
PASS when cursor moves on screen
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class TestScreenHinge(TestMixin, Test):
|
||||||
|
"""
|
||||||
|
Whether screen hinge works correctly.
|
||||||
|
|
||||||
|
Laptop Test Ref in R2 Provision 6 pag.22 example:
|
||||||
|
PASS when laptop screen stays open/closed at desired angles
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class TestPowerAdapter(TestMixin, Test):
|
||||||
|
"""
|
||||||
|
Whether power adapter charge battery device without problems.
|
||||||
|
|
||||||
|
Laptop Test Ref in R2 Provision 6 pag.22 example:
|
||||||
|
PASS when plug power adapter into laptop and charges the battery.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class TestBios(TestMixin, Test):
|
class TestBios(TestMixin, Test):
|
||||||
"""Tests the working condition and grades the usability of the BIOS."""
|
"""
|
||||||
bios_power_on = Column(Boolean)
|
Tests the working condition and grades the usability of the BIOS.
|
||||||
bios_power_on.comment = """Whether there are no beeps or error
|
|
||||||
|
:class: 'Severtity'
|
||||||
|
Info/Pass(0):
|
||||||
|
|
||||||
|
Notice(1):
|
||||||
|
|
||||||
|
Warning(2):
|
||||||
|
|
||||||
|
Error/Fail(3):
|
||||||
|
|
||||||
|
"""
|
||||||
|
beeps_power_on = Column(Boolean)
|
||||||
|
beeps_power_on.comment = """Whether there are no beeps or error
|
||||||
codes when booting up.
|
codes when booting up.
|
||||||
|
|
||||||
Reference: R2 standard page 23.
|
Reference: R2 provision 6 page 23.
|
||||||
"""
|
"""
|
||||||
access_range = Column(DBEnum(BiosAccessRange))
|
access_range = Column(DBEnum(BiosAccessRange))
|
||||||
access_range.comment = """Difficulty to modify the boot menu.
|
access_range.comment = """Difficulty to modify the boot menu.
|
||||||
|
@ -842,8 +935,25 @@ class TestBios(TestMixin, Test):
|
||||||
|
|
||||||
|
|
||||||
class VisualTest(TestMixin, Test):
|
class VisualTest(TestMixin, Test):
|
||||||
"""The act of visually inspecting the appearance and functionality
|
"""
|
||||||
|
The act of visually inspecting the appearance and functionality
|
||||||
of the device.
|
of the device.
|
||||||
|
|
||||||
|
Reference R2 provision 6 Templates Ready for Resale Checklist (Desktop)
|
||||||
|
https://sustainableelectronics.org/sites/default/files/6.c.2%20Desktop%20R2-Ready%20for%20Resale%20Checklist.docx
|
||||||
|
Physical condition grade
|
||||||
|
|
||||||
|
|
||||||
|
:class: 'Severtity'
|
||||||
|
Info/Pass(0):
|
||||||
|
|
||||||
|
Notice(1):
|
||||||
|
|
||||||
|
Warning(2):
|
||||||
|
|
||||||
|
Error/Fail(3):
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
appearance_range = Column(DBEnum(AppearanceRange), nullable=False)
|
appearance_range = Column(DBEnum(AppearanceRange), nullable=False)
|
||||||
appearance_range.comment = AppearanceRange.__doc__
|
appearance_range.comment = AppearanceRange.__doc__
|
||||||
|
@ -860,7 +970,14 @@ class VisualTest(TestMixin, Test):
|
||||||
|
|
||||||
|
|
||||||
class Rate(JoinedWithOneDeviceMixin, ActionWithOneDevice):
|
class Rate(JoinedWithOneDeviceMixin, ActionWithOneDevice):
|
||||||
"""The act of computing a rate based on different categories"""
|
"""
|
||||||
|
The act of computing a rate based on different categories:
|
||||||
|
|
||||||
|
• Functionality (F). Tests, the act of testing usage condition of a device
|
||||||
|
• Appearance (A). Visual evaluation, surface deterioration.
|
||||||
|
• Performance (Q). Components characteristics and components benchmarks.
|
||||||
|
|
||||||
|
"""
|
||||||
# todo jn: explain in each comment what the rate considers.
|
# todo jn: explain in each comment what the rate considers.
|
||||||
N = 2
|
N = 2
|
||||||
"""The number of significant digits for rates.
|
"""The number of significant digits for rates.
|
||||||
|
@ -938,7 +1055,11 @@ class RateMixin:
|
||||||
|
|
||||||
|
|
||||||
class RateComputer(RateMixin, Rate):
|
class RateComputer(RateMixin, Rate):
|
||||||
"""The act of rating a computer."""
|
"""
|
||||||
|
The act of rating a computer type devices.
|
||||||
|
It's the starting point for calculating the rate.
|
||||||
|
Algorithm explained in v1.0 file
|
||||||
|
"""
|
||||||
_processor = Column('processor',
|
_processor = Column('processor',
|
||||||
Float(decimal_return_scale=Rate.N),
|
Float(decimal_return_scale=Rate.N),
|
||||||
check_range('processor', *R_POSITIVE))
|
check_range('processor', *R_POSITIVE))
|
||||||
|
|
|
@ -12,6 +12,51 @@ from ereuse_devicehub.resources.device.models import Computer, DataStorage, Proc
|
||||||
class RateAlgorithm(BaseRate):
|
class RateAlgorithm(BaseRate):
|
||||||
"""The algorithm that generates the Rate v1.0.
|
"""The algorithm that generates the Rate v1.0.
|
||||||
|
|
||||||
|
Rate v1.0 is mainly based on 3 components (Processor, RAM and Data Storage)
|
||||||
|
and 2 visual grades (one for appearance aspects and other for functionality aspects).
|
||||||
|
|
||||||
|
From components we take into account their main characteristics and
|
||||||
|
also some tests and benchmarks. In particular:
|
||||||
|
|
||||||
|
* Processor:
|
||||||
|
- Cores
|
||||||
|
- Speed
|
||||||
|
- Benchmark processor
|
||||||
|
|
||||||
|
* RAM:
|
||||||
|
- Size
|
||||||
|
- Speed
|
||||||
|
|
||||||
|
* Data Storage:
|
||||||
|
- Size
|
||||||
|
- Benchmark data storage (Read and write speed)
|
||||||
|
|
||||||
|
Step by step to compute Rate v1.0:
|
||||||
|
|
||||||
|
1. Normalization the components characteristics.
|
||||||
|
Normalized the characteristics of the components between 0 and 1.
|
||||||
|
with xMin and xMax and standardize the values applying
|
||||||
|
the following formula:
|
||||||
|
|
||||||
|
**Normalization characteristic value = (x −xMin)/(xMax −xMin)**
|
||||||
|
|
||||||
|
2. Merge the characteristics of every component in one score for component.
|
||||||
|
|
||||||
|
|
||||||
|
3. Merge the components individual rates into a single components rate.
|
||||||
|
We calculate this rate using the weighted harmonic mean.
|
||||||
|
We establish all the components weights, 50% for processor,
|
||||||
|
20% for data storage, 30% for RAM.
|
||||||
|
The result is a unique performance score (components rate).
|
||||||
|
|
||||||
|
4. Grouping all categories aspects sum all in unique final rate.
|
||||||
|
To get Functionality and Appearance Rates values, only directly
|
||||||
|
related a value for each grade.
|
||||||
|
|
||||||
|
**Final Rate = Components Rate + Functionality Rate + Appearance Rate**
|
||||||
|
|
||||||
|
Final Rate are ranged from 0 to 4.7.
|
||||||
|
|
||||||
Do not call directly this class, but use
|
Do not call directly this class, but use
|
||||||
:meth:`ereuse_devicehub.resources.action.models.RateComputer.compute`,
|
:meth:`ereuse_devicehub.resources.action.models.RateComputer.compute`,
|
||||||
which then calls this.
|
which then calls this.
|
||||||
|
@ -74,7 +119,7 @@ class RateAlgorithm(BaseRate):
|
||||||
rate.functionality = self.Functionality[visual_test.functionality_range.name].value
|
rate.functionality = self.Functionality[visual_test.functionality_range.name].value
|
||||||
rate.rating = rate_components + rate.functionality + rate.appearance
|
rate.rating = rate_components + rate.functionality + rate.appearance
|
||||||
device.actions_one.add(rate)
|
device.actions_one.add(rate)
|
||||||
assert 0 <= rate.rating <= 4.7, 'Rate ranges from 0 to 4.7'
|
assert 0 <= rate.rating <= 4.7
|
||||||
return rate
|
return rate
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,12 +133,11 @@ class ProcessorRate(BaseRate):
|
||||||
DEFAULT_CORES = 1
|
DEFAULT_CORES = 1
|
||||||
DEFAULT_SPEED = 1.6
|
DEFAULT_SPEED = 1.6
|
||||||
|
|
||||||
# In case of i2, i3,.. result penalized.
|
|
||||||
# Intel(R) Core(TM) i3 CPU 530 @ 2.93GHz, score = 23406.92 but results inan score of 17503.
|
|
||||||
DEFAULT_SCORE = 4000
|
DEFAULT_SCORE = 4000
|
||||||
|
|
||||||
def compute(self, processor: Processor):
|
def compute(self, processor: Processor):
|
||||||
""" Compute processor rate
|
""" Compute processor rate
|
||||||
|
We assume always exists a Benchmark Processor
|
||||||
Obs: cores and speed are possible NULL value
|
Obs: cores and speed are possible NULL value
|
||||||
:return: result is a rate (score) of Processor characteristics
|
:return: result is a rate (score) of Processor characteristics
|
||||||
"""
|
"""
|
||||||
|
@ -106,7 +150,7 @@ class ProcessorRate(BaseRate):
|
||||||
benchmark_cpu = benchmark_cpu.rate or self.DEFAULT_SCORE
|
benchmark_cpu = benchmark_cpu.rate or self.DEFAULT_SCORE
|
||||||
|
|
||||||
# STEP: Fusion components
|
# STEP: Fusion components
|
||||||
processor_rate = (benchmark_cpu + speed * 2000 * cores) / 2 # todo magic number!
|
processor_rate = (benchmark_cpu + speed * 2000 * cores) / 2
|
||||||
|
|
||||||
# STEP: Normalize values
|
# STEP: Normalize values
|
||||||
processor_norm = max(self.norm(processor_rate, *self.PROCESSOR_NORM), 0)
|
processor_norm = max(self.norm(processor_rate, *self.PROCESSOR_NORM), 0)
|
||||||
|
@ -136,7 +180,7 @@ class RamRate(BaseRate):
|
||||||
|
|
||||||
def compute(self, ram_devices: Iterable[RamModule]):
|
def compute(self, ram_devices: Iterable[RamModule]):
|
||||||
"""
|
"""
|
||||||
Obs: RamModule.speed is possible NULL value & size != NULL or NOT??
|
If ram speed or ram size, we assume default values before declared
|
||||||
:return: result is a rate (score) of all RamModule components
|
:return: result is a rate (score) of all RamModule components
|
||||||
"""
|
"""
|
||||||
size = 0.0
|
size = 0.0
|
||||||
|
|
|
@ -8,7 +8,7 @@ from teal.marshmallow import ValidationError
|
||||||
from teal.resource import View
|
from teal.resource import View
|
||||||
|
|
||||||
from ereuse_devicehub.db import db
|
from ereuse_devicehub.db import db
|
||||||
from ereuse_devicehub.resources.action.models import Action, RateComputer, Snapshot
|
from ereuse_devicehub.resources.action.models import Action, RateComputer, Snapshot, VisualTest
|
||||||
from ereuse_devicehub.resources.action.rate.workbench.v1_0 import CannotRate
|
from ereuse_devicehub.resources.action.rate.workbench.v1_0 import CannotRate
|
||||||
from ereuse_devicehub.resources.device.models import Component, Computer
|
from ereuse_devicehub.resources.device.models import Component, Computer
|
||||||
from ereuse_devicehub.resources.enums import SnapshotSoftware
|
from ereuse_devicehub.resources.enums import SnapshotSoftware
|
||||||
|
@ -28,6 +28,9 @@ class ActionView(View):
|
||||||
a = resource_def.schema.load(json)
|
a = resource_def.schema.load(json)
|
||||||
if json['type'] == Snapshot.t:
|
if json['type'] == Snapshot.t:
|
||||||
return self.snapshot(a, resource_def)
|
return self.snapshot(a, resource_def)
|
||||||
|
if json['type'] == VisualTest.t:
|
||||||
|
pass
|
||||||
|
# TODO JN add compute rate with new visual test and old components device
|
||||||
Model = db.Model._decl_class_registry.data[json['type']]()
|
Model = db.Model._decl_class_registry.data[json['type']]()
|
||||||
action = Model(**a)
|
action = Model(**a)
|
||||||
db.session.add(action)
|
db.session.add(action)
|
||||||
|
|
|
@ -273,13 +273,13 @@ class Severity(IntEnum):
|
||||||
"""A flag evaluating the action execution. Ex. failed actions
|
"""A flag evaluating the action execution. Ex. failed actions
|
||||||
have the value `Severity.Error`. Devicehub uses 4 severity levels:
|
have the value `Severity.Error`. Devicehub uses 4 severity levels:
|
||||||
|
|
||||||
* Info: default neutral severity. The action succeeded.
|
* Info (Pass): default neutral severity. The action succeeded.
|
||||||
* Notice: The action succeeded but it is raising awareness.
|
* Notice: The action succeeded but it is raising awareness.
|
||||||
Notices are not usually that important but something
|
Notices are not usually that important but something
|
||||||
(good or bad) worth checking.
|
(good or bad) worth checking.
|
||||||
* Warning: The action succeeded but there is something important
|
* Warning: The action succeeded but there is something important
|
||||||
to check negatively affecting the action.
|
to check negatively affecting the action.
|
||||||
* Error: the action failed.
|
* Error (Fail): the action failed.
|
||||||
|
|
||||||
Devicehub specially raises user awareness when an action
|
Devicehub specially raises user awareness when an action
|
||||||
has a Severity of ``Warning`` or greater.
|
has a Severity of ``Warning`` or greater.
|
||||||
|
|
Reference in New Issue