diff --git a/aoc b/aoc index dbfb0d6..becdee3 100755 --- a/aoc +++ b/aoc @@ -11,6 +11,8 @@ use trizz\AdventOfCode\Commands\TestDay; (new CollisionProvider())->register(); +require_once __DIR__.'/src/bootstrap.php'; + $application = new Application('Advent of Code by trizz'); $application->add(new Puzzle()); diff --git a/src/Y21/Day1.php b/data/Y21/day1/Day1.php similarity index 100% rename from src/Y21/Day1.php rename to data/Y21/day1/Day1.php diff --git a/src/Y21/Day2.php b/data/Y21/day2/Day2.php similarity index 100% rename from src/Y21/Day2.php rename to data/Y21/day2/Day2.php diff --git a/src/Y21/Day3.php b/data/Y21/day3/Day3.php similarity index 100% rename from src/Y21/Day3.php rename to data/Y21/day3/Day3.php diff --git a/src/Y21/Day4.php b/data/Y21/day4/Day4.php similarity index 100% rename from src/Y21/Day4.php rename to data/Y21/day4/Day4.php diff --git a/src/Y21/Day6.php b/data/Y21/day6/Day6.php similarity index 100% rename from src/Y21/Day6.php rename to data/Y21/day6/Day6.php diff --git a/src/Y21/Day7.php b/data/Y21/day7/Day7.php similarity index 100% rename from src/Y21/Day7.php rename to data/Y21/day7/Day7.php diff --git a/src/Y21/Day8.php b/data/Y21/day8/Day8.php similarity index 100% rename from src/Y21/Day8.php rename to data/Y21/day8/Day8.php diff --git a/src/Y22/Day1.php b/data/Y22/day1/Day1.php similarity index 96% rename from src/Y22/Day1.php rename to data/Y22/day1/Day1.php index 4444af5..ab61a44 100644 --- a/src/Y22/Day1.php +++ b/data/Y22/day1/Day1.php @@ -1,6 +1,6 @@ \\> but returns array\\\\|string\\>\\.$#" count: 1 - path: src/Y23/Day2.php + path: data/Y23/day2/Day2.php diff --git a/phpstan.neon b/phpstan.neon index c343fad..7ea665b 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,6 +2,7 @@ parameters: level: 8 paths: - src + - data includes: - phpstan-baseline.neon diff --git a/rector.php b/rector.php index d0bbba5..cfeaec2 100644 --- a/rector.php +++ b/rector.php @@ -10,6 +10,7 @@ return static function (RectorConfig $rectorConfig): void { $rectorConfig->paths( [ __DIR__.'/src', + __DIR__.'/data', ] ); diff --git a/src/Commands/AbstractDayCommand.php b/src/Commands/AbstractDayCommand.php index e51d055..a527dbc 100644 --- a/src/Commands/AbstractDayCommand.php +++ b/src/Commands/AbstractDayCommand.php @@ -77,6 +77,7 @@ abstract class AbstractDayCommand extends Command protected function loadClass(): Solution { + require_once sprintf('%s/Y%d/day%d/Day%d.php', DATA_DIR, $this->year, $this->day, $this->day); $className = sprintf('%s\\Y%d\\Day%d', substr(__NAMESPACE__, 0, -9), $this->year, $this->day); /** @var Solution $class */ diff --git a/src/Commands/AddDay.php b/src/Commands/AddDay.php index f658671..25605a2 100644 --- a/src/Commands/AddDay.php +++ b/src/Commands/AddDay.php @@ -15,6 +15,8 @@ use function Laravel\Prompts\text; final class AddDay extends Command { + private string $dataDir; + #[\Override] protected function configure(): void { @@ -37,60 +39,57 @@ final class AddDay extends Command placeholder: '3', default: date('j'), required: true, - validate: fn ($value) => is_numeric($value) && $value > 0 && $value < 26 ? null : 'Please enter a valid day number.' + validate: static fn ($value): ?string => is_numeric($value) && $value > 0 && $value < 26 ? null : 'Please enter a valid day number.' ); } $example1Result = text( label: 'Please enter the result for example 1.', required: true, - validate: fn ($value) => is_numeric($value) ? null : 'Please enter a valid number.' + validate: static fn ($value): ?string => is_numeric($value) ? null : 'Please enter a valid number.' ); // Create short year. - $year = strlen($year) === 4 ? substr($year, 2) : $year; - - $output->writeln("Adding files for day {$day} of year '{$year}."); + $year = strlen((string) $year) === 4 ? substr((string) $year, 2) : $year; + $this->dataDir = DATA_DIR.'/Y'.$year.'/day'.$day; + $output->writeln(sprintf("Adding files for day %s of year '%s.", $day, $year)); $this - ->createDirs($year, $day) - ->createClass($day, $year, $example1Result) - ->addExampleDirs($year, $day); + ->addDirsAndExampleFiles($year, $day) + ->createClass($day, $year, $example1Result); return Command::SUCCESS; } - protected function createDirs(int $year, int $day): self + private function createClass(string $day, string $year, string $example1Result): self { - if (!is_dir($dir = "src/Y{$year}") && !mkdir($dir) && !is_dir($dir)) { - throw new \RuntimeException(sprintf('Directory "%s" was not created', $dir)); - } + $phpNamespace = new PhpNamespace('trizz\AdventOfCode\Y'.$year); + $classType = new ClassType('Day'.$day); - if (!is_dir($dir = "data/Y{$year}/day{$day}") && !mkdir($dir) && !is_dir($dir)) { - throw new \RuntimeException(sprintf('Directory "%s" was not created', $dir)); - } + $classType->setFinal()->setExtends(Solution::class); + + $this->createClassProperties($classType, $example1Result); + $this->createClassMethods($classType); + + $phpNamespace->add($classType); + $this->printClassToFile($classType, $year, $day, $phpNamespace); return $this; } - protected function createClass(string $day, string $year, string $example1Result): self + private function addDirsAndExampleFiles(mixed $year, mixed $day): self { - $namespace = new PhpNamespace('trizz\AdventOfCode\Y'.$year); - $class = new ClassType('Day'.$day); + if (!is_dir($this->dataDir) && !mkdir($this->dataDir) && !is_dir($this->dataDir)) { + throw new \RuntimeException(sprintf('Directory "%s" was not created', $this->dataDir)); + } - $class->setFinal() - ->setExtends(Solution::class); - - $this->createClassProperties($class, $example1Result); - $this->createClassMethods($class); - - $namespace->add($class); - $this->printClassToFile($class, $year, $day, $namespace); + touch($this->dataDir.'/example.txt'); + touch($this->dataDir.'/data.txt'); return $this; } - private function createClassProperties(ClassType $class, string $example1Result): void + private function createClassProperties(ClassType $classType, string $example1Result): void { $properties = [ 'part1ExampleResult' => $example1Result, @@ -100,7 +99,7 @@ final class AddDay extends Command ]; foreach ($properties as $name => $value) { - $class + $classType ->addProperty($name, $value) ->setPublic() ->setStatic() @@ -108,43 +107,29 @@ final class AddDay extends Command } } - private function createClassMethods(ClassType $class): void + private function createClassMethods(ClassType $classType): void { $methods = ['part1', 'part2']; - foreach ($methods as $methodName) { - $class - ->addMethod($methodName) + foreach ($methods as $method) { + $classType + ->addMethod($method) ->setReturnType('int') ->setBody('return -1;') ->addParameter('data')->setType('array'); } } - private function printClassToFile(ClassType $class, string $year, string $day, PhpNamespace $namespace): void + private function printClassToFile(ClassType $classType, string $year, string $day, PhpNamespace $phpNamespace): void { $printer = new Printer(); $printer->indentation = ' '; - $filename = __DIR__.'/../Y'.$year.'/Day'.$day.'.php'; + $filename = $this->dataDir.'/Day'.$day.'.php'; if (file_exists($filename)) { - throw new \RuntimeException("File {$filename} already exists."); + throw new \RuntimeException(sprintf('File %s already exists.', $filename)); } - file_put_contents($filename, 'printNamespace($namespace)); - } - - protected function addExampleDirs(mixed $year, mixed $day): self - { - $dataDir = __DIR__.'/../../data/Y'.$year.'/day'.$day; - - if (!is_dir($dataDir) && !mkdir($dataDir) && !is_dir($dataDir)) { - throw new \RuntimeException(sprintf('Directory "%s" was not created', $dataDir)); - } - - touch($dataDir.'/example.txt'); - touch($dataDir.'/data.txt'); - - return $this; + file_put_contents($filename, 'printNamespace($phpNamespace)); } } diff --git a/src/bootstrap.php b/src/bootstrap.php new file mode 100644 index 0000000..fefcad1 --- /dev/null +++ b/src/bootstrap.php @@ -0,0 +1,3 @@ +extend('toBeOne', fn() => $this->toBe(1)); +expect()->extend('toBeOne', fn () => $this->toBe(1)); /* |-------------------------------------------------------------------------- @@ -45,12 +45,16 @@ expect()->extend('toBeOne', fn() => $this->toBe(1)); function loadSolutions(int $year): array { $classes = []; - if (is_dir(__DIR__.'/../src/Y'.$year)) { - for ($day = 1; $day < 26; ++$day) { - $className = sprintf('trizz\\AdventOfCode\\Y%d\\Day%d', $year, $day); - if (class_exists($className)) { - $classes["Year '".$year.' / Day '.$day] = $className; - } + for ($day = 1; $day < 26; ++$day) { + $classFile = sprintf('%s/../data/Y%d/day%d/Day%d.php', __DIR__, $year, $day, $day); + if (!file_exists($classFile)) { + continue; + } + + require_once $classFile; + $className = sprintf('trizz\\AdventOfCode\\Y%d\\Day%d', $year, $day); + if (class_exists($className)) { + $classes["Year '".$year.' / Day '.$day] = $className; } } @@ -60,7 +64,7 @@ function loadSolutions(int $year): array function runTestForDay($class, string $name, $testDataMethod, $expectedResult, $isExampleData): void { $fullName = $name.' / '.($isExampleData ? 'Example' : 'Input'); - test($fullName, function () use ($isExampleData, $class, $testDataMethod, $expectedResult) : void { + test($fullName, function () use ($isExampleData, $class, $testDataMethod, $expectedResult): void { expect($class->{$testDataMethod}($isExampleData))->toBe($class::${$expectedResult}); })->skip(!$class->hasExampleData() || $class::${$expectedResult} === null); } @@ -69,7 +73,7 @@ function testYear(int $year): void { $solutions = loadSolutions($year); foreach ($solutions as $name => $className) { - describe('Y'.$year, static function () use ($name, $className) : void { + describe('Y'.$year, static function () use ($name, $className): void { /** @var Solution $class */ $class = new $className(); $class->loadData();