vehicle.cpp 6.95 KB
Newer Older
1
/*
2
    SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
3

4
    SPDX-License-Identifier: LGPL-2.0-or-later
5
6
7
8
9
*/

#include "vehicle.h"
#include "json_p.h"
#include "datatypes_p.h"
10
#include "mergeutil_p.h"
11
12

#include <QDebug>
13
#include <QMetaEnum>
14
15
#include <QVariant>

16
17
#include <limits>

18
19
20
21
22
23
24
25
using namespace KPublicTransport;

namespace KPublicTransport {

class VehicleSectionPrivate : public QSharedData
{
public:
    QString name;
26
27
    float platformPositionBegin = -1.0;
    float platformPositionEnd = -1.0;
Volker Krause's avatar
Volker Krause committed
28
    VehicleSection::Type type = VehicleSection::UnknownType;
29
    VehicleSection::Classes classes = VehicleSection::UnknownClass;
30
    VehicleSection::Features features = VehicleSection::NoFeatures;
31
32
    int deckCount = 1;
    VehicleSection::Sides connectedSides = VehicleSection::Front | VehicleSection::Back;
33
    QString platformSectionName;
34
35
36
37
38
};

class VehiclePrivate : public QSharedData
{
public:
39
    QString name;
40
    std::vector<VehicleSection> sections;
Volker Krause's avatar
Volker Krause committed
41
    Vehicle::Direction direction = Vehicle::UnknownDirection;
42
43
44
45
46
47
};

}

KPUBLICTRANSPORT_MAKE_GADGET(VehicleSection)
KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, QString, name, setName)
48
49
KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, float, platformPositionBegin, setPlatformPositionBegin)
KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, float, platformPositionEnd, setPlatformPositionEnd)
Volker Krause's avatar
Volker Krause committed
50
KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Type, type, setType)
51
KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Classes, classes, setClasses)
52
KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Features, features, setFeatures)
53
54
KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, int, deckCount, setDeckCount)
KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Sides, connectedSides, setConnectedSides)
55
KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, QString, platformSectionName, setPlatformSectionName)
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
VehicleSection VehicleSection::merge(const VehicleSection &lhs, const VehicleSection &rhs)
{
    if (lhs.name() != rhs.name()) { // safety check, as we don't properly check for equalness before merging yet
        return lhs;
    }

    auto res = lhs;
    res.setPlatformPositionBegin(lhs.platformPositionBegin() < 0.0 ? rhs.platformPositionBegin() : lhs.platformPositionBegin());
    res.setPlatformPositionEnd(lhs.platformPositionEnd() < 0.0 ? rhs.platformPositionEnd() : lhs.platformPositionEnd());
    res.setType(std::max(lhs.type(), rhs.type()));
    if (res.type() == VehicleSection::PassengerCar && lhs.type() != VehicleSection::UnknownType && rhs.type() != VehicleSection::UnknownType) {
        res.setType(std::min(lhs.type(), rhs.type()));
    }
    res.setClasses(lhs.classes() | rhs.classes());
    res.setFeatures(lhs.features() | rhs.features());
    res.setDeckCount(std::max(lhs.deckCount(), rhs.deckCount()));
    res.setConnectedSides(lhs.connectedSides() & rhs.connectedSides());
74
    res.setPlatformSectionName(MergeUtil::mergeString(lhs.platformSectionName(), rhs.platformSectionName()));
75
76
77
    return res;
}

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
QJsonObject VehicleSection::toJson(const VehicleSection &section)
{
    return Json::toJson(section);
}

QJsonArray VehicleSection::toJson(const std::vector<VehicleSection> &sections)
{
    return Json::toJson(sections);
}

VehicleSection VehicleSection::fromJson(const QJsonObject &obj)
{
    return Json::fromJson<VehicleSection>(obj);
}

std::vector<VehicleSection> VehicleSection::fromJson(const QJsonArray &array)
{
    return Json::fromJson<VehicleSection>(array);
}

98
99
100
101
102
103
104
105
106
107
QVariantList VehicleSection::featureList() const
{
    QVariantList l;
    const auto me = QMetaEnum::fromType<VehicleSection::Features>();
    for (int i = 0; i < me.keyCount(); ++i) {
        if (features() & static_cast<VehicleSection::Feature>(1 << i))
            l.push_back(static_cast<VehicleSection::Feature>(1 << i));
    }
    return l;
}
108
109

