From c966d048b636f01dc31813091a8cb3b44940cbd3 Mon Sep 17 00:00:00 2001 From: xp986 <> Date: Wed, 8 Oct 2025 23:44:36 -0500 Subject: [PATCH] Initial commit with working version. --- ReportTruncate_0.1.cpp | 148 +++++++++++++++++++++++++++++++++ ReportTruncate_0.2.cpp | 143 ++++++++++++++++++++++++++++++++ ReportTruncate_0.3.cpp | 157 +++++++++++++++++++++++++++++++++++ ReportTruncate_0.4.cpp | 159 ++++++++++++++++++++++++++++++++++++ ReportTruncate_0.5.cpp | 163 +++++++++++++++++++++++++++++++++++++ ReportTruncate_0.6.cpp | 181 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 951 insertions(+) create mode 100644 ReportTruncate_0.1.cpp create mode 100644 ReportTruncate_0.2.cpp create mode 100644 ReportTruncate_0.3.cpp create mode 100644 ReportTruncate_0.4.cpp create mode 100644 ReportTruncate_0.5.cpp create mode 100644 ReportTruncate_0.6.cpp diff --git a/ReportTruncate_0.1.cpp b/ReportTruncate_0.1.cpp new file mode 100644 index 0000000..92606b5 --- /dev/null +++ b/ReportTruncate_0.1.cpp @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include +#include + +static const std::regex number_regex_full(R"(\d+)"); +static const std::regex number_regex_1to3(R"(\b\d{1,3}\b)"); + +// Helper: find first number in 's', put into out, return true if found +bool find_first_number_in_line(const std::string &s, int &out, const std::regex &rx) { + std::smatch m; + if (std::regex_search(s, m, rx)) { + out = std::stoi(m.str()); + return true; + } + return false; +} + +int main(int argc, char* argv[]) { + if (argc < 3) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + + std::ifstream infile(argv[1]); + if (!infile) { + std::cerr << "Error opening input file.\n"; + return 1; + } + + std::ofstream outfile(argv[2]); + if (!outfile) { + std::cerr << "Error opening output file.\n"; + return 1; + } + + // Read entire file into memory + std::vector lines; + std::string line; + while (std::getline(infile, line)) { + lines.push_back(line); + } + + const std::string marker = "F.L.C.M. %"; + + // === 1) Find marker index (for truncation) === + bool marker_found = false; + size_t marker_index = 0; + for (size_t i = 0; i < lines.size(); ++i) { + if (lines[i].find(marker) != std::string::npos) { + marker_found = true; + marker_index = i; + break; + } + } + + if (!marker_found) { + for (const auto &l : lines) outfile << l << '\n'; + return 0; + } + + // === 2) Extract gyros (first number on SAME line as "BBGYRO") === + int gyros = 0; + bool gyros_found = false; + size_t bbgyro_index = std::string::npos; + const std::string bbgyro_token = "BBGYRO"; + + for (size_t i = 0; i < lines.size(); ++i) { + size_t pos = lines[i].find(bbgyro_token); + if (pos != std::string::npos) { + bbgyro_index = i; + std::string tail = lines[i].substr(pos + bbgyro_token.size()); + if (find_first_number_in_line(tail, gyros, number_regex_full)) { + gyros_found = true; + } + break; // only first occurrence matters + } + } + + // === 3) Extract total_subs (1–3 digit number after 'Ä' line) === + int total_subs = 0; + bool total_found = false; + + auto find_total_after_start_index = [&](size_t start_index)->bool { + for (size_t j = start_index; j < lines.size(); ++j) { + size_t countA = 0; + for (u_char c : lines[j]) if (c == u'Ä') ++countA; + if (countA >= 10) { + // look in the next line and up to 3 lines after if needed + for (size_t k = j + 1; k < lines.size(); ++k) { + if (find_first_number_in_line(lines[k], total_subs, number_regex_1to3)) { + return true; + } + } + return false; + } + } + return false; + }; + + if (gyros_found) { + total_found = find_total_after_start_index(bbgyro_index + 1); + } else { + // BBGYRO not found -> find 2nd occurrence of "SUBS" then start from there + int subs_count = 0; + size_t subs_index = std::string::npos; + for (size_t i = 0; i < lines.size(); ++i) { + if (lines[i].find("SUBS") != std::string::npos) { + subs_count++; + if (subs_count == 2) { + subs_index = i; + break; + } + } + } + if (subs_index != std::string::npos) { + total_found = find_total_after_start_index(subs_index + 1); + } + } + + // === 4) Truncate to include up to and including the marker line === + std::vector truncated(lines.begin(), lines.begin() + marker_index + 1); + + // === 5) Insert "TOTAL SUBS --- " immediately before first form feed === + int diff = total_subs - gyros; + const std::string insert_line = "\n\n TOTAL SUBS --- " + std::to_string(diff); + + bool inserted = false; + for (const auto &l : truncated) { + size_t ff_pos = l.find('\f'); + if (!inserted && ff_pos != std::string::npos) { + // insert directly before first form feed + std::string modified = l.substr(0, ff_pos) + insert_line + l.substr(ff_pos); + outfile << modified << '\n'; + inserted = true; + } else { + outfile << l << '\n'; + } + } + if (!inserted) { + outfile << insert_line << '\n'; + } + + return 0; +} + diff --git a/ReportTruncate_0.2.cpp b/ReportTruncate_0.2.cpp new file mode 100644 index 0000000..892472e --- /dev/null +++ b/ReportTruncate_0.2.cpp @@ -0,0 +1,143 @@ +#include +#include +#include +#include +#include +#include + +static const std::regex number_regex_full(R"(\d+)"); +static const std::regex number_regex_1to3(R"(\b\d{1,3}\b)"); +static const std::regex exact_24_A(R"((? \n"; + return 1; + } + + std::ifstream infile(argv[1]); + if (!infile) { + std::cerr << "Error opening input file.\n"; + return 1; + } + + std::ofstream outfile(argv[2]); + if (!outfile) { + std::cerr << "Error opening output file.\n"; + return 1; + } + + std::vector lines; + std::string line; + while (std::getline(infile, line)) { + lines.push_back(line); + } + + const std::string marker = "F.L.C.M. %"; + + // === 1) Find marker index === + bool marker_found = false; + size_t marker_index = 0; + for (size_t i = 0; i < lines.size(); ++i) { + if (lines[i].find(marker) != std::string::npos) { + marker_found = true; + marker_index = i; + break; + } + } + + if (!marker_found) { + for (const auto &l : lines) outfile << l << '\n'; + return 0; + } + + // === 2) Extract gyros from "BBGYRO" line === + int gyros = 0; + bool gyros_found = false; + size_t bbgyro_index = std::string::npos; + const std::string bbgyro_token = "BBGYRO"; + + for (size_t i = 0; i < lines.size(); ++i) { + size_t pos = lines[i].find(bbgyro_token); + if (pos != std::string::npos) { + bbgyro_index = i; + std::string tail = lines[i].substr(pos + bbgyro_token.size()); + if (find_first_number_in_line(tail, gyros, number_regex_full)) { + gyros_found = true; + } + break; + } + } + + // === 3) Extract total_subs === + int total_subs = 0; + bool total_found = false; + + auto find_total_after_start_index = [&](size_t start_index)->bool { + for (size_t j = start_index; j < lines.size(); ++j) { + if (std::regex_search(lines[j], exact_24_A)) { + if (j + 1 < lines.size()) { + if (find_first_number_in_line(lines[j + 1], total_subs, number_regex_1to3)) { + return true; + } + } + } + } + return false; + }; + + if (gyros_found) { + total_found = find_total_after_start_index(bbgyro_index + 1); + } else { + // Fallback: second "SUBS" + int subs_count = 0; + size_t subs_index = std::string::npos; + for (size_t i = 0; i < lines.size(); ++i) { + if (lines[i].find("SUBS") != std::string::npos) { + subs_count++; + if (subs_count == 2) { + subs_index = i; + break; + } + } + } + if (subs_index != std::string::npos) { + total_found = find_total_after_start_index(subs_index + 1); + } + } + + // === 4) Truncate document after the marker === + std::vector truncated(lines.begin(), lines.begin() + marker_index + 1); + + // === 5) Insert TOTAL SUBS --- diff before first form feed === + int diff = total_subs - gyros; + const std::string insert_line = "\n\n TOTAL SUBS --- " + std::to_string(diff); + + bool inserted = false; + for (const auto &l : truncated) { + size_t ff_pos = l.find('\f'); + if (!inserted && ff_pos != std::string::npos) { + std::string modified = l.substr(0, ff_pos) + insert_line + l.substr(ff_pos); + outfile << modified << '\n'; + inserted = true; + } else { + outfile << l << '\n'; + } + } + + if (!inserted) { + outfile << insert_line << '\n'; + } + + return 0; +} + diff --git a/ReportTruncate_0.3.cpp b/ReportTruncate_0.3.cpp new file mode 100644 index 0000000..dead32a --- /dev/null +++ b/ReportTruncate_0.3.cpp @@ -0,0 +1,157 @@ +#include +#include +#include +#include +#include +#include +#include + +static const std::regex number_regex_full(R"(\d+)"); +static const std::regex number_regex_1to3(R"(\b\d{1,3}\b)"); + +// Find the first number in a line using the given regex +bool find_first_number_in_line(const std::string &s, int &out, const std::regex &rx) { + std::smatch m; + if (std::regex_search(s, m, rx)) { + out = std::stoi(m.str()); + return true; + } + return false; +} + +// Check if a line contains exactly 24 consecutive 'Ä' +bool has_exactly_24_A(const std::string &s) { + int count = 0; + for (size_t i = 0; i <= s.size(); ++i) { + if (i < s.size() && s[i] == (char)196) { + count++; + } else { + if (count == 24) return true; // exact match found + count = 0; // reset counter + } + } + return false; +} + +int main(int argc, char* argv[]) { + if (argc < 3) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + + std::ifstream infile(argv[1]); + if (!infile) { + std::cerr << "Error opening input file.\n"; + return 1; + } + + std::ofstream outfile(argv[2]); + if (!outfile) { + std::cerr << "Error opening output file.\n"; + return 1; + } + + std::vector lines; + std::string line; + while (std::getline(infile, line)) { + lines.push_back(line); + } + + const std::string marker = "F.L.C.M. %"; + + // === 1) Find marker index === + bool marker_found = false; + size_t marker_index = 0; + for (size_t i = 0; i < lines.size(); ++i) { + if (lines[i].find(marker) != std::string::npos) { + marker_found = true; + marker_index = i; + break; + } + } + + if (!marker_found) { + for (const auto &l : lines) outfile << l << '\n'; + return 0; + } + + // === 2) Extract gyros from "BBGYRO" line === + int gyros = 0; + bool gyros_found = false; + size_t bbgyro_index = std::string::npos; + const std::string bbgyro_token = "BBGYRO"; + + for (size_t i = 0; i < lines.size(); ++i) { + size_t pos = lines[i].find(bbgyro_token); + if (pos != std::string::npos) { + bbgyro_index = i; + std::string tail = lines[i].substr(pos + bbgyro_token.size()); + if (find_first_number_in_line(tail, gyros, number_regex_full)) { + gyros_found = true; + } + break; + } + } + + // === 3) Extract total_subs === + int total_subs = 0; + bool total_found = false; + + auto find_total_after_start_index = [&](size_t start_index) -> bool { + for (size_t j = start_index; j < lines.size(); ++j) { + if (has_exactly_24_A(lines[j])) { + if (j + 1 < lines.size()) { + if (find_first_number_in_line(lines[j + 1], total_subs, number_regex_1to3)) { + return true; + } + } + } + } + return false; + }; + + if (gyros_found) { + total_found = find_total_after_start_index(bbgyro_index + 1); + } else { + // Fallback: second "SUBS" + int subs_count = 0; + size_t subs_index = std::string::npos; + for (size_t i = 0; i < lines.size(); ++i) { + if (lines[i].find("SUBS") != std::string::npos) { + subs_count++; + if (subs_count == 2) { + subs_index = i; + break; + } + } + } + if (subs_index != std::string::npos) { + total_found = find_total_after_start_index(subs_index + 1); + } + } + + // === 4) Truncate document after the marker === + std::vector truncated(lines.begin(), lines.begin() + marker_index + 1); + + // === 5) Insert TOTAL SUBS --- diff before first form feed === + int diff = total_subs - gyros; + const std::string insert_line = "\n\n TOTAL ROLLS (Total - Gyros) --- " + std::to_string(diff); + + bool inserted = false; + for (const auto &l : truncated) { + size_t ff_pos = l.find('\f'); + if (!inserted && ff_pos != std::string::npos) { + std::string modified = l.substr(0, ff_pos) + insert_line + l.substr(ff_pos); + outfile << modified << '\n'; + inserted = true; + } else { + outfile << l << '\n'; + } + } + + if (!inserted) { + outfile << insert_line << '\n'; + } + + return 0; +} diff --git a/ReportTruncate_0.4.cpp b/ReportTruncate_0.4.cpp new file mode 100644 index 0000000..03e9ecf --- /dev/null +++ b/ReportTruncate_0.4.cpp @@ -0,0 +1,159 @@ +#include +#include +#include +#include +#include +#include + +static const std::regex number_regex_full(R"(\d+)"); +static const std::regex number_regex_1to3(R"(\b\d{1,3}\b)"); + +// Find the first number in a line using the given regex +bool find_first_number_in_line(const std::string &s, int &out, const std::regex &rx) { + std::smatch m; + if (std::regex_search(s, m, rx)) { + out = std::stoi(m.str()); + return true; + } + return false; +} + +// Check if a line contains exactly 24 consecutive 'Ä' +bool has_exactly_24_A(const std::string &s) { + int count = 0; + for (size_t i = 0; i <= s.size(); ++i) { + if (i < s.size() && s[i] == (char)196) { + count++; + } else { + if (count == 24) return true; // exact match found + count = 0; // reset counter + } + } + return false; +} + +int main(int argc, char* argv[]) { + if (argc < 3) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + + std::ifstream infile(argv[1]); + if (!infile) { + std::cerr << "Error opening input file.\n"; + return 1; + } + + std::ofstream outfile(argv[2]); + if (!outfile) { + std::cerr << "Error opening output file.\n"; + return 1; + } + + std::vector lines; + std::string line; + while (std::getline(infile, line)) { + lines.push_back(line); + } + + const std::string marker = "F.L.C.M. %"; + + // === 1) Find marker index === + bool marker_found = false; + size_t marker_index = 0; + for (size_t i = 0; i < lines.size(); ++i) { + if (lines[i].find(marker) != std::string::npos) { + marker_found = true; + marker_index = i; + break; + } + } + + if (!marker_found) { + for (const auto &l : lines) outfile << l << '\n'; + return 0; + } + + // === 2) Extract gyros from "BBGYRO" line === + int gyros = 0; + bool gyros_found = false; + size_t bbgyro_index = std::string::npos; + const std::string bbgyro_token = "BBGYRO"; + + for (size_t i = 0; i < lines.size(); ++i) { + size_t pos = lines[i].find(bbgyro_token); + if (pos != std::string::npos) { + bbgyro_index = i; + std::string tail = lines[i].substr(pos + bbgyro_token.size()); + if (find_first_number_in_line(tail, gyros, number_regex_full)) { + gyros_found = true; + } + break; + } + } + + // === 3) Extract total_subs === + int total_subs = 0; + + auto find_total_after_start_index = [&](size_t start_index) -> bool { + for (size_t j = start_index; j < lines.size(); ++j) { + if (has_exactly_24_A(lines[j])) { + if (j + 1 < lines.size()) { + if (find_first_number_in_line(lines[j + 1], total_subs, number_regex_1to3)) { + return true; + } + } + } + } + return false; + }; + + if (gyros_found) { + find_total_after_start_index(bbgyro_index + 1); + } else { + // Fallback: second "SUBS" + int subs_count = 0; + size_t subs_index = std::string::npos; + for (size_t i = 0; i < lines.size(); ++i) { + if (lines[i].find("SUBS") != std::string::npos) { + subs_count++; + if (subs_count == 2) { + subs_index = i; + break; + } + } + } + if (subs_index != std::string::npos) { + find_total_after_start_index(subs_index + 1); + } + } + + // === 4) Truncate document after the marker === + std::vector truncated(lines.begin(), lines.begin() + marker_index + 1); + + // === 5) Insert TOTAL SUBS --- diff before first form feed === + int diff = total_subs - gyros; + const std::string insert_line = "\n\n ROLLS USED --- " + std::to_string(diff); + + bool inserted = false; + for (const auto &l : truncated) { + size_t ff_pos = l.find('\f'); + if (!inserted && ff_pos != std::string::npos) { + std::string modified = l.substr(0, ff_pos) + insert_line + l.substr(ff_pos); + outfile << modified << '\n'; + inserted = true; + } else { + outfile << l << '\n'; + } + } + + if (!inserted) { + outfile << insert_line << '\n'; + } + + // === 6) Append a form feed to the very end of the truncated document === + outfile << '\f'; + + return 0; +} + diff --git a/ReportTruncate_0.5.cpp b/ReportTruncate_0.5.cpp new file mode 100644 index 0000000..2184046 --- /dev/null +++ b/ReportTruncate_0.5.cpp @@ -0,0 +1,163 @@ +#include +#include +#include +#include +#include +#include + +static const std::regex number_regex_full(R"(\d+)"); +static const std::regex number_regex_1to3(R"(\b\d{1,3}\b)"); + +// Find the first number in a line using the given regex +bool find_first_number_in_line(const std::string &s, int &out, const std::regex &rx) { + std::smatch m; + if (std::regex_search(s, m, rx)) { + out = std::stoi(m.str()); + return true; + } + return false; +} + +// Check if a line contains exactly 24 consecutive 'Ä' +bool has_exactly_24_A(const std::string &s) { + int count = 0; + for (size_t i = 0; i <= s.size(); ++i) { + if (i < s.size() && s[i] == (char)196) { + count++; + } else { + if (count == 24) return true; // exact match found + count = 0; // reset counter + } + } + return false; +} + +int main(int argc, char* argv[]) { + if (argc < 3) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + + std::ifstream infile(argv[1]); + if (!infile) { + std::cerr << "Error opening input file.\n"; + return 1; + } + + std::ofstream outfile(argv[2]); + if (!outfile) { + std::cerr << "Error opening output file.\n"; + return 1; + } + + std::vector lines; + std::string line; + while (std::getline(infile, line)) { + lines.push_back(line); + } + + const std::string marker = "F.L.C.M. %"; + + // === 1) Find marker index === + bool marker_found = false; + size_t marker_index = 0; + for (size_t i = 0; i < lines.size(); ++i) { + if (lines[i].find(marker) != std::string::npos) { + marker_found = true; + marker_index = i; + break; + } + } + + if (!marker_found) { + for (const auto &l : lines) outfile << l << '\n'; + return 0; + } + + // === 2) Extract gyros from "BBGYRO" line === + int gyros = 0; + bool gyros_found = false; + size_t bbgyro_index = std::string::npos; + const std::string bbgyro_token = "BBGYRO"; + + for (size_t i = 0; i < lines.size(); ++i) { + size_t pos = lines[i].find(bbgyro_token); + if (pos != std::string::npos) { + bbgyro_index = i; + std::string tail = lines[i].substr(pos + bbgyro_token.size()); + if (find_first_number_in_line(tail, gyros, number_regex_full)) { + gyros_found = true; + } + break; + } + } + + // === 3) Extract total_subs === + int total_subs = 0; + + auto find_total_after_start_index = [&](size_t start_index) -> bool { + for (size_t j = start_index; j < lines.size(); ++j) { + if (has_exactly_24_A(lines[j])) { + if (j + 1 < lines.size()) { + if (find_first_number_in_line(lines[j + 1], total_subs, number_regex_1to3)) { + return true; + } + } + } + } + return false; + }; + + if (gyros_found) { + find_total_after_start_index(bbgyro_index + 1); + } else { + // Fallback: second "SUBS" + int subs_count = 0; + size_t subs_index = std::string::npos; + for (size_t i = 0; i < lines.size(); ++i) { + if (lines[i].find("SUBS") != std::string::npos) { + subs_count++; + if (subs_count == 2) { + subs_index = i; + break; + } + } + } + if (subs_index != std::string::npos) { + find_total_after_start_index(subs_index + 1); + } + } + + // === 4) Truncate document after the marker === + std::vector truncated(lines.begin(), lines.begin() + marker_index + 1); + + // === 5) Insert TOTAL SUBS --- diff before first form feed === + int diff = total_subs - gyros; + const std::string insert_line = "\n\n ROLLS USED --- " + std::to_string(diff); + + bool inserted = false; + for (const auto &l : truncated) { + size_t ff_pos = l.find('\f'); + if (!inserted && ff_pos != std::string::npos) { + std::string modified = l.substr(0, ff_pos) + insert_line + l.substr(ff_pos); + outfile << modified << '\n'; + inserted = true; + } else { + outfile << l << '\n'; + } + } + + /* + if (!inserted) { + outfile << insert_line << '\n'; + } + */ + + if (inserted) { + // === 6) Append a form feed to the very end of the truncated document === + outfile << '\f'; + } + + return 0; +} + diff --git a/ReportTruncate_0.6.cpp b/ReportTruncate_0.6.cpp new file mode 100644 index 0000000..80231f8 --- /dev/null +++ b/ReportTruncate_0.6.cpp @@ -0,0 +1,181 @@ +#include +#include +#include +#include +#include +#include + +static const std::regex number_regex_full(R"(\d+)"); +static const std::regex number_regex_1to3(R"(\b\d{1,3}\b)"); + +// Find the first number in a line using the given regex +bool find_first_number_in_line(const std::string& s, int& out, const std::regex& rx) { + std::smatch m; + if (std::regex_search(s, m, rx)) { + out = std::stoi(m.str()); + return true; + } + return false; +} + +// Check if a line contains exactly 24 consecutive 'Ä' +bool has_exactly_24_A(const std::string& s) { + int count = 0; + for (size_t i = 0; i <= s.size(); ++i) { + if (i < s.size() && s[i] == (char)196) { + count++; + } + else { + if (count == 24) return true; // exact match found + count = 0; // reset counter + } + } + return false; +} + +int main(int argc, char* argv[]) { + if (argc < 3) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + + // Read entire file into memory as lines + std::ifstream infile(argv[1], std::ios::binary); + if (!infile) { + std::cerr << "Error opening input file.\n"; + return 1; + } + + std::ofstream outfile(argv[2], std::ios::binary); + if (!outfile) { + std::cerr << "Error opening output file.\n"; + return 1; + } + + std::vector lines; + std::string line; + while (std::getline(infile, line)) { + if (!infile.eof()) line += '\n'; // preserve original line endings + lines.push_back(line); + } + + // Detect if document should be modified + bool has_bbgyro = false; + bool has_subs = false; + for (const auto& l : lines) { + if (!has_bbgyro && l.find("BBGYRO") != std::string::npos) has_bbgyro = true; + if (!has_subs && l.find("SUBS") != std::string::npos) has_subs = true; + if (has_bbgyro || has_subs) break; + } + + // If neither BBGYRO nor SUBS appears, pass file through unmodified + if (!has_bbgyro && !has_subs) { + infile.clear(); + infile.seekg(0, std::ios::beg); + outfile << infile.rdbuf(); // exact byte-for-byte copy + return 0; + } + + const std::string marker = "F.L.C.M. %"; + + // === 1) Find marker index === + bool marker_found = false; + size_t marker_index = 0; + for (size_t i = 0; i < lines.size(); ++i) { + if (lines[i].find(marker) != std::string::npos) { + marker_found = true; + marker_index = i; + break; + } + } + + if (!marker_found) { + // Marker not found, write original file unchanged + infile.clear(); + infile.seekg(0, std::ios::beg); + outfile << infile.rdbuf(); + return 0; + } + + // === 2) Extract gyros from "BBGYRO" line === + int gyros = 0; + bool gyros_found = false; + size_t bbgyro_index = std::string::npos; + const std::string bbgyro_token = "BBGYRO"; + + for (size_t i = 0; i < lines.size(); ++i) { + size_t pos = lines[i].find(bbgyro_token); + if (pos != std::string::npos) { + bbgyro_index = i; + std::string tail = lines[i].substr(pos + bbgyro_token.size()); + if (find_first_number_in_line(tail, gyros, number_regex_full)) { + gyros_found = true; + } + break; + } + } + + // === 3) Extract total_subs === + int total_subs = 0; + + auto find_total_after_start_index = [&](size_t start_index) -> bool { + for (size_t j = start_index; j < lines.size(); ++j) { + if (has_exactly_24_A(lines[j])) { + if (j + 1 < lines.size()) { + if (find_first_number_in_line(lines[j + 1], total_subs, number_regex_1to3)) { + return true; + } + } + } + } + return false; + }; + + if (gyros_found) { + find_total_after_start_index(bbgyro_index + 1); + } + else { + // Fallback: second "SUBS" + int subs_count = 0; + size_t subs_index = std::string::npos; + for (size_t i = 0; i < lines.size(); ++i) { + if (lines[i].find("SUBS") != std::string::npos) { + subs_count++; + if (subs_count == 2) { + subs_index = i; + break; + } + } + } + if (subs_index != std::string::npos) { + find_total_after_start_index(subs_index + 1); + } + } + + // === 4) Truncate document after the marker === + std::vector truncated(lines.begin(), lines.begin() + marker_index + 1); + + // === 5) Insert TOTAL SUBS --- diff before first form feed === + int diff = total_subs - gyros; + const std::string insert_line = "\n\n\r ROLLS USED --- " + std::to_string(diff); + + bool inserted = false; + for (const auto& l : truncated) { + size_t ff_pos = l.find('\f'); + if (!inserted && ff_pos != std::string::npos) { + std::string modified = l.substr(0, ff_pos) + insert_line + l.substr(ff_pos); + outfile << modified; + inserted = true; + } + else { + outfile << l; + } + } + + if (inserted) { + // === 6) Append a form feed to the very end of the truncated document === + outfile << '\f'; + } + + return 0; +}