Allow to extract ranges from paramaters

This commit is contained in:
Jan Böhmer 2023-07-15 01:41:29 +02:00
parent f9fdae9de9
commit 94a26ae75a
2 changed files with 202 additions and 6 deletions

View file

@ -38,27 +38,59 @@ class ParameterDTO
}
/**
* This function tries to decide on the value, if it is a numerical value (which is then stored in one of the value_*) fields) or a text value (which is stored in value_text).
* It is possible to give ranges like 1...2 here, which will be parsed as value_min: 1.0, value_max: 2.0.
* @param string $name
* @param string|float $value
* @param string|null $unit
* @param string|null $symbol
* @param string|null $group
* @return self
*/
public static function parseValueField(string $name, string|float $value, ?string $unit = null, ?string $symbol = null, ?string $group = null): self
{
if (is_float($value) || is_numeric($value)) {
return new self($name, value_typ: (float) $value, unit: $unit, symbol: $symbol, group: $group);
}
//Try to parse as range
if (str_contains($value, '...')) {
$parts = explode('...', $value);
if (count($parts) === 2) {
//Ensure that both parts are numerical
if (is_numeric($parts[0]) && is_numeric($parts[1])) {
return new self($name, value_min: (float) $parts[0], value_max: (float) $parts[1], unit: $unit, symbol: $symbol, group: $group);
}
}
}
return new self($name, value_text: $value, unit: $unit, symbol: $symbol, group: $group);
}
/**
* This function tries to decide on the value, if it is a numerical value (which is then stored in one of the value_*) fields) or a text value (which is stored in value_text).
* It also tries to extract the unit from the value field (so 3kg will be parsed as value_typ: 3.0, unit: kg).
* Ranges like 1...2 will be parsed as value_min: 1.0, value_max: 2.0.
* @param string $name
* @param string|float $value
* @param string|null $symbol
* @param string|null $group
* @return self
*/
public static function parseValueIncludingUnit(string $name, string|float $value, ?string $symbol = null, ?string $group = null): self
{
if (is_float($value) || is_numeric($value)) {
return new self($name, value_typ: (float) $value, symbol: $symbol, group: $group);
}
//Try to extract unit from value
$unit = null;
if (preg_match('/^(?<value>[0-9.]+)\s*(?<unit>[a-zA-Z]+)$/', $value, $matches)) {
if (is_string($value) && preg_match('/^(?<value>[0-9.]+)\s*(?<unit>[°a-zA-Z_]+\s?\w{0,4})$/u', $value, $matches)) {
$value = $matches['value'];
$unit = $matches['unit'];
return self::parseValueField(name: $name, value: $value, unit: $unit, symbol: $symbol, group: $group);
}
return new self($name, value_text: $value, unit: $unit, symbol: $symbol, group: $group);
//Otherwise we assume that no unit is given
return self::parseValueField(name: $name, value: $value, unit: null, symbol: $symbol, group: $group);
}
}

View file

@ -0,0 +1,164 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace App\Tests\Services\InfoProviderSystem\DTOs;
use App\Services\InfoProviderSystem\DTOs\ParameterDTO;
use PHPUnit\Framework\TestCase;
class ParameterDTOTest extends TestCase
{
public function parseValueFieldDataProvider(): \Generator
{
//Text value
yield [
new ParameterDTO('test', value_text: 'test', unit: 'm', symbol: 'm', group: 'test'),
'test',
'test',
'm',
'm',
'test'
];
//Numerical value
yield [
new ParameterDTO('test', value_typ: 1.0, unit: 'm', symbol: 'm', group: 'test'),
'test',
1.0,
'm',
'm',
'test'
];
//Numerical value with unit should be parsed as text value
yield [
new ParameterDTO('test', value_text: '1.0 m', unit: 'm', symbol: 'm', group: 'test'),
'test',
'1.0 m',
'm',
'm',
'test'
];
//Test ranges
yield [
new ParameterDTO('test', value_min: 1.0, value_max: 2.0, unit: 'kg', symbol: 'm', group: 'test'),
'test',
'1.0...2.0',
'kg',
'm',
'test'
];
}
public function parseValueIncludingUnitDataProvider(): \Generator
{
//Text value
yield [
new ParameterDTO('test', value_text: 'test', unit: null, symbol: 'm', group: 'test'),
'test',
'test',
'm',
'test'
];
//Numerical value
yield [
new ParameterDTO('test', value_typ: 1.0, unit: null, symbol: 'm', group: 'test'),
'test',
1.0,
'm',
'test'
];
//Numerical value with unit should extract unit correctly
yield [
new ParameterDTO('test', value_typ: 1.0, unit: 'kg', symbol: 'm', group: 'test'),
'test',
'1.0 kg',
'm',
'test'
];
//Should work without space between value and unit
yield [
new ParameterDTO('test', value_typ: 1.0, unit: 'kg', symbol: 'm', group: 'test'),
'test',
'1.0kg',
'm',
'test'
];
//Allow ° as unit symbol
yield [
new ParameterDTO('test', value_typ: 1.0, unit: '°C', symbol: 'm', group: 'test'),
'test',
'1.0°C',
'm',
'test'
];
//Allow _ in units
yield [
new ParameterDTO('test', value_typ: 1.0, unit: 'C_m', symbol: 'm', group: 'test'),
'test',
'1.0C_m',
'm',
'test'
];
//Allow a single space in units
yield [
new ParameterDTO('test', value_typ: 1.0, unit: 'C m', symbol: 'm', group: 'test'),
'test',
'1.0C m',
'm',
'test'
];
//Test ranges
yield [
new ParameterDTO('test', value_min: 1.0, value_max: 2.0, unit: 'kg', symbol: 'm', group: 'test'),
'test',
'1.0...2.0 kg',
'm',
'test'
];
}
/**
* @dataProvider parseValueFieldDataProvider
* @return void
*/
public function testParseValueField(ParameterDTO $expected, string $name, string|float $value, ?string $unit = null, ?string $symbol = null, ?string $group = null)
{
$this->assertEquals($expected, ParameterDTO::parseValueField($name, $value, $unit, $symbol, $group));
}
/**
* @dataProvider parseValueIncludingUnitDataProvider
* @return void
*/
public function testParseValueIncludingUnit(ParameterDTO $expected, string $name, string|float $value, ?string $symbol = null, ?string $group = null)
{
$this->assertEquals($expected, ParameterDTO::parseValueIncludingUnit($name, $value, $symbol, $group));
}
}