refactor score to new rate version structure

This commit is contained in:
nad 2019-04-23 21:27:31 +02:00
parent 75e1817e9c
commit 880b5e706e
12 changed files with 165 additions and 134 deletions

View File

@ -39,6 +39,7 @@ class DevicehubConfig(Config):
} }
API_DOC_CLASS_DISCRIMINATOR = 'type' API_DOC_CLASS_DISCRIMINATOR = 'type'
# TODO is necessary??
WORKBENCH_RATE_VERSION = StrictVersion('1.0') WORKBENCH_RATE_VERSION = StrictVersion('1.0')
PHOTOBOX_RATE_VERSION = StrictVersion('1.0') PHOTOBOX_RATE_VERSION = StrictVersion('1.0')
""" """

View File

@ -175,10 +175,10 @@ class Device(Thing):
@property @property
def rate(self): def rate(self):
"""The last AggregateRate of the device.""" """The last Rate of the device."""
with suppress(LookupError, ValueError): with suppress(LookupError, ValueError):
from ereuse_devicehub.resources.event.models import AggregateRate from ereuse_devicehub.resources.event.models import Rate
return self.last_event_of(AggregateRate) return self.last_event_of(Rate)
@property @property
def price(self): def price(self):
@ -756,32 +756,3 @@ 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

@ -73,7 +73,7 @@ class Device(Thing):
pass pass
@property @property
def rate(self) -> Optional[e.AggregateRate]: def rate(self) -> Optional[e.Rate]:
pass pass
@property @property

View File

@ -37,7 +37,7 @@ class Device(Thing):
many=True, many=True,
dump_only=True, dump_only=True,
description='The lots where this device is directly under.') description='The lots where this device is directly under.')
rate = NestedOn('AggregateRate', dump_only=True, description=m.Device.rate.__doc__) rate = NestedOn('Rate', dump_only=True, description=m.Device.rate.__doc__)
price = NestedOn('Price', dump_only=True, description=m.Device.price.__doc__) price = NestedOn('Price', dump_only=True, description=m.Device.price.__doc__)
trading = EnumField(states.Trading, dump_only=True, description=m.Device.trading.__doc__) trading = EnumField(states.Trading, dump_only=True, description=m.Device.trading.__doc__)
physical = EnumField(states.Physical, dump_only=True, description=m.Device.physical.__doc__) physical = EnumField(states.Physical, dump_only=True, description=m.Device.physical.__doc__)

View File

@ -70,7 +70,7 @@ class AggregateRatingVersions(Enum):
v1 = StrictVersion('1.0') v1 = StrictVersion('1.0')
""" """
This version is set to aggregate :class:`ereuse_devicehub.resources. This version is set to aggregate :class:`ereuse_devicehub.resources.
event.models.WorkbenchRate` version X and :class:`ereuse_devicehub. event.models.RateComputer` version X and :class:`ereuse_devicehub.
resources.event.models.PhotoboxRate` version Y. resources.event.models.PhotoboxRate` version Y.
""" """
@ -89,9 +89,6 @@ class AppearanceRange(Enum):
E = 'E. Is unacceptable; severity visual damage, missing essential parts' E = 'E. Is unacceptable; severity visual damage, missing essential parts'
NONE = 'NA. Grade doesnt exists' NONE = 'NA. Grade doesnt exists'
def __str__(self):
return self.name
APPEARANCE_RANGE = 0.5, -0.3 APPEARANCE_RANGE = 0.5, -0.3
@ -105,8 +102,6 @@ class FunctionalityRange(Enum):
D = 'D. Chassis severity usage problems. All buttons, screen or camera don\'t work; broken or unusable it' D = 'D. Chassis severity usage problems. All buttons, screen or camera don\'t work; broken or unusable it'
NONE = 'NA. Grade doesnt exists' NONE = 'NA. Grade doesnt exists'
def __str__(self):
return self.name
FUNCTIONALITY_RANGE = -0.3, 0.4 FUNCTIONALITY_RANGE = -0.3, 0.4
@ -122,8 +117,6 @@ class BatteryHealthRange(Enum):
E = 'E. Battery health is very bad; and status is dead; unusable or miss it ' E = 'E. Battery health is very bad; and status is dead; unusable or miss it '
NONE = 'NA. Grade doesnt exists' NONE = 'NA. Grade doesnt exists'
def __str__(self):
return self.name
@unique @unique
@ -135,9 +128,6 @@ class BiosAccessRange(Enum):
D = 'D. Like B or C, but you had to unlock the BIOS (i.e. by removing the battery)' D = 'D. Like B or C, but you had to unlock the BIOS (i.e. by removing the battery)'
E = 'E. The device could not be booted through the network.' E = 'E. The device could not be booted through the network.'
def __str__(self):
return self.name
@unique @unique
class Orientation(Enum): class Orientation(Enum):