KPUBLICTRANSPORT_MAKE_GADGET(Vehicle)
110
KPUBLICTRANSPORT_MAKE_PROPERTY(Vehicle, QString, name, setName)
Volker Krause's avatar
Volker Krause committed
111
KPUBLICTRANSPORT_MAKE_PROPERTY(Vehicle, Vehicle::Direction, direction, setDirection)
112

113
114
115
116
117
bool Vehicle::isEmpty() const
{
    return d->name.isEmpty() && d->sections.empty() && d->direction == Vehicle::UnknownDirection;
}

118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
const std::vector<VehicleSection>& Vehicle::sections() const
{
    return d->sections;
}

std::vector<VehicleSection>&& Vehicle::takeSections()
{
    return std::move(d->sections);
}

void Vehicle::setSections(std::vector<VehicleSection> &&sections)
{
    d.detach();
    d->sections = std::move(sections);
}

134
135
136
137
138
139
void Vehicle::setSections(const std::vector<VehicleSection> &sections)
{
    d.detach();
    d->sections = sections;
}

140
141
142
143
144
145
146
147
QVariantList Vehicle::sectionsVariant() const
{
    QVariantList l;
    l.reserve(d->sections.size());
    std::transform(d->sections.begin(), d->sections.end(), std::back_inserter(l), [](const auto &sec) { return QVariant::fromValue(sec); });
    return l;
}

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
float Vehicle::platformPositionBegin() const
{
    float p = std::numeric_limits<float>::max();
    for (const auto &section : sections()) {
        p = std::min(p, section.platformPositionBegin());
    }
    return p;
}

float Vehicle::platformPositionEnd() const
{
    float p = -1.0f;
    for (const auto &section : sections()) {
        p = std::max(p, section.platformPositionEnd());
    }
    return p;
}

166
167
168
169
170
171
172
173
174
175
float Vehicle::platformPositionForSection(const QString &sectionName) const
{
    for (const auto &section : sections()) {
        if (section.name() == sectionName) {
            return (section.platformPositionBegin() + section.platformPositionEnd()) / 2.0f;
        }
    }
    return -1.0f;
}

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
Vehicle Vehicle::merge(const Vehicle &lhs, const Vehicle &rhs)
{
    Vehicle res;
    res.setDirection(lhs.direction() == Vehicle::UnknownDirection ? rhs.direction() : lhs.direction());
    res.setName(MergeUtil::mergeString(lhs.name(), rhs.name()));

    if (lhs.sections().size() == rhs.sections().size()) {
        std::vector<VehicleSection> secs;
        secs.reserve(lhs.sections().size());
        for (std::size_t i = 0; i < lhs.sections().size(); ++i) {
            const auto &lhsSec = lhs.sections()[i];
            const auto &rhsSec = rhs.sections()[i];
            secs.push_back(VehicleSection::merge(lhsSec, rhsSec));
        }
        res.setSections(std::move(secs));
    } else {
        res.setSections(lhs.sections().size() < rhs.sections().size() ? rhs.sections() : lhs.sections());
    }

    return res;
}

198
199
200
201
202
203
204
205
206
QJsonObject Vehicle::toJson(const Vehicle &vehicle)
{
    auto obj = Json::toJson(vehicle);
    if (!vehicle.sections().empty()) {
        obj.insert(QStringLiteral("sections"), VehicleSection::toJson(vehicle.sections()));
    }
    return obj;
}

207
208
209
210
211
QJsonArray Vehicle::toJson(const std::vector<Vehicle> &vehicles)
{
    return Json::toJson(vehicles);
}

212
213
214
215
216
217
218
Vehicle Vehicle::fromJson(const QJsonObject &obj)
{
    auto v = Json::fromJson<Vehicle>(obj);
    v.setSections(VehicleSection::fromJson(obj.value(QLatin1String("sections")).toArray()));
    return v;
}

219
220
221
222
223
std::vector<Vehicle> Vehicle::fromJson(const QJsonArray &array)
{
    return Json::fromJson<Vehicle>(array);
}

224
#include "moc_vehicle.cpp"