$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) {
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);
}
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(
);
}
-// 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;
$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)))
])
]);
}
];
$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)) {
'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!',
'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',
'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:'
];
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' => [
(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 = [
)
);
},
- // 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
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)])]));
-}
-<?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'),
(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));
+}