KOSMIndoorMap

openinghourscache.cpp
1/*
2 SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "openinghourscache_p.h"
8#include "logging.h"
9
10#include <KOpeningHours/Interval>
11#include <KOpeningHours/OpeningHours>
12
13#include <QTimeZone>
14
15using namespace KOSMIndoorMap;
16
17bool OpeningHoursCache::Entry::operator<(const Entry &other) const
18{
19 if (elementId == other.elementId) {
20 return oh < other.oh;
21 }
22 return elementId < other.elementId;
23}
24
25OpeningHoursCache::OpeningHoursCache()
26{
27 setTimeRange({}, {});
28}
29
30OpeningHoursCache::~OpeningHoursCache() = default;
31
32void OpeningHoursCache::setMapData(const MapData &mapData)
33{
34 if (m_mapData == mapData) {
35 return;
36 }
37 m_mapData = mapData;
38 m_cacheEntries.clear();
39}
40
41void OpeningHoursCache::setTimeRange(const QDateTime &begin, const QDateTime &end)
42{
43 const auto actualBegin = begin.isValid() ? begin : QDateTime::currentDateTime();
44 const auto actualEnd = (end.isValid() && end > actualBegin) ? end : actualBegin.addYears(1);
45
46 if (actualBegin == m_begin && actualEnd == m_end) {
47 return;
48 }
49
50 m_begin = actualBegin;
51 m_end = actualEnd;
52 m_cacheEntries.clear();
53}
54
55bool OpeningHoursCache::isEntirelyClosedInRange(OSM::Element elem, const QByteArray &oh)
56{
57 Entry entry{elem.id(), oh, UnknownResult};
58 const auto it = std::lower_bound(m_cacheEntries.begin(), m_cacheEntries.end(), entry);
59 if (it != m_cacheEntries.end() && (*it).elementId == elem.id() && (*it).oh == oh) {
60 if ((*it).results & HasEntireRangeResult) {
61 return (*it).results & EntirelyClosedInTimeRange;
62 }
63 entry.results = (*it).results;
64 }
65
67 expr.setLocation(elem.center().latF(), elem.center().lonF());
68 expr.setRegion(m_mapData.regionCode());
69 expr.setTimeZone(m_mapData.timeZone());
70
71 if (expr.error() != KOpeningHours::OpeningHours::NoError) {
72 qCDebug(Log) << "opening hours expression error:" << expr.error() << oh << elem.url();
73 } else {
74 auto i = expr.interval(m_begin);
75 while (i.state() == KOpeningHours::Interval::Closed && !i.hasOpenEnd() && (i.end() < m_end || !m_end.isValid())) {
76 i = expr.nextInterval(i);
77 }
78 if (expr.error() != KOpeningHours::OpeningHours::NoError) {
79 qCDebug(Log) << "opening hours expression runtime error:" << expr.error() << oh << i << elem.url();
80 }
81 if (i.state() == KOpeningHours::Interval::Closed) {
82 entry.results |= EntirelyClosedInTimeRange;
83 }
84 }
85 entry.results |= HasEntireRangeResult;
86 const bool closed = entry.results & EntirelyClosedInTimeRange;
87
88 if (it != m_cacheEntries.end() && (*it).elementId == elem.id() && (*it).oh == oh) {
89 *it = std::move(entry);
90 } else {
91 m_cacheEntries.insert(it, std::move(entry));
92 }
93 return closed;
94}
95
96bool OpeningHoursCache::isAtCurrentTime(OSM::Element elem, const QByteArray &oh)
97{
98 Entry entry{elem.id(), oh, UnknownResult};
99 const auto it = std::lower_bound(m_cacheEntries.begin(), m_cacheEntries.end(), entry);
100 if (it != m_cacheEntries.end() && (*it).elementId == elem.id() && (*it).oh == oh) {
101 if ((*it).results & HasCurrentTimeResult) {
102 return (*it).results & IsAtCurrentTime;
103 }
104 entry.results = (*it).results;
105 }
106
108 expr.setLocation(elem.center().latF(), elem.center().lonF());
109 expr.setRegion(m_mapData.regionCode());
110 expr.setTimeZone(m_mapData.timeZone());
111
112 if (expr.error() != KOpeningHours::OpeningHours::NoError) {
113 qCDebug(Log) << "opening hours expression error:" << expr.error() << oh << elem.url();
114 } else {
115 const auto i = expr.interval(currentDateTime());
116 if (i.state() == KOpeningHours::Interval::Open) {
117 entry.results |= IsAtCurrentTime;
118 }
119 }
120
121 entry.results |= HasCurrentTimeResult;
122 const bool open = entry.results & IsAtCurrentTime;
123
124 if (it != m_cacheEntries.end() && (*it).elementId == elem.id() && (*it).oh == oh) {
125 *it = std::move(entry);
126 } else {
127 m_cacheEntries.insert(it, std::move(entry));
128 }
129 return open;
130}
131
132QDateTime OpeningHoursCache::currentDateTime() const
133{
134 if (!m_begin.isValid() && !m_end.isValid()) {
136 }
137 if (!m_begin.isValid()) {
138 return std::min(m_end.addSecs(-1), QDateTime::currentDateTime());
139 }
140 if (!m_end.isValid()) {
141 return std::max(m_begin, QDateTime::currentDateTime());
142 }
143 return std::clamp(QDateTime::currentDateTime(), m_begin, m_end.addSecs(-1));
144}
Raw OSM map data, separated by levels.
Definition mapdata.h:60
A reference to any of OSM::Node/OSMWay/OSMRelation.
Definition element.h:24
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
OSM-based multi-floor indoor maps for buildings.
KGuiItem open()
const QList< QKeySequence > & begin()
QDateTime addSecs(qint64 s) const const
QDateTime currentDateTime()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 26 2024 11:57:46 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.