Implement script to warn about unfinished tasks
authorCameron Ball <cameron@cameron1729.xyz>
Sat, 15 Dec 2018 16:20:17 +0000 (00:20 +0800)
committerCameron Ball <cameron@cameron1729.xyz>
Fri, 28 Dec 2018 06:27:17 +0000 (14:27 +0800)
common.php
purjolok.php
strings.php
taskMatrix.php
tasks.php
unfinished.php

index a6e9212..f07c970 100644 (file)
@@ -45,11 +45,11 @@ function partition(int $numPartitions, $array) {
     $partitionSize = (int)ceil(count($array) / $numPartitions);
 
     return
-        filter(notEmpty)(
+        array_values(filter(notEmpty)(
             map(function($p) use ($array, $partitionSize) {
                 return array_slice($array, $p*$partitionSize, $partitionSize);
             })(range(0, $numPartitions-1))
-        );
+        ));
 }
 
 function getInbox($inbox) {
@@ -216,14 +216,15 @@ function ∪($a, $b) {
     return array_merge($a, $b);
 }
 
-function getSeason($monthNum) {
-    return ['summer', 'autumn', 'winter', 'spring'][floor(($monthNum)%12/3)];
+function getSeason(int $monthNum) {
+    return ['summer', 'autumn', 'winter', 'spring'][floor(($monthNum%12)/3)];
 }
 
 function getMonthName($monthNum) {
     return ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'][$monthNum-1];
 }
 
+// XXX: Consider renaming these to "is[First/Last]WeekOf[Month/Season]"
 function isStartOfSeason($monthNum, $dayNum) {
     return ($monthNum)%3 == 0 && isStartOfMonth($dayNum);
 }
@@ -232,6 +233,18 @@ function isStartOfMonth($dayNum) {
     return $dayNum < 8;
 }
 
+function isEndOfSeason($yearNum, $monthNum, $dayNum) {
+    return ($monthNum+1)%3 == 0 && isEndOfMonth($yearNum, $monthNum, $dayNum);
+}
+
+function isEndOfMonth($yearNum, $monthNum, $dayNum) {
+    return $dayNum + 7 > cal_days_in_month(CAL_GREGORIAN, $monthNum, $yearNum);
+}
+
+function isEndOfYear($yearNum, $monthNum, $dayNum) {
+    return $monthNum == 12 && isEndOfMonth($yearNum, $monthNum, $dayNum);
+}
+
 function getTasksForTheSeason($season, $taskMatrix) {
     return array_unique(
         array_reduce(
@@ -263,15 +276,49 @@ function getTasksForTheMonth($monthNum, $taskMatrix) {
     );
 }
 
-// NB weeknum is 1-4 (the week of the month, not consistent with other things)
-function getTasksForTheWeek($weekNum, $monthNum, $taskMatrix) {
+function getTasksForTheWeek(int $weekNum, int $monthNum, array $taskMatrix) {
     return  array_merge(
         $weekNum % 2 == 0 ? $taskMatrix['bimonthly'] : [],
         $taskMatrix['annualy'][getSeason($monthNum)][getMonthName($monthNum)]['weekly'] ?? [],
-        partition(4, getTasksForTheMonth($monthNum, $taskMatrix))[$weekNum]
+        partition(4, getTasksForTheMonth($monthNum, $taskMatrix))[$weekNum-1]
+    );
+}
+
+const getFilePathForWeek = 'getFilePathForWeek';
+function getFilePathForWeek(int $year, int $monthNum, int $weekNum) {
+    // December is part of next year's summer
+    $seasonYear = $year;
+    return sprintf(
+        'tasks/%s/%s/%s/week%s.txt',
+        $seasonYear,
+        getSeason($monthNum),
+        getMonthName($monthNum),
+        $weekNum
     );
 }
 
+function getFilePathsForMonth(int $year, int $monthNum) {
+    return map(function($week) use ($year, $monthNum){
+        return getFilePathForWeek($year, $monthNum, $week);
+    })(range(1,4));
+}
+
+function getFilePathsForSeason(int $year, string $season) {
+    return array_merge(...map(function($monthNum) use ($year) {
+        // Summer of the current year includes december of the previous year.
+        $seasonYear = $year - ($monthNum == 12 ? 1 : 0);
+        return getFilePathsForMonth($seasonYear, $monthNum);
+    })(array_filter(range(1,12), function($month) use ($season) {
+        return getSeason($month) == $season;
+    })));
+}
+
+function getFilePathsForYear(int $year) {
+    return array_merge(...map(function($season) use ($year) {
+        return getFilePathsForSeason($year, $season);
+    })(['summer', 'winter', 'spring', 'autumn']));
+}
+
 function closest($n, $list) {
     $a = array_filter($list, function($value) use ($n) {
         return $value <= $n;
index 395f41d..5cab7de 100644 (file)
@@ -142,21 +142,17 @@ getTelegram()->addCommand(
 
             $tasksForTheWeek = getTasksForTheWeek(
                 array_search($closestMonday, $mondays),
-                $dt->format('m'),
+                (int)$dt->format('m'),
                 require 'taskMatrix.php'
             );
 
             $completedTasksFile = "$directory" . "/completed.txt";
             $completedTasks = file_exists($completedTasksFile) ? lines(trim(file_get_contents($completedTasksFile))) : [];
 
-            $stringAndCode = function($string) {
-                return getString($string) . " (" . $string . ")";
-            };
-
             $this->replyWithMessage([
                 'text' => ununlines([
                     getString('tasksForTheWeek'),
-                    unlines(map($stringAndCode)(array_diff($tasksForTheWeek, $completedTasks)))
+                    unlines(map(getStringAndCode)(array_diff($tasksForTheWeek, $completedTasks)))
                 ])
             ]);
         }
@@ -178,24 +174,18 @@ getTelegram()->addCommand(
             ];
             $closestMonday = closest($dt->format('d'), $mondays);
 
-            $directory = sprintf(
-                "tasks/%s/%s/%s",
-                $dt->format('Y'),
-                $dt->format('F'),
-                $dt->format('W')
-            );
+            $completedTasksFile = getFilePathForWeek((int)$dt->format('Y'), (int)$dt->format('n'), array_search($closestMonday, $mondays));
 
             $tasksForTheWeek = getTasksForTheWeek(
                 array_search($closestMonday, $mondays),
-                $dt->format('m'),
+                (int)$dt->format('m'),
                 require 'taskMatrix.php'
             );
 
-            $completedTasksFile = "$directory" . "/completed.txt";
             $completedTasks = file_exists($completedTasksFile) ? lines(trim(file_get_contents($completedTasksFile))) : [];
 
-            if (!is_dir($directory)) {
-                mkdir($directory, 0777, true);
+            if (!is_dir(dirname($completedTasksFile))) {
+                mkdir(dirname($completedTasksFile), 0777, true);
             }
 
             if (in_array($arguments, $completedTasks)) {
index a4e03c1..b9471c4 100644 (file)
@@ -9,19 +9,53 @@ return [
     'goodnightNormal' => 'I\'m signing off for the night. Before I go; tomorrow it\'s going to be about %s when you get up and %s later in the day. Jumper and trousers, maybe?',
     'goodnight' => 'Goodnight!',
 
-    'beginningOfSummer' => 'It\'s the start of summer! To get you prepared, here are the unique things that will happen this season (in addition to regular weekly(ish) shit)...',
-    'beginningOfWinter' => 'It\'s the start of winter (at last, fuck summer). Heads up lads, here are the unique tasks that are wanting doing this season (in addition to regular junk)...',
+    'beginningOfSummer' => 'It\'s the start of summer! To get you prepared, here are the unique things that will happen this season...',
+    'beginningOfWinter' => 'It\'s the start of winter (at last, fuck summer). Heads up lads, here are the unique tasks that are wanting doing this season...',
+    'beginningOfAutumn' => 'Autumn is here 🍂🍃 Here\'s an overview of the unique tasks for this season...',
+    'beginningOfSpring' => 'Spring has spring 🌻☀️ Here are the upcomming seasonal tasks...',
 
-    'beginningOfDecember' => 'Welcome to December! Oh boy!',
-    'beginningOfJanuary' => 'Welcome to January! Oh boy.',
+    'beginningOfJanuary' => 'Welcome to January! Oh boy. Here\'s a summary of tasks for the month:',
+    'beginningOfFebruary' => 'February is here! Here\'s an overview of what to expect:',
+    'beginningOfMarch' => 'It\'s March! Here\'s what you\'re up against:',
+    'beginningOfApril' => 'It\'s the start of April, you know what that means. Here\s the overview:',
+    'beginningOfMay' => 'Welcome to May! Hooo geez. Check out the doozies you gotta do:',
+    'beginningOfJune' => 'June is here, time to scope out the tasks for this month:',
+    'beginningOfJuly' => 'Over halway through the year... It\'s July :O let\'s look at what needs to happen:',
+    'beginningOfAugust' => 'It\'s the start of August, let\'s have a look at the tasks for the month:',
+    'beginningOfSeptember' => 'Time to remember the September tasks!',
+    'beinningOfOctober' => 'Välkommen till oktober! Here\'s the tasks for this month:',
+    'beginningOfNovember' => 'Happy november! The year is almost gone D: Have a look at what needs doing this month:',
+    'beginningOfDecember' => 'Less than a month left of the year. It\'s the home stretch, get through these bad boys!',
 
     'anywayHeresTheMonth' => 'Anyway, here\'s the normal start of the month breakdown...',
     'anywayHeresTheWeek' => 'Anyway, like normal here\'s some stuff I think you guys should do this week...',
     'finallyHeresTheWeek' => 'And finally... Like always, here\'s some stuff I think you guys should do this week:',
     'happyMonday' => 'Happy Monday! Here are some tasks I think should get nutted out this week:',
 
+    'endOfYear' => 'The year is coming to an end, and it looks like there\'s some stuff that wasn\'t done. I hope none of it is critical; if it is, make sure to do it because I may not remind you again for a while!',
+    'endOfYearGood' => 'The year is coming to a close, and it looks like you did everything! Good luck for next year :)',
+
+    'endOfSummer' => 'Summer is (finally) about to be over. That said, there\'s some outstanding stuff. Try get it done because I won\'t remind you about it again D:',
+    'endOfSummerGood' => 'Summer is finally almost over, and to make it better, you managed to do all the tasks!',
+    'endOfWinter' => 'Winter is coming to a close, but there\'s still some outstanding work to do... Try to finish these tasks because I won\'t be able to remind you again.',
+    'endOfWinterGood' => 'Winter is wrapping up, and you managed to get through everything, nice :D',
+    'endOfAutumn' => 'Autumn is coming to a close, but there\'s some outstanding work... Try to get through this stuff pls b0ss...',
+    'endOfAutumnGood' => 'Autumn is neary aut-dumn (sorry). And you finished everytihng! Good work.',
+    '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!',
+    '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:',
+    'endOfWeekGood' => 'It\'s Friday and all the tasks are done! Nice',
+    'andAlsoEndOfWeek' => 'Also, it\'s the end of a week, so here\'s the outstanding stuff...',
+    'andAlsoEndOfWeekGood' => 'Also, it\'s the end of a week, but it looks like you got everything done, sick :D',
+    'finallyEndOfWeek' => 'Finally, it\'s the end of a week, so here\'s the outstanding stuff...',
+    'finallyEndOfWeekGood' => 'Finally, it\'s the end of a week, but it looks like you got everything done, sick :D',
+
     'thisMonthThereAre' => 'This month there are %d tasks that need completing (as well as the regular tasks). I\'ll try my best to space them out over the coming weeks. As a heads up, here they are:',
-    'seasonalMeme' => 'Please also enjoy this seasonal meme I picked for you: %s',
     'tasksForTheWeek' => 'Here are the incomplete tasks for this week...',
     'taskAlreadyCompleted' => 'Hmm... It looks as though that task was already done this week.',
     'taskCompleted' => 'Marked as completed, nice one!',
@@ -51,7 +85,7 @@ return [
     'cleangutters' => 'Clean out gutters to prepare for rain',
     'checkdrains' => 'Check down pipe drains for blockages',
     'coverpool' => 'Cover the pool',
-    'cleanchimeny' => 'Clean soot out of the chimney',
+    'cleanchimney' => 'Clean soot out of the chimney',
     'tightenfixings' => 'Inspect and tighten (if needed) any fixings',
     'fanfilters' => 'Clean extractor fan filters (bathroom and air conditioner)',
     'bulkrubbish' => 'Prepare for bulk rubbish collection',
@@ -60,5 +94,7 @@ return [
     'shrubs' => 'Prune shrubs',
     'palmtrees' => 'Remove dead branches and seeds from palm trees',
     'uncoverpool' => 'Uncover the pool',
-    'checktaps' => 'Inspect taps for leaks and repair as needed'
+    'checktaps' => 'Inspect taps for leaks and repair as needed',
+
+    'unfinishedtasks' => 'Aw geez Rick, it\'s Friday and these tasks still haven\'nt been completed, please try to do them over the weekend D:'
 ];
index 408e845..4b4ef37 100644 (file)
@@ -5,7 +5,7 @@
 return [
     'monthly' => ['rangehoodfilters', 'poolwater', 'weeds', 'ants', 'leaves', 'cobwebs', 'fireextinguisher', 'mowlawn'],
     'bimonthly' => ['vacuum', 'mop', 'kitchen'],
-    'biannualy' => ['cleanhouse', 'cleangarage', 'testreliefevalve', 'smokealarmstest', 'smokealarmbatteries', 'fridgecoils'],
+    'biannualy' => ['cleanhouse', 'cleangarage', 'testreliefevalve', 'testsmokealarms', 'smokealarmbatteries', 'fridgecoils'],
     'quadriannualy' => ['chlorinatorplates'],
     'annualy' => [
         'summer' => [
index b03ff5a..f58a7d4 100644 (file)
--- a/tasks.php
+++ b/tasks.php
@@ -9,14 +9,14 @@ $mondays = [
     (int)(new DateTimeImmutable('third monday of this month'))->format('d'),
     (int)(new DateTimeImmutable('fourth monday of this month'))->format('d'),
 ];
-$currentMonth = (new DateTimeImmutable())->format('m');
+$currentMonth = (int)(new DateTimeImmutable())->format('m');
 $currentDayOfMonth = closest((new DateTimeImmutable())->format('d'), $mondays);
 $currentWeekOfMonth = array_search($currentDayOfMonth, $mondays);
 
 $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($currentMonth, $currentDayOfMonth) ? [unlines(map(getStringAndCode)(getTasksForTheSeason(getSeason($currentMonth), $taskMatrix)))] : [],
+    isStartOfMonth($currentDayOfMonth) ? [unlines(map(getStringAndCode)(getTasksForTheMonth($currentMonth, $taskMatrix)))] : [],
+    [unlines(map(getStringAndCode)(getTasksForTheWeek($currentWeekOfMonth, $currentMonth, $taskMatrix)))]
 );
 
 $taskMessages = [
@@ -41,7 +41,7 @@ $messages = zipWith(
             )
         );
     },
-    // Magic. startOfSeason implis startofMonth so we get 2, start of month without start of season gives 1 and
+    // 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[isStartOfSeason($currentMonth, $currentDayOfMonth) + isStartOfMonth($currentDayOfMonth)],
     $taskLists
@@ -51,11 +51,3 @@ foreach ($messages as $message) {
     sendToGroupChat($message);
     sleep(rand(2,4));
 }
-
-$seasonalMemes = [
-    'summer' => ['https://www.youtube.com/watch?v=NqktmrKB3ko']
-];
-
-if (isStartOfSeason($currentMonth, $currentDayOfMonth)) {
-    sendToGroupChat(getString('seasonalMeme', $seasonalMemes[getSeason($currentMonth)][array_rand($seasonalMemes[getSeason($currentMonth)])]));
-}
index e637ba9..55cb519 100644 (file)
@@ -1,8 +1,8 @@
-<?php
+<?php declare(strict_types=1);
 
 require_once('common.php');
 
-$dt = new DateTimeImmutable();
+$taskMatrix = require 'taskMatrix.php';
 
 $mondays = [
     (int)(new DateTimeImmutable('first monday of this month'))->format('d'),
@@ -11,25 +11,92 @@ $mondays = [
     (int)(new DateTimeImmutable('fourth monday of this month'))->format('d'),
 ];
 
-$directory = sprintf(
-    "tasks/%s/%s/%s",
-    $dt->format('Y'),
-    $dt->format('F'),
-    $dt->format('W')
+$currentMonth = (int)(new DateTimeImmutable())->format('n');
+$currentDayOfMonth = closest((new DateTimeImmutable())->format('d'), $mondays);
+$currentSeason = getSeason($currentMonth);
+$currentYear = (int)(new DateTimeImmutable())->format('Y');
+$currentWeekOfMonth = array_search($currentDayOfMonth, $mondays);
+
+$extractTasks = function($tasks, $path) {
+    return array_merge($tasks, file_exists($path) ? lines(trim(file_get_contents($path))) : []);
+};
+
+$unfinishedForYear = array_diff(
+     array_merge(...map(
+         function($season) use ($taskMatrix) {
+             return getTasksForTheSeason($season, $taskMatrix);
+         }
+     )(['summer', 'autumn', 'winter', 'spring'])),
+     array_reduce(getFilePathsForYear($currentYear), $extractTasks, [])
+);
+
+$unfinishedForSeason = array_diff(
+    getTasksForTheSeason($currentSeason, $taskMatrix),
+    array_reduce(getFilePathsForSeason($currentYear, $currentSeason), $extractTasks, [])
+);
+
+$unfinishedForMonth = array_diff(
+    getTasksForTheMonth($currentMonth, $taskMatrix),
+    array_reduce(getFilePathsForMonth($currentYear, $currentMonth), $extractTasks, [])
 );
-$completedTasksFile = "$directory" . "/completed.txt";
-$completedTasks = file_exists($completedTasksFile) ? lines(trim(file_get_contents($completedTasksFile))) : [];
 
-$closestMonday = closest($dt->format('d'), $mondays);
+$filePathForWeek = getFilePathForWeek($currentYear, $currentMonth, $currentWeekOfMonth);
+$unfinishedForWeek = array_diff(
+    getTasksForTheWeek($currentWeekOfMonth, $currentMonth, $taskMatrix),
+    file_exists($filePathForWeek) ? lines(trim(file_get_contents($filePathForWeek))) : []
+);
 
-$tasksForTheWeek = getTasksForTheWeek(
-    array_search($closestMonday, $mondays),
-    $dt->format('m'),
-    require 'taskMatrix.php'
+//EOY => (EOM & EOW) & !EOS
+//EOS => (EOM & EOW) & !EOY
+$taskLists = array_merge(
+    isEndOfYear($currentYear, $currentMonth, $currentDayOfMonth) ? [unlines(map(getStringAndCode)($unfinishedForYear))] : [],
+    isEndOfSeason($currentYear, $currentMonth, $currentDayOfMonth) ? [unlines(map(getStringAndCode)($unfinishedForSeason))] : [],
+    isEndOfMonth($currentYear, $currentMonth, $currentDayOfMonth) ? [unlines(map(getStringAndCode)($unfinishedForMonth))] : [],
+    [unlines(map(getStringAndCode)($unfinishedForWeek))]
 );
 
-$unfinished = array_diff($tasksForTheWeek, $completedTasks);
+$seasonName = ucfirst($currentSeason);
+$goodOrBad = function($string, $goodOrBad) {
+    return getString($string . ($goodOrBad ? '' : 'Good'));
+};
 
-print_r(
-    array_diff(['treeflowers', 'someothershit'], ['treeflowers'])
+$taskMessages = [
+    [$goodOrBad('endOfWeek', $unfinishedForWeek)],
+    [
+        $goodOrBad('endOfMonth', $unfinishedForMonth),
+        $goodOrBad('andAlsoEndOfWeek', $unfinishedForWeek)
+    ],
+    [
+        $goodOrBad('endOf' . $seasonName, $unfinishedForSeason),
+        $goodOrBad('andAlsoEndOfMonth', $unfinishedForMonth),
+        $goodOrBad('finallyEndOfWeek', $unfinishedForWeek)
+    ],
+    [
+        $goodOrBad('endOfYear', $unfinishedForYear),
+        $goodOrBad('andAlsoEndOfMonth', $unfinishedForMonth),
+        $goodOrBad('finallyEndOfWeek', $unfinishedForWeek)
+    ]
+];
+
+$messages = zipWith(
+    function($message, $list) {
+        return ununlines(
+            array_merge(
+                is_array($message) ? $message : [$message],
+                [$list]
+            )
+        );
+    },
+    // 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.
+    ],
+    $taskLists
 );
+
+foreach ($messages as $message) {
+    sendToGroupChat($message);
+    sleep(rand(2,4));
+}