Commit 4e649084 authored by Kučera Petr RNDr. Ph.D.'s avatar Kučera Petr RNDr. Ph.D.
Browse files

Output files handling

parent a58680e5
......@@ -27,35 +27,78 @@
#include "train_route.h"
#include "trapts_parser.h"
namespace Loco
{
std::ofstream log_file;
template <class Parser, class Printer>
void process_file(const std::string &fname, Loco::InputData &input_data,
Printer p);
InputData read_input();
void init_log_file();
template <class Printer>
void print_to_file(const std::optional<std::filesystem::path> &fname,
Printer p);
void print_physical_graph(const InputData &input_data);
SectionGraphCPtr init_section_graph(const InputData &input_data);
void debug_print_subgraphs(const InputData &input_data,
const SectionGraphCPtr &sg);
} // namespace Loco
template <class Parser, class Printer>
void
process_file(const std::string &fname, Loco::InputData &input_data, Printer p)
Loco::process_file(const std::string &fname, Loco::InputData &input_data,
Printer p)
{
Parser parser;
parser.ParseFile(fname, input_data);
std::cout << "\nFile: " << fname << std::endl;
p(std::cout, "");
if (Loco::check_verbosity(4))
{
std::clog << "\nFile: " << fname << std::endl;
p(std::clog, "");
}
}
int
main([[maybe_unused]] int argc, char *argv[])
void
Loco::init_log_file()
{
Loco::InputData input_data;
std::string cfg_file = Loco::Cfg::kDefaultCfgFile;
if (argc > 2)
if (!Loco::global_cfg.output.diagnostic)
{
std::cerr << "Call " << argv[0] << " [cfg_file]" << std::endl;
return 1;
return;
}
if (argc == 2)
log_file.open(*Loco::global_cfg.output.diagnostic);
std::clog.rdbuf(log_file.rdbuf());
}
template <class Printer>
void
Loco::print_to_file(const std::optional<std::filesystem::path> &fname,
Printer p)
{
if (!fname)
{
cfg_file = argv[1];
return;
}
if (!Loco::global_cfg.ParseFile(cfg_file))
std::ofstream f(*fname);
if (!f.good())
{
std::cerr << "Failed to parse the configuration file" << std::endl;
return 1;
std::clog << "[ERROR] Failed to open file \"" << *fname
<< "\" for writing" << std::endl;
return;
}
p(f);
}
auto
Loco::read_input() -> InputData
{
InputData input_data;
process_file<Loco::NodeParser>(
Loco::global_cfg.input.nodes, input_data,
[&input_data](std::ostream &os, const std::string &prefix) {
......@@ -97,30 +140,42 @@ main([[maybe_unused]] int argc, char *argv[])
input_data.PrintTrainList(os, prefix);
});
Loco::PhysicalGraph g(input_data);
{
std::ofstream f(Loco::global_cfg.debug.phys_graph);
g.PrintGraph(f);
}
return input_data;
}
void
Loco::print_physical_graph(const InputData &input_data)
{
if (!global_cfg.debug.phys_graph && !global_cfg.debug.phys_line_graph)
{
std::ofstream f(Loco::global_cfg.debug.phys_line_graph);
g.PrintLineGraph(f);
return;
}
PhysicalGraph g(input_data);
print_to_file(global_cfg.debug.phys_graph,
[&g](std::ostream &os) { g.PrintGraph(os); });
print_to_file(global_cfg.debug.phys_line_graph,
[&g](std::ostream &os) { g.PrintLineGraph(os); });
}
auto
Loco::init_section_graph(const InputData &input_data) -> SectionGraphCPtr
{
Loco::LogicalGraph lg(input_data);
{
std::ofstream f(Loco::global_cfg.debug.logical_graph);
lg.PrintGraph(f);
}
print_to_file(global_cfg.debug.logical_graph,
[&lg](std::ostream &os) { lg.PrintGraph(os); });
Loco::SectionGraphCPtr sg =
std::make_shared<const Loco::SectionGraph>(input_data, lg);
{
std::ofstream f(Loco::global_cfg.debug.section_graph);
sg->PrintGraph(f);
}
{
std::ofstream f(Loco::global_cfg.debug.section_graph_info);
sg->PrintSectionInfo(f);
}
print_to_file(global_cfg.debug.section_graph,
[&sg](std::ostream &os) { sg->PrintGraph(os); });
print_to_file(global_cfg.debug.section_graph_info,
[&sg](std::ostream &os) { sg->PrintSectionInfo(os); });
return sg;
}
void
Loco::debug_print_subgraphs(const InputData &input_data,
const SectionGraphCPtr &sg)
{
auto tp_zababov = input_data.mTrafficPoints.Find("Bod Zababov");
tp_zababov->Print(std::cout, "", "");
auto tp_divisov = input_data.mTrafficPoints.Find("Bod Divisov");
......@@ -144,16 +199,54 @@ main([[maybe_unused]] int argc, char *argv[])
std::ofstream f("data/graph/subg_kopanky_petrov.dot");
sg->PrintSubgraph(f, subg_kopanky_petrov, "subg_kopanky_petrov");
}
}
int
main([[maybe_unused]] int argc, char *argv[])
{
std::string cfg_file = Loco::Cfg::kDefaultCfgFile;
if (argc > 2)
{
std::clog << "Call " << argv[0] << " [cfg_file]" << std::endl;
return 1;
}
if (argc == 2)
{
cfg_file = argv[1];
}
if (!Loco::global_cfg.ParseFile(cfg_file))
{
std::clog << "Failed to parse the configuration file" << std::endl;
return 1;
}
Loco::init_log_file();
Loco::InputData input_data = Loco::read_input();
print_physical_graph(input_data);
auto sg = init_section_graph(input_data);
// debug_print_subgraphs(input_data, sg);
Loco::TrainRoutes routes(input_data, sg);
routes.UpdateActivities(input_data.mTrainList,
Loco::global_cfg.model.current_time.Seconds(), true);
Loco::print_to_file(
Loco::global_cfg.output.places,
[&routes](std::ostream &os) { routes.PrintPlacesAsINI(os, ""); });
if (Loco::global_cfg.output.model_data)
{
std::ofstream f(Loco::global_cfg.output.model_data);
routes.PrintModelData(f, "");
// routes.PrintActivities(f, "", true);
std::ofstream f(*Loco::global_cfg.output.model_data);
if (f.good())
{
routes.PrintModelData(f, "");
}
else
{
std::clog << "[ERROR] Failed to open the model data file for writing"
<< std::endl;
return 2;
}
}
else
{
std::ofstream f(Loco::global_cfg.output.places);
routes.PrintPlacesAsINI(f, "");
routes.PrintModelData(std::cout, "");
}
return 0;
}
......@@ -12,9 +12,14 @@ default-directory = data
[output]
directory = data/out
# If empty (or commented), indications are not written
indications = indications.ini
# If empty (or commented), diagnostic is written to error output
diagnostic = deadlock.log
verbosity = 3
# If empty (or commented), the model data are written to standard output
model-data = model.dat
# If empty (or commented), places.ini is not output
places = places.ini
[message]
......@@ -25,8 +30,10 @@ default-directory = data
# PK: Měl by tu být i soubor s postavenými cestami, ale nevím, jak by měl vypadat
[debug]
phys-graph = graph/phys_graph.dot
phys-line-graph = graph/phys_line_graph.dot
# If any of the following properties is empty (or commented), the corresponding
# file is not written to
# phys-graph = graph/phys_graph.dot
# phys-line-graph = graph/phys_line_graph.dot
logical-graph = graph/logical_graph.dot
section-graph = graph/section_graph.dot
section-graph-info = graph/section_graph_info.txt
......
......@@ -22,7 +22,7 @@ Loco::Cfg::ParseFile(const std::filesystem::path &fname)
ini_file.InitWithFileName(fname);
if (ini_file.GetStatus() != INIFile::Status::FINISHED)
{
std::cerr << "[Cfg::ParserFile] Error reading configuration file "
std::clog << "[Cfg::ParserFile] Error reading configuration file "
<< fname << std::endl;
return false;
}
......@@ -72,7 +72,7 @@ Loco::Cfg::Parse(const INISection &sect)
}
else
{
std::cerr << "[Cfg::Parse] Ignoring unknown config file section "
std::clog << "[Cfg::Parse] Ignoring unknown config file section "
<< subsect.mIdent << std::endl;
}
}
......@@ -99,10 +99,10 @@ Loco::CfgOutput::Parse(const INISection &sect,
const std::string &default_directory)
{
directory = sect.ValueWithDefault("directory", default_directory);
indications = sect.PathValue("indications", directory, indications);
diagnostic = sect.PathValue("diagnostic", directory, diagnostic);
model_data = sect.PathValue("model-data", directory, model_data);
places = sect.PathValue("places", directory, places);
indications = sect.PathValue("indications", directory);
diagnostic = sect.PathValue("diagnostic", directory);
model_data = sect.PathValue("model-data", directory);
places = sect.PathValue("places", directory);
return true;
}
......@@ -121,13 +121,11 @@ Loco::CfgDebug::Parse(const INISection &sect,
const std::string &default_directory)
{
directory = sect.ValueWithDefault("directory", default_directory);
phys_graph = sect.PathValue("phys-graph", directory, phys_graph);
phys_line_graph =
sect.PathValue("phys-line-graph", directory, phys_line_graph);
logical_graph = sect.PathValue("logical-graph", directory, logical_graph);
section_graph = sect.PathValue("section-graph", directory, section_graph);
section_graph_info =
sect.PathValue("section-graph-info", directory, section_graph_info);
phys_graph = sect.PathValue("phys-graph", directory);
phys_line_graph = sect.PathValue("phys-line-graph", directory);
logical_graph = sect.PathValue("logical-graph", directory);
section_graph = sect.PathValue("section-graph", directory);
section_graph_info = sect.PathValue("section-graph-info", directory);
return true;
}
......
......@@ -12,6 +12,7 @@
#define __CFGFILE_H
#include <filesystem>
#include <optional>
#include "iniparser.h"
#include "loco_types.h"
......@@ -35,10 +36,11 @@ namespace Loco
struct CfgOutput
{
std::filesystem::path directory{};
std::filesystem::path indications{"indications.ini"};
std::filesystem::path diagnostic{"deadlock.log"};
std::filesystem::path model_data{"model.dat"};
std::filesystem::path places{"places.ini"};
std::optional<std::filesystem::path> indications{"indications.ini"};
std::optional<std::filesystem::path> diagnostic{};
std::optional<std::filesystem::path> model_data{"model.dat"};
std::optional<std::filesystem::path> places{"places.ini"};
unsigned verbosity{3};
bool Parse(const INISection &sect, const std::string &default_directory);
};
......@@ -55,11 +57,11 @@ namespace Loco
struct CfgDebug
{
std::filesystem::path directory{};
std::filesystem::path phys_graph{"graph/phys_graph.dot"};
std::filesystem::path phys_line_graph{"graph/phys_line_graph.dot"};
std::filesystem::path logical_graph{"graph/logical_graph.dot"};
std::filesystem::path section_graph{"graph/section_graph.dot"};
std::filesystem::path section_graph_info{"graph/section_graph_info.dot"};
std::optional<std::filesystem::path> phys_graph{};
std::optional<std::filesystem::path> phys_line_graph{};
std::optional<std::filesystem::path> logical_graph{};
std::optional<std::filesystem::path> section_graph{};
std::optional<std::filesystem::path> section_graph_info{};
bool Parse(const INISection &sect, const std::string &default_directory);
};
......@@ -95,6 +97,12 @@ namespace Loco
extern Cfg global_cfg;
inline bool
check_verbosity(unsigned vl)
{
return vl <= global_cfg.output.verbosity;
}
} // namespace Loco
#endif
......@@ -131,7 +131,7 @@ Loco::RegionDataParser::GetObjectByField(InputData &data,
{
if (!sect.HasValue(label))
{
std::cerr << "[RegionDataParser::GetObjectByField] Field " << label
std::clog << "[RegionDataParser::GetObjectByField] Field " << label
<< " not found in section " << sect.mIdent << std::endl;
return nullptr;
}
......@@ -150,7 +150,7 @@ Loco::RegionDataParser::GetObjectByValue(InputData &data, const Region &reg,
ptr = getter(reg, ident.mIdent);
if (!ptr)
{
std::cerr << "[RegionDataParser::GetObjectByValue(" << value
std::clog << "[RegionDataParser::GetObjectByValue(" << value
<< ")] Object " << ident.mIdent << " (with current region "
<< reg.mIdent << ") not found" << std::endl;
}
......@@ -168,7 +168,7 @@ Loco::RegionDataParser::GetObjectByValue(InputData &data, const Region &reg,
ptr = getter(*reg, ident.mIdent);
if (!ptr)
{
std::cerr << "[RegionDataParser::GetObjectByValue(" << value
std::clog << "[RegionDataParser::GetObjectByValue(" << value
<< ")] Object " << ident.mIdent << " in region "
<< reg->mIdent << " not found" << std::endl;
}
......@@ -185,7 +185,7 @@ Loco::RegionDataParser::GetObjectArrayByField(InputData &data,
{
if (!sect.HasValue(label))
{
std::cerr << "[RegionDataParser::GetObjectArray] Field " << label
std::clog << "[RegionDataParser::GetObjectArray] Field " << label
<< " not found in section " << sect.mIdent << std::endl;
return {};
}
......@@ -238,7 +238,7 @@ Loco::BaseParser::GetObjectByField(InputData &data, const INISection &sect,
{
if (!sect.HasValue(label))
{
std::cerr << "[BaseParser::GetObjectByField] Field " << label
std::clog << "[BaseParser::GetObjectByField] Field " << label
<< " not found in section " << sect.mIdent << std::endl;
return nullptr;
}
......@@ -268,7 +268,7 @@ Loco::BaseParser::GetObjectByValue(InputData &data, const std::string &value,
ptr = getter(*reg, ident.mIdent);
if (!ptr)
{
std::cerr << "[BaseParser::GetObjectByValue(" << value << ")] Object "
std::clog << "[BaseParser::GetObjectByValue(" << value << ")] Object "
<< ident.mIdent << " in region " << reg->mIdent << " not found"
<< std::endl;
}
......@@ -282,7 +282,7 @@ Loco::BaseParser::GetObjectArrayByField(InputData &data, const INISection &sect,
{
if (!sect.HasValue(label))
{
std::cerr << "[RegionDataParser::GetObjectArray] Field " << label
std::clog << "[RegionDataParser::GetObjectArray] Field " << label
<< " not found in section " << sect.mIdent << std::endl;
return {};
}
......
......@@ -87,7 +87,7 @@ Loco::INIFile::ParseLine(const std::string &s)
void
Loco::INIFile::SyntaxError(const std::string &desc)
{
std::cerr << "Line " << mLineCount << ": " << desc << std::endl;
std::clog << "Line " << mLineCount << ": " << desc << std::endl;
mStatus = Status::ERR_SYNTAX;
}
......@@ -346,6 +346,17 @@ Loco::INISection::PathValue(const std::string &v_ident,
return directory / Value(v_ident);
}
std::optional<std::filesystem::path>
Loco::INISection::PathValue(const std::string &v_ident,
const std::filesystem::path &directory) const
{
if (!HasValue(v_ident))
{
return {};
}
return directory / Value(v_ident);
}
std::optional<Loco::GlobalIdent>
Loco::INISection::IdentValue(const std::string &v_ident) const
{
......
......@@ -66,6 +66,9 @@ namespace Loco
PathValue(const std::string &v_ident,
const std::filesystem::path &directory,
const std::filesystem::path &default_path) const;
std::optional<std::filesystem::path>
PathValue(const std::string &v_ident,
const std::filesystem::path &directory) const;
};
std::string strip_comment(std::string s);
......
......@@ -30,7 +30,7 @@ Loco::TrainListParser::AddSectionTrainList(InputData &data,
auto train_ptr = data.mTrains.Find(train_ident);
if (!train_ptr)
{
std::cerr << "[AddSectionTrainList] No train with ident '"
std::clog << "[AddSectionTrainList] No train with ident '"
<< train_ident << "' found, adding a train for this purpose"
<< std::endl;
auto [tp, ins] =
......
......@@ -76,7 +76,7 @@ Loco::TrainParser::ParseSingleStop(const InputData &data,
auto tp = data.mTrafficPoints.Find(sect.mIdent);
if (!tp)
{
std::cerr << "[TrainParser::ParseSingleStop] Train '" << train_ident
std::clog << "[TrainParser::ParseSingleStop] Train '" << train_ident
<< "' - stop '" << sect.mIdent
<< "' has no traffic point, adding one just for this train"
<< std::endl;
......
......@@ -443,8 +443,8 @@ Loco::TrainRouteGraph::UpdateInitialActivity(const SectionCPtr &initial_section,
unsigned elem_id = ElementWithSection(sect_id);
if (elem_id == mElements.size())
{
std::cerr << "[TrainRouteGraph::UpdateWithInitialSection] Train is not "
"on the route, it shall be not part of the schedule"
std::clog << "[TrainRouteGraph::UpdateWithInitialSection] Train is not "
"on the route, it shall not be part of the schedule"
<< std::endl;
mActList.front().mForced = false;
mActList.front().mUse = false;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment