Skip to content

Commit

Permalink
[0.10] SI-Attribute (#478)
Browse files Browse the repository at this point in the history
* add basic functionality

* set defaults to label instead of symbol

* add si unit options to add attribute template

* fix table attribute

* add backend logic; set initial default unit value

* 0.10 feature si attribute rework (#502)

* Creating SI Classes

* Reworked Si Handling with additional Classes

* Fixed reset not working and error on multiple saves

* simplify unit class(es); fix unit order; use constants for all units

* fix several vue warnings and missing/wrong i18n strings

* move singleton

* Added tests fixed some minor errors

* Added german translations

---------

Signed-off-by: Vinzenz Rosenkranz <vinzenz.rosenkranz@uni-tuebingen.de>
Co-authored-by: Severino <severin.opel@hotmail.com>
Co-authored-by: Sev <captain.sev@outlook.com>
  • Loading branch information
3 people authored Jun 7, 2024
1 parent dbee73e commit ae7d9d6
Show file tree
Hide file tree
Showing 46 changed files with 1,801 additions and 72 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## General ##
_legacy
*.cache

### NPM ###
node_modules
Expand All @@ -13,6 +14,7 @@ thesaurex

## Created by PHPUnit/Coveralls
/build
phpunit.xml.bak

## Created by Laravel
/node_modules
Expand Down
1 change: 1 addition & 0 deletions app/Attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class Attribute extends Model

protected $casts = [
'restrictions' => 'array',
'metadata' => 'array',
];

public function getActivitylogOptions() : LogOptions
Expand Down
14 changes: 10 additions & 4 deletions app/AttributeTypes/AttributeBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ abstract class AttributeBase
"timeperiod" => TimeperiodAttribute::class,
"userlist" => UserlistAttribute::class,
"url" => UrlAttribute::class,
"si-unit" => SiUnitAttribute::class,
];

public static function serialized() : array {
Expand All @@ -51,7 +52,7 @@ public static function serialized() : array {
];
}

public static function getTypes(array $filters = []) : array {
public static function getTypes(bool $serialized = false, array $filters = []) : array {
if(count($filters) > 0) {
$types = Arr::where(self::$types, function(string $attr, string $key) use($filters) {
foreach($filters as $on => $value) {
Expand All @@ -70,9 +71,14 @@ public static function getTypes(array $filters = []) : array {
} else {
$types = self::$types;
}
return array_values(array_map(function(string $class) {
return $class::serialized();
}, $types));

if($serialized) {
return array_values(array_map(function(string $class) {
return $class::serialized();
}, $types));
} else {
return $types;
}
}

public static function getMatchingClass(string $datatype) : bool|AttributeBase {
Expand Down
75 changes: 75 additions & 0 deletions app/AttributeTypes/SiUnitAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

namespace App\AttributeTypes;

use App\AttributeTypes\Units\Implementations\UnitManager;
use App\Exceptions\InvalidDataException;


class SiUnitAttribute extends AttributeBase {
protected static string $type = "si-unit";
protected static bool $inTable = true;
protected static ?string $field = 'json_val';


public static function getGlobalData(): array {
$unitsArray = [];
foreach (UnitManager::get()->getUnitSystems() as $unitSystem) {
$unitsArray[$unitSystem->name] = $unitSystem->toArray();
}

return $unitsArray;
}

public static function fromImport(int|float|bool|string $data): mixed {
if (!is_string($data)) {
throw new InvalidDataException(__('validation.string', ['attribute' => __('dictionary.value')]));
}

$parts = explode(';', $data);

if (count($parts) != 2) {
$format = __('dictionary.value') . ';' . __('dictionary.unit');
throw new InvalidDataException(__('validation.import_format', ['format' => $format]));
}

$value = trim($parts[0]);
if (!is_numeric($value)) {
$section_1 = __('dictionary.section') . ' 1';
throw new InvalidDataException(__('validation.numeric', ['attribute' => $section_1]));
}

$value = floatval($value);
$unit = trim($parts[1]);
$unitFound = UnitManager::get()->findUnitByAny($unit);

if (!isset($unitFound)) {
$section_2 = __('dictionary.section') . ' 2';
throw new InvalidDataException(__('validation.unit', ['attribute' => $section_2]));
}

return json_encode([
'value' => $value,
'unit' => $unitFound->getSymbol(),
'normalized' => $unitFound->normalize($value),
]);
}

public static function unserialize(mixed $data): mixed {

if (isset($data["unit"])) {
$unit = UnitManager::get()->findUnitByAny($data['unit']);
}

if (!isset($unit) || !isset($data["value"]) || !isset($data["unit"])) {
throw new InvalidDataException(__('validation.unit', ['attribute' => __('dictionary.value')]));
}

$data['normalized'] = $unit->normalize($data['value']);
return json_encode($data);
}

public static function serialize(mixed $data): mixed {
return json_decode($data);
}
}
2 changes: 1 addition & 1 deletion app/AttributeTypes/TableAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class TableAttribute extends AttributeBase
public static function getSelection(Attribute $a) {
$types = array_map(function(array $entry) {
return $entry["datatype"];
}, AttributeBase::getTypes(['in_table' => true, 'has_selection' => true]));
}, AttributeBase::getTypes(true, ['in_table' => true, 'has_selection' => true]));

$columns = Attribute::where('parent_id', $a->id)
->whereIn('datatype', $types)
Expand Down
26 changes: 26 additions & 0 deletions app/AttributeTypes/Units/Call.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace App\AttributeTypes\Units;

use App\AttributeTypes\Units\SiPrefix\SiPrefix;

class Call {

public static function identity(): callable {
return function ($value) {
return $value;
};
}

public static function multiply(float $factor, float $dimension = 1): callable {
return function ($value) use ($factor, $dimension) {
return $value * ($factor ** $dimension);
};
}

public static function si(float $factor, float $dimension = 1): callable {
return function ($value) use ($factor, $dimension) {
return $value * 10 ** ($factor * $dimension);
};
}
}
7 changes: 7 additions & 0 deletions app/AttributeTypes/Units/Constants/General.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace App\AttributeTypes\Units\Constants;

class General {
public const /*int*/ LIGHTYEAR = 9460730472580800;
}
17 changes: 17 additions & 0 deletions app/AttributeTypes/Units/Constants/Imperial.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace App\AttributeTypes\Units\Constants;

class Imperial {
public const /*float*/ INCH_2_M = 0.0254;
public const /*float*/ FOOT_2_M = 0.3048;
public const /*float*/ YARD_2_M = 0.9144;
public const /*float*/ MILE_2_M = 1609.344;
public const /*float*/ ACRE_2_M2 = 4046.8564224;
public const /*float*/ OUNCE_2_G = 28.349523125;
public const /*float*/ POUND_2_G = 453.59237;
public const /*float*/ FLUID_OUNCE_US = 2.95735295625e-5;
public const /*float*/ PINT_US = 4.73176473e-4;
public const /*float*/ CUPS_US = 2.365882372125699e-4;
public const /*float*/ GALLON_US = 3.785411784e-3;
}
26 changes: 26 additions & 0 deletions app/AttributeTypes/Units/Constants/Si.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace App\AttributeTypes\Units\Constants;

class Si {
public const /*int*/ YOTTA = 24;
public const /*int*/ ZETTA = 21;
public const /*int*/ EXA = 18;
public const /*int*/ PETA = 15;
public const /*int*/ TERA = 12;
public const /*int*/ GIGA = 9;
public const /*int*/ MEGA = 6;
public const /*int*/ KILO = 3;
public const /*int*/ HECTO = 2;
public const /*int*/ DECA = 1;
public const /*int*/ DECI = -1;
public const /*int*/ CENTI = -2;
public const /*int*/ MILLI = -3;
public const /*int*/ MICRO = -6;
public const /*int*/ NANO = -9;
public const /*int*/ PICO = -12;
public const /*int*/ FEMTO = -15;
public const /*int*/ ATTO = -18;
public const /*int*/ ZEPTO = -21;
public const /*int*/ YOCTO = -24;
}
21 changes: 21 additions & 0 deletions app/AttributeTypes/Units/Constants/Temperature.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace App\AttributeTypes\Units\Constants;

class Temperature {
public static function CELSIUS_2_KELVIN() {
return function($value) {
return $value + 273.15;
};
}
public static function FAHRENHEIT_2_KELVIN() {
return function($value) {
return ($value + 459.67) * 5/9;
};
}
public static function REAUMUR_2_KELVIN() {
return function($value) {
return $value * 1.25 + 273.15;
};
}
}
10 changes: 10 additions & 0 deletions app/AttributeTypes/Units/Constants/Time.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace App\AttributeTypes\Units\Constants;

class Time {
public const /*int*/ MINUTE_2_SECOND = 60;
public const /*int*/ HOUR_2_SECOND = 3600; // 60 * 60
public const /*int*/ DAY_2_SECOND = 86400; // 60 * 60 * 24
public const /*int*/ YEAR_2_SECOND = 31536000; // 60 * 60 * 24 * 365
}
29 changes: 29 additions & 0 deletions app/AttributeTypes/Units/Implementations/AreaUnits.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace App\AttributeTypes\Units\Implementations;

use App\AttributeTypes\Units\Constants\Imperial;
use App\AttributeTypes\Units\Constants\Si;
use App\AttributeTypes\Units\Unit;
use App\AttributeTypes\Units\UnitSystem;
use App\AttributeTypes\Units\UnitType;

class AreaUnits extends UnitSystem {
private const /*int*/ DIM = 2;

public function __construct() {
parent::__construct('area', [
Unit::createUnit('square_centimetre', 'cm²', Si::CENTI, self::DIM, UnitType::SI),
Unit::createBase( 'square_metre' , ''),
Unit::createUnit('square_kilometre' , 'km²', Si::KILO, self::DIM, UnitType::SI),
]);

$this->addMultiple([
Unit::createUnit('square_inch' , 'in²', Imperial::INCH_2_M , self::DIM),
Unit::createUnit('square_feet' , 'ft²', Imperial::FOOT_2_M, self::DIM),
Unit::createUnit('square_yard' , 'yd²', Imperial::YARD_2_M, self::DIM),
Unit::createUnit('acre' , 'ac' , Imperial::ACRE_2_M2),
Unit::createUnit('square_mile' , 'mi²', Imperial::MILE_2_M, self::DIM),
]);
}
}
34 changes: 34 additions & 0 deletions app/AttributeTypes/Units/Implementations/LengthUnits.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace App\AttributeTypes\Units\Implementations;

use App\AttributeTypes\Units\Constants\Imperial;
use App\AttributeTypes\Units\Constants\General;
use App\AttributeTypes\Units\Constants\Si;
use App\AttributeTypes\Units\Unit;
use App\AttributeTypes\Units\UnitSystem;
use App\AttributeTypes\Units\UnitType;

class LengthUnits extends UnitSystem {

public function __construct() {
parent::__construct('length', [
Unit::createUnit('nanometre' , 'nm', Si::NANO, 1, UnitType::SI),
Unit::createUnit('micrometre', 'µm', Si::MICRO, 1, UnitType::SI),
Unit::createUnit('millimetre', 'mm', Si::MILLI, 1, UnitType::SI),
Unit::createUnit('centimetre', 'cm', Si::CENTI, 1, UnitType::SI),
Unit::createBase( 'metre' , 'm'),
Unit::createUnit('kilometre' , 'km', Si::KILO, 1, UnitType::SI),
]);

$this->addMultiple([
Unit::createUnit('inch' , 'in', Imperial::INCH_2_M),
Unit::createUnit('feet' , 'ft', Imperial::FOOT_2_M),
Unit::createUnit('yard' , 'yd', Imperial::YARD_2_M),
Unit::createUnit('mile' , 'mi', Imperial::MILE_2_M),
]);
$this->add(
Unit::createUnit('light_year', 'ly', General::LIGHTYEAR),
);
}
}
34 changes: 34 additions & 0 deletions app/AttributeTypes/Units/Implementations/MassUnits.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace App\AttributeTypes\Units\Implementations;

use App\AttributeTypes\Units\Constants\Imperial;
use App\AttributeTypes\Units\Constants\Si;
use App\AttributeTypes\Units\Unit;
use App\AttributeTypes\Units\UnitSystem;
use App\AttributeTypes\Units\UnitType;

class MassUnits extends UnitSystem
{

public function __construct()
{
parent::__construct('mass', [
Unit::createUnit('milligram', 'mg', Si::MILLI, 1, UnitType::SI),
Unit::createBase( 'gram' , 'g'),
Unit::createUnit('kilogram' , 'kg', Si::KILO, 1, UnitType::SI),
Unit::createUnit('ton' , 't', Si::MEGA, 1, UnitType::SI),
]);

$this->addImperialUnits();
}

private function addImperialUnits(){
$this->addMultiple([
Unit::createUnit('ounce', 'oz', Imperial::OUNCE_2_G),
Unit::createUnit('pound', 'lb', Imperial::POUND_2_G),
]);
}


}
19 changes: 19 additions & 0 deletions app/AttributeTypes/Units/Implementations/TemperatureUnits.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\AttributeTypes\Units\Implementations;

use App\AttributeTypes\Units\Constants\Temperature as Temp;
use App\AttributeTypes\Units\Unit;
use App\AttributeTypes\Units\UnitSystem;

class TemperatureUnits extends UnitSystem{

public function __construct() {
parent::__construct('temperature', [
Unit::createBase('kelvin' , 'K'),
Unit::createWith('celsius' , '°C', Temp::CELSIUS_2_KELVIN()),
Unit::createWith('fahrenheit', '°F', Temp::FAHRENHEIT_2_KELVIN()),
Unit::createWith('réaumur' , '°Ré', Temp::REAUMUR_2_KELVIN()),
]);
}
}
Loading

0 comments on commit ae7d9d6

Please sign in to comment.