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) {
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]);
}, [])
);
},
);
}
-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]
);
}
);
}
+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) {
})(['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);
})
return array_keys($a)[0];
}
-function closest($n, array $list) : int {
+function closest(int $n, array $list) : int {
return $list[closestIndex($n, $list)];
}
'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:',
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')
]
];
},
// 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
);
$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))) : []);
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'));
};
},
// 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
);