From 04fce9354b6c5300177344c7dab20543a4bc3fe3 Mon Sep 17 00:00:00 2001 From: Reveares Date: Fri, 7 Dec 2018 22:20:37 +0100 Subject: [PATCH] Added code --- CMakeLists.txt | 20 +++++ CMakeSettings.json | 30 +++++++ src/CMakeLists.txt | 3 + src/Converter.cpp | 220 +++++++++++++++++++++++++++++++++++++++++++++ src/Converter.h | 17 ++++ src/Waypoint.h | 21 +++++ src/main.cpp | 25 ++++++ 7 files changed, 336 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 CMakeSettings.json create mode 100644 src/CMakeLists.txt create mode 100644 src/Converter.cpp create mode 100644 src/Converter.h create mode 100644 src/Waypoint.h create mode 100644 src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ce42fa0 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required (VERSION 3.8) + +project ("WayNetConverter") + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if (MSVC) + # /W3 - Level 3 warnings + # /MP - Multi-threaded compilation + # /permissive- - enables stricter C++ standards conformance checks + set(CMAKE_C_FLAGS "/W4 /MP /permissive-" CACHE STRING "" FORCE) + # /EHsc - C++-only exception handling semantics + # /Zc:throwingNew - let codegen assume `operator new` will never return null + # /Zc:inline - let codegen omit inline functions in object files + set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} /EHsc /Zc:throwingNew,inline" CACHE STRING "" FORCE) +endif() + + +add_subdirectory ("src") diff --git a/CMakeSettings.json b/CMakeSettings.json new file mode 100644 index 0000000..eaeb47f --- /dev/null +++ b/CMakeSettings.json @@ -0,0 +1,30 @@ +{ + "configurations": [ + { + "name": "x64-Release", + "generator": "Ninja", + "configurationType": "Release", + "inheritEnvironments": [ + "msvc_x64_x64" + ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ + "msvc_x64_x64" + ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + } + ] +} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..da52178 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required (VERSION 3.8) + +add_executable (WayNetConverter "main.cpp" "Converter.cpp" "Converter.h" "Waypoint.h") diff --git a/src/Converter.cpp b/src/Converter.cpp new file mode 100644 index 0000000..34cd2c7 --- /dev/null +++ b/src/Converter.cpp @@ -0,0 +1,220 @@ +#include "Converter.h" +#include +#include +#include +#include +#include + +void Converter::read(const std::string fileName) +{ + std::ifstream file(fileName, std::ifstream::binary); + + std::cout << "Read file: " << fileName << std::endl; + if (!file.is_open()) + { + std::cerr << "Couldn't open file!" << std::endl; + return; + } + std::cout << "Reading... " << std::endl; + + // Connections. + std::vector wayl; + std::vector wayr; + + // Skip until '[WayNet' tag. + bool foundWayNet = false; + std::string line; + while (std::getline(file, line)) + { + if (!foundWayNet) + { + foundWayNet = line.find("[WayNet") != std::string::npos; + } + else if (line.find("[way") != std::string::npos) + { + // Get object id. + auto vector = split(line); + if (vector.size() != 4) + { + std::cerr << "Too many split result (" << vector.size() << ") instead of 3 from line:" << std::endl << "'" << line << "'" << std::endl; + return; + } + vector[3].erase(vector[3].end() - 1); // Remove ']'. + int objectId = std::stoi(vector[3]); + + std::shared_ptr waypoint; + + // Create a new Waypoint if this line is not a reference. + if (line.find("§") == std::string::npos) + { + std::string attribute; + size_t location; + std::string lineWaypoint; + + // Get name. + std::getline(file, lineWaypoint); + attribute = "wpName=string:"; + location = lineWaypoint.find(attribute); + if (location == std::string::npos) + { + std::cerr << "Awaited '" << attribute << "' but instead line is:" << std::endl << "'" << lineWaypoint << "'" << std::endl; + return; + } + std::string name(lineWaypoint.substr(location + attribute.length())); + + // Skip waterDepth and underWater. + std::getline(file, lineWaypoint); + std::getline(file, lineWaypoint); + + // Get position + std::getline(file, lineWaypoint); + attribute = "position=vec3:"; + location = lineWaypoint.find(attribute); + if (location == std::string::npos) + { + std::cerr << "Awaited '" << attribute << "' but instead line is:" << std::endl << "'" << lineWaypoint << "'" << std::endl; + return; + } + std::vector positions = split(lineWaypoint.substr(location + attribute.length())); + if (positions.size() != 3) + { + std::cerr << "Too many split result (" << positions.size() << ") instead of 3 from line:" << std::endl << "'" << lineWaypoint << "'" << std::endl; + return; + } + double x = std::stod(positions[0]); + double y = std::stod(positions[1]); + double z = std::stod(positions[2]); + + // Get direction + std::getline(file, lineWaypoint); + attribute = "direction=vec3:"; + location = lineWaypoint.find(attribute); + if (location == std::string::npos) + { + std::cerr << "Awaited '" << attribute << "' but instead line is:" << std::endl << "'" << lineWaypoint << "'" << std::endl; + return; + } + std::vector directions = split(lineWaypoint.substr(location + attribute.length())); + if (directions.size() != 3) + { + std::cerr << "Too many split result (" << directions.size() << ") instead of 3 from line:" << std::endl << "'" << lineWaypoint << "'" << std::endl; + return; + } + double dX = std::stod(directions[0]); + double dZ = std::stod(directions[2]); + + waypoint = std::make_shared(name, x, y, z, dX, dZ); + waypoints[objectId] = waypoint; + } + + // Don't create a Way for Waypoints. + if (line.find("[waypoint") == std::string::npos) + { + Way way{ objectId, waypoint }; + if (line.find("[wayl") != std::string::npos) + { + wayl.push_back(way); + } + else if (line.find("[wayr") != std::string::npos) + { + wayr.push_back(way); + } + + // After a left Way there must be a right Way. The difference should never be higher than 1. + if (wayr.size() > wayl.size() && wayl.size() - 1 > wayr.size()) + { + std::cerr << "WayNet didn't started with left Way or two right/left Way successively." << std::endl; + } + } + } + } + file.close(); + + // Fill out empty waypoint pointers. + for (auto& way : wayl) + { + if (way.waypoint == nullptr) + { + auto result = waypoints.find(way.objectId); + if (result != waypoints.end()) + { + way.waypoint = result->second; + } + else + { + std::cerr << "For id: " << way.objectId << " doesn't exists a Waypoint!" << std::endl; + } + } + } + for (auto& way : wayr) + { + if (way.waypoint == nullptr) + { + auto result = waypoints.find(way.objectId); + if (result != waypoints.end()) + { + way.waypoint = result->second; + } + else + { + std::cerr << "For id: " << way.objectId << " doesn't exists a Waypoint!" << std::endl; + } + } + } + + // Insert Waypoint connections. + for (int i = 0; i < wayl.size(); i++) + { + auto left = waypoints.find(wayl[i].objectId); + auto right = waypoints.find(wayr[i].objectId); + if (left != waypoints.end() && right != waypoints.end()) + { + left->second->connections.push_back(right->second->name); + right->second->connections.push_back(left->second->name); + } + else + { + std::cerr << "Couldn't get Waypoint with object id: " << wayl[i].objectId << " or " << wayr[i].objectId << std::endl; + } + } + + std::cout << "Done. Waypoints: " << waypoints.size() << " and Ways: " << wayl.size() << std::endl; +} + +std::vector Converter::split(const std::string line) const +{ + std::istringstream iss(line); + return { std::istream_iterator{ iss }, std::istream_iterator{} }; +} + +void Converter::write(const std::string fileName) const +{ + if (waypoints.size() == 0) + { + std::cerr << "Nothing to write." << std::endl; + return; + } + + std::ofstream file(fileName); + + std::cout << std::endl << "Write file: " << fileName << std::endl; + if (!file.is_open()) + { + std::cerr << "Couldn't open file!" << std::endl; + return; + } + std::cout << "Writing... " << std::endl; + + for (const auto& wp : waypoints) + { + auto waypoint = wp.second; + file << waypoint->name << ";" << waypoint->x << ";" << waypoint->y << ";" << waypoint->z << ";" << waypoint->dX << ";" << waypoint->dZ; + for (const auto& connection : waypoint->connections) + { + file << ";" << connection; + } + file << std::endl; + } + + std::cout << "Done. Waypoints: " << waypoints.size() << std::endl; +} diff --git a/src/Converter.h b/src/Converter.h new file mode 100644 index 0000000..dcba673 --- /dev/null +++ b/src/Converter.h @@ -0,0 +1,17 @@ +#pragma once +#include "Waypoint.h" +#include +#include +#include + +class Converter +{ +public: + void read(const std::string fileName); + void write(const std::string fileName) const; + +private: + std::vector split(const std::string line) const; + + std::map> waypoints; +}; \ No newline at end of file diff --git a/src/Waypoint.h b/src/Waypoint.h new file mode 100644 index 0000000..13fca39 --- /dev/null +++ b/src/Waypoint.h @@ -0,0 +1,21 @@ +#pragma once +#include +#include +#include + +struct Waypoint +{ + Waypoint(std::string name, double x, double y, double z, double dX, double dZ) + : name(name), x(x), y(y), z(z), dX(dX), dZ(dZ) {} + + std::string name; + double x, y, z; + double dX, dZ; + std::vector connections; +}; + +struct Way +{ + int objectId; + std::shared_ptr waypoint; +}; diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..9c7582d --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,25 @@ +#include +#include +#include "Converter.h" + +int main(int argc, char **argv) +{ + std::cout << "Reveares' Waypoint Converter" << std::endl << std::endl; + + if (argc != 3) + { + std::cerr << "2 Arguments are needed!" << std::endl << "first: path/to/file.zen" << std::endl << "second: filename.wp" << std::endl; + return -1; + } + + auto start = std::chrono::high_resolution_clock::now(); + + Converter converter; + converter.read(argv[1]); + converter.write(argv[2]); + + auto end = std::chrono::high_resolution_clock::now(); + std::cout << "Which took " << std::chrono::duration(end - start).count() << " seconds." << std::endl; + + return 0; +}