sclass Schedule extends Meta {
sclass Entry {}
srecord Action(A action) extends Entry {}
srecord Jump (Seconds dest) extends Entry {}
new TreeMultiMap entries;
Timestamp start;
TreeMultiMap currentEntries;
void add(double seconds, A a) {
entries.put(Seconds(seconds), new Action(a));
}
void jumpFromTo(double from, double to) {
entries.put(Seconds(from), new Jump(Seconds(to)));
}
void speedUp(double factor) {
entries = (TreeMultiMap) mapMultiMapKeys(entries, seconds -> seconds.div(factor));
}
run {
start = tsNow();
reschedule(Seconds(0));
while ping (nempty(currentEntries))
fire(first(currentEntries));
}
void reschedule(Seconds startInSchedule) {
currentEntries = (TreeMultiMap) cloneTailMultiMap(entries, startInSchedule, true);
/*if (scaffoldActive(this))
printStruct(this);*/
}
scaffolded void fire(Pair p) {
if (p == null) ret;
currentEntries.removePair(p);
sleepUntil(start.plus(p.a));
var e = p.b;
if (e cast Action)
pcallF(e.action);
else if (e cast Jump) {
start = start.plus(p.a.minus(e.dest));
reschedule(e.dest);
} else
fail(e);
}
}