View File

@ -84,7 +84,59 @@ class BenchmarkRamSysbenchDef(BenchmarkWithRateDef):
SCHEMA = schemas.BenchmarkRamSysbench SCHEMA = schemas.BenchmarkRamSysbench
# TODO add test defs class TestDef(EventDef):
VIEW = None
SCHEMA = schemas.Test
class TestDataStorageDef(TestDef):
VIEW = None
SCHEMA = schemas.TestDataStorage
class StressTestDef(TestDef):
VIEW = None
SCHEMA = schemas.StressTest
class TestAudioDef(TestDef):
VIEW = None
SCHEMA = schemas.TestAudio
class TestConnectivityDef(TestDef):
VIEW = None
SCHEMA = schemas.TestConnectivity
class TestBatteryDef(TestDef):
VIEW = None
SCHEMA = schemas.TestBattery
class TestCameraDef(TestDef):
VIEW = None
SCHEMA = schemas.TestCamera
class TestKeyboardDef(TestDef):
VIEW = None
SCHEMA = schemas.TestKeyboard
class TestTrackpadDef(TestDef):
VIEW = None
SCHEMA = schemas.TestTrackpad
class TestBiosDef(TestDef):
VIEW = None
SCHEMA = schemas.TestBios
class TestVisualDef(TestDef):
VIEW = None
SCHEMA = schemas.TestVisual
class RateDef(EventDef): class RateDef(EventDef):
@ -126,21 +178,6 @@ class SnapshotDef(EventDef):
self.sync = Sync() self.sync = Sync()
class TestDef(EventDef):
VIEW = None
SCHEMA = schemas.Test
class TestDataStorageDef(TestDef):
VIEW = None
SCHEMA = schemas.TestDataStorage
class StressTestDef(TestDef):
VIEW = None
SCHEMA = schemas.StressTest
class ToRepairDef(EventDef): class ToRepairDef(EventDef):
VIEW = None VIEW = None
SCHEMA = schemas.ToRepair SCHEMA = schemas.ToRepair

View File

@ -1,3 +1,15 @@
"""
This file contains all events can apply to a device and is sorted according to a structure based on:
* Generic Events
* Benchmarks
* Tests
* Rates
* Prices
Within the above general classes are subclasses in A order.
"""
from collections import Iterable from collections import Iterable
from datetime import datetime, timedelta from datetime import datetime, timedelta
from decimal import Decimal, ROUND_HALF_EVEN, ROUND_UP from decimal import Decimal, ROUND_HALF_EVEN, ROUND_UP
@ -571,6 +583,13 @@ class Benchmark(JoinedWithOneDeviceMixin, EventWithOneDevice):
return args return args
class BenchmarkMixin:
# noinspection PyMethodParameters
@declared_attr
def id(cls):
return Column(UUID(as_uuid=True), ForeignKey(Test.id), primary_key=True)
class BenchmarkDataStorage(Benchmark): class BenchmarkDataStorage(Benchmark):
"""Benchmarks the data storage unit reading and writing speeds.""" """Benchmarks the data storage unit reading and writing speeds."""
id = Column(UUID(as_uuid=True), ForeignKey(Benchmark.id), primary_key=True) id = Column(UUID(as_uuid=True), ForeignKey(Benchmark.id), primary_key=True)
@ -607,6 +626,9 @@ class BenchmarkProcessorSysbench(BenchmarkProcessor):
class BenchmarkRamSysbench(BenchmarkWithRate): class BenchmarkRamSysbench(BenchmarkWithRate):
"""Benchmarks a RAM by using the ram benchmarking
utility of `sysbench <https://github.com/akopytov/sysbench>`_.
"""
pass pass
@ -621,7 +643,6 @@ class Test(JoinedWithOneDeviceMixin, EventWithOneDevice):
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`.
""" """
elapsed = Column(Interval, nullable=False)
@declared_attr @declared_attr
def __mapper_args__(cls): def __mapper_args__(cls):
@ -638,7 +659,14 @@ class Test(JoinedWithOneDeviceMixin, EventWithOneDevice):
return args return args
class TestDataStorage(Test): class TestMixin:
# noinspection PyMethodParameters
@declared_attr
def id(cls):
return Column(UUID(as_uuid=True), ForeignKey(Test.id), primary_key=True)
class TestDataStorage(TestMixin, Test):
""" """
The act of testing the data storage. The act of testing the data storage.
@ -650,7 +678,6 @@ class TestDataStorage(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.
""" """
id = Column(UUID(as_uuid=True), ForeignKey(Test.id), primary_key=True)
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)
lifetime = Column(Interval) lifetime = Column(Interval)
@ -662,6 +689,7 @@ class TestDataStorage(Test):
current_pending_sector_count = Column(SmallInteger) current_pending_sector_count = Column(SmallInteger)
offline_uncorrectable = Column(SmallInteger) offline_uncorrectable = Column(SmallInteger)
remaining_lifetime_percentage = Column(SmallInteger) remaining_lifetime_percentage = Column(SmallInteger)
elapsed = Column(Interval, nullable=False)
def __init__(self, **kwargs) -> None: def __init__(self, **kwargs) -> None:
super().__init__(**kwargs) super().__init__(**kwargs)
@ -686,11 +714,12 @@ class TestDataStorage(Test):
return t return t
class StressTest(Test): class StressTest(TestMixin, Test):
"""The act of stressing (putting to the maximum capacity) """The act of stressing (putting to the maximum capacity)
a device for an amount of minutes. If the device is not in great a device for an amount of minutes. If the device is not in great
condition won't probably survive such test. condition won't probably survive such test.
""" """
elapsed = Column(Interval, nullable=False)
@validates('elapsed') @validates('elapsed')
def is_minute_and_bigger_than_1_minute(self, _, value: timedelta): def is_minute_and_bigger_than_1_minute(self, _, value: timedelta):
@ -703,7 +732,7 @@ class StressTest(Test):
return '{}. Computing for {}'.format(self.severity, self.elapsed) return '{}. Computing for {}'.format(self.severity, self.elapsed)
class TestAudio(Test): class TestAudio(TestMixin, Test):
""" """
Test to check all this aspects related with audio functions, Manual Tests?? Test to check all this aspects related with audio functions, Manual Tests??
""" """
@ -713,7 +742,7 @@ class TestAudio(Test):
microphone.comment = 'This evaluate if microphone works correctly' microphone.comment = 'This evaluate if microphone works correctly'
class TestConnectivity(Test): class TestConnectivity(TestMixin, 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
""" """
@ -724,18 +753,18 @@ class TestConnectivity(Test):
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_port = Column(Boolean()) usb_port = Column(Boolean)
usb_port.comment = 'Evaluate if usb port was detected and charger plug works' usb_port.comment = 'Evaluate if usb port was detected and charger plug works'
locked = Column(Boolean) locked = Column(Boolean)
locked.comment = 'Test to check if devices is locked' locked.comment = 'Test to check if devices is locked'
class TestBattery(Test): class TestBattery(TestMixin, Test):
""" """
Test battery health, status and length of charge. Minimum X minutes discharging the device Test battery health, status and length of charge. Minimum X minutes discharging the device
""" """
# TODO how to determinate if test PASS depend on battery stat and/or health # TODO how to determinate if test PASS depend on battery stat and/or health
battery_stat = Column(Boolean()) battery_stat = Column(Boolean)
battery_stat.comment = """ battery_stat.comment = """
Some batteries can report a self-check life status. Some batteries can report a self-check life status.
""" """
@ -743,7 +772,7 @@ class TestBattery(Test):
battery_health.comment = BatteryHealthRange.__doc__ battery_health.comment = BatteryHealthRange.__doc__
class TestCamera(Test): class TestCamera(TestMixin, Test):
""" """
Test to determinate functionality and defects on camera when take pictures or record video Test to determinate functionality and defects on camera when take pictures or record video
# TODO define when test FAIL # TODO define when test FAIL
@ -752,39 +781,38 @@ class TestCamera(Test):
camera.comment = "" camera.comment = ""
class TestKeyboard(Test): class TestKeyboard(TestMixin, Test):
""" """
Test to determinate if keyboard layout are and works correctly Test to determinate if keyboard layout are and works correctly
# TODO define when test FAIL
""" """
keyboard = Column(Boolean) keyboard = Column(Boolean)
keyboard.comment = "" keyboard.comment = ""
class TestTrackpad(Test): class TestTrackpad(TestMixin, Test):
"""Test trackpad works correctly""" """
Test trackpad works correctly
# TODO define when test FAIL
"""
trackpad = Column(Boolean) trackpad = Column(Boolean)
trackpad.comment = "" trackpad.comment = ""
class TestBios(Test): class TestBios(TestMixin, 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..
"""
bios_access_range = Column(DBEnum(BiosAccessRange)) bios_access_range = Column(DBEnum(BiosAccessRange))
bios_access_range.comment = 'Range of difficult to access BIOS' bios_access_range.comment = 'Range of difficult to access BIOS'
class TestVisual(Test): class TestVisual(TestMixin, Test):
""" """
Manual rate test its are represented with grade and focuses mainly on Manual rate test its are represented with grade and focuses mainly on
the aesthetic or cosmetic defects of important parts of a device. the aesthetic or cosmetic defects of important parts of a device.
@ -849,8 +877,7 @@ class Rate(JoinedWithOneDeviceMixin, EventWithOneDevice):
""" """
The act of compute general computer rate The act of compute general computer rate
""" """
from ereuse_devicehub.resources.event.rate.workbench.v1_0 import rate_algorithm raise NotImplementedError()
return rate_algorithm.compute(device)
class RateComputer(Rate): class RateComputer(Rate):
@ -886,6 +913,14 @@ class RateComputer(Rate):
if self.processor: if self.processor:
return RatingRange.from_score(self.processor) return RatingRange.from_score(self.processor)
@classmethod
def compute(cls, device) -> 'RateComputer':
"""
The act of compute general computer rate
"""
from ereuse_devicehub.resources.event.rate.workbench.v1_0 import rate_algorithm
return rate_algorithm.compute(device)
class Price(JoinedWithOneDeviceMixin, EventWithOneDevice): class Price(JoinedWithOneDeviceMixin, EventWithOneDevice):
"""The act of setting a trading price for the device. """The act of setting a trading price for the device.
@ -913,7 +948,7 @@ class Price(JoinedWithOneDeviceMixin, EventWithOneDevice):
version = Column(StrictVersionType) version = Column(StrictVersionType)
version.comment = """The version of the software, or None.""" version.comment = """The version of the software, or None."""
rating_id = Column(UUID(as_uuid=True), ForeignKey(Rate.id)) rating_id = Column(UUID(as_uuid=True), ForeignKey(Rate.id))
rating_id.comment = """The AggregateRate used to auto-compute rating_id.comment = """The Rate used to auto-compute
this price, if it has not been set manually.""" this price, if it has not been set manually."""
rating = relationship(Rate, rating = relationship(Rate,
backref=backref('price', backref=backref('price',

View File

@ -224,9 +224,10 @@ class BenchmarkGraphicCard(BenchmarkWithRate):
class Test(EventWithOneDevice): class Test(EventWithOneDevice):
elapsed = ... # type: Column
def __init__(self, **kwargs) -> None: def __init__(self, **kwargs) -> None:
super().__init__(**kwargs) super().__init__(**kwargs)
self.elapsed = ... # type: timedelta self.elapsed = ... # type: Optional[timedelta]
self.success = ... # type: bool self.success = ... # type: bool
@ -288,9 +289,6 @@ class TestTrackpad(Test):
class TestBios(Test): class TestBios(Test):
bios_power_on = ... # type: Column bios_power_on = ... # type: Column
class TestBiosDifficulty:
bios_access_range = ... # type: BiosAccessRange bios_access_range = ... # type: BiosAccessRange
@ -321,6 +319,10 @@ class RateComputer(Rate):
ram = ... ram = ...
data_storage = ... data_storage = ...
@classmethod
def compute(cls, device) -> 'RateComputer':
pass
class Price(EventWithOneDevice): class Price(EventWithOneDevice):
SCALE = ... SCALE = ...
@ -338,7 +340,7 @@ class Price(EventWithOneDevice):
self.currency = ... # type: Currency self.currency = ... # type: Currency
self.software = ... # type: PriceSoftware self.software = ... # type: PriceSoftware
self.version = ... # type: StrictVersion self.version = ... # type: StrictVersion
self.rating = ... # type: AggregateRate self.rating = ... # type: Rate
@classmethod @classmethod
def to_price(cls, value: Union[Decimal, float], rounding=ROUND) -> Decimal: def to_price(cls, value: Union[Decimal, float], rounding=ROUND) -> Decimal:
@ -360,7 +362,7 @@ class EreusePrice(Price):
self.standard = ... # type: EreusePrice.Type self.standard = ... # type: EreusePrice.Type
self.warranty2 = ... # type: EreusePrice.Type self.warranty2 = ... # type: EreusePrice.Type
def __init__(self, rating: AggregateRate, **kwargs) -> None: def __init__(self, rating: Rate, **kwargs) -> None:
super().__init__(**kwargs) super().__init__(**kwargs)
self.retailer = ... # type: EreusePrice.Service self.retailer = ... # type: EreusePrice.Service
self.platform = ... # type: EreusePrice.Service self.platform = ... # type: EreusePrice.Service

View File

@ -1,25 +0,0 @@
from ereuse_devicehub.resources.device.models import Device
from ereuse_devicehub.resources.event.models import RateComputer
from ereuse_devicehub.resources.event.rate.workbench import v1_0
RATE_TYPES = {
RateComputer: {
'1.0': v1_0.Rate()
}
}
def rate(device: Device, version):
"""
Rates the passed-in ``rate`` using values from the rate itself
and the ``device``.
This method mutates ``rate``.
:param device: The device to use as a model.
:param rate: A half-filled rate.
"""
assert cls in RATE_TYPES, 'Rate type {} not supported.'.format(cls)
assert str(rate.version) in RATE_TYPES[cls], \
'Rate version {} not supported.'.format(rate.version)
RATE_TYPES[cls][str(rate.version)].compute(device)

View File

@ -53,7 +53,7 @@ class RateAlgorithm(BaseRate):
This mutates "rate". This mutates "rate".
""" """
assert isinstance(device, (Desktop, Laptop, Server)) assert isinstance(device, Computer)
rate = RateComputer() rate = RateComputer()
@ -70,7 +70,7 @@ class RateAlgorithm(BaseRate):
result = rate_cls.compute(components, rate) result = rate_cls.compute(components, rate)
if result: if result:
setattr(rate, field, result) setattr(rate, field, result)
# TODO is necessary check if TestVisual exists?? cause StopIteration Error
test_visual = next(e for e in device.events if isinstance(e, TestVisual)) test_visual = next(e for e in device.events if isinstance(e, TestVisual))
rate_components = self.harmonic_mean_rates(rate.processor, rate.data_storage, rate.ram) rate_components = self.harmonic_mean_rates(rate.processor, rate.data_storage, rate.ram)
@ -212,7 +212,7 @@ class DataStorageRate(BaseRate):
# STEP: Filtering, data cleaning and merging of component parts # STEP: Filtering, data cleaning and merging of component parts
for storage in data_storage_devices: for storage in data_storage_devices:
# todo fix StopIteration if don't exists BenchmarkDataStorage # We assume all hdd snapshots have BenchmarkDataStorage
benchmark = next(e for e in storage.events if isinstance(e, BenchmarkDataStorage)) benchmark = next(e for e in storage.events if isinstance(e, BenchmarkDataStorage))
# prevent NULL values # prevent NULL values
_size = storage.size or 0 _size = storage.size or 0

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, BiosAccessRange, FunctionalityRange, \ from ereuse_devicehub.resources.enums import AppearanceRange, BiosAccessRange, FunctionalityRange, \
PhysicalErasureMethod, PriceSoftware, RATE_POSITIVE, RatingRange, ReceiverRole, \ PhysicalErasureMethod, PriceSoftware, RATE_POSITIVE, RatingRange, ReceiverRole, \
Severity, SnapshotExpectedEvents, SnapshotSoftware, TestDataStorageLength Severity, SnapshotExpectedEvents, SnapshotSoftware, TestDataStorageLength, BatteryHealthRange
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
@ -143,11 +143,11 @@ class BenchmarkGraphicCard(BenchmarkWithRate):
class Test(EventWithOneDevice): class Test(EventWithOneDevice):
__doc__ = m.Test.__doc__ __doc__ = m.Test.__doc__
elapsed = TimeDelta(precision=TimeDelta.SECONDS, required=True)
class TestDataStorage(Test): class TestDataStorage(Test):
__doc__ = m.TestDataStorage.__doc__ __doc__ = m.TestDataStorage.__doc__
elapsed = TimeDelta(precision=TimeDelta.SECONDS, required=True)
length = EnumField(TestDataStorageLength, required=True) length = EnumField(TestDataStorageLength, required=True)
status = SanitizedStr(lower=True, validate=Length(max=STR_SIZE), required=True) status = SanitizedStr(lower=True, validate=Length(max=STR_SIZE), required=True)
lifetime = TimeDelta(precision=TimeDelta.HOURS) lifetime = TimeDelta(precision=TimeDelta.HOURS)
@ -163,6 +163,7 @@ class TestDataStorage(Test):
class StressTest(Test): class StressTest(Test):
__doc__ = m.StressTest.__doc__ __doc__ = m.StressTest.__doc__
elapsed = TimeDelta(precision=TimeDelta.SECONDS, required=True)
class TestAudio(Test): class TestAudio(Test):
@ -173,22 +174,41 @@ class TestAudio(Test):
class TestConnectivity(Test): class TestConnectivity(Test):
__doc__ = m.TestConnectivity.__doc__ __doc__ = m.TestConnectivity.__doc__
cellular_network = Boolean()
wifi = Boolean()
bluetooth = Boolean()
usb_port = Boolean()
locked = Boolean()
class TestBattery(Test): class TestBattery(Test):
__doc__ = m.TestBattery.__doc__ __doc__ = m.TestBattery.__doc__
battery_stat = Boolean()
battery_health = EnumField(BatteryHealthRange, data_key='batteryHealthRange')
class TestBios: class TestCamera(Test):
__doc__ = m.TestCamera.__doc__
camera = Boolean()
class TestKeyboard(Test):
__doc__ = m.TestKeyboard.__doc__
keyboard = Boolean()
class TestTrackpad(Test):
__doc__ = m.TestTrackpad.__doc__
trackpad = Boolean()
class TestBios(Test):
__doc__ = m.TestBios.__doc__ __doc__ = m.TestBios.__doc__
bios_power_on = Boolean()
bios_access_range = EnumField(BiosAccessRange, data_key='accessRange')
class TestBiosDifficulty: class TestVisual(Test):
__doc__ = m.TestBiosDifficulty.__doc__
bios_access_range = EnumField(BiosAccessRange, dump_only=True, data_key='biosAccessRange')
class TestVisual():
__doc__ = m.TestVisual.__doc__ __doc__ = m.TestVisual.__doc__
appearance_range = EnumField(AppearanceRange, dump_only=True, data_key='appearanceRange') appearance_range = EnumField(AppearanceRange, dump_only=True, data_key='appearanceRange')
functionality_range = EnumField(FunctionalityRange, dump_only=True, data_key='functionalityRange') functionality_range = EnumField(FunctionalityRange, dump_only=True, data_key='functionalityRange')

View File

@ -10,7 +10,7 @@ from teal.resource import View
from ereuse_devicehub.db import db from ereuse_devicehub.db import db
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
from ereuse_devicehub.resources.event.models import Event, Snapshot, Rate from ereuse_devicehub.resources.event.models import Event, Snapshot, Rate, RateComputer
SUPPORTED_WORKBENCH = StrictVersion('11.0') SUPPORTED_WORKBENCH = StrictVersion('11.0')
@ -81,9 +81,9 @@ class EventView(View):
snapshot.events |= events snapshot.events |= events
# Compute ratings # Compute ratings
for rate in (e for e in events_device if isinstance(e, Rate)): if isinstance(device, Computer):
rates = rate.ratings() rate_computer = RateComputer.compute(device)
snapshot.events |= rates snapshot.events.add(rate_computer)
db.session.add(snapshot) db.session.add(snapshot)
db.session().final_flush() db.session().final_flush()