Files
tp-modelisation-problemes/src/JsonReader.hpp
2025-10-20 14:07:37 +02:00

336 lines
12 KiB
C++

/**
* @file Base.hpp
* @author The ARTIS Development Team
* See the AUTHORS or Authors.txt file
*/
/*
* ARTIS - the multimodeling and simulation environment
* This file is a part of the ARTIS environment
*
* Copyright (C) 2013-2023 ULCO http://www.univ-littoral.fr
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ARTIS_FACTORY_JSON_READER_HPP
#define ARTIS_FACTORY_JSON_READER_HPP
#include "Combiner.hpp"
#include "Conveyor.hpp"
#include "Machine.hpp"
#include "Processor.hpp"
#include "ProductionOrderGenerator.hpp"
#include "Separator.hpp"
#include "Sink.hpp"
#include <nlohmann/json.hpp>
namespace artis::factory {
struct MachineJob {
unsigned int _machine_id;
std::vector<In> _ins;
std::vector<Out> _outs;
std::shared_ptr<Durations> _durations;
};
struct PoolJob {
unsigned int _pool_id;
std::vector<MachineJob> _machine_jobs;
};
struct Product {
unsigned int _id;
std::vector<std::pair<unsigned int, unsigned int>> _components;
std::vector<PoolJob> _pool_jobs;
bool final;
};
struct Generator {
uint _random_seed;
uint _min_send_speed_rate;
uint _max_send_speed_rate;
int _po_number;
std::vector<unsigned int> _po_order;
};
struct IntermediateStock {
unsigned int _id;
int _capacity; // if -1 then infinity
};
struct Item {
unsigned int _id;
int _quantity; // if -1 then infinity
};
struct GlobalStock {
unsigned int _id;
std::vector<Item> _items;
};
struct Factory {
Generator _generator;
std::vector<std::tuple<unsigned int, unsigned int, std::vector<std::shared_ptr<MachineParameters>>, std::vector<IntermediateStock> >> _pools;
std::map<unsigned int, Product> _products;
std::vector<GlobalStock> _stocks;
};
class JsonReader {
public:
JsonReader() = default;
const Factory &factory() const { return _factory; }
Factory &factory() { return _factory; }
void parse(const std::string &str) {
nlohmann::json data = nlohmann::json::parse(str);
parse_products(data["products"]);
parse_generator(data["generator"]);
parse_pools(data["pools"]);
parse_product_job_durations(data["products"]);
if (data.contains("stocks")) {
parse_item_stocks(data["stocks"]);
}
}
private:
void parse_generator(const nlohmann::json &data) {
_factory._generator = Generator{data["random_seed"].get<unsigned int>(),
data["min_send_speed_rate"].get<unsigned int>(),
data["max_send_speed_rate"].get<unsigned int>(),
-1, {}};
}
std::vector<In> parse_ins(const nlohmann::json &data) {
std::vector<In> ins;
for (const nlohmann::json &in: data) {
int item_id = in.contains("itemID") ? in["itemID"].get<int>() : -1;
int source_pool_id = in["source"].contains("poolID") ? in["source"]["poolID"].get<int>() : -1;
unsigned int source_stock_id = in["source"]["stockID"].get<unsigned int>();
unsigned int quantity = in.contains("quantity") ? in["quantity"].get<int>() : 1;
ins.push_back(In{item_id, Location{source_pool_id, source_stock_id}, quantity});
}
return ins;
}
std::vector<std::shared_ptr<MachineParameters>> parse_machines(const nlohmann::json &data, unsigned int pool_id) {
std::vector<std::shared_ptr<MachineParameters>> machines;
for (const nlohmann::json &machine: data) {
unsigned int machine_id = machine["id"].get<unsigned int>();
unsigned int machine_type = machine["type"].get<unsigned int>();
unsigned int capacity = machine.contains("capacity") ? machine["capacity"].get<unsigned int>() : 1;
std::map<unsigned int, InOut> in_out;
for (const auto &product: _factory._products) {
for (const auto &pool_job: product.second._pool_jobs) {
if (pool_job._pool_id == pool_id) {
for (const auto &machine_job: pool_job._machine_jobs) {
if (machine_job._machine_id == machine_id) {
in_out[product.first] = InOut{machine_job._ins, machine_job._outs};
}
}
}
}
}
switch (machine_type) {
case PROCESSOR: {
unsigned int load_time = machine.contains("load_time") ? machine["load_time"].get<unsigned int>() : 0;
unsigned int processing_time = machine.contains("processing_time")
? machine["processing_time"].get<unsigned int>() : 0;
unsigned int unload_time = machine.contains("unload_time") ? machine["unload_time"].get<unsigned int>() : 0;
machines.push_back(
std::make_shared<ProcessorParameters>(ProcessorParameters{{machine_id, machine_type, pool_id, capacity},
ProcessorDurations{{}, load_time, processing_time,
unload_time}, in_out, {}}));
break;
}
case SINK: {
machines.push_back(
std::make_shared<SinkParameters>(SinkParameters{{machine_id, machine_type, pool_id, capacity}}));
break;
}
case SEPARATOR: {
// TODO
machines.push_back(
std::make_shared<SeparatorParameters>(SeparatorParameters{{machine_id, machine_type, pool_id, capacity}}));
break;
}
case COMBINER : {
// TODO
machines.push_back(
std::make_shared<CombinerParameters>(CombinerParameters{{machine_id, machine_type, pool_id, capacity}}));
break;
}
case CONVEYOR : {
// TODO
machines.push_back(
std::make_shared<ConveyorParameters>(ConveyorParameters{{machine_id, machine_type, pool_id, capacity}}));
break;
}
default: {
}
}
}
return machines;
}
std::vector<Out> parse_outs(const nlohmann::json &data) {
std::vector<Out> outs;
for (const nlohmann::json &out: data) {
int item_id = out.contains("itemID") ? out["itemID"].get<int>() : -1;
int destination_pool_id = out["destination"].contains("poolID") ? out["destination"]["poolID"].get<int>() : -1;
unsigned int destination_stock_id = out["destination"]["stockID"].get<unsigned int>();
unsigned int quantity = out.contains("quantity") ? out["quantity"].get<int>() : 1;
outs.push_back(Out{item_id, Location{destination_pool_id, destination_stock_id}, quantity});
}
return outs;
}
void parse_pools(const nlohmann::json &data) {
for (const nlohmann::json &pool: data) {
unsigned int pool_id = pool["id"].get<unsigned int>();
unsigned int pool_type = pool["type"].get<unsigned int>();
std::vector<IntermediateStock> stocks;
if (pool.contains("stocks")) {
for (const nlohmann::json &stock: pool["stocks"]) {
unsigned int stock_id = stock["id"].get<unsigned int>();
int capacity = stock["capacity"].get<int>();
stocks.push_back({stock_id, capacity});
}
}
_factory._pools.emplace_back(pool_id, pool_type, parse_machines(pool["machines"], pool_id), stocks);
}
}
void parse_products(const nlohmann::json &data) {
for (const nlohmann::json &product: data) {
unsigned int product_id = product["id"].get<unsigned int>();
bool final = product.contains("final") ? product["final"].get<bool>() : true;
std::vector<std::pair<unsigned int, unsigned int>> components;
if (product.contains("components")) {
for (const nlohmann::json &component: product["components"]) {
components.emplace_back(component["id"].get<unsigned int>(), component["number"].get<unsigned int>());
}
}
_factory._products[product_id] = Product{product_id, components, parse_program(product["program"]), final};
}
}
void parse_product_job_durations(const nlohmann::json &data) {
for (const nlohmann::json &product: data) {
unsigned int product_id = product["id"].get<unsigned int>();
unsigned int pool_index = 0;
for (const nlohmann::json &pool_machine: product["program"]) {
unsigned int pool_id = pool_machine["poolID"].get<unsigned int>();
const auto &pool = *std::find_if(_factory._pools.cbegin(), _factory._pools.cend(),
[pool_id](const auto &e) { return std::get<0>(e) == pool_id; });
const auto &machines = std::get<2>(pool);
unsigned int sequence_index = 0;
for (const nlohmann::json &machine: pool_machine["sequence"]) {
if (machine.is_object()) {
unsigned int machine_id = machine["machineID"].get<unsigned int>();
const auto &m = *std::find_if(machines.cbegin(), machines.cend(),
[machine_id](const auto &e) { return e->machine_id == machine_id; });
if (m->machine_type == PROCESSOR) {
auto &M = (ProcessorParameters &) (*m);
auto d = std::make_shared<ProcessorDurations>(
ProcessorDurations{{},
machine.contains("load_time") ? machine["load_time"].get<unsigned int>() : 0,
machine.contains("processing_time")
? machine["processing_time"].get<unsigned int>() : 0,
machine.contains("unload_time") ? machine["unload_time"].get<unsigned int>() : 0
});
_factory._products[product_id]._pool_jobs[pool_index]._machine_jobs[sequence_index]._durations = d;
M.product_durations[product_id] = d;
}
}
++sequence_index;
}
++pool_index;
}
}
}
std::vector<PoolJob> parse_program(const nlohmann::json &data) {
std::vector<PoolJob> program;
for (const nlohmann::json &pool_machine: data) {
unsigned int pool_id = pool_machine["poolID"].get<unsigned int>();
program.push_back(PoolJob{pool_id, parse_sequence(pool_machine["sequence"])});
}
return program;
}
std::vector<MachineJob> parse_sequence(const nlohmann::json &data) {
std::vector<MachineJob> sequence;
for (const nlohmann::json &machine: data) {
if (machine.is_object()) {
std::vector<In> ins;
std::vector<Out> outs;
if (machine.contains("ins")) {
ins = parse_ins(machine["ins"]);
}
if (machine.contains("outs")) {
outs = parse_outs(machine["outs"]);
}
sequence.push_back(MachineJob{machine["machineID"].get<unsigned int>(), ins, outs, {}});
} else {
sequence.push_back(MachineJob{machine.get<unsigned int>(), {}, {}, {}});
}
}
return sequence;
}
void parse_item_stocks(const nlohmann::json &data) {
for (const nlohmann::json &stock: data) {
unsigned int stock_id = stock["id"].get<unsigned int>();
std::vector<Item> items;
for (const nlohmann::json &item: stock["items"]) {
unsigned int item_id = item["id"].get<unsigned int>();
int quantity = item["quantity"].get<int>();
items.push_back({item_id, quantity});
}
_factory._stocks.push_back({stock_id, items});
}
}
Factory _factory;
};
}
#endif //ARTIS_FACTORY_JSON_READER_HPP