// SPDX-FileCopyrightText: 2021 Quotient contributors // SPDX-License-Identifier: LGPL-2.1-or-later #include "eventstats.h" using namespace Quotient; EventStats EventStats::fromRange(const Room* room, const Room::rev_iter_t& from, const Room::rev_iter_t& to, const EventStats& init) { Q_ASSERT(to <= room->historyEdge()); Q_ASSERT(from >= Room::rev_iter_t(room->syncEdge())); Q_ASSERT(from <= to); QElapsedTimer et; et.start(); const auto result = accumulate(from, to, init, [room](EventStats acc, const TimelineItem& ti) { acc.notableCount += room->isEventNotable(ti); acc.highlightCount += room->notificationFor(ti).type == Notification::Highlight; return acc; }); if (et.nsecsElapsed() > profilerMinNsecs() / 10) qCDebug(PROFILER).nospace() << "Event statistics collection over index range [" << from->index() << "," << (to - 1)->index() << "] took " << et; return result; } EventStats EventStats::fromMarker(const Room* room, const EventStats::marker_t& marker) { const auto s = fromRange(room, marker_t(room->syncEdge()), marker, { 0, 0, marker == room->historyEdge() }); Q_ASSERT(s.isValidFor(room, marker)); return s; } EventStats EventStats::fromCachedCounters(Omittable notableCount, Omittable highlightCount) { const auto hCount = std::max(0, highlightCount.value_or(0)); if (!notableCount.has_value()) return { 0, hCount, true }; auto nCount = notableCount.value_or(0); return { std::max(0, nCount), hCount, nCount != -1 }; } bool EventStats::updateOnMarkerMove(const Room* room, const marker_t& oldMarker, const marker_t& newMarker) { if (newMarker == oldMarker) return false; // Double-check consistency between the old marker and the old stats Q_ASSERT(isValidFor(room, oldMarker)); Q_ASSERT(oldMarker > newMarker); // A bit of optimisation: only calculate the difference if the marker moved // less than half the remaining timeline ahead; otherwise, recalculation // over the remaining timeline will very likely be faster. if (oldMarker != room->historyEdge() && oldMarker - newMarker < newMarker - marker_t(room->syncEdge())) { const auto removedStats = fromRange(room, newMarker, oldMarker); Q_ASSERT(notableCount >= removedStats.notableCount && highlightCount >= removedStats.highlightCount); notableCount -= removedStats.notableCount; highlightCount -= removedStats.highlightCount; return removedStats.notableCount > 0 || removedStats.highlightCount > 0; } const auto newStats = EventStats::fromMarker(room, newMarker); if (!isEstimate && newStats == *this) return false; *this = newStats; return true; } bool EventStats::isValidFor(const Room* room, const marker_t& marker) const { const auto markerAtHistoryEdge = marker == room->historyEdge(); // Either markerAtHistoryEdge and isEstimate are in the same state, or it's // a special case of no notable events and the marker at history edge // (then isEstimate can assume any value). return markerAtHistoryEdge == isEstimate || (markerAtHistoryEdge && notableCount == 0); } QDebug Quotient::operator<<(QDebug dbg, const EventStats& es) { QDebugStateSaver _(dbg); dbg.nospace() << es.notableCount << '/' << es.highlightCount; if (es.isEstimate) dbg << " (estimated)"; return dbg; } >28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205