/** * @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 . */ #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 namespace artis::factory { struct MachineJob { unsigned int _machine_id; std::vector _ins; std::vector _outs; std::shared_ptr _durations; }; struct PoolJob { unsigned int _pool_id; std::vector _machine_jobs; }; struct Product { unsigned int _id; std::vector> _components; std::vector _pool_jobs; bool final; }; struct Generator { uint _random_seed; uint _min_send_speed_rate; uint _max_send_speed_rate; int _po_number; std::vector _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 _items; }; struct Factory { Generator _generator; std::vector>, std::vector >> _pools; std::map _products; std::vector _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(), data["min_send_speed_rate"].get(), data["max_send_speed_rate"].get(), -1, {}}; } std::vector parse_ins(const nlohmann::json &data) { std::vector ins; for (const nlohmann::json &in: data) { int item_id = in.contains("itemID") ? in["itemID"].get() : -1; int source_pool_id = in["source"].contains("poolID") ? in["source"]["poolID"].get() : -1; unsigned int source_stock_id = in["source"]["stockID"].get(); unsigned int quantity = in.contains("quantity") ? in["quantity"].get() : 1; ins.push_back(In{item_id, Location{source_pool_id, source_stock_id}, quantity}); } return ins; } std::vector> parse_machines(const nlohmann::json &data, unsigned int pool_id) { std::vector> machines; for (const nlohmann::json &machine: data) { unsigned int machine_id = machine["id"].get(); unsigned int machine_type = machine["type"].get(); unsigned int capacity = machine.contains("capacity") ? machine["capacity"].get() : 1; std::map 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() : 0; unsigned int processing_time = machine.contains("processing_time") ? machine["processing_time"].get() : 0; unsigned int unload_time = machine.contains("unload_time") ? machine["unload_time"].get() : 0; machines.push_back( std::make_shared(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{{machine_id, machine_type, pool_id, capacity}})); break; } case SEPARATOR: { // TODO machines.push_back( std::make_shared(SeparatorParameters{{machine_id, machine_type, pool_id, capacity}})); break; } case COMBINER : { // TODO machines.push_back( std::make_shared(CombinerParameters{{machine_id, machine_type, pool_id, capacity}})); break; } case CONVEYOR : { // TODO machines.push_back( std::make_shared(ConveyorParameters{{machine_id, machine_type, pool_id, capacity}})); break; } default: { } } } return machines; } std::vector parse_outs(const nlohmann::json &data) { std::vector outs; for (const nlohmann::json &out: data) { int item_id = out.contains("itemID") ? out["itemID"].get() : -1; int destination_pool_id = out["destination"].contains("poolID") ? out["destination"]["poolID"].get() : -1; unsigned int destination_stock_id = out["destination"]["stockID"].get(); unsigned int quantity = out.contains("quantity") ? out["quantity"].get() : 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 pool_type = pool["type"].get(); std::vector stocks; if (pool.contains("stocks")) { for (const nlohmann::json &stock: pool["stocks"]) { unsigned int stock_id = stock["id"].get(); int capacity = stock["capacity"].get(); 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(); bool final = product.contains("final") ? product["final"].get() : true; std::vector> components; if (product.contains("components")) { for (const nlohmann::json &component: product["components"]) { components.emplace_back(component["id"].get(), component["number"].get()); } } _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 pool_index = 0; for (const nlohmann::json &pool_machine: product["program"]) { unsigned int pool_id = pool_machine["poolID"].get(); 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(); 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{{}, machine.contains("load_time") ? machine["load_time"].get() : 0, machine.contains("processing_time") ? machine["processing_time"].get() : 0, machine.contains("unload_time") ? machine["unload_time"].get() : 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 parse_program(const nlohmann::json &data) { std::vector program; for (const nlohmann::json &pool_machine: data) { unsigned int pool_id = pool_machine["poolID"].get(); program.push_back(PoolJob{pool_id, parse_sequence(pool_machine["sequence"])}); } return program; } std::vector parse_sequence(const nlohmann::json &data) { std::vector sequence; for (const nlohmann::json &machine: data) { if (machine.is_object()) { std::vector ins; std::vector 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(), ins, outs, {}}); } else { sequence.push_back(MachineJob{machine.get(), {}, {}, {}}); } } return sequence; } void parse_item_stocks(const nlohmann::json &data) { for (const nlohmann::json &stock: data) { unsigned int stock_id = stock["id"].get(); std::vector items; for (const nlohmann::json &item: stock["items"]) { unsigned int item_id = item["id"].get(); int quantity = item["quantity"].get(); items.push_back({item_id, quantity}); } _factory._stocks.push_back({stock_id, items}); } } Factory _factory; }; } #endif //ARTIS_FACTORY_JSON_READER_HPP