Skip to content

Commit 4265ed7

Browse files
authored
Merge pull request #39 from popmonkey/v2.2
* standard solver + diagnostic solver are now merged as an elastic solver that can do both * fixed (re-added because it was lost between v1 and v2) full minimum rest enforcement
2 parents b23613f + 0a87b60 commit 4265ed7

19 files changed

Lines changed: 925 additions & 573 deletions

CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,6 @@ add_library(jres_solver_lib
161161
src/jres_internal_types.cpp
162162
src/jres_solver_base.cpp
163163
src/jres_standard_solver.cpp
164-
src/jres_diagnostic_solver.cpp
165164
)
166165
set_target_properties(jres_solver_lib PROPERTIES OUTPUT_NAME "jres_solver")
167166

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ The C-API uses the following structs to pass data to and from the solver.
3939
| `isDriver` | `int` | `1` if the member can drive, `0` otherwise. |
4040
| `isSpotter` | `int` | `1` if the member can spot, `0` otherwise. |
4141
| `maxStints`| `int` | Hard constraint: Maximum number of consecutive stints a member can perform. |
42-
| `minimumRestHours` | `int` | Hard constraint: Minimum rest time required after a driving shift before driving again. |
42+
| `minimumRestHours` | `int` | Hard constraint: Minimum contiguous rest time required once per race. <br> **Integrated Mode:** Applies to combined Driving and Spotting time. <br> **Sequential Mode:** Applies only to Driving. |
4343
| `tzOffset` | `double` | Timezone offset in hours from UTC. |
4444

4545
`JresStint`
@@ -180,7 +180,7 @@ The `raceDataJson` string passed to `jres_input_from_json` must strictly follow
180180
| `isDriver` | Boolean | `true` | Can this member drive? |
181181
| `isSpotter` | Boolean | `false` | Can this member spot? |
182182
| `maxStints` | Integer| `1` | Hard constraint: Maximum number of consecutive stints a member can perform. |
183-
| `minimumRestHours` | Integer| `0` | Hard constraint: Minimum rest time required after a driving shift before driving again. |
183+
| `minimumRestHours` | Integer| `0` | Hard constraint: Minimum contiguous rest time required once per race. <br> **Integrated Mode:** Applies to combined Driving and Spotting time. <br> **Sequential Mode:** Applies only to Driving. |
184184
| `tzOffset` | Number | `0.0` | Timezone offset in hours from UTC. |
185185
186186
#### Availability Map & Time Formatting

cmd/solver/cli.cpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,24 @@ int main(int argc, char **argv)
135135
return 1;
136136
}
137137

