Skip to content

Commit

Permalink
Merge pull request #2 from mesozoic-drones/add-updates-for-structs
Browse files Browse the repository at this point in the history
Updates for enums & structs
  • Loading branch information
mesozoic-drones authored Mar 1, 2023
2 parents b2b96ad + c5b227b commit 94b35ee
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 24 deletions.
63 changes: 43 additions & 20 deletions include/just_gtfs/just_gtfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ class Time
inline Time() = default;
inline explicit Time(const std::string & raw_time_str);
inline Time(uint16_t hours, uint16_t minutes, uint16_t seconds);
inline Time(size_t seconds);
inline bool is_provided() const;
inline size_t get_total_seconds() const;
inline std::tuple<uint16_t, uint16_t, uint16_t> get_hh_mm_ss() const;
Expand Down Expand Up @@ -543,6 +544,16 @@ inline Time::Time(uint16_t hours, uint16_t minutes, uint16_t seconds)
time_is_provided = true;
}

inline Time::Time(size_t seconds)
: time_is_provided(true)
, total_seconds(seconds)
, hh(seconds / 3600)
, mm((seconds % 3600) / 60)
, ss(seconds % 3600)
{
set_raw_time();
}

inline bool Time::is_provided() const { return time_is_provided; }

inline size_t Time::get_total_seconds() const { return total_seconds; }
Expand Down Expand Up @@ -644,7 +655,7 @@ using CurrencyCode = std::string;
using LanguageCode = std::string;

// Helper enums for some GTFS fields ---------------------------------------------------------------
enum class StopLocationType
enum class StopLocationType : int8_t
{
StopOrPlatform = 0,
Station = 1,
Expand All @@ -654,7 +665,7 @@ enum class StopLocationType
};

// The type of transportation used on a route.
enum class RouteType
enum class RouteType : int16_t
{
// GTFS route types
Tram = 0, // Tram, Streetcar, Light rail
Expand Down Expand Up @@ -752,74 +763,74 @@ enum class RouteType
HorseDrawnCarriage = 1702
};

enum class TripDirectionId
enum class TripDirectionId : bool
{
DefaultDirection = 0, // e.g. outbound
OppositeDirection = 1 // e.g. inbound
};

enum class TripAccess
enum class TripAccess : int8_t
{
NoInfo = 0,
Yes = 1,
No = 2
};

enum class StopTimeBoarding
enum class StopTimeBoarding : int8_t
{
RegularlyScheduled = 0,
No = 1, // Not available
Phone = 2, // Must phone agency to arrange
CoordinateWithDriver = 3 // Must coordinate with driver to arrange
};

enum class StopTimePoint
enum class StopTimePoint : bool
{
Approximate = 0,
Exact = 1
};

enum class CalendarAvailability
enum class CalendarAvailability : bool
{
NotAvailable = 0,
Available = 1
};

enum class CalendarDateException
enum class CalendarDateException : int8_t
{
Added = 1, // Service has been added for the specified date
Removed = 2
};

enum class FarePayment
enum class FarePayment : bool
{
OnBoard = 0,
BeforeBoarding = 1 // Fare must be paid before boarding
};

enum class FareTransfers
enum class FareTransfers : int8_t
{
No = 0, // No transfers permitted on this fare
Once = 1,
Twice = 2,
Unlimited = 3
};

enum class FrequencyTripService
enum class FrequencyTripService : bool
{
FrequencyBased = 0, // Frequency-based trips
ScheduleBased = 1 // Schedule-based trips with the exact same headway throughout the day
};

enum class TransferType
enum class TransferType : int8_t
{
Recommended = 0,
Timed = 1,
MinimumTime = 2,
NotPossible = 3
};

enum class PathwayMode
enum class PathwayMode : int8_t
{
Walkway = 1,
Stairs = 2,
Expand All @@ -830,13 +841,13 @@ enum class PathwayMode
ExitGate = 7
};

enum class PathwayDirection
enum class PathwayDirection : bool
{
Unidirectional = 0,
Bidirectional = 1
};

enum class AttributionRole
enum class AttributionRole : bool
{
No = 0, // Organization doesn’t have this role
Yes = 1 // Organization does have this role
Expand Down Expand Up @@ -888,7 +899,7 @@ struct Stop
Text stop_code;
Text stop_desc;
Text stop_url;
StopLocationType location_type = StopLocationType::GenericNode;
StopLocationType location_type = StopLocationType::StopOrPlatform;
Text stop_timezone;
Text wheelchair_boarding;
Id level_id;
Expand Down Expand Up @@ -999,6 +1010,14 @@ struct FareAttributesItem
size_t transfer_duration = 0; // Length of time in seconds before a transfer expires
};

inline bool operator==(const FareAttributesItem & lhs, const FareAttributesItem & rhs)
{
return std::tie(lhs.fare_id, lhs.price, lhs.currency_type, lhs.payment_method, lhs.transfers,
lhs.agency_id, lhs.transfer_duration) ==
std::tie(rhs.fare_id, rhs.price, rhs.currency_type, rhs.payment_method, rhs.transfers,
rhs.agency_id, rhs.transfer_duration);
}

