Termine gebündelt ausgeben #1
|
@ -27,6 +27,8 @@
|
|||
"targets/email.ts",
|
||||
"targets/_functions.ts",
|
||||
"conf.ts",
|
||||
"logic.ts",
|
||||
"test.ts",
|
||||
"main.ts"
|
||||
]
|
||||
}
|
||||
|
|
300
source/logic.ts
Normal file
300
source/logic.ts
Normal file
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
This file is part of »munin«.
|
||||
|
||||
Copyright 2025 'Fenris Wolf' <fenris@folksprak.org>
|
||||
|
||||
»munin« is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
»munin« is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with »munin«. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
namespace _munin.logic
|
||||
{
|
||||
|
||||
/**
|
||||
* @todo Tests schreiben
|
||||
*/
|
||||
function shall_remind(
|
||||
event : _munin.type_event,
|
||||
reminder : type_reminder,
|
||||
{
|
||||
"pit": pit = lib_plankton.pit.now(),
|
||||
"interval": interval = 1,
|
||||
} : {
|
||||
pit ?: lib_plankton.pit.type_pit;
|
||||
interval ?: int;
|
||||
} = {
|
||||
}
|
||||
) : boolean
|
||||
{
|
||||
const window_from : lib_plankton.pit.type_pit = lib_plankton.pit.shift_hour(
|
||||
pit,
|
||||
0
|
||||
);
|
||||
const window_to : lib_plankton.pit.type_pit = lib_plankton.pit.shift_hour(
|
||||
pit,
|
||||
interval
|
||||
);
|
||||
const event_begin : lib_plankton.pit.type_pit = lib_plankton.pit.from_datetime(
|
||||
event.begin
|
||||
);
|
||||
const reminder_time : lib_plankton.pit.type_pit = lib_plankton.pit.shift_hour(
|
||||
event_begin,
|
||||
(-reminder)
|
||||
);
|
||||
return lib_plankton.pit.is_between(
|
||||
reminder_time,
|
||||
window_from,
|
||||
window_to
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function frequency_anchor(
|
||||
frequency : _munin.enum_frequency,
|
||||
{
|
||||
"pit": pit = lib_plankton.pit.now(),
|
||||
} : {
|
||||
pit ?: lib_plankton.pit.type_pit,
|
||||
} = {
|
||||
}
|
||||
) : lib_plankton.pit.type_pit
|
||||
{
|
||||
switch (frequency)
|
||||
{
|
||||
case _munin.enum_frequency.hourly: return lib_plankton.pit.trunc_hour(pit);
|
||||
case _munin.enum_frequency.daily: return lib_plankton.pit.trunc_day(pit);
|
||||
case _munin.enum_frequency.weekly: return lib_plankton.pit.trunc_week(pit);
|
||||
case _munin.enum_frequency.monthly: return lib_plankton.pit.trunc_month(pit);
|
||||
default:
|
||||
{
|
||||
throw (new Error("unhandled frequency: " + frequency));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export function reminder_due(
|
||||
reminder : type_reminder_new,
|
||||
{
|
||||
"pit": pit = lib_plankton.pit.now(),
|
||||
"interval": interval = 1,
|
||||
} : {
|
||||
pit ?: lib_plankton.pit.type_pit;
|
||||
interval ?: int;
|
||||
} = {
|
||||
}
|
||||
) : boolean
|
||||
{
|
||||
const anchor : lib_plankton.pit.type_pit = frequency_anchor(
|
||||
reminder.frequency,
|
||||
{"pit": pit}
|
||||
);
|
||||
// 0 ≤ ((p - a(p)) - o) < i
|
||||
const x : float = (
|
||||
(
|
||||
(
|
||||
lib_plankton.pit.to_unix_timestamp(pit)
|
||||
-
|
||||
lib_plankton.pit.to_unix_timestamp(anchor)
|
||||
)
|
||||
/
|
||||
(60 * 60)
|
||||
)
|
||||
-
|
||||
reminder.offset
|
||||
);
|
||||
return ((0 <= x) && (x < interval));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export function reminder_event_in_window(
|
||||
reminder : type_reminder_new,
|
||||
event : _munin.type_event,
|
||||
{
|
||||
"pit": pit = lib_plankton.pit.now(),
|
||||
"interval": interval = 1,
|
||||
} : {
|
||||
pit ?: lib_plankton.pit.type_pit;
|
||||
interval ?: int;
|
||||
} = {
|
||||
}
|
||||
) : boolean
|
||||
{
|
||||
const anchor : lib_plankton.pit.type_pit = frequency_anchor(
|
||||
reminder.frequency,
|
||||
{"pit": pit}
|
||||
);
|
||||
const window_from : lib_plankton.pit.type_pit = lib_plankton.pit.shift_hour(
|
||||
anchor,
|
||||
reminder.from
|
||||
);
|
||||
const window_to : lib_plankton.pit.type_pit = lib_plankton.pit.shift_hour(
|
||||
anchor,
|
||||
reminder.to
|
||||
);
|
||||
const event_begin : lib_plankton.pit.type_pit = lib_plankton.pit.from_datetime(
|
||||
event.begin
|
||||
);
|
||||
return lib_plankton.pit.is_between(
|
||||
event_begin,
|
||||
window_from,
|
||||
window_to
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function shall_remind_new(
|
||||
reminder : type_reminder_new,
|
||||
event : _munin.type_event,
|
||||
{
|
||||
"pit": pit = lib_plankton.pit.now(),
|
||||
"interval": interval = 1,
|
||||
} : {
|
||||
pit ?: lib_plankton.pit.type_pit;
|
||||
interval ?: int;
|
||||
} = {
|
||||
}
|
||||
) : boolean
|
||||
{
|
||||
return (
|
||||
reminder_due(
|
||||
reminder,
|
||||
{"pit": pit, "interval": interval}
|
||||
)
|
||||
&&
|
||||
reminder_event_in_window(
|
||||
reminder,
|
||||
event,
|
||||
{"pit": pit, "interval": interval}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
async function run_iteration(
|
||||
conf : _munin.conf.type_conf,
|
||||
sources : Array<_munin.type_source>,
|
||||
targets : Array<_munin.type_target>,
|
||||
{
|
||||
"dry_run": dry_run = false,
|
||||
} : {
|
||||
dry_run ?: boolean;
|
||||
} = {
|
||||
}
|
||||
) : Promise<void>
|
||||
{
|
||||
const now : lib_plankton.pit.type_pit = lib_plankton.pit.now();
|
||||
const events : Array<_munin.type_event> = (
|
||||
(await Promise.all(sources.map(source => source.fetch())))
|
||||
.reduce((x, y) => x.concat(y), [])
|
||||
);
|
||||
for (const target of targets) {
|
||||
for (const reminder_hours of target.reminders) {
|
||||
for (const event of events) {
|
||||
const remind : boolean = shall_remind(
|
||||
event,
|
||||
reminder_hours,
|
||||
{
|
||||
"pit": now,
|
||||
"interval": conf.settings.interval,
|
||||
}
|
||||
);
|
||||
if (! remind) {
|
||||
// do nothing
|
||||
}
|
||||
else {
|
||||
lib_plankton.log._info(
|
||||
"munin.remind.do",
|
||||
{
|
||||
"details": {
|
||||
"event": event,
|
||||
"target": target.show(),
|
||||
}
|
||||
}
|
||||
);
|
||||
if (dry_run) {
|
||||
// do nothing
|
||||
}
|
||||
else {
|
||||
try {
|
||||
await target.send(conf.labels, event);
|
||||
}
|
||||
catch (error) {
|
||||
lib_plankton.log.error(
|
||||
"munin.remind.error",
|
||||
{
|
||||
"details": {
|
||||
"message": String(error),
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export async function run(
|
||||
conf : _munin.conf.type_conf,
|
||||
{
|
||||
"single_run": single_run = false,
|
||||
"dry_run": dry_run = false,
|
||||
} : {
|
||||
single_run ?: boolean;
|
||||
dry_run ?: boolean;
|
||||
} = {
|
||||
}
|
||||
) : Promise<void>
|
||||
{
|
||||
const sources : Array<_munin.type_source> = conf.sources.map(
|
||||
source_raw => _munin.sources.factory(source_raw)
|
||||
);
|
||||
const targets : Array<_munin.type_target> = conf.targets.map(
|
||||
target_raw => _munin.targets.factory(target_raw)
|
||||
);
|
||||
lib_plankton.log._info(
|
||||
"munin.run.start",
|
||||
{
|
||||
"details": {
|
||||
}
|
||||
}
|
||||
);
|
||||
if (single_run) {
|
||||
await run_iteration(conf, sources, targets, {"dry_run": dry_run});
|
||||
}
|
||||
else {
|
||||
while (true) {
|
||||
await run_iteration(conf, sources, targets, {"dry_run": dry_run});
|
||||
await lib_plankton.call.sleep(conf.settings.interval * 60 * 60);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
256
source/main.ts
256
source/main.ts
|
@ -21,145 +21,6 @@ along with »munin«. If not, see <http://www.gnu.org/licenses/>.
|
|||
namespace _munin
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
async function run_iteration(
|
||||
conf : _munin.conf.type_conf,
|
||||
sources : Array<_munin.type_source>,
|
||||
targets : Array<_munin.type_target>,
|
||||
{
|
||||
"dry_run": dry_run = false,
|
||||
} : {
|
||||
dry_run ?: boolean;
|
||||
} = {
|
||||
}
|
||||
) : Promise<void>
|
||||
{
|
||||
const now : lib_plankton.pit.type_pit = lib_plankton.pit.now();
|
||||
const events : Array<_munin.type_event> = (
|
||||
(await Promise.all(sources.map(source => source.fetch())))
|
||||
.reduce((x, y) => x.concat(y), [])
|
||||
);
|
||||
for (const target of targets) {
|
||||
const window_from : lib_plankton.pit.type_pit = lib_plankton.pit.shift_hour(
|
||||
now,
|
||||
0
|
||||
);
|
||||
const window_to : lib_plankton.pit.type_pit = lib_plankton.pit.shift_hour(
|
||||
now,
|
||||
conf.settings.interval
|
||||
);
|
||||
lib_plankton.log._info(
|
||||
"munin.run.iteration",
|
||||
{
|
||||
"details": {
|
||||
"target": target.show(),
|
||||
"window_from": lib_plankton.pit.to_date_object(window_from).toISOString(),
|
||||
"window_to": lib_plankton.pit.to_date_object(window_to).toISOString(),
|
||||
}
|
||||
}
|
||||
);
|
||||
for (const reminder_hours of target.reminders) {
|
||||
for (const event of events) {
|
||||
const event_begin : lib_plankton.pit.type_pit = lib_plankton.pit.from_datetime(
|
||||
event.begin
|
||||
);
|
||||
const reminder_time : lib_plankton.pit.type_pit = lib_plankton.pit.shift_hour(
|
||||
event_begin,
|
||||
(-reminder_hours)
|
||||
);
|
||||
lib_plankton.log._info(
|
||||
"munin.run.check_dueness",
|
||||
{
|
||||
"details": {
|
||||
"event_begin": lib_plankton.pit.to_date_object(event_begin).toISOString(),
|
||||
"reminder_hours": reminder_hours,
|
||||
"reminder_time": lib_plankton.pit.to_date_object(reminder_time).toISOString(),
|
||||
}
|
||||
}
|
||||
);
|
||||
const remind : boolean = lib_plankton.pit.is_between(
|
||||
reminder_time,
|
||||
window_from,
|
||||
window_to
|
||||
);
|
||||
if (! remind) {
|
||||
// do nothing
|
||||
}
|
||||
else {
|
||||
lib_plankton.log._info(
|
||||
"munin.remind.do",
|
||||
{
|
||||
"details": {
|
||||
"event": event,
|
||||
"target": target.show(),
|
||||
}
|
||||
}
|
||||
);
|
||||
if (dry_run) {
|
||||
// do nothing
|
||||
}
|
||||
else {
|
||||
try {
|
||||
await target.send(conf.labels, event);
|
||||
}
|
||||
catch (error) {
|
||||
lib_plankton.log.error(
|
||||
"munin.remind.error",
|
||||
{
|
||||
"details": {
|
||||
"message": String(error),
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
async function run(
|
||||
conf : _munin.conf.type_conf,
|
||||
{
|
||||
"single_run": single_run = false,
|
||||
"dry_run": dry_run = false,
|
||||
} : {
|
||||
single_run ?: boolean;
|
||||
dry_run ?: boolean;
|
||||
} = {
|
||||
}
|
||||
) : Promise<void>
|
||||
{
|
||||
const sources : Array<_munin.type_source> = conf.sources.map(
|
||||
source_raw => _munin.sources.factory(source_raw)
|
||||
);
|
||||
const targets : Array<_munin.type_target> = conf.targets.map(
|
||||
target_raw => _munin.targets.factory(target_raw)
|
||||
);
|
||||
lib_plankton.log._info(
|
||||
"munin.run.start",
|
||||
{
|
||||
"details": {
|
||||
}
|
||||
}
|
||||
);
|
||||
if (single_run) {
|
||||
await run_iteration(conf, sources, targets, {"dry_run": dry_run});
|
||||
}
|
||||
else {
|
||||
while (true) {
|
||||
await run_iteration(conf, sources, targets, {"dry_run": dry_run});
|
||||
await lib_plankton.call.sleep(conf.settings.interval * 60 * 60);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export async function main(
|
||||
|
@ -169,16 +30,14 @@ namespace _munin
|
|||
// args
|
||||
const arg_handler : lib_plankton.args.class_handler = new lib_plankton.args.class_handler(
|
||||
{
|
||||
/*
|
||||
"action": lib_plankton.args.class_argument.positional({
|
||||
"index": 0,
|
||||
"type": lib_plankton.args.enum_type.string,
|
||||
"mode": lib_plankton.args.enum_mode.replace,
|
||||
"default": "run",
|
||||
"info": "what to do : help | run",
|
||||
"info": "what to do : test | run",
|
||||
"name": "action",
|
||||
}),
|
||||
*/
|
||||
"conf_path": lib_plankton.args.class_argument.volatile({
|
||||
"indicators_long": ["conf-path"],
|
||||
"indicators_short": ["c"],
|
||||
|
@ -274,67 +133,76 @@ namespace _munin
|
|||
);
|
||||
}
|
||||
else {
|
||||
// init
|
||||
const conf : _munin.conf.type_conf = await _munin.conf.load(args.conf_path);
|
||||
lib_plankton.log.set_main_logger(
|
||||
[
|
||||
{
|
||||
"kind": "filtered",
|
||||
"data": {
|
||||
"core": {
|
||||
"kind": "std",
|
||||
"data": {
|
||||
"target": "stdout",
|
||||
"format": {
|
||||
"kind": "human_readable",
|
||||
"data": {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"predicate": [
|
||||
[
|
||||
{
|
||||
"item": {
|
||||
"kind": "level",
|
||||
"data": {
|
||||
"threshold": args.verbosity,
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
],
|
||||
}
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
// exec
|
||||
if (args.conf_expose) {
|
||||
process.stdout.write(
|
||||
lib_plankton.json.encode(
|
||||
conf,
|
||||
{
|
||||
"formatted": true,
|
||||
}
|
||||
)
|
||||
+
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
switch (/*args.action*/"run") {
|
||||
default: {
|
||||
switch (args.action) {
|
||||
default:
|
||||
{
|
||||
throw (new Error("unhandled action: " + args.action));
|
||||
break;
|
||||
}
|
||||
case "run": {
|
||||
run(
|
||||
case "test":
|
||||
{
|
||||
_munin.test.all();
|
||||
break;
|
||||
}
|
||||
case "run":
|
||||
{
|
||||
// init
|
||||
const conf : _munin.conf.type_conf = await _munin.conf.load(args.conf_path);
|
||||
lib_plankton.log.set_main_logger(
|
||||
[
|
||||
{
|
||||
"kind": "filtered",
|
||||
"data": {
|
||||
"core": {
|
||||
"kind": "std",
|
||||
"data": {
|
||||
"target": "stdout",
|
||||
"format": {
|
||||
"kind": "human_readable",
|
||||
"data": {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"predicate": [
|
||||
[
|
||||
{
|
||||
"item": {
|
||||
"kind": "level",
|
||||
"data": {
|
||||
"threshold": args.verbosity,
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
],
|
||||
}
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
// exec
|
||||
if (args.conf_expose) {
|
||||
process.stdout.write(
|
||||
lib_plankton.json.encode(
|
||||
conf,
|
||||
{
|
||||
"formatted": true,
|
||||
}
|
||||
)
|
||||
+
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
_munin.logic.run(
|
||||
conf,
|
||||
{
|
||||
"single_run": args.single_run,
|
||||
"dry_run": args.dry_run,
|
||||
}
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
384
source/test.ts
Normal file
384
source/test.ts
Normal file
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
This file is part of »munin«.
|
||||
|
||||
Copyright 2025 'Fenris Wolf' <fenris@folksprak.org>
|
||||
|
||||
»munin« is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
»munin« is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with »munin«. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
namespace _munin.test
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
type type_datetime = {
|
||||
year : int;
|
||||
month : int;
|
||||
day : int;
|
||||
hour : int;
|
||||
minute : int;
|
||||
second : int;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function datetime_to_pit(
|
||||
datetime : type_datetime
|
||||
) : lib_plankton.pit.type_pit
|
||||
{
|
||||
return lib_plankton.pit.from_datetime(
|
||||
{
|
||||
"date": {
|
||||
"year": datetime.year,
|
||||
"month": datetime.month,
|
||||
"day": datetime.day,
|
||||
},
|
||||
"time": {
|
||||
"hour": datetime.hour,
|
||||
"minute": datetime.minute,
|
||||
"second": datetime.second,
|
||||
},
|
||||
"timezone_shift": 0,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function start(
|
||||
name : string
|
||||
) : void
|
||||
{
|
||||
lib_plankton.log._info(
|
||||
"test.run",
|
||||
{
|
||||
"details": {
|
||||
"name": name,
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function fail(
|
||||
name : string
|
||||
) : void
|
||||
{
|
||||
lib_plankton.log._error(
|
||||
"test.failed",
|
||||
{
|
||||
"details": {
|
||||
"name": name,
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function frequency_decode(
|
||||
frequency_encoded : string
|
||||
) : _munin.enum_frequency
|
||||
{
|
||||
switch (frequency_encoded)
|
||||
{
|
||||
case "hourly": return _munin.enum_frequency.hourly;
|
||||
case "daily": return _munin.enum_frequency.daily;
|
||||
case "weekly": return _munin.enum_frequency.weekly;
|
||||
case "monthly": return _munin.enum_frequency.monthly;
|
||||
default: {throw new Error("unhandled");}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export function reminder_due(
|
||||
) : void
|
||||
{
|
||||
type type_testcase = {
|
||||
name : string;
|
||||
input : {
|
||||
reminder : {
|
||||
frequency : string;
|
||||
offset : int;
|
||||
from : int;
|
||||
to : int;
|
||||
};
|
||||
datetime : type_datetime;
|
||||
interval : int;
|
||||
};
|
||||
output : boolean;
|
||||
};
|
||||
const testcases : Array<type_testcase> = [
|
||||
{
|
||||
"name": "reminder_due.test1",
|
||||
"input": {
|
||||
"reminder": {
|
||||
"frequency": "daily",
|
||||
"offset": 16,
|
||||
"from": 24,
|
||||
"to": 48
|
||||
},
|
||||
"datetime": {
|
||||
"year": 2025,
|
||||
"month": 6,
|
||||
"day": 27,
|
||||
"hour": 15,
|
||||
"minute": 30,
|
||||
"second": 0
|
||||
},
|
||||
"interval": 1
|
||||
},
|
||||
"output": false
|
||||
},
|
||||
{
|
||||
"name": "reminder_due.test2",
|
||||
"input": {
|
||||
"reminder": {
|
||||
"frequency": "daily",
|
||||
"offset": 16,
|
||||
"from": 24,
|
||||
"to": 48
|
||||
},
|
||||
"datetime": {
|
||||
"year": 2025,
|
||||
"month": 6,
|
||||
"day": 27,
|
||||
"hour": 16,
|
||||
"minute": 30,
|
||||
"second": 0,
|
||||
},
|
||||
"interval": 1
|
||||
},
|
||||
"output": true
|
||||
},
|
||||
{
|
||||
"name": "reminder_due.test3",
|
||||
"input": {
|
||||
"reminder": {
|
||||
"frequency": "daily",
|
||||
"offset": 16,
|
||||
"from": 24,
|
||||
"to": 48
|
||||
},
|
||||
"datetime": {
|
||||
"year": 2025,
|
||||
"month": 6,
|
||||
"day": 27,
|
||||
"hour": 17,
|
||||
"minute": 30,
|
||||
"second": 0
|
||||
},
|
||||
"interval": 1
|
||||
},
|
||||
"output": false
|
||||
},
|
||||
];
|
||||
for (const testcase of testcases)
|
||||
{
|
||||
start(testcase.name);
|
||||
|
||||
// execution
|
||||
const result : boolean = _munin.logic.reminder_due(
|
||||
{
|
||||
"frequency": frequency_decode(testcase.input.reminder.frequency),
|
||||
"offset": testcase.input.reminder.offset,
|
||||
"from": testcase.input.reminder.from,
|
||||
"to": testcase.input.reminder.to,
|
||||
},
|
||||
{
|
||||
"pit": datetime_to_pit(testcase.input.datetime),
|
||||
"interval": testcase.input.interval,
|
||||
}
|
||||
);
|
||||
|
||||
// assertions
|
||||
if (result !== testcase.output)
|
||||
{
|
||||
fail(testcase.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export function reminder_event_in_window(
|
||||
) : void
|
||||
{
|
||||
type type_testcase = {
|
||||
name : string;
|
||||
input : {
|
||||
reminder : {
|
||||
frequency : string;
|
||||
offset : int;
|
||||
from : int;
|
||||
to : int;
|
||||
};
|
||||
event : {
|
||||
begin : type_datetime;
|
||||
};
|
||||
datetime : type_datetime;
|
||||
interval : int;
|
||||
};
|
||||
output : boolean;
|
||||
};
|
||||
const testcases : Array<type_testcase> = [
|
||||
{
|
||||
"name": "reminder_event_in_window.test1",
|
||||
"input": {
|
||||
"reminder": {
|
||||
"frequency": "daily",
|
||||
"offset": 0,
|
||||
"from": 24,
|
||||
"to": 48
|
||||
},
|
||||
"event": {
|
||||
"begin": {
|
||||
"year": 2025,
|
||||
"month": 6,
|
||||
"day": 25,
|
||||
"hour": 12,
|
||||
"minute": 0,
|
||||
"second": 0
|
||||
}
|
||||
},
|
||||
"datetime": {
|
||||
"year": 2025,
|
||||
"month": 6,
|
||||
"day": 23,
|
||||
"hour": 10,
|
||||
"minute": 0,
|
||||
"second": 0
|
||||
},
|
||||
"interval": 1
|
||||
},
|
||||
"output": false
|
||||
},
|
||||
{
|
||||
"name": "reminder_event_in_window.test2",
|
||||
"input": {
|
||||
"reminder": {
|
||||
"frequency": "daily",
|
||||
"offset": 0,
|
||||
"from": 24,
|
||||
"to": 48
|
||||
},
|
||||
"event": {
|
||||
"begin": {
|
||||
"year": 2025,
|
||||
"month": 6,
|
||||
"day": 25,
|
||||
"hour": 12,
|
||||
"minute": 0,
|
||||
"second": 0
|
||||
}
|
||||
},
|
||||
"datetime": {
|
||||
"year": 2025,
|
||||
"month": 6,
|
||||
"day": 24,
|
||||
"hour": 10,
|
||||
"minute": 0,
|
||||
"second": 0
|
||||
},
|
||||
"interval": 1
|
||||
},
|
||||
"output": true
|
||||
},
|
||||
{
|
||||
"name": "reminder_event_in_window.test3",
|
||||
"input": {
|
||||
"reminder": {
|
||||
"frequency": "daily",
|
||||
"offset": 0,
|
||||
"from": 24,
|
||||
"to": 48
|
||||
},
|
||||
"event": {
|
||||
"begin": {
|
||||
"year": 2025,
|
||||
"month": 6,
|
||||
"day": 25,
|
||||
"hour": 12,
|
||||
"minute": 0,
|
||||
"second": 0
|
||||
}
|
||||
},
|
||||
"datetime": {
|
||||
"year": 2025,
|
||||
"month": 6,
|
||||
"day": 25,
|
||||
"hour": 10,
|
||||
"minute": 0,
|
||||
"second": 0
|
||||
},
|
||||
"interval": 1
|
||||
},
|
||||
"output": false
|
||||
},
|
||||
];
|
||||
|
||||
for (const testcase of testcases)
|
||||
{
|
||||
start(testcase.name);
|
||||
|
||||
// execution
|
||||
const result : boolean = _munin.logic.reminder_event_in_window(
|
||||
{
|
||||
"frequency": frequency_decode(testcase.input.reminder.frequency),
|
||||
"offset": testcase.input.reminder.offset,
|
||||
"from": testcase.input.reminder.from,
|
||||
"to": testcase.input.reminder.to,
|
||||
},
|
||||
{
|
||||
"title": "test",
|
||||
"begin": lib_plankton.pit.to_datetime(datetime_to_pit(testcase.input.event.begin)),
|
||||
"end": null,
|
||||
"description": null,
|
||||
"location": null,
|
||||
"tags": null,
|
||||
},
|
||||
{
|
||||
"pit": datetime_to_pit(testcase.input.datetime),
|
||||
"interval": testcase.input.interval,
|
||||
}
|
||||
);
|
||||
|
||||
// assertions
|
||||
if (result !== testcase.output)
|
||||
{
|
||||
fail(testcase.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export function all(
|
||||
) : void
|
||||
{
|
||||
reminder_due();
|
||||
reminder_event_in_window();
|
||||
}
|
||||
|
||||
}
|
|
@ -21,6 +21,16 @@ along with »munin«. If not, see <http://www.gnu.org/licenses/>.
|
|||
namespace _munin
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
export enum enum_frequency {
|
||||
hourly = "hourly",
|
||||
daily = "daily",
|
||||
weekly = "weekly",
|
||||
monthly = "monthly",
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export type type_labels = {
|
||||
|
@ -55,10 +65,28 @@ namespace _munin
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* @todo rename
|
||||
* @todo extend
|
||||
*/
|
||||
export type type_reminder = int;
|
||||
|
||||
|
||||
/**
|
||||
* @todo rename
|
||||
*/
|
||||
export type type_reminder_new = {
|
||||
frequency : enum_frequency;
|
||||
offset : int;
|
||||
from : int;
|
||||
to : int;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export type type_target = {
|
||||
reminders : Array<int>;
|
||||
reminders : Array<type_reminder>;
|
||||
show : (() => string);
|
||||
send : (
|
||||
(
|
||||
|
|
Loading…
Reference in a new issue