Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/dsm/dsm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

static constexpr uint8_t DSM_VERSION_MAJOR = 2;
static constexpr uint8_t DSM_VERSION_MINOR = 6;
static constexpr uint8_t DSM_VERSION_PATCH = 25;
static constexpr uint8_t DSM_VERSION_PATCH = 26;

static auto const DSM_VERSION =
std::format("{}.{}.{}", DSM_VERSION_MAJOR, DSM_VERSION_MINOR, DSM_VERSION_PATCH);
Expand Down
155 changes: 75 additions & 80 deletions src/dsm/headers/RoadDynamics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@
continue;
}
auto const& pAgentTemp2{pStreetTemp->queue(i).front()};
if (!pAgentTemp2->streetId().has_value()) {
if (!pAgentTemp2->nextStreetId().has_value()) {
continue;
}
auto const& otherDirection{
Expand Down Expand Up @@ -828,6 +828,9 @@
}
continue;
}
if (!pAgentTemp->streetId().has_value()) {
Logger::error(std::format("Agent {} has no street id", pAgentTemp->id()));

Check warning on line 832 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L832

Added line #L832 was not covered by tests
}
auto const& nextStreet{this->graph().edge(pAgentTemp->nextStreetId().value())};
if (nextStreet->isFull()) {
continue;
Expand Down Expand Up @@ -885,7 +888,7 @@
it = intersection.agents().erase(it);
break;
}
} else if (pNode->isRoundabout()) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 15.5 rule Note

MISRA 15.5 rule
auto& roundabout = dynamic_cast<Roundabout&>(*pNode);
if (roundabout.agents().empty()) {
return;
Expand Down Expand Up @@ -1027,6 +1030,13 @@
0, static_cast<Size>(this->itineraries().size() - 1)};
std::uniform_int_distribution<Size> streetDist{
0, static_cast<Size>(this->graph().nEdges() - 1)};
if (this->nAgents() + nAgents > this->graph().maxCapacity()) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.1 rule Note

MISRA 12.1 rule
Logger::error(std::format(

Check warning on line 1034 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1034

Added line #L1034 was not covered by tests
"Cannot add {} agents. The graph has reached its maximum capacity of {}",
nAgents,
this->graph().maxCapacity()));
return;

Check warning on line 1038 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1037-L1038

Added lines #L1037 - L1038 were not covered by tests
}
for (Size i{0}; i < nAgents; ++i) {
if (bRandomItinerary) {
auto itineraryIt{this->itineraries().cbegin()};
Expand All @@ -1039,8 +1049,7 @@
Size step = streetDist(this->m_generator);
std::advance(streetIt, step);
streetId = streetIt->first;
} while (this->graph().edge(streetId)->isFull() &&
this->nAgents() < this->graph().maxCapacity());
} while (this->graph().edge(streetId)->isFull());

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
const auto& street{this->graph().edge(streetId)};
auto pAgent{std::make_unique<Agent>(this->time(), itineraryId, street->source())};
pAgent->setStreetId(streetId);
Expand Down Expand Up @@ -1253,15 +1262,17 @@
auto const streetId{sourceId * N + pNode->id()};
auto const& pStreet{this->graph().edge(streetId)};
if (bUpdateData && pNode->isTrafficLight()) {
if (!m_queuesAtTrafficLights.contains(streetId)) {
if (!m_queuesAtTrafficLights.contains(pStreet->id())) {
auto& tl = dynamic_cast<TrafficLight&>(*pNode);
for (auto const& [streetId, pair] : tl.cycles()) {
assert(!tl.cycles().empty());
for (auto const& [id, pair] : tl.cycles()) {
for (auto const& [direction, cycle] : pair) {
m_queuesAtTrafficLights[streetId].emplace(direction, 0.);
m_queuesAtTrafficLights[id].emplace(direction, 0.);
}
}
}
for (auto& [direction, value] : m_queuesAtTrafficLights.at(streetId)) {
for (auto& [direction, value] :
m_queuesAtTrafficLights.at(pStreet->id())) {
value += pStreet->nExitingAgents(direction, true);
}
}
Expand Down Expand Up @@ -1396,7 +1407,7 @@
Dynamics<RoadNetwork>::m_evolve();
}

template <typename delay_t>

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
requires(is_numeric_v<delay_t>)
void RoadDynamics<delay_t>::m_trafficlightSingleTailOptimizer(
double const& beta, std::optional<std::ofstream>& logStream) {
Expand Down Expand Up @@ -1518,7 +1529,7 @@
} else {
if (direction == Direction::LEFT ||
direction == Direction::LEFTANDSTRAIGHT) {
greenTimes[3] += cycle.greenTime();

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
++n[3];
} else {
greenTimes[2] += cycle.greenTime();
Expand Down Expand Up @@ -1807,87 +1818,71 @@
Logger::error(std::format("Could not open log file: {}", logFile));
}
}
if (optimizationType == TrafficLightOptimization::SINGLE_TAIL) {
this->m_trafficlightSingleTailOptimizer(threshold, logStream);
} else if (optimizationType == TrafficLightOptimization::DOUBLE_TAIL) {
if (threshold < 0) {
Logger::error(std::format("The threshold parameter ({}) must be greater than 0.",
threshold));
}
auto const nCycles{static_cast<double>(this->time() - m_previousOptimizationTime) /
m_dataUpdatePeriod.value()};
for (const auto& [nodeId, pNode] : this->graph().nodes()) {
this->m_trafficlightSingleTailOptimizer(threshold, logStream);
if (optimizationType == TrafficLightOptimization::DOUBLE_TAIL) {
// Try to synchronize congested traffic lights
std::unordered_map<Id, double> densities;

Check warning on line 1824 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1824

Added line #L1824 was not covered by tests

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
for (auto const& [nodeId, pNode] : this->graph().nodes()) {
if (!pNode->isTrafficLight()) {
continue;
}
if (logStream.has_value()) {
*logStream << std::format("\tTraffic Light {}\n", nodeId);
}
auto& tl = dynamic_cast<TrafficLight&>(*pNode);
auto const& streetPriorities = tl.streetPriorities();
auto const meanGreenFraction{tl.meanGreenTime(true) / tl.cycleTime()};
auto const meanRedFraction{tl.meanGreenTime(false) / tl.cycleTime()};

double inputGreenSum{0.}, inputRedSum{0.};
auto const N{this->graph().nNodes()};
auto column = this->graph().adjacencyMatrix().getCol(nodeId);
for (const auto& sourceId : column) {
auto const streetId = sourceId * N + nodeId;
auto const& pStreet{this->graph().edge(streetId)};
if (streetPriorities.contains(streetId)) {
for (auto const& pair : m_queuesAtTrafficLights.at(streetId)) {
inputGreenSum += pair.second / pStreet->nLanes();
}
} else {
for (auto const& pair : m_queuesAtTrafficLights.at(streetId)) {
inputRedSum += pair.second / pStreet->nLanes();
}
double density{0.}, n{0.};

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
auto const& inNeighbours{this->graph().adjacencyMatrix().getCol(nodeId)};

Check warning on line 1830 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1829-L1830

Added lines #L1829 - L1830 were not covered by tests
for (auto const& sourceId : inNeighbours) {
if (!this->graph().node(sourceId)->isTrafficLight()) {
continue;

Check warning on line 1833 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1833

Added line #L1833 was not covered by tests
}
density += this->graph()
.edge(sourceId * this->graph().nNodes() + nodeId)
->density(true);
++n;

Check warning on line 1838 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1835-L1838

Added lines #L1835 - L1838 were not covered by tests
}
inputGreenSum /= meanGreenFraction;
inputRedSum /= meanRedFraction;
auto const inputDifference{(inputGreenSum - inputRedSum) / nCycles};
delay_t const delta = std::round(std::abs(inputDifference) / column.size());
auto const greenTime = tl.minGreenTime(true);
auto const redTime = tl.minGreenTime(false);
// If the difference is not less than the threshold
// - Check that the incoming streets have a density less than the mean one (eventually + tolerance): I want to avoid being into the cluster, better to be out or on the border
// - If the previous check fails, do nothing
double outputGreenSum{0.}, outputRedSum{0.};
for (auto const& targetId : this->graph().adjacencyMatrix().getRow(nodeId)) {
auto const streetId = nodeId * N + targetId;
if (!m_queuesAtTrafficLights.contains(streetId)) {
density /= n;
densities[nodeId] = density;

Check warning on line 1841 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1840-L1841

Added lines #L1840 - L1841 were not covered by tests
}
// Sort densities map from big to small values
std::vector<std::pair<Id, double>> sortedDensities(densities.begin(),

Check warning on line 1844 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1844

Added line #L1844 was not covered by tests

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
densities.end());

// Sort by density descending
std::sort(sortedDensities.begin(),

Check warning on line 1848 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1848

Added line #L1848 was not covered by tests
sortedDensities.end(),
[](auto const& a, auto const& b) { return a.second > b.second; });

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 15.5 rule Note

MISRA 15.5 rule
std::unordered_set<Id> optimizedNodes;

Check warning on line 1851 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1850-L1851

Added lines #L1850 - L1851 were not covered by tests

for (auto const& [nodeId, density] : sortedDensities) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
auto const& inNeighbours{this->graph().adjacencyMatrix().getCol(nodeId)};

Check warning on line 1854 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1854

Added line #L1854 was not covered by tests
for (auto const& sourceId : inNeighbours) {
if (!densities.contains(sourceId) || optimizedNodes.contains(sourceId)) {
continue;
}
auto const& pStreet{this->graph().edge(streetId)};
if (streetPriorities.contains(streetId)) {
for (auto const& pair : m_queuesAtTrafficLights.at(streetId)) {
outputGreenSum += pair.second / pStreet->nLanes();
}
} else {
for (auto const& pair : m_queuesAtTrafficLights.at(streetId)) {
outputGreenSum += pair.second / pStreet->nLanes();
}
}
}
auto const outputDifference{(outputGreenSum - outputRedSum) / nCycles};
if ((inputDifference * outputDifference > 0) ||
std::max(std::abs(inputDifference), std::abs(outputDifference)) < threshold ||
delta == 0) {
tl.resetCycles();
continue;
}
if (std::abs(inputDifference) > std::abs(outputDifference)) {
if ((inputDifference > 0) && (redTime > delta)) {
tl.increaseGreenTimes(delta);
} else if ((inputDifference < 0) && (greenTime > delta)) {
tl.decreaseGreenTimes(delta);
auto const& neighbourDensity{densities.at(sourceId)};

Check warning on line 1859 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1859

Added line #L1859 was not covered by tests
if (neighbourDensity < 1.3 * density) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.1 rule Note

MISRA 12.1 rule
continue;

Check warning on line 1861 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1861

Added line #L1861 was not covered by tests
}
} else {
if ((outputDifference < 0) && (redTime > delta)) {
tl.increaseGreenTimes(delta);
} else if ((outputDifference > 0) && (greenTime > delta)) {
tl.decreaseGreenTimes(delta);
// Try to green-wave the situation
auto& tl{static_cast<TrafficLight&>(*(this->graph().node(sourceId)))};

Check warning on line 1864 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1864

Added line #L1864 was not covered by tests
auto const& pStreet{
this->graph().edge(sourceId * this->graph().nNodes() + nodeId)};
tl.increasePhases(pStreet->length() /
(pStreet->maxSpeed() * (1. - 0.6 * pStreet->density(true))));

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.1 rule Note

MISRA 12.1 rule
optimizedNodes.insert(sourceId);

Check warning on line 1869 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1866-L1869

Added lines #L1866 - L1869 were not covered by tests
if (logStream.has_value()) {
std::string logMsg =
std::format("\tNew cycles for TL {} ({}):\n", tl.id(), tl.cycleTime());

Check warning on line 1872 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1871-L1872

Added lines #L1871 - L1872 were not covered by tests
for (auto const& [streetId, pair] : tl.cycles()) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
auto const& pStreet{this->graph().edge(streetId)};
logMsg += std::format(
"\t\tStreet {} -> {}: ", pStreet->source(), pStreet->target());

Check warning on line 1876 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1874-L1876

Added lines #L1874 - L1876 were not covered by tests
for (auto const& [direction, cycle] : pair) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
logMsg += std::format("{}= ({} {}) ",

Check warning on line 1878 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1878

Added line #L1878 was not covered by tests
directionToString[direction],
cycle.greenTime(),
cycle.phase());

Check warning on line 1881 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1880-L1881

Added lines #L1880 - L1881 were not covered by tests
}
logMsg += '\n';

Check warning on line 1883 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1883

Added line #L1883 was not covered by tests
}
*logStream << logMsg << '\n';

Check warning on line 1885 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L1885

Added line #L1885 was not covered by tests
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/dsm/headers/RoadNetwork.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ namespace dsm {
/// - coilcode: An integer code to identify the coil located on the street
void importOSMEdges(const std::string& fileName);

Copy link

Copilot AI May 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a Doxygen comment describing importTrafficLights, its expected file format, and behavior on parsing errors.

Suggested change
/**
* @brief Import traffic light data from a file.
* @param fileName The path to the file containing traffic light data.
* @details The file format is csv-like with the ';' separator. Supported columns (in order):
* - id: The unique identifier of the traffic light
* - junctionId: The id of the junction where the traffic light is located
* - state: The initial state of the traffic light (e.g., "red", "green", "yellow")
* - timing: The timing configuration for the traffic light, in seconds
*
* Parsing errors, such as missing or malformed columns, will be logged as warnings,
* and the corresponding traffic light entry will be skipped.
*/

Copilot uses AI. Check for mistakes.
void importTrafficLights(const std::string& fileName);

/// @brief Export the graph's nodes to a csv-like file separated with ';'
/// @param path The path to the file to export the nodes to
/// @details The file format is csv-like, with the first line being the column names: id;lon;lat
Expand Down
2 changes: 2 additions & 0 deletions src/dsm/headers/TrafficLight.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ namespace dsm {
/// @brief Decrease the green times of the traffic light for priority streets and increase the green times for non-priority streets
/// @param delta Delay, the time to increase or decrease the green times
void decreaseGreenTimes(Delay const delta);

Copy link

Copilot AI May 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a brief Doxygen comment above increasePhases explaining its purpose and parameters to keep the public API documented.

Suggested change
/// @brief Increase the phase times of the traffic light cycles
/// @param phase Delay, the amount of time to increase the phase for each cycle

Copilot uses AI. Check for mistakes.
void increasePhases(Delay const phase);
/// @brief Get the traffic light's cycles
/// @return std::unordered_map<Id, std::unordered_map<Direction, TrafficLightCycle>> const& The traffic light's cycles
inline std::unordered_map<Id, std::unordered_map<Direction, TrafficLightCycle>> const&
Expand Down
72 changes: 70 additions & 2 deletions src/dsm/sources/RoadNetwork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
higherNLanes = std::max(higherNLanes, nLan);
lowerNLanes = std::min(lowerNLanes, nLan);
}
if (tl.streetPriorities().empty()) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
/*************************************************************
* 1. Check for street names with multiple occurrences
* ***********************************************************/
Expand Down Expand Up @@ -197,8 +197,30 @@
}
}
if (tl.streetPriorities().empty()) {
Logger::warning(std::format("Failed to auto-init Traffic Light {}", id));
continue;
/*************************************************************
* 3. Check for streets with opposite angles
* ***********************************************************/
auto const& streetId = streetAngles.begin()->first;
auto const& angle = streetAngles.begin()->second;

Check warning on line 204 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L203-L204

Added lines #L203 - L204 were not covered by tests
for (auto const& [streetId2, angle2] : streetAngles) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
if (std::abs(angle - angle2) > 0.75 * std::numbers::pi) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.1 rule Note

MISRA 12.1 rule
tl.addStreetPriority(streetId);
tl.addStreetPriority(streetId2);
break;

Check warning on line 209 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L207-L209

Added lines #L207 - L209 were not covered by tests
}
}
}
if (tl.streetPriorities().empty()) {
Logger::warning(
std::format("Failed to auto-init Traffic Light {} - going random", id));

Check warning on line 215 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L214-L215

Added lines #L214 - L215 were not covered by tests
// Assign first and third keys of capacity map
auto it = capacities.begin();
auto const& firstKey = it->first;
++it;
++it;
auto const& thirdKey = it->first;
tl.addStreetPriority(firstKey);
tl.addStreetPriority(thirdKey);

Check warning on line 223 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L217-L223

Added lines #L217 - L223 were not covered by tests
}

// Assign cycles
Expand Down Expand Up @@ -521,7 +543,7 @@
}
auto const& pNode{m_nodes.at(nodeId)};
pNode->setCapacity(value);
value = 0.;

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 18.4 rule Note

MISRA 18.4 rule
for (const auto& targetId : m_adjacencyMatrix.getRow(nodeId)) {
auto const streetId{nodeId * N + targetId};
auto const& pStreet{m_edges.at(streetId)};
Expand Down Expand Up @@ -926,6 +948,52 @@

Logger::info(std::format("Successfully imported {} edges", nEdges()));
}
void RoadNetwork::importTrafficLights(const std::string& fileName) {
std::ifstream file{fileName};

Check warning on line 952 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L951-L952

Added lines #L951 - L952 were not covered by tests
if (!file.is_open()) {
throw std::invalid_argument(
Logger::buildExceptionMessage("Cannot find file: " + fileName));

Check warning on line 955 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L955

Added line #L955 was not covered by tests
}
std::string line;
std::getline(file, line); // skip first line

Check warning on line 958 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L957-L958

Added lines #L957 - L958 were not covered by tests
while (!file.eof()) {
std::getline(file, line);

Check warning on line 960 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L960

Added line #L960 was not covered by tests
Copy link

Copilot AI May 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using while (!file.eof()) is error-prone; prefer while (std::getline(file, line)) to handle file input more robustly.

Suggested change
while (!file.eof()) {
std::getline(file, line);
while (std::getline(file, line)) {

Copilot uses AI. Check for mistakes.
if (line.empty()) {
continue;

Check warning on line 962 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L962

Added line #L962 was not covered by tests
}
std::unordered_map<Id, Delay> storedGreenTimes;

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
Copy link

Copilot AI May 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

storedGreenTimes is reinitialized on every loop iteration, preventing multi-line grouping; move its declaration outside the while to accumulate across all lines.

Suggested change
while (!file.eof()) {
std::getline(file, line);
if (line.empty()) {
continue;
}
std::unordered_map<Id, Delay> storedGreenTimes;
std::unordered_map<Id, Delay> storedGreenTimes;
while (!file.eof()) {
std::getline(file, line);
if (line.empty()) {
continue;
}

Copilot uses AI. Check for mistakes.
std::istringstream iss{line};
std::string strId, streetSource, strCycleTime, strGT;

Check warning on line 966 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L964-L966

Added lines #L964 - L966 were not covered by tests

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
// id;streetSource;streetTarget;cycleTime;greenTime
std::getline(iss, strId, ';');
std::getline(iss, streetSource, ';');
std::getline(iss, strCycleTime, ';');
std::getline(iss, strGT, '\n');

Check warning on line 971 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L968-L971

Added lines #L968 - L971 were not covered by tests

auto const cycleTime{static_cast<Delay>(std::stoul(strCycleTime))};

Check warning on line 973 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L973

Added line #L973 was not covered by tests
// Cast node(id) to traffic light
auto& pNode{m_nodes.at(m_nodeMapping.at(strId))};

Check warning on line 975 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L975

Added line #L975 was not covered by tests
if (!pNode->isTrafficLight()) {
pNode = std::make_unique<TrafficLight>(
pNode->id(), cycleTime, pNode->coords().value());

Check warning on line 978 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L977-L978

Added lines #L977 - L978 were not covered by tests
}
auto& tl = static_cast<TrafficLight&>(*pNode);
auto const srcId{m_nodeMapping.at(streetSource)};
auto const streetId{srcId * m_nodes.size() + pNode->id()};
auto const greenTime{static_cast<Delay>(std::stoul(strGT))};

Check warning on line 983 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L980-L983

Added lines #L980 - L983 were not covered by tests
if (!storedGreenTimes.contains(pNode->id())) {
storedGreenTimes.emplace(pNode->id(), greenTime);

Check warning on line 985 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L985

Added line #L985 was not covered by tests
}
auto const storedGT{storedGreenTimes.at(pNode->id())};

Check warning on line 987 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L987

Added line #L987 was not covered by tests
if (storedGT == greenTime) {
auto cycle = TrafficLightCycle(greenTime, 0);
tl.setCycle(streetId, dsm::Direction::ANY, cycle);

Check warning on line 990 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L989-L990

Added lines #L989 - L990 were not covered by tests
} else {
auto cycle = TrafficLightCycle(greenTime, storedGT);
tl.setCycle(streetId, dsm::Direction::ANY, cycle);

Check warning on line 993 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L992-L993

Added lines #L992 - L993 were not covered by tests
}
}
}

Check warning on line 996 in src/dsm/sources/RoadNetwork.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/RoadNetwork.cpp#L995-L996

Added lines #L995 - L996 were not covered by tests

void RoadNetwork::exportNodes(std::string const& path) {
// assert that path ends with ".csv"
Expand Down
23 changes: 19 additions & 4 deletions src/dsm/sources/TrafficLight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@

namespace dsm {
bool TrafficLightCycle::isGreen(Delay const cycleTime, Delay const counter) const {
auto const rest{(m_phase + m_greenTime) / cycleTime};
if (rest) {
return (counter < rest) || (counter >= m_phase);
auto const greenStart = m_phase % cycleTime;

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 10.6 rule Note

MISRA 10.6 rule
auto const greenEnd = (m_phase + m_greenTime) % cycleTime;

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 10.6 rule Note

MISRA 10.6 rule

if (greenStart < greenEnd) {
// Normal case: green does not wrap around
return (counter >= greenStart) && (counter < greenEnd);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 15.5 rule Note

MISRA 15.5 rule

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 10.4 rule Note

MISRA 10.4 rule
} else {
// Wraparound case: green spans cycle boundary
return (counter >= greenStart) || (counter < greenEnd);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 10.4 rule Note

MISRA 10.4 rule

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 15.5 rule Note

MISRA 15.5 rule
}
return (counter >= m_phase) && (counter < m_phase + m_greenTime);
}

bool TrafficLight::m_allowFreeTurns{true};
Expand Down Expand Up @@ -128,10 +133,20 @@
for (auto& [direction, cycle] : cycles) {
cycle = TrafficLightCycle(cycle.greenTime() - delta, cycle.phase() + delta);
}
}

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
}
}

void TrafficLight::increasePhases(Delay const phase) {

Check warning on line 140 in src/dsm/sources/TrafficLight.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/TrafficLight.cpp#L140

Added line #L140 was not covered by tests
for (auto& [streetId, cycles] : m_cycles) {
for (auto& [direction, cycle] : cycles) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
// Module new phase with cycleTime
auto newPhase{(phase + cycle.phase()) % m_cycleTime};
cycle = TrafficLightCycle(cycle.greenTime(), newPhase);

Check warning on line 145 in src/dsm/sources/TrafficLight.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/TrafficLight.cpp#L144-L145

Added lines #L144 - L145 were not covered by tests
}
}
}

Check warning on line 148 in src/dsm/sources/TrafficLight.cpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/sources/TrafficLight.cpp#L148

Added line #L148 was not covered by tests

void TrafficLight::decreaseGreenTimes(Delay const delta) {
for (auto& [streetId, cycles] : m_cycles) {
if (!m_streetPriorities.contains(streetId)) {
Expand Down
Loading