// Optional dataset file
struct FareRule
{
Expand Down Expand Up @@ -1340,6 +1359,7 @@ class Feed
inline void write_translations(std::ofstream & out) const;
inline void write_attributions(std::ofstream & out) const;

protected:
std::string gtfs_directory;

Agencies agencies;
Expand Down Expand Up @@ -1840,7 +1860,7 @@ inline Result Feed::add_fare_attributes(const ParsedCsvRow & row)

item.currency_type = row.at("currency_type");
set_field(item.payment_method, row, "payment_method", false);
set_field(item.transfers, row, "transfers", false);
set_field(item.transfers, row, "transfers");

// Conditionally optional:
item.agency_id = get_value_or_default(row, "agency_id");
Expand Down Expand Up @@ -2778,9 +2798,12 @@ inline void Feed::write_fare_attributes(std::ofstream & out) const
for (const auto & attribute : fare_attributes)
{
std::vector<std::string> fields{
wrap(attribute.fare_id), wrap(attribute.price), attribute.currency_type,
wrap(attribute.payment_method), wrap(attribute.transfers), wrap(attribute.agency_id),
wrap(attribute.transfer_duration)};
wrap(attribute.fare_id), wrap(attribute.price), attribute.currency_type,
wrap(attribute.payment_method),
// Here we handle GTFS specification corner case: "The fact that this field can be left
// empty is an exception to the requirement that a Required field must not be empty.":
attribute.transfers == FareTransfers::Unlimited ? "" : wrap(attribute.transfers),
wrap(attribute.agency_id), wrap(attribute.transfer_duration)};
write_joined(out, std::move(fields));
}
}
Expand Down
3 changes: 2 additions & 1 deletion tests/data/sample_feed/fare_attributes.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
fare_id,price,currency_type,payment_method,transfers,transfer_duration
p,1.25,USD,0,0,
a,5.25,USD,0,0,
a,5.25,USD,1,1,
x,20,USD,0,,60
25 changes: 22 additions & 3 deletions tests/unit_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ TEST_CASE("Read GTFS feed")
CHECK_EQ(feed.get_attributions().size(), 1);
CHECK_EQ(feed.get_calendar().size(), 2);
CHECK_EQ(feed.get_calendar_dates().size(), 1);
CHECK_EQ(feed.get_fare_attributes().size(), 2);
CHECK_EQ(feed.get_fare_attributes().size(), 3);
CHECK_EQ(feed.get_fare_rules().size(), 4);
CHECK(!feed.get_feed_info().feed_publisher_name.empty());
CHECK_EQ(feed.get_levels().size(), 3);
Expand Down Expand Up @@ -395,7 +395,7 @@ TEST_CASE("Stops")
CHECK_EQ(stops[0].stop_id, "FUR_CREEK_RES");
CHECK(stops[0].stop_desc.empty());
CHECK_EQ(stops[0].stop_name, "Furnace Creek Resort (Demo)");
CHECK_EQ(stops[0].location_type, StopLocationType::GenericNode);
CHECK_EQ(stops[0].location_type, StopLocationType::StopOrPlatform);
CHECK(stops[0].zone_id.empty());

auto const & stop = feed.get_stop("FUR_CREEK_RES");
Expand Down Expand Up @@ -494,17 +494,36 @@ TEST_CASE("Fare attributes")
REQUIRE_EQ(feed.read_fare_attributes(), ResultCode::OK);

const auto & attributes = feed.get_fare_attributes();
REQUIRE_EQ(attributes.size(), 2);
REQUIRE_EQ(attributes.size(), 3);
CHECK_EQ(attributes[0].fare_id, "p");
CHECK_EQ(attributes[0].price, 1.25);
CHECK_EQ(attributes[0].currency_type, "USD");
CHECK_EQ(attributes[0].payment_method, FarePayment::OnBoard);
CHECK_EQ(attributes[0].transfers, FareTransfers::No);
CHECK_EQ(attributes[0].transfer_duration, 0);

CHECK_EQ(attributes[1].fare_id, "a");
CHECK_EQ(attributes[1].price, 5.25);
CHECK_EQ(attributes[1].currency_type, "USD");
CHECK_EQ(attributes[1].payment_method, FarePayment::BeforeBoarding);
CHECK_EQ(attributes[1].transfers, FareTransfers::Once);
CHECK_EQ(attributes[1].transfer_duration, 0);

CHECK_EQ(attributes[2].fare_id, "x");
CHECK_EQ(attributes[2].price, 20);
CHECK_EQ(attributes[2].currency_type, "USD");
CHECK_EQ(attributes[2].payment_method, FarePayment::OnBoard);
CHECK_EQ(attributes[2].transfers, FareTransfers::Unlimited);
CHECK_EQ(attributes[2].transfer_duration, 60);

const auto & attributes_for_id = feed.get_fare_attributes("a");
REQUIRE_EQ(attributes_for_id.size(), 1);
CHECK_EQ(attributes_for_id[0].price, 5.25);

REQUIRE_EQ(feed.write_fare_attributes("data/output_feed"), ResultCode::OK);
Feed feed_copy("data/output_feed");
REQUIRE_EQ(feed_copy.read_fare_attributes(), ResultCode::OK);
CHECK_EQ(attributes, feed_copy.get_fare_attributes());
}

TEST_CASE("Fare rules")
Expand Down

0 comments on commit 94b35ee

Please sign in to comment.