138+
if (!quiet && solverOutput->stats) {
139+
std::cout << "\n--- Complexity ---" << std::endl;
140+
std::cout << "Rows: " << solverOutput->stats->modelRows << " | "
141+
<< "Cols: " << solverOutput->stats->modelColumns << " | "
142+
<< "Nodes: " << solverOutput->stats->searchNodes << std::endl;
143+
if (solverOutput->stats->finalGap > 0) {
144+
std::cout << "Final Gap: " << solverOutput->stats->finalGap << std::endl;
145+
}
146+
147+
std::cout << "\n--- Timing Performance ---" << std::endl;
148+
std::cout << std::fixed << std::setprecision(2);
149+
std::cout << "Setup/Model Build : " << std::setw(8) << solverOutput->stats->setupDurationMs << " ms" << std::endl;
150+
std::cout << "Driver Solve : " << std::setw(8) << solverOutput->stats->driverSolveDurationMs << " ms" << std::endl;
151+
if (solverOutput->stats->spotterSolveDurationMs > 0) {
152+
std::cout << "Spotter Solve : " << std::setw(8) << solverOutput->stats->spotterSolveDurationMs << " ms" << std::endl;
153+
}
154+
}
155+
138156
if (solverOutput->diagnosis_len > 0) {
139157
if (runDiagnostics) {
140158
if (!quiet) {
@@ -150,23 +168,6 @@ int main(int argc, char **argv)
150168
}
151169
}
152170
} else if (!quiet) {
153-
if (solverOutput->stats) {
154-
std::cout << "\n--- Complexity ---" << std::endl;
155-
std::cout << "Rows: " << solverOutput->stats->modelRows << " | "
156-
<< "Cols: " << solverOutput->stats->modelColumns << " | "
157-
<< "Nodes: " << solverOutput->stats->searchNodes << std::endl;
158-
if (solverOutput->stats->finalGap > 0) {
159-
std::cout << "Final Gap: " << solverOutput->stats->finalGap << std::endl;
160-
}
161-
162-
std::cout << "\n--- Timing Performance ---" << std::endl;
163-
std::cout << std::fixed << std::setprecision(2);
164-
std::cout << "Setup/Model Build : " << std::setw(8) << solverOutput->stats->setupDurationMs << " ms" << std::endl;
165-
std::cout << "Driver Solve : " << std::setw(8) << solverOutput->stats->driverSolveDurationMs << " ms" << std::endl;
166-
if (solverOutput->stats->spotterSolveDurationMs > 0) {
167-
std::cout << "Spotter Solve : " << std::setw(8) << solverOutput->stats->spotterSolveDurationMs << " ms" << std::endl;
168-
}
169-
}
170171
// Print the schedule
171172
std::cout << "\n--- Race Schedule ---" << std::endl;
172173
bool hasSpotters = (solverOptions.spotterMode != JRES_SPOTTER_MODE_NONE);

data/24h_race.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,47 +7,47 @@
77
"isSpotter": true,
88
"tzOffset": 1,
99
"maxStints": 1,
10-
"minimumRestHours": 8
10+
"minimumRestHours": 6
1111
},
1212
{
1313
"name": "Ayrton",
1414
"isDriver": true,
1515
"isSpotter": false,
1616
"tzOffset": -3,
1717
"maxStints": 2,
18-
"minimumRestHours": 8
18+
"minimumRestHours": 6
1919
},
2020
{
2121
"name": "Jack",
2222
"isDriver": true,
2323
"isSpotter": true,
2424
"tzOffset": 11,
2525
"maxStints": 3,
26-
"minimumRestHours": 8
26+
"minimumRestHours": 6
2727
},
2828
{
2929
"name": "James",
3030
"isDriver": true,
3131
"isSpotter": true,
3232
"tzOffset": 0,
3333
"maxStints": 2,
34-
"minimumRestHours": 8
34+
"minimumRestHours": 6
3535
},
3636
{
3737
"name": "Mario",
3838
"isDriver": true,
3939
"isSpotter": true,
4040
"tzOffset": -5,
4141
"maxStints": 1,
42-
"minimumRestHours": 8
42+
"minimumRestHours": 6
4343
},
4444
{
4545
"name": "Ricky",
4646
"isDriver": false,
4747
"isSpotter": true,
4848
"tzOffset": -6,
4949
"maxStints": 2,
50-
"minimumRestHours": 8
50+
"minimumRestHours": 6
5151
}
5252
],
5353
"availability": {
@@ -368,4 +368,4 @@
368368
}
369369
],
370370
"firstStintDriver": "James"
371-
}
371+
}

data/short_race.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,23 @@
77
"isDriver": true,
88
"isSpotter": true,
99
"preferredStints": 2,
10-
"minimumRestHours": 8
10+
"minimumRestHours": 0
1111
},
1212
{
1313
"name": "Ayrton",
1414
"tzOffset": -3,
1515
"isDriver": true,
1616
"isSpotter": true,
1717
"preferredStints": 2,
18-
"minimumRestHours": 8
18+
"minimumRestHours": 0
1919
},
2020
{
2121
"name": "Alain",
2222
"tzOffset": 1,
2323
"isDriver": false,
2424
"isSpotter": true,
2525
"preferredStints": 2,
26-
"minimumRestHours": 8
26+
"minimumRestHours": 0
2727
}
2828
],
2929
"availability": {

src/formatter/formatter_core.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,13 +287,19 @@ std::string generate_full_text_report(
287287
for (const auto& [name, itinerary] : itineraries) {
288288
if (itinerary.items.empty()) continue;
289289

290+
size_t max_activity_width = 0;
291+
for (const auto& item : itinerary.items) {
292+
max_activity_width = std::max(max_activity_width, item.activity.length());
293+
}
294+
290295
std::string tz_string = std::string("UTC") + (itinerary.tz_offset >= 0 ? "+" : "") + std::to_string(itinerary.tz_offset);
291296
f << "\nSchedule for " << name << " (" << tz_string << "):\n";
292297

293298
for (const auto& item : itinerary.items) {
294299
double dur = item.end_local.diff_seconds(item.start_local);
295300
f << " " << item.start_local.to_string() << " to " << item.end_local.time_string()
296-
<< " (" << DateTime::format_duration((long long)dur) << "): " << item.activity << "\n";
301+
<< " " << std::left << std::setw(max_activity_width) << item.activity
302+
<< " (" << DateTime::format_duration((long long)dur) << ")\n";
297303
}
298304
}
299305
return f.str();

0 commit comments

Comments
 (0)