From ddbe1d66be500b6150e72950371b9754c2489476 Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Thu, 23 Mar 2023 15:13:52 +0100 Subject: [PATCH] feature: add `FluidXScanner`-class --- CHANGELOG.md | 6 ++ composer.lock | 54 +++++----- rector.php | 7 ++ src/FluidXPlate/FluidXScanner.php | 103 +++++++++++++++++++ src/FluidXPlate/ScanFluidXPlateException.php | 7 ++ src/FluidXPlate/TestPlate.txt | 96 +++++++++++++++++ tests/Unit/FluidXPlate/FluidXScannerTest.php | 22 ++++ 7 files changed, 268 insertions(+), 27 deletions(-) create mode 100644 src/FluidXPlate/FluidXScanner.php create mode 100644 src/FluidXPlate/ScanFluidXPlateException.php create mode 100644 src/FluidXPlate/TestPlate.txt create mode 100644 tests/Unit/FluidXPlate/FluidXScannerTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index f03c658..e6cef4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## v5.1.0 + +### Added + +- Add `FluidXScanner`-class + ## v5.0.0 ### Added diff --git a/composer.lock b/composer.lock index 3834ec4..42f67e6 100644 --- a/composer.lock +++ b/composer.lock @@ -8253,26 +8253,26 @@ }, { "name": "orchestra/testbench", - "version": "v7.22.1", + "version": "v7.22.2", "source": { "type": "git", "url": "https://github.com/orchestral/testbench.git", - "reference": "987f5383f597a54f8d9868f98411899398348c02" + "reference": "2b46f51b61404313156f180a0b3ebda7233a309b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/orchestral/testbench/zipball/987f5383f597a54f8d9868f98411899398348c02", - "reference": "987f5383f597a54f8d9868f98411899398348c02", + "url": "https://api.github.com/repos/orchestral/testbench/zipball/2b46f51b61404313156f180a0b3ebda7233a309b", + "reference": "2b46f51b61404313156f180a0b3ebda7233a309b", "shasum": "" }, "require": { "fakerphp/faker": "^1.21", "laravel/framework": "^9.52.4", "mockery/mockery": "^1.5.1", - "orchestra/testbench-core": "^7.22.1", + "orchestra/testbench-core": "^7.22.2", "php": "^8.0", "phpunit/phpunit": "^9.5.10", - "spatie/laravel-ray": "^1.28", + "spatie/laravel-ray": "^1.32.4", "symfony/process": "^6.0.9", "symfony/yaml": "^6.0.9", "vlucas/phpdotenv": "^5.4.1" @@ -8306,22 +8306,22 @@ ], "support": { "issues": "https://github.com/orchestral/testbench/issues", - "source": "https://github.com/orchestral/testbench/tree/v7.22.1" + "source": "https://github.com/orchestral/testbench/tree/v7.22.2" }, - "time": "2023-02-24T01:07:22+00:00" + "time": "2023-03-23T09:07:28+00:00" }, { "name": "orchestra/testbench-core", - "version": "v7.22.1", + "version": "v7.22.2", "source": { "type": "git", "url": "https://github.com/orchestral/testbench-core.git", - "reference": "75b42f9130e7903ffa0ef8dbb466962ca6635261" + "reference": "c34bcaf4888cb680f76eaca11ec9c4a67c019a0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/75b42f9130e7903ffa0ef8dbb466962ca6635261", - "reference": "75b42f9130e7903ffa0ef8dbb466962ca6635261", + "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/c34bcaf4888cb680f76eaca11ec9c4a67c019a0b", + "reference": "c34bcaf4888cb680f76eaca11ec9c4a67c019a0b", "shasum": "" }, "require": { @@ -8333,9 +8333,9 @@ "laravel/pint": "^1.4", "mockery/mockery": "^1.5.1", "orchestra/canvas": "^7.0", - "phpstan/phpstan": "^1.9.14", + "phpstan/phpstan": "^1.10.7", "phpunit/phpunit": "^9.5.10", - "spatie/laravel-ray": "^1.28", + "spatie/laravel-ray": "^1.32.4", "symfony/process": "^6.0.9", "symfony/yaml": "^6.0.9", "vlucas/phpdotenv": "^5.4.1" @@ -8394,7 +8394,7 @@ "issues": "https://github.com/orchestral/testbench/issues", "source": "https://github.com/orchestral/testbench-core" }, - "time": "2023-02-23T12:15:23+00:00" + "time": "2023-03-23T08:52:15+00:00" }, { "name": "phar-io/manifest", @@ -9525,16 +9525,16 @@ }, { "name": "rector/rector", - "version": "0.15.21", + "version": "0.15.23", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "1cee8cc5d6d836e1bf9a3006d7b062adde3a6022" + "reference": "f4984ebd62b3613002869b0ddd6868261d62819e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/1cee8cc5d6d836e1bf9a3006d7b062adde3a6022", - "reference": "1cee8cc5d6d836e1bf9a3006d7b062adde3a6022", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/f4984ebd62b3613002869b0ddd6868261d62819e", + "reference": "f4984ebd62b3613002869b0ddd6868261d62819e", "shasum": "" }, "require": { @@ -9574,7 +9574,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/0.15.21" + "source": "https://github.com/rectorphp/rector/tree/0.15.23" }, "funding": [ { @@ -9582,7 +9582,7 @@ "type": "github" } ], - "time": "2023-03-06T11:44:29+00:00" + "time": "2023-03-22T15:22:45+00:00" }, { "name": "sanmai/later", @@ -10735,16 +10735,16 @@ }, { "name": "spatie/laravel-ray", - "version": "1.32.3", + "version": "1.32.4", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ray.git", - "reference": "8c7ea86c8092bcfe7a046f640b6ac9e5d7ec98cd" + "reference": "2274653f0a90dd87fbb887437be1c1ea1388a47c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ray/zipball/8c7ea86c8092bcfe7a046f640b6ac9e5d7ec98cd", - "reference": "8c7ea86c8092bcfe7a046f640b6ac9e5d7ec98cd", + "url": "https://api.github.com/repos/spatie/laravel-ray/zipball/2274653f0a90dd87fbb887437be1c1ea1388a47c", + "reference": "2274653f0a90dd87fbb887437be1c1ea1388a47c", "shasum": "" }, "require": { @@ -10804,7 +10804,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-ray/issues", - "source": "https://github.com/spatie/laravel-ray/tree/1.32.3" + "source": "https://github.com/spatie/laravel-ray/tree/1.32.4" }, "funding": [ { @@ -10816,7 +10816,7 @@ "type": "other" } ], - "time": "2023-03-03T13:37:21+00:00" + "time": "2023-03-23T08:04:54+00:00" }, { "name": "spatie/macroable", diff --git a/rector.php b/rector.php index a88fbd1..881e15c 100644 --- a/rector.php +++ b/rector.php @@ -2,6 +2,7 @@ use Rector\Config\RectorConfig; use Rector\Core\ValueObject\PhpVersion; +use Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector; use Rector\Set\ValueObject\SetList; use Rector\TypeDeclaration\Rector\Closure\AddClosureReturnTypeRector; @@ -18,4 +19,10 @@ ]); $config->paths([__DIR__ . '/src', __DIR__ . '/tests']); $config->phpVersion(PhpVersion::PHP_74); + + $config->skip([ + FinalizeClassesWithoutChildrenRector::class => [ + __DIR__ . '/src/FluidXPlate/FluidXScanner.php', // enabled for mocking + ], + ]); }; diff --git a/src/FluidXPlate/FluidXScanner.php b/src/FluidXPlate/FluidXScanner.php new file mode 100644 index 0000000..2305c70 --- /dev/null +++ b/src/FluidXPlate/FluidXScanner.php @@ -0,0 +1,103 @@ +getMessage()}. Verify that the FluidX Scanner is turned on and the FluidX software is started.", 0, $e); + } + + \Safe\fwrite($socket, "get\r\n"); + + $answer = ''; + do { + $content = fgets($socket); + $answer .= $content; + } while (is_string($content) && ! Str::contains($content, 'H12')); + + \Safe\fclose($socket); + + return self::parseRawContent($answer); + } + + public static function parseRawContent(string $rawContent): FluidXPlate + { + if ('' === $rawContent) { + throw new ScanFluidXPlateException('Der Scanner lieferte ein leeres Ergebnis zurück.'); + } + + $lines = StringUtil::splitLines($rawContent); + $barcodes = []; + $id = null; + foreach ($lines as $line) { + if ('' === $line || self::READING === $line || self::XTR_96_CONNECTED === $line) { + continue; + } + $content = explode(', ', $line); + if (count($content) <= 3) { + continue; + } + + // All valid lines contain the same plate barcode + $id = $content[3]; + if (FluidXScanner::NO_READ === $id && isset($content[4])) { + $id = $content[4]; + } + + $barcodeScanResult = $content[1]; + $coordinateString = $content[0]; + if (self::NO_READ !== $barcodeScanResult && self::NO_TUBE !== $barcodeScanResult) { + $barcodes[$coordinateString] = $barcodeScanResult; + } + } + + if (is_null($id)) { + throw new ScanFluidXPlateException('Der Scanner lieferte keinen Plattenbarcode zurück.'); + } + + if (FluidXScanner::NO_READ === $id) { + throw new ScanFluidXPlateException([] === $barcodes + ? 'Weder Platten-Barcode noch Tube-Barcodes konnten gescannt werden. Bitte überprüfen Sie, dass die Platte korrekt in den FluidX-Scanner eingelegt wurde.' + : 'Platten-Barcode konnte nicht gescannt werden. Bitte überprüfen Sie, dass die Platte mit der korrekten Orientierung in den FluidX-Scanner eingelegt wurde.'); + } + + $plate = new FluidXPlate($id); + foreach ($barcodes as $coordinate => $barcode) { + $plate->addWell(Coordinate::fromString($coordinate, new CoordinateSystem96Well()), $barcode); + } + + return $plate; + } + + private static function returnTestPlate(): FluidXPlate + { + return self::parseRawContent(\Safe\file_get_contents(__DIR__ . '/TestPlate.txt')); + } +} diff --git a/src/FluidXPlate/ScanFluidXPlateException.php b/src/FluidXPlate/ScanFluidXPlateException.php new file mode 100644 index 0000000..4399603 --- /dev/null +++ b/src/FluidXPlate/ScanFluidXPlateException.php @@ -0,0 +1,7 @@ +scanPlate(FluidXScanner::LOCALHOST); + + self::assertSame('SA00826894', $fluidXPlate->rackId); + $filledWells = $fluidXPlate->filledWells(); + self::assertCount(3, $filledWells); + self::assertSame('FD20024619', $filledWells->get('A1')); + self::assertSame('FD20024698', $filledWells->get('A2')); + self::assertSame('FD20024711', $filledWells->get('A3')); + } +}