From: Cameron Ball Date: Fri, 4 Jan 2019 08:29:16 +0000 (+0800) Subject: Improved logic in tasks and unfinished scripts plus some bug fixes X-Git-Url: http://git.cameron1729.xyz/?p=SonOfLokstallBot.git;a=commitdiff_plain;h=c7b185a88e72bc635df2fc068c67d891894bd20d Improved logic in tasks and unfinished scripts plus some bug fixes --- diff --git a/src/common.php b/src/common.php index 173bd32..bc627f4 100644 --- a/src/common.php +++ b/src/common.php @@ -43,11 +43,11 @@ function canChatWith(TelegramUpdate $update) : bool { function partition(int $numPartitions, array $array) : array { $partitionSize = (int)ceil(count($array) / $numPartitions); - return array_values(filter(notEmpty)( + return array_values( map(function($p) use ($array, $partitionSize) { return array_slice($array, $p*$partitionSize, $partitionSize); })(range(0, $numPartitions-1)) - )); + ); } function getInbox(string $inbox) { @@ -260,7 +260,7 @@ function getTasksForTheSeason($season, $taskMatrix) { return array_merge( $c, array_reduce($v, function($c, $v) { - return array_merge($c, is_array($v) ? $v : [$v]); + return array_merge($c, is_array($v) ? [] : [$v]); }, []) ); }, @@ -283,11 +283,11 @@ function getTasksForTheMonth($monthNum, $taskMatrix) { ); } -function getTasksForTheWeek(int $weekNum, int $monthNum, array $taskMatrix) { +function getTasksForTheWeek(int $year, int $monthNum, int $weekNum, array $taskMatrix) { return array_merge( $weekNum % 2 == 0 ? $taskMatrix['bimonthly'] : [], $taskMatrix['annualy'][getSeason($monthNum)][getMonthName($monthNum)]['weekly'] ?? [], - partition(4, getTasksForTheMonth($monthNum, $taskMatrix))[$weekNum-1] + partition(count(getMondaysForMonth($year, $monthNum)), getTasksForTheMonth($monthNum, $taskMatrix))[$weekNum-1] ); } @@ -304,10 +304,77 @@ function getFilePathForWeek(int $year, int $monthNum, int $weekNum) { ); } +function getMondaysForMonth(int $year, int $monthNum) { + $dt = DateTimeImmutable::createFromFormat('Y n', "$year $monthNum"); + $m = $dt->format('F'); + $y = $dt->format('Y'); + $fifthMonday = (int)(new DateTimeImmutable("fifth monday of $m $y"))->format('d'); + $mondays = [ + (int)(new DateTimeImmutable("first monday of $m $y"))->format('d'), + (int)(new DateTimeImmutable("second monday of $m $y"))->format('d'), + (int)(new DateTimeImmutable("third monday of $m $y"))->format('d'), + (int)(new DateTimeImmutable("fourth monday of $m $y"))->format('d'), + ]; + + return array_merge( + $mondays, + $fifthMonday > $mondays[3] ? [$fifthMonday] : [] + ); +} + +function getDayNumber(int $year, int $month, int $day) { + $potentialMondays = array_filter( + getMondaysForMonth($year, $month), + function($monday) use ($day) { + return $monday <= $day; + } + ); + + return $potentialMondays + ? closest($day, $potentialMondays) + : array_values( + array_slice( + getMondaysForMonth( + getYearWeekBeginsIn($year, $month, $day), + getMonthWeekBeginsIn($year, $month, $day) + ), + -1 + ) + )[0]; +} + +function getWeekNumber(int $year, int $month, int $day) { + $potentialMondays = array_filter( + getMondaysForMonth($year, $month), + function($monday) use ($day) { + return $monday <= $day; + } + ); + + return $potentialMondays + ? closestIndex($day, $potentialMondays) + 1 + : count( + getMondaysForMonth( + getYearWeekBeginsIn($year, $month, $day), + getMonthWeekBeginsIn($year, $month, $day) + ) + ); +} + +function getMonthWeekBeginsIn(int $year, int $month, int $day) { + return array_merge([12], range(1,11), [12])[ + $month - ($day < getMondaysForMonth($year, $month)[0] ? 1 : 0) + ]; +} + +function getYearWeekBeginsIn(int $year, int $month, int $day) { + return $year - (int)($month == 1 && getMonthWeekBeginsIn($year, $month, $day) == 12); +} + function getFilePathsForMonth(int $year, int $monthNum) { return map(function($week) use ($year, $monthNum){ return getFilePathForWeek($year, $monthNum, $week); - })(range(1,4)); + })(range(1, count(getMondaysForMonth($year, $monthNum)))); } function getFilePathsForSeason(int $year, string $season) { @@ -326,7 +393,7 @@ function getFilePathsForYear(int $year) { })(['summer', 'winter', 'spring', 'autumn'])); } -function closestIndex($n, array $list) { +function closestIndex(int $n, array $list) { $a = map(function(int $v) use ($n) : int { return (int)abs($v - $n); }) @@ -336,7 +403,7 @@ function closestIndex($n, array $list) { return array_keys($a)[0]; } -function closest($n, array $list) : int { +function closest(int $n, array $list) : int { return $list[closestIndex($n, $list)]; } diff --git a/src/strings.php b/src/strings.php index 4350620..38e4266 100644 --- a/src/strings.php +++ b/src/strings.php @@ -44,8 +44,8 @@ return [ 'endOfSpring' => 'Spring is almost over, and there are still some outstanding tasks. Try to get them done because I won\'t be reminding you again until next year :o', 'endOfSpringGood' => 'Spring is about to end! And you did everything that needed doing. Epic!', - 'endOfMonth' => 'November is coming to a close, and there are still some tasks outstanding. Try your best to get them done...', - 'endOfMonthGood' => 'November is almost over, and it looks like you\'ve completed everything! Nice one!', + 'endOfMonth' => 'The month is coming to a close, and there are still some tasks outstanding. Try your best to get them done...', + 'endOfMonthGood' => 'The month is almost over, and it looks like you\'ve completed everything! Nice one!', 'andAlsoEndOfMonth' => 'Also, it\'s the end of the month, and there are these monthly tasks that still need doing...', 'andAlsoEndOfMonthGood' => 'It\'s the end of the month too, and you did all the tasks! Nice.', 'endOfWeek' => 'Aw geez Rick, it\'s Friday and these tasks still haven\'nt been completed, please try to do them over the weekend D:', diff --git a/src/tasks.php b/src/tasks.php index eb37cc7..38ecb83 100644 --- a/src/tasks.php +++ b/src/tasks.php @@ -3,31 +3,34 @@ require_once('common.php'); $taskMatrix = require 'taskMatrix.php'; -$mondays = [ - (int)(new DateTimeImmutable('first monday of this month'))->format('d'), - (int)(new DateTimeImmutable('second monday of this month'))->format('d'), - (int)(new DateTimeImmutable('third monday of this month'))->format('d'), - (int)(new DateTimeImmutable('fourth monday of this month'))->format('d'), -]; -$currentMonth = (int)(new DateTimeImmutable())->format('m'); -$currentDayOfMonth = closest((new DateTimeImmutable())->format('d'), $mondays); -$currentWeekOfMonth = closestIndex($currentDayOfMonth, $mondays) + 1; + +// The actual date/time when the script is called +$currentYear = (int)(new DateTimeImmutable())->format('Y'); +$currentMonth = (int)(new DateTimeImmutable())->format('n'); +$currentDay = (int)(new DateTimeImmutable())->format('d'); + +// The years/months/weeks that we are "rewinding" to, for calculations +$yearForThisWeek = getYearWeekBeginsIn($currentYear, $currentMonth, $currentDay); +$monthForThisWeek = getMonthWeekBeginsIn($currentYear, $currentMonth, $currentDay); +$seasonForThisWeek = getSeason($monthForThisWeek); +$weekNum = getWeekNumber($currentYear, $currentMonth, $currentDay); +$dayNum = getDayNumber($currentYear, $currentMonth, $currentDay); $taskLists = array_merge( - isStartOfSeason($currentMonth, $currentDayOfMonth) ? [unlines(map(getString)(getTasksForTheSeason(getSeason($currentMonth), $taskMatrix)))] : [], - isStartOfMonth($currentDayOfMonth) ? [unlines(map(getString)(getTasksForTheMonth($currentMonth, $taskMatrix)))] : [], - [unlines(map(getString)(getTasksForTheWeek($currentWeekOfMonth, $currentMonth, $taskMatrix)))] + isStartOfSeason($monthForThisWeek, $dayNum) ? [unlines(map(getString)(getTasksForTheSeason($seasonForThisWeek, $taskMatrix)))] : [], + isStartOfMonth($dayNum) ? [unlines(map(getString)(getTasksForTheMonth($monthForThisWeek, $taskMatrix)))] : [], + [unlines(map(getString)(getTasksForTheWeek($yearForThisWeek, $monthForThisWeek, $weekNum, $taskMatrix)))] ); $taskMessages = [ [getString('happyMonday')], [ - [getString('beginningOf'. ucfirst(getMonthName($currentMonth))), getString('thisMonthThereAre', count(getTasksForTheMonth($currentMonth, $taskMatrix)))], + [getString('beginningOf'. ucfirst(getMonthName($monthForThisWeek))), getString('thisMonthThereAre', count(getTasksForTheMonth($monthForThisWeek, $taskMatrix)))], getString('anywayHeresTheWeek') ], [ - getString('beginningOf' . ucfirst(getSeason($currentMonth))), - [getString('anywayHeresTheMonth'), getString('thisMonthThereAre', count(getTasksForTheMonth($currentMonth, $taskMatrix)))], + getString('beginningOf' . ucfirst(getSeason($monthForThisWeek))), + [getString('anywayHeresTheMonth'), getString('thisMonthThereAre', count(getTasksForTheMonth($monthForThisWeek, $taskMatrix)))], getString('finallyHeresTheWeek') ] ]; @@ -43,7 +46,7 @@ $messages = zipWith( }, // Magic. startOfSeason implies startofMonth so we get 2, start of month without start of season gives 1 and // a regular week (not the start of a season or month) gives 0. And this is how the indicies are ordered in the array. - $taskMessages[(int)isStartOfSeason($currentMonth, $currentDayOfMonth) + (int)isStartOfMonth($currentDayOfMonth)], + $taskMessages[(int)isStartOfSeason($monthForThisWeek, $dayNum) + (int)isStartOfMonth($dayNum)], $taskLists ); diff --git a/src/unfinished.php b/src/unfinished.php index 8c7369d..b106c76 100644 --- a/src/unfinished.php +++ b/src/unfinished.php @@ -4,18 +4,17 @@ require_once('common.php'); $taskMatrix = require 'taskMatrix.php'; -$mondays = [ - (int)(new DateTimeImmutable('first monday of this month'))->format('d'), - (int)(new DateTimeImmutable('second monday of this month'))->format('d'), - (int)(new DateTimeImmutable('third monday of this month'))->format('d'), - (int)(new DateTimeImmutable('fourth monday of this month'))->format('d'), -]; - -$currentMonth = (int)(new DateTimeImmutable())->format('n'); -$currentDayOfMonth = closest((new DateTimeImmutable())->format('d'), $mondays); -$currentSeason = getSeason($currentMonth); +// The actual date/time when the script is called $currentYear = (int)(new DateTimeImmutable())->format('Y'); -$currentWeekOfMonth = closestIndex($currentDayOfMonth, $mondays) + 1; +$currentMonth = (int)(new DateTimeImmutable())->format('n'); +$currentDay = (int)(new DateTimeImmutable())->format('d'); + +// The years/months/weeks that we are "rewinding" to, for calculations +$yearForThisWeek = getYearWeekBeginsIn($currentYear, $currentMonth, $currentDay); +$monthForThisWeek = getMonthWeekBeginsIn($currentYear, $currentMonth, $currentDay); +$seasonForThisWeek = getSeason($monthForThisWeek); +$weekNum = getWeekNumber($currentYear, $currentMonth, $currentDay); +$dayNum = getDayNumber($currentYear, $currentMonth, $currentDay); $extractTasks = function($tasks, $path) { return array_merge($tasks, file_exists($path) ? lines(trim(file_get_contents($path))) : []); @@ -27,35 +26,35 @@ $unfinishedForYear = array_diff( return getTasksForTheSeason($season, $taskMatrix); } )(['summer', 'autumn', 'winter', 'spring'])), - array_reduce(getFilePathsForYear($currentYear), $extractTasks, []) + array_reduce(getFilePathsForYear($yearForThisWeek), $extractTasks, []) ); $unfinishedForSeason = array_diff( - getTasksForTheSeason($currentSeason, $taskMatrix), - array_reduce(getFilePathsForSeason($currentYear, $currentSeason), $extractTasks, []) + getTasksForTheSeason($seasonForThisWeek, $taskMatrix), + array_reduce(getFilePathsForSeason($yearForThisWeek, $seasonForThisWeek), $extractTasks, []) ); $unfinishedForMonth = array_diff( - getTasksForTheMonth($currentMonth, $taskMatrix), - array_reduce(getFilePathsForMonth($currentYear, $currentMonth), $extractTasks, []) + getTasksForTheMonth($monthForThisWeek, $taskMatrix), + array_reduce(getFilePathsForMonth($yearForThisWeek, $monthForThisWeek), $extractTasks, []) ); -$filePathForWeek = getFilePathForWeek($currentYear, $currentMonth, $currentWeekOfMonth); +$filePathForWeek = getFilePathForWeek($yearForThisWeek, $monthForThisWeek, $weekNum); $unfinishedForWeek = array_diff( - getTasksForTheWeek($currentWeekOfMonth, $currentMonth, $taskMatrix), + getTasksForTheWeek($yearForThisWeek, $monthForThisWeek, $weekNum, $taskMatrix), file_exists($filePathForWeek) ? lines(trim(file_get_contents($filePathForWeek))) : [] ); //EOY => (EOM & EOW) & !EOSx //EOS => (EOM & EOW) & !EOY $taskLists = array_merge( - isEndOfYear($currentYear, $currentMonth, $currentDayOfMonth) ? [unlines(map(getString)($unfinishedForYear))] : [], - isEndOfSeason($currentYear, $currentMonth, $currentDayOfMonth) ? [unlines(map(getString)($unfinishedForSeason))] : [], - isEndOfMonth($currentYear, $currentMonth, $currentDayOfMonth) ? [unlines(map(getString)($unfinishedForMonth))] : [], + isEndOfYear($yearForThisWeek, $monthForThisWeek, $dayNum) ? [unlines(map(getString)($unfinishedForYear))] : [], + isEndOfSeason($yearForThisWeek, $monthForThisWeek, $dayNum) ? [unlines(map(getString)($unfinishedForSeason))] : [], + isEndOfMonth($yearForThisWeek, $monthForThisWeek, $dayNum) ? [unlines(map(getString)($unfinishedForMonth))] : [], [unlines(map(getString)($unfinishedForWeek))] ); -$seasonName = ucfirst($currentSeason); +$seasonName = ucfirst($seasonForThisWeek); $goodOrBad = function($string, $goodOrBad) { return getString($string . ($goodOrBad ? '' : 'Good')); }; @@ -89,9 +88,9 @@ $messages = zipWith( }, // Similar magic to tasks.php $taskMessages[ - isEndOfMonth($currentYear, $currentMonth, $currentDayOfMonth) + - isEndOfSeason($currentYear, $currentMonth, $currentDayOfMonth) + - (isEndOfYear($currentYear, $currentMonth, $currentDayOfMonth) ? 2 : 0) // EOY is independant of EOS, to get the right index need to add 2 instead of 1. + isEndOfMonth($yearForThisWeek, $monthForThisWeek, $dayNum) + + isEndOfSeason($yearForThisWeek, $monthForThisWeek, $dayNum) + + (isEndOfYear($yearForThisWeek, $monthForThisWeek, $dayNum) ? 2 : 0) // EOY is independant of EOS, to get the right index need to add 2 instead of 1. ], $taskLists );