!7 sclass CentralRestartBotLog extends DynCalculatedList { L data; transient bool updateRequested; // We are locked already. L calc() { if (!updateRequested && data != null) ret data; updateRequested = false; new MultiSet ms; for (S s : tlft(centralRestartLogSince_raw(unixTime_startOfToday()*1000))) { SS map = parseEqualParameters(s); ms.add(map.get('programID)); } ret setFieldAndReturn(data := mapMultiSet(ms, func(S programID, int count) -> S { programID + ": " + count + " [" + snippetTitle_cached(programID) + "]" })); } void start { super.start(); ownTimer(doEvery(60.0, r uv_refresh)); } // uv = user-visible void uv_refresh() { updateRequested = true; } }