[ 'url-aoc'=>'https://adventofcode.com/2017/day/', 'blog-id' => 25, 'github' => 'https://github.com/Mikescher/AdventOfCode2017' ], '2018' => [ 'url-aoc'=>'https://adventofcode.com/2018/day/', 'blog-id' => 23, 'github' => 'https://github.com/Mikescher/AdventOfCode2018' ], '2019' => [ 'url-aoc'=>'https://adventofcode.com/2019/day/', 'blog-id' => 24, 'github' => 'https://github.com/Mikescher/AdventOfCode2019' ], ]; const LANGUAGES = [ 'cs' => ['ext'=>'linq', 'css'=>'language-csharp', 'name'=>'C#'], 'java' => ['ext'=>'java', 'css'=>'language-java', 'name'=>'Java'], 'bef' => ['ext'=>'b93', 'css'=>'language-befungerunner', 'name'=>'Befunge-93+'], 'cpp' => ['ext'=>'cpp', 'css'=>'language-cpp', 'name'=>'C++'], 'pyth' => ['ext'=>'py', 'css'=>'language-python', 'name'=>'Python'], 'rust' => ['ext'=>'rs', 'css'=>'language-rust', 'name'=>'Rust'], 'go' => ['ext'=>'go', 'css'=>'language-go', 'name'=>'Go'], 'js' => ['ext'=>'js', 'css'=>'language-javascript', 'name'=>'Javascript'], 'pas' => ['ext'=>'pas', 'css'=>'language-pascal', 'name'=>'Pascal/Delphi'], 'ts' => ['ext'=>'ts', 'css'=>'language-typescript', 'name'=>'Typescript'], ]; /** @var array */ private $staticData; public function __construct() { $this->load(); } private function load() { $all = require (__DIR__ . '/../../statics/aoc/__all.php'); array_walk($all, function(&$value, $year) { array_walk($value, function (&$innervalue) use ($year) { $innervalue = self::readSingle($year, $innervalue); }); }); $this->staticData = $all; } public function listAllFromAllYears() { return $this->staticData; } public function listAllDays() { $r = []; foreach ($this->staticData as $year => $yeardata) foreach ($yeardata as $daydata) $r []= $daydata; return $this->staticData; } public function listSingleYear($year) { return $this->staticData[$year]; } public function listSingleYearAssociative($year) { $all = $this->listSingleYear($year); $result = array_fill(0, 25, null); foreach ($all as $d) { $result[$d['day'] - 1] = $d; } return $result; } public function listYears() { return array_keys($this->staticData); } private static function readSingle($year, $a) { $yeardata = self::YEARS[$year]; $n2p = str_pad($a['day'], 2, '0', STR_PAD_LEFT); $a['day-padded'] = $n2p; $a['url'] = '/blog/' . $yeardata['blog-id'] . '/Advent_of_Code_' . $year . '/day-' . $n2p; $a['canonical'] = "https://www.mikescher.com" . $a['url']; $a['url_aoc'] = $yeardata['url-aoc'] . $a['day']; // adventofcode.com/{year}/day/{day} $a['file_challenge'] = (__DIR__ . '/../../statics/aoc/'.$year.'/'.$n2p.'_challenge.txt'); $a['file_input'] = (__DIR__ . '/../../statics/aoc/'.$year.'/'.$n2p.'_input.txt'); $a['year'] = $year; $a['date'] = $year . '-' . 12 . '-' . $n2p; $solutionfiles = []; for ($i=1; $i <= $a['parts']; $i++) { $solutionfiles []= (__DIR__ . '/../../statics/aoc/' . $year . '/' . $n2p . '_solution-' . $i . '.' . self::LANGUAGES[$a['language']]['ext']); } $a['file_solutions'] = $solutionfiles; return $a; } public function getDayFromStrIdent($year, $ident) { $e = explode('-', $ident, 2); // day-xxx if (count($e)!==2) return null; $i = intval($e[1], 10); if ($i == 0) return null; return self::getSingleDay($year, $i); } public function getSingleDay($year, $day) { foreach ($this->listSingleYear($year) as $aocd) { if ($aocd['day'] == $day) return $aocd; } return null; } public function getGithubLink($year) { return self::YEARS['' . $year]['github']; } public function getURLForYear($year) { return '/blog/' . self::YEARS[''.$year]['blog-id'] . '/Advent_of_Code_' . $year . '/'; } public function getPrevYear($year) { $last = null; foreach (self::YEARS as $y => $d) { if ($y == $year) return $last; $last = $y; } return null; } public function getNextYear($year) { $found = false; foreach (self::YEARS as $y => $d) { if ($found) return $y; if ($y == $year) $found = true; } return null; } public function getLanguageCSS($data) { return self::LANGUAGES[$data['language']]['css']; } public function getSolutionCode($data, $i) { $raw = file_get_contents($data['file_solutions'][$i]); if ($data['language'] === 'cs') { $raw = trim($raw); if (startsWith($raw, '')) $raw = substr($raw, strlen('')); if (startsWith($raw, '')) $raw = substr($raw, strlen('')); if (startsWith($raw, '')) $raw = substr($raw, strlen('')); $raw = trim($raw); } return $raw; } public function checkConsistency() { $warn = null; $this->load(); foreach ($this->listAllFromAllYears() as $year => $yd) { $daylist = []; $titlelist = []; if (!array_key_exists($year, self::YEARS)) return ['result'=>'err', 'message' => 'Invalid Year: ' . $year]; foreach ($yd as $aocdata) { if (in_array($aocdata['day'], $daylist)) return ['result'=>'err', 'message' => 'Duplicate day ' . $aocdata['day']]; $daylist []= $aocdata['day']; if (in_array($aocdata['title'], $titlelist)) return ['result'=>'err', 'message' => 'Duplicate title ' . $aocdata['title']]; $titlelist []= $aocdata['title']; if ($aocdata['day'] < 1 || $aocdata['day'] > 25) return ['result'=>'err', 'message' => 'Invali [day]-value title ' . $aocdata['day']]; if (count($aocdata['solutions']) !== $aocdata['parts']) return ['result'=>'err', 'message' => 'Not enough solution-values in day' . $aocdata['day']]; if (count($aocdata['file_solutions']) !== $aocdata['parts']) return ['result'=>'err', 'message' => 'Not enough solution-files in day' . $aocdata['day']]; if (!file_exists($aocdata['file_challenge'])) return ['result'=>'err', 'message' => 'file_challenge not found ' . $aocdata['file_challenge']]; if (!file_exists($aocdata['file_input'])) return ['result'=>'err', 'message' => 'file_input not found ' . $aocdata['file_input']]; foreach ($aocdata['file_solutions'] as $sfile) { if (!file_exists($sfile)) return ['result'=>'err', 'message' => 'file_solution[?] not found ' . $sfile]; } if (!array_key_exists($aocdata['language'], self::LANGUAGES)) return ['result'=>'err', 'message' => 'Unknown language ' . $aocdata['language']]; } } if ($warn != null) return $warn; return ['result'=>'ok', 'message' => '']; } }