LCOV - code coverage report
Current view: top level - app/src/Com/http - dynamicSimulationPost.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 74 0.0 %
Date: 2023-08-17 16:45:52 Functions: 0 2 0.0 %

          Line data    Source code
       1             : #include <spdlog/spdlog.h>
       2             : 
       3             : #include <future>
       4             : #include <nlohmann/json.hpp>
       5             : #include <stdexcept>
       6             : 
       7             : #include "Com/HTTPServer.hpp"
       8             : #include "Dynamic/Demand/Demand.hpp"
       9             : #include "Dynamic/Demand/UniformDemandLoader.hpp"
      10             : #include "Dynamic/Env/Env.hpp"
      11             : #include "Dynamic/Env/Loader.hpp"
      12             : #include "Dynamic/Policy/RandomPolicy.hpp"
      13             : #include "Dynamic/Policy/RewardFunction/RewardFunction.hpp"
      14             : #include "Dynamic/Policy/RewardFunction/RewardFunctionGreedy.hpp"
      15             : #include "GlobalState.hpp"
      16             : #include "Log/ProgressLoggerJsonOStream.hpp"
      17             : #include "data/SUMO/NetState.hpp"
      18             : #include "utils/require_env.hpp"
      19             : 
      20             : using namespace std;
      21             : using namespace Com;
      22             : 
      23             : using namespace utils::stringify;
      24             : 
      25             : using json = nlohmann::json;
      26             : 
      27             : /**yaml POST /dynamic/simulation/{id}
      28             :  * summary: Run dynamic simulation.
      29             :  * tags:
      30             :  *   - Dynamic
      31             :  * consumes:
      32             :  *   - application/json
      33             :  * parameters:
      34             :  *   - name: id
      35             :  *     in: path
      36             :  *     required: true
      37             :  *     description: ID of simulation
      38             :  *     schema:
      39             :  *       type: string
      40             :  *       pattern: '^[\w\-]+$'
      41             :  * requestBody:
      42             :  *   description: Configuration of simulation to run.
      43             :  *   content:
      44             :  *     application/json:
      45             :  *       schema:
      46             :  *         $ref: '#/components/schemas/DynamicSimulation'
      47             :  * responses:
      48             :  *   '200':
      49             :  *     description: Simulation executed successfully
      50             :  */
      51           0 : void HTTPServer::dynamicSimulationPost(const httplib::Request &req, httplib::Response &res) {
      52           0 :     const string WS_HOST = utils::require_env("WS_HOST");
      53             : 
      54           0 :     json data = json::parse(req.body);
      55             : 
      56           0 :     const string &resourceID = req.matches[0];
      57             : 
      58           0 :     string        netPath, tazPath, demandPath;
      59           0 :     Dynamic::Time beginTime, endTime;
      60           0 :     try {
      61           0 :         netPath    = data.at("netPath");
      62           0 :         tazPath    = data.at("tazPath");
      63           0 :         demandPath = data.at("demandPath");
      64           0 :         beginTime  = data.at("begin");
      65           0 :         endTime    = data.at("end");
      66             : 
      67           0 :         if(endTime < beginTime)
      68           0 :             throw logic_error("endTime < beginTime");
      69           0 :     } catch(const json::out_of_range &e) {
      70           0 :         res.status = 400;
      71           0 :         return;
      72           0 :     } catch(const logic_error &e) {
      73           0 :         res.status = 400;
      74           0 :         res.set_content("what(): "s + e.what(), "text/plain");
      75           0 :         return;
      76             :     }
      77             : 
      78           0 :     Dynamic::Time stepTime = 1.0;
      79           0 :     if(data.contains("step")) {
      80           0 :         stepTime = data.at("step");
      81             :     }
      82             : 
      83           0 :     optional<string> netstatePath;
      84           0 :     if(data.contains("netstatePath")) {
      85           0 :         netstatePath = data.at("netstatePath");
      86             :     }
      87             : 
      88           0 :     try {
      89           0 :         GlobalState::ResourceID taskID = "task://"s + resourceID;
      90             : 
      91           0 :         GlobalState::ResourceID streamID = "stream://"s + resourceID;
      92           0 :         utils::pipestream      &ios      = GlobalState::streams.create(streamID);
      93             : 
      94           0 :         GlobalState::tasks.create(
      95             :             taskID,
      96           0 :             [netPath,
      97             :              tazPath,
      98             :              demandPath,
      99             :              beginTime,
     100             :              endTime,
     101             :              taskID,
     102             :              streamID,
     103             :              &ios,
     104             :              netstatePath,
     105           0 :              stepTime]() -> GlobalState::TaskReturn {
     106           0 :                 try {
     107           0 :                     Log::ProgressLoggerJsonOStream logger(ios.o());
     108             : 
     109             :                     // Supply
     110           0 :                     shared_ptr<SUMO::Network> sumoNetwork = SUMO::Network::loadFromFile(netPath);
     111           0 :                     SUMO::TAZs                sumoTAZs    = SUMO::TAZ::loadFromFile(tazPath);
     112           0 :                     SUMO::NetworkTAZs         sumo{*sumoNetwork, sumoTAZs};
     113             : 
     114             :                     // clang-format off
     115           0 :                     Dynamic::Env::Loader<
     116             :                         const SUMO::NetworkTAZs &,
     117             :                         Dynamic::RewardFunction &
     118           0 :                     > loader;
     119             :                     // clang-format on
     120             : 
     121           0 :                     shared_ptr<Dynamic::Env::Env> env = loader.load(sumo, Dynamic::RewardFunctionGreedy::INSTANCE);
     122             : 
     123             :                     // Demand
     124           0 :                     VISUM::OFormatDemand oDemand = VISUM::OFormatDemand::loadFromFile(demandPath);
     125             :                     // clang-format off
     126           0 :                     Static::Demand::Loader<
     127             :                         const VISUM::OFormatDemand &,
     128             :                         const Static::SUMOAdapter &
     129             :                     > staticDemandLoader;
     130             :                     // clang-format on
     131           0 :                     Static::Demand staticDemand = staticDemandLoader.load(
     132             :                         oDemand,
     133             :                         (Static::SUMOAdapter &)loader.adapter
     134           0 :                     );
     135           0 :                     Dynamic::RandomPolicy::Factory policyFactory;
     136           0 :                     Dynamic::UniformDemandLoader   demandLoader(1.0, beginTime, endTime, policyFactory);
     137           0 :                     Dynamic::Demand                demand = demandLoader.load(staticDemand, *env, loader.adapter).first;
     138             : 
     139             :                     // Simulation
     140           0 :                     env->addDemand(demand);
     141             : 
     142           0 :                     Dynamic::Time delta = (endTime - beginTime) / 100;
     143           0 :                     env->log(logger, beginTime, endTime, delta);
     144             : 
     145           0 :                     optional<SUMO::NetState> netstate;
     146           0 :                     if(netstatePath.has_value()) {
     147           0 :                         size_t numberDumps = (size_t)((endTime - beginTime) / stepTime);
     148             : 
     149           0 :                         netstate.emplace(netstatePath.value(), ios_base::out);
     150             : 
     151           0 :                         env->dump(netstate.value(), loader.adapter, beginTime, endTime, numberDumps);
     152             :                     }
     153             : 
     154             :                     // TODO: run simulation
     155             : 
     156           0 :                     ios.closeWrite();
     157           0 :                     GlobalState::streams.erase(streamID);
     158             : 
     159           0 :                 } catch(const exception &e) {
     160           0 :                     spdlog::error(
     161             :                         "Task {} aborted, what(): {}",
     162           0 :                         taskID,
     163           0 :                         e.what()
     164             :                     );
     165           0 :                     return {500, "what(): "s + e.what()};
     166             :                 }
     167             : 
     168           0 :                 spdlog::info("Task {} finished", taskID);
     169           0 :                 return {200, ""};
     170             :             }
     171           0 :         );
     172             :         // clang-format on
     173             : 
     174             :         // clang-format off
     175           0 :         json resData = {
     176             :             {"log", {
     177             :                 {"resourceID", resourceID},
     178           0 :                 {"url", "ws://" + WS_HOST + resourceID + "/log"}
     179             :             }}
     180           0 :         };
     181             :         // clang-format on
     182           0 :         res.set_content(resData.dump(), "application/json");
     183             : 
     184           0 :     } catch(const exception &e) {
     185           0 :         res.status = 500;
     186           0 :         res.set_content("what(): "s + e.what(), "text/plain");
     187             :     }
     188             : }

Generated by: LCOV version 1.14