Commit 42d06659 authored by Volker Krause's avatar Volker Krause
Browse files

Support per-type capacity/availability values for rental vehicle docks

Filled from GBFS data where available.
parent 9bf04287
......@@ -8,6 +8,8 @@
#include "datatypes_p.h"
#include "json_p.h"
#include <QMetaEnum>
using namespace KPublicTransport;
namespace KPublicTransport {
......@@ -24,6 +26,8 @@ public:
int availableVehicles = -1;
int capacity = -1;
RentalVehicleNetwork network;
std::vector<int> capacities;
std::vector<int> availabilities;
};
class RentalVehiclePrivate : public QSharedData
......@@ -69,24 +73,119 @@ bool RentalVehicleStation::isValid() const
return d->network.isValid() || d->capacity >= 0 || d->availableVehicles >= 0;
}
int RentalVehicleStation::capacity(RentalVehicle::VehicleType type) const
{
const auto me = QMetaEnum::fromType<RentalVehicle::VehicleType>();
for (auto i = 0; i < me.keyCount() && i < (int)d->capacities.size(); ++i) {
if (me.value(i) == type) {
return d->capacities[i];
}
}
return -1;
}
void RentalVehicleStation::setCapacity(RentalVehicle::VehicleType type, int capacity)
{
const auto me = QMetaEnum::fromType<RentalVehicle::VehicleType>();
for (auto i = 0; i < me.keyCount(); ++i) {
if (me.value(i) != type) {
continue;
}
d->capacities.resize(std::max(d->capacities.size(), (std::size_t)(i + 1)), -1);
d->capacities[i] = capacity;
return;
}
}
int RentalVehicleStation::availableVehicles(RentalVehicle::VehicleType type) const
{
const auto me = QMetaEnum::fromType<RentalVehicle::VehicleType>();
for (auto i = 0; i < me.keyCount() && i < (int)d->availabilities.size(); ++i) {
if (me.value(i) == type) {
return d->availabilities[i];
}
}
return -1;
}
void RentalVehicleStation::setAvailableVehicles(RentalVehicle::VehicleType type, int count)
{
const auto me = QMetaEnum::fromType<RentalVehicle::VehicleType>();
for (auto i = 0; i < me.keyCount(); ++i) {
if (me.value(i) != type) {
continue;
}
d->availabilities.resize(std::max(d->availabilities.size(), (std::size_t)(i + 1)), -1);
d->availabilities[i] = count;
return;
}
}
bool RentalVehicleStation::isSame(const RentalVehicleStation &lhs, const RentalVehicleStation &rhs)
{
return RentalVehicleNetwork::isSame(lhs.network(), rhs.network());
}
static QJsonValue typeVectorToJson(const std::vector<int> &v)
{
if (v.empty()) {
return {};
}
QJsonObject obj;
const auto me = QMetaEnum::fromType<RentalVehicle::VehicleType>();
for (auto i = 0; i < me.keyCount() && i < (int)v.size(); ++i) {
if (v[i] < 0) {
continue;
}
obj.insert(QLatin1String(me.key(i)), v[i]);
}
return obj.isEmpty() ? QJsonValue() : obj;
}
QJsonObject RentalVehicleStation::toJson(const RentalVehicleStation &station)
{
auto obj = Json::toJson(station);
if (station.network().isValid()) {
obj.insert(QStringLiteral("network"), RentalVehicleNetwork::toJson(station.network()));
}
auto v = typeVectorToJson(station.d->capacities);
if (v.isObject()) {
obj.insert(QLatin1String("capacitiesByType"), v);
}
v = typeVectorToJson(station.d->availabilities);
if (v.isObject()) {
obj.insert(QLatin1String("availabilitiesByType"), v);
}
return obj;
}
static std::vector<int> typeVectorFromJson(const QJsonValue &v)
{
std::vector<int> out;
const auto obj = v.toObject();
if (obj.isEmpty()) {
return out;
}
const auto me = QMetaEnum::fromType<RentalVehicle::VehicleType>();
for (auto i = 0; i < me.keyCount(); ++i) {
const auto it = obj.find(QLatin1String(me.key(i)));
if (it == obj.end()) {
continue;
}
out.resize(i + 1, -1);
out[i] = it.value().toInt();
}
return out;
}
RentalVehicleStation RentalVehicleStation::fromJson(const QJsonObject &obj)
{
auto station = Json::fromJson<RentalVehicleStation>(obj);
station.setNetwork(RentalVehicleNetwork::fromJson(obj.value(QLatin1String("network")).toObject()));
station.d->capacities = typeVectorFromJson(obj.value(QLatin1String("capacitiesByType")));
station.d->availabilities = typeVectorFromJson(obj.value(QLatin1String("availabilitiesByType")));
return station;
}
......
......@@ -12,42 +12,6 @@
namespace KPublicTransport {
class RentalVehicleNetwork;
class RentalVehicleStationPrivate;
/** Additional information for a vehicle renting station, attached to Location objects.
* This is typically needed for dock-based bike sharing systems.
*
* @see https://github.com/NABSA/gbfs/blob/master/gbfs.md#station_informationjson
* @see https://github.com/NABSA/gbfs/blob/master/gbfs.md#station_statusjson
*/
class KPUBLICTRANSPORT_EXPORT RentalVehicleStation
{
KPUBLICTRANSPORT_GADGET(RentalVehicleStation)
/** Number of available (rentable) vehicles at this station. */
KPUBLICTRANSPORT_PROPERTY(int, availableVehicles, setAvailableVehicles)
/** Number of dock positions at this station.
* If capacity == availableVehicles no vehicles can be returned at this station.
*/
KPUBLICTRANSPORT_PROPERTY(int, capacity, setCapacity)
/** Sharing network operator. */
KPUBLICTRANSPORT_PROPERTY(KPublicTransport::RentalVehicleNetwork, network, setNetwork)
/** Not an empty/default constructed object. */
Q_PROPERTY(bool isValid READ isValid)
public:
bool isValid() const;
/** Checks if two instances refer to the same station. */
static bool isSame(const RentalVehicleStation &lhs, const RentalVehicleStation &rhs);
/** Serializes one object to JSON. */
static QJsonObject toJson(const RentalVehicleStation &station);
/** Deserialize an object from JSON. */
static RentalVehicleStation fromJson(const QJsonObject &obj);
};
class RentalVehiclePrivate;
/** An individual rental vehicle used on a JourneySection, ie. a vehicle you don't own yourself but have to drive yourself.
......@@ -93,6 +57,52 @@ public:
Q_DECLARE_OPERATORS_FOR_FLAGS(RentalVehicle::VehicleTypes)
class RentalVehicleStationPrivate;
/** Additional information for a vehicle renting station, attached to Location objects.
* This is typically needed for dock-based bike sharing systems.
*
* @see https://github.com/NABSA/gbfs/blob/master/gbfs.md#station_informationjson
* @see https://github.com/NABSA/gbfs/blob/master/gbfs.md#station_statusjson
*/
class KPUBLICTRANSPORT_EXPORT RentalVehicleStation
{
KPUBLICTRANSPORT_GADGET(RentalVehicleStation)
/** Number of available (rentable) vehicles at this station. */
KPUBLICTRANSPORT_PROPERTY(int, availableVehicles, setAvailableVehicles)
/** Number of dock positions at this station.
* If capacity == availableVehicles no vehicles can be returned at this station.
*/
KPUBLICTRANSPORT_PROPERTY(int, capacity, setCapacity)
/** Sharing network operator. */
KPUBLICTRANSPORT_PROPERTY(KPublicTransport::RentalVehicleNetwork, network, setNetwork)
/** Not an empty/default constructed object. */
Q_PROPERTY(bool isValid READ isValid)
public:
bool isValid() const;
/** Capacity for a given vehicle type. */
Q_INVOKABLE int capacity(KPublicTransport::RentalVehicle::VehicleType type) const;
/** Set the capacity for a specific vehicle type. */
void setCapacity(RentalVehicle::VehicleType type, int capacity);
/** Available vehicles for a given vehicle type. */
Q_INVOKABLE int availableVehicles(KPublicTransport::RentalVehicle::VehicleType type) const;
/** Sets the number of available vehicles for a given vehicle type. */
void setAvailableVehicles(RentalVehicle::VehicleType type, int count);
/** Checks if two instances refer to the same station. */
static bool isSame(const RentalVehicleStation &lhs, const RentalVehicleStation &rhs);
/** Serializes one object to JSON. */
static QJsonObject toJson(const RentalVehicleStation &station);
/** Deserialize an object from JSON. */
static RentalVehicleStation fromJson(const QJsonObject &obj);
};
class RentalVehicleNetworkPrivate;
/** A vehicle sharing system/network.
......
......@@ -132,8 +132,13 @@ static void appendResults(const GBFSService &service, const LocationRequest &req
RentalVehicleStation s;
s.setNetwork(network);
s.setCapacity(station.value(QLatin1String("capacity")).toInt(-1));
loc.setData(s);
const auto vehicleCapacities = station.value(QLatin1String("vehicle_capacity")).toObject();
for (auto it = vehicleCapacities.begin(); it != vehicleCapacities.end(); ++it) {
const auto type = gbfs2kptVehicleType(vehicleTypes.vehicleType(it.key()));
s.setCapacity(type, it.value().toInt(-1));
}
loc.setData(s);
selectedStationIds.push_back(stationId);
context->result.push_back(loc);
}
......@@ -150,7 +155,15 @@ static void appendResults(const GBFSService &service, const LocationRequest &req
auto &loc = context->result[context->result.size() - selectedStationIds.size() + std::distance(selectedStationIds.begin(), it)];
auto s = loc.rentalVehicleStation();
s.setAvailableVehicles(stat.value(QLatin1String("num_bikes_available")).toInt(-1));
const auto availableVehicleTypes = stat.value(QLatin1String("vehicle_types_available")).toArray();
for (const auto &v : availableVehicleTypes) {
const auto obj = v.toObject();
const auto type = gbfs2kptVehicleType(vehicleTypes.vehicleType(obj.value(QLatin1String("vehicle_type_id")).toString()));
s.setAvailableVehicles(type, obj.value(QLatin1String("count")).toInt(-1));
}
loc.setData(s);
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment