Implement reminders for house maintenance
[SonOfLokstallBot.git] / common.php
index 904c28a..1d996ef 100644 (file)
@@ -18,6 +18,11 @@ function identity($x) {
     return $x;
 }
 
+const notEmpty = 'notEmpty';
+function notEmpty($value) {
+    return !empty($value);
+}
+
 function getMessageSender($update) {
     return PARTICIPANT_IDS[$update->get('message')->get('from')->get('id')];
 }
@@ -36,6 +41,17 @@ function debug($whatever) {
     echo '</pre>';
 }
 
+function partition(int $numPartitions, $array) {
+    $partitionSize = (int)ceil(count($array) / $numPartitions);
+
+    return
+        filter(notEmpty)(
+            map(function($p) use ($array, $partitionSize) {
+                return array_slice($array, $p*$partitionSize, $partitionSize);
+            })(range(0, $numPartitions-1))
+        );
+}
+
 function getInbox($inbox) {
     STATIC $inboxes;
 
@@ -55,11 +71,12 @@ function getRules() {
     return $rules = $rules ?? require 'rules.php';
 }
 
+const getString = 'getString';
 function getString($identifier, ...$vars) {
     STATIC $strings;
     $strings = $strings ?? require 'strings.php';
 
-    return sprintf($strings[$identifier], ...$vars);
+    return isset($strings[$identifier]) ? sprintf($strings[$identifier], ...$vars) : "[[$identifier]]";
 }
 
 function formatDate($date) {
@@ -116,6 +133,16 @@ function unlines($lines) {
     return implode("\n", $lines);
 }
 
+const ununlines = 'ununlines';
+function ununlines($lines) {
+    return implode("\n\n", $lines);
+}
+
+const zipWith = 'zipWith';
+function zipWith(callable $zipper, array $a, array $b) {
+    return array_map($zipper, $a, $b);
+}
+
 function field($field) {
     return function($array) use ($field) {
         return $array[$field];
@@ -184,6 +211,71 @@ function ∪($a, $b) {
     return array_merge($a, $b);
 }
 
+function getSeason($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];
+}
+
+function isStartOfSeason($monthNum, $dayNum) {
+    return ($monthNum)%3 == 0 && isStartOfMonth($dayNum);
+}
+
+function isStartOfMonth($dayNum) {
+    return $dayNum < 8;
+}
+
+function getTasksForTheSeason($season, $taskMatrix) {
+    return array_unique(
+        array_reduce(
+            $taskMatrix['annualy'][$season],
+            function($c, $v) {
+                return array_merge(
+                    $c,
+                    array_reduce($v, function($c, $v) {
+                        return array_merge($c, is_array($v) ? $v : [$v]);
+                    }, [])
+                );
+            },
+            []
+        )
+    );
+}
+
+function getTasksForTheMonth($monthNum, $taskMatrix) {
+    return array_merge(
+        $taskMatrix['monthly'],
+        $monthNum % 6 == 0 ? $taskMatrix['biannualy'] : [],
+        $monthNum % 3 == 0 ? $taskMatrix['quadriannualy'] : [],
+        array_filter(
+            $taskMatrix['annualy'][getSeason($monthNum)][getMonthName($monthNum)],
+            function($v) {
+                return !is_array($v);
+            }
+        )
+    );
+}
+
+// NB weeknum is 1-4 (the week of the month, not consistent with other things)
+function getTasksForTheWeek($weekNum, $monthNum, $taskMatrix) {
+    return  array_merge(
+        $weekNum % 2 == 0 ? $taskMatrix['bimonthly'] : [],
+        $taskMatrix['annualy'][getSeason($monthNum)][getMonthName($monthNum)]['weekly'] ?? [],
+        partition(4, getTasksForTheMonth($monthNum, $taskMatrix))[$weekNum]
+    );
+}
+
+function closest($n, $list) {
+    $a = array_filter($list, function($value) use ($n) {
+        return $value <= $n;
+    });
+
+    arsort($a);
+    return array_values($a)[0];
+}
+
 function getMessagesFromInbox($inbox, array $rules, $unseenOnly = true) {
     return array_filter(
         array_map(