[traffxml] Parse duration quantifier and use it for delays

Signed-off-by: mvglasow <michael -at- vonglasow.com>
This commit is contained in:
mvglasow
2025-06-09 21:56:06 +03:00
parent b98fe1999c
commit b48310e6a5
3 changed files with 88 additions and 5 deletions

View File

@@ -200,8 +200,14 @@ std::optional<TrafficImpact> TraffMessage::GetTrafficImpact()
impact.m_maxspeed = event.m_speed.value(); impact.m_maxspeed = event.m_speed.value();
// TODO if no explicit speed given, look up in kEventMaxspeedMap (once we have entries) // TODO if no explicit speed given, look up in kEventMaxspeedMap (once we have entries)
// TODO if event is in delay class and has an explicit duration quantifier, use that and skip the map lookup. if (event.m_class == EventClass::Delay
if (auto it = kEventDelayMap.find(event.m_type); it != kEventDelayMap.end()) && event.m_type != EventType::DelayClearance
&& event.m_type != EventType::DelayForecastWithdrawn
&& event.m_type != EventType::DelaySeveralHours
&& event.m_type != EventType::DelayUncertainDuration
&& event.m_qDurationMins)
impact.m_delayMins = event.m_qDurationMins.value();
else if (auto it = kEventDelayMap.find(event.m_type); it != kEventDelayMap.end())
impact.m_delayMins = it->second; impact.m_delayMins = it->second;
// TempBlock overrules everything else, return immediately // TempBlock overrules everything else, return immediately
@@ -458,7 +464,12 @@ std::string DebugPrint(TraffEvent event)
os << "type: " << DebugPrint(event.m_type) << ", "; os << "type: " << DebugPrint(event.m_type) << ", ";
os << "length: " << (event.m_length ? std::to_string(event.m_length.value()) : "nullopt") << ", "; os << "length: " << (event.m_length ? std::to_string(event.m_length.value()) : "nullopt") << ", ";
os << "probability: " << (event.m_probability ? std::to_string(event.m_probability.value()) : "nullopt") << ", "; os << "probability: " << (event.m_probability ? std::to_string(event.m_probability.value()) : "nullopt") << ", ";
// TODO optional quantifier os << "q_duration: "
<< (event.m_qDurationMins
? std::format("{:1d}:{:02d}", event.m_qDurationMins.value() / 60, event.m_qDurationMins.value() % 60)
: "nullopt")
<< ", ";
// TODO other quantifiers
os << "speed: " << (event.m_speed ? std::to_string(event.m_speed.value()) : "nullopt"); os << "speed: " << (event.m_speed ? std::to_string(event.m_speed.value()) : "nullopt");
// TODO supplementary information // TODO supplementary information
os << " }"; os << " }";

View File

@@ -109,6 +109,19 @@ enum class RoadClass
Other Other
}; };
enum class QuantifierType
{
Dimension,
Duration,
Int,
Ints,
Speed,
Temperature,
Time,
Weight,
Invalid
};
/* /*
* When adding a new event class to this enum, be sure to do the following: * When adding a new event class to this enum, be sure to do the following:
* *
@@ -312,7 +325,17 @@ struct TraffEvent
EventType m_type = EventType::Invalid; EventType m_type = EventType::Invalid;
std::optional<uint8_t> m_length; std::optional<uint8_t> m_length;
std::optional<uint8_t> m_probability; std::optional<uint8_t> m_probability;
// TODO optional quantifier std::optional<uint16_t> m_qDurationMins;
/*
* TODO remaining quantifiers
* q_dimension
* q_int
* q_ints
* q_speed
* q_temperature
* q_time
* q_weight
*/
std::optional<uint8_t> m_speed; std::optional<uint8_t> m_speed;
// TODO supplementary information // TODO supplementary information
}; };

View File

@@ -480,6 +480,53 @@ bool LocationFromXml(pugi::xml_node node, TraffLocation & location)
return true; return true;
} }
/**
* @brief Retrieves a `TraffQuantifier` from an XML element.
*
* The TraFF specification allows only one quantifier per event. The quantifier type depends on the
* event type, and not all events allow quantifiers.
*
* Quantifiers which violate these constraints are not filtered out, i.e. this function may return a
* quantifier for event types that do not allow quantifiers, or of a type illegal for the event type.
* If an event contains multiple quantifiers of different types, any one of these quantifiers may be
* returned, with no preference for legal quantifiers over illegal ones.
*
* @param node The node from which to retrieve the quantifier (`event`).
* @return The quantifier, or `std::nullopt`
*/
std::optional<uint16_t> OptionalDurationFromXml(pugi::xml_attribute attribute)
{
std::string durationString;
if (!StringFromXml(attribute, durationString))
return std::nullopt;
/*
* Valid time formats:
* 01:30 (hh:mm)
* 1 h
* 30 min
*/
std::regex durationRegex("(([0-9]+):([0-9]{2}))|(([0-9]+) *h)|(([0-9]+) *min)");
std::smatch durationMatcher;
if (std::regex_search(durationString, durationMatcher, durationRegex))
{
if (!durationMatcher.str(2).empty() && !durationMatcher.str(3).empty())
return std::stoi(durationMatcher[2]) * 60 + std::stoi(durationMatcher[3]);
else if (!durationMatcher.str(5).empty())
return std::stoi(durationMatcher[5]) * 60;
else if (!durationMatcher.str(7).empty())
return std::stoi(durationMatcher[7]);
UNREACHABLE();
return std::nullopt;
}
else
{
LOG(LINFO, ("Not a valid duration:", durationString));
return std::nullopt;
}
}
/** /**
* @brief Retrieves a `TraffEvent` from an XML element. * @brief Retrieves a `TraffEvent` from an XML element.
* @param node The XML element to retrieve (`event`). * @param node The XML element to retrieve (`event`).
@@ -514,7 +561,9 @@ bool EventFromXml(pugi::xml_node node, TraffEvent & event)
event.m_length = OptionalIntegerFromXml(node.attribute("length")); event.m_length = OptionalIntegerFromXml(node.attribute("length"));
event.m_probability = OptionalIntegerFromXml(node.attribute("probability")); event.m_probability = OptionalIntegerFromXml(node.attribute("probability"));
// TODO optional quantifier (not yet implemented in struct) event.m_qDurationMins = OptionalDurationFromXml(node.attribute("q_duration"));
// TODO other quantifiers (not yet implemented in struct)
event.m_speed = OptionalIntegerFromXml(node.attribute("speed")); event.m_speed = OptionalIntegerFromXml(node.attribute("speed"));