diff --git a/.gitignore b/.gitignore index ec670c9..453bac9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,15 @@ -### Maven - -/target - -### IntelliJ - +### Intellij ### # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 ## Directory-based project format -.idea/ +.idea + +# CMake +cmake-build-debug/ ## File-based project format *.iws -*.iml ## Plugin-specific files: @@ -25,6 +22,12 @@ # JIRA plugin atlassian-ide-plugin.xml +# Cursive Clojure plugin +.idea/replstate.xml + +# Ruby plugin and RubyMine +/.rakeTasks + # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties @@ -32,102 +35,55 @@ crashlytics-build.properties fabric.properties -### Python ### -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -env/ -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -*.egg-info/ -.installed.cfg -*.egg - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*,cover -.hypothesis/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# pyenv -.python-version - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# dotenv -.env - -# virtualenv -.venv -venv/ -ENV/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + + +### Rust ### +# Generated by Cargo +# will have compiled files and executables +/target/ + +# These are backup files generated by rustfmt +**/*.rs.bk + + +### SublimeText ### +# cache files for sublime text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# workspace files are user-specific +*.sublime-workspace + +# project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using SublimeText +# *.sublime-project + +# sftp configuration file +sftp-config.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + + +# End of https://www.gitignore.io/api/rust,intellij,sublimetext diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..a842230 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,201 @@ +[[package]] +name = "backtrace" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cc" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "dtoa" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "failure" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num-traits" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-demangle" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive_internals" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "zeps-core" +version = "0.1.0" +dependencies = [ + "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" +"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" +"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719" +"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" +"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" +"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" +"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" +"checksum libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)" = "96264e9b293e95d25bfcbbf8a88ffd1aedc85b754eba8b7d78012f638ba220eb" +"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" +"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526" +"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0" +"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5" +"checksum serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db7266c7d63a4c4b7fe8719656ccdd51acf1bed6124b174f933b009fb10bcb" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b09fb3b6f248ea4cd42c9a65113a847d612e17505d6ebd1f7357ad68a8bf8693" +"checksum winapi-i686-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ec6667f60c23eca65c561e63a13d81b44234c2e38a6b6c959025ee907ec614cc" +"checksum winapi-x86_64-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98f12c52b2630cd05d2c3ffd8e008f7f48252c042b4871c72aed9dc733b96668" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..ff7ed66 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "zeps-core" +version = "0.1.0" +authors = ["The zDevelopers"] + +[dependencies] +serde = "1.0.8" +serde_json = "1.0.2" +serde_derive = "1.0.8" +failure = "0.1.1" +failure_derive = "0.1.1" + +[lib] +name = "zeps" +path = "src/lib.rs" + +[[bin]] +name = "zeps-core" +path = "src/main.rs" diff --git a/Jenkinsfile b/Jenkinsfile index 1c4b033..a369834 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,13 +1,30 @@ pipeline { - agent any - stages { - stage('Build') { - agent any - steps { - checkout scm - sh 'mvn clean install' - archiveArtifacts(artifacts: '**/target/*.jar', fingerprint: true) - } + agent { + docker 'rust:latest' + } + stages { + stage('Prepare') { + steps { + checkout scm; + } + } + + stage('Clean') { + steps { + sh 'cargo clean' + } + } + + stage('Build') { + steps { + sh 'cargo build' + } + } + + stage('Test') { + steps { + sh 'cargo test' + } + } } - } } diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 8e4da39..0000000 --- a/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - 4.0.0 - - me.cassayre.florian - NetherRail - 1.1-SNAPSHOT - - - - com.google.code.gson - gson - 2.3.1 - - - - - - - maven-assembly-plugin - - - - me.cassayre.florian.netherrail.Main - - - - jar-with-dependencies - - - - - make-assembly - package - - single - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.5.1 - - 1.7 - 1.7 - - - - - \ No newline at end of file diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 79fa3ea..0000000 --- a/requirements.txt +++ /dev/null @@ -1,11 +0,0 @@ -appdirs==1.4.3 -click==6.7 -Flask==0.12.2 -itsdangerous==0.24 -Jinja2==2.9.6 -MarkupSafe==1.0 -packaging==16.8 -path.py==10.3.1 -pyparsing==2.2.0 -six==1.10.0 -Werkzeug==0.12.2 diff --git a/serve_api.py b/serve_api.py deleted file mode 100644 index 3cf3a0d..0000000 --- a/serve_api.py +++ /dev/null @@ -1,54 +0,0 @@ -# Python 3.5+ required - -import json -import os -import sys -import subprocess - -from flask import Flask, request, make_response, jsonify -from path import Path - -app = Flask(__name__) - -if not 'ZEPS_CORE_JAR' in os.environ: - print('Please specify ZePS-Core JAR with the ZEPS_CORE_JAR environment variable.', file=sys.stderr) - sys.exit(1) - -zeps_core = Path(os.environ.get('ZEPS_CORE_JAR')).expand() - -if not zeps_core.exists(): - print('ZePS Core JAR not found. Check the ZEPS_CORE_JAR environment variable.', file=sys.stderr) - sys.exit(1) - -def call_core(command, *args): - process = subprocess.run(['java', '-jar', zeps_core, command, *[str(arg) for arg in args]], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - try: - process.check_returncode() - return make_response(process.stdout, 200, {'Content-Type': 'application/json'}) - except: - return jsonify(error=str(process.stderr), exit_code=process.returncode) - -@app.route('/list') -def list(): - return call_core('list') - -@app.route('/list/network') -def list_with_network(): - return call_core('list', 'true') - -@app.route('/path//') -def path(from_id, to_id): - official = 'official' in request.args - accessible = 'accessible' in request.args - return call_core('pathfinder', from_id, to_id, official, accessible) - -@app.route('/colors') -def colors(): - return call_core('colors') - -@app.route('/version') -def version(): - return jsonify( - version=zeps_core.namebase.replace('-jar-with-dependencies', ''), - sha256=str(zeps_core.read_hexhash('sha256')) - ) diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..3df06d0 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,76 @@ +use std::collections::HashMap; +use std::io::Read; + +use failure::Error; +use failure::ResultExt; + +use serde_json; + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(untagged)] +pub enum Coordinates { + Simple(i64,i64), + Complete(i64,i64,i64), +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(untagged)] +pub enum LinePoint { + Simple(String), + WithMetadata { + station: String, + path_type: Option, + path_secure: Option, + path_to_next: Option>, + } +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Line { + pub name: String, + pub color: String, + pub path: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Station { + pub name: String, + pub sub_name: String, + pub description: String, + pub coordinates: Coordinates, + pub real_coordinates: Option, + + pub is_main: bool, + pub has_fast_access: bool, + pub fast_access_time: f64, + pub is_hidden: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Network { + pub name: String, + pub world: String, + pub is_nether: Option, + pub coordinates_factor: Option, + pub stations: HashMap, + pub lines: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct NetworkConnection { + pub networks: (String, String), + pub autoconnect_by_name: Option, + pub autoconnect_by_proximity: Option, + pub connections: Option>, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Universe { + pub name: String, + pub networks: HashMap, + pub networks_connections: Vec, +} + +pub fn read_universe(reader: R) -> Result { + Ok(serde_json::from_reader(reader).context("Unable to parse universe data")?) +} diff --git a/src/data/coordinates.rs b/src/data/coordinates.rs new file mode 100644 index 0000000..2dc6151 --- /dev/null +++ b/src/data/coordinates.rs @@ -0,0 +1,66 @@ + +#[derive(Copy, Clone, Default, Debug)] +pub struct Coordinates { + x: i64, + y: i64, + z: i64 +} + +impl Coordinates { + pub fn new(x: i64, y: i64, z: i64) -> Coordinates { + Coordinates { + x, + y, + z, + } + } + + pub fn new_2d(x: i64, z: i64) -> Coordinates { + Coordinates { + x, + y: 0, + z, + } + } + + pub fn x(&self) -> i64 { + self.x + } + + pub fn y(&self) -> i64 { + self.y + } + + pub fn z(&self) -> i64 { + self.z + } + + /// Calculates the distance between this point and another. + /// + /// # Example + /// + /// ``` + /// # use zeps::data::Coordinates; + /// let c1 = Coordinates::new(0, 0, 0); + /// let c2 = Coordinates::new(3, 4, 0); + /// + /// assert_eq!(c1.distance(&c2), 5.0); + /// ``` + pub fn distance(&self, other: &Coordinates) -> f64 { + let x = self.x - other.x; + let y = self.y - other.y; + let z = self.z - other.z; + + ((x * x + y * y + z * z) as f64).sqrt() + } +} + + +impl From<::config::Coordinates> for Coordinates { + fn from(coord: ::config::Coordinates) -> Self { + match coord { + ::config::Coordinates::Simple(x, z) => Coordinates::new_2d(x, z), + ::config::Coordinates::Complete(x, y, z) => Coordinates::new(x, y, z), + } + } +} diff --git a/src/data/error.rs b/src/data/error.rs new file mode 100644 index 0000000..570f2b2 --- /dev/null +++ b/src/data/error.rs @@ -0,0 +1,12 @@ + +#[derive(Debug, Fail)] +pub enum InvalidConfigurationError { + #[fail(display = "Network '{}' does not exist", name)] + NetworkNotFound { name: String }, + + #[fail(display= "Station '{}' does not exist", name)] + StationNotFound { name: String }, + + #[fail(display= "Path type '{}' is not recognized", name)] + InvalidPathType { name: String } +} diff --git a/src/data/line.rs b/src/data/line.rs new file mode 100644 index 0000000..8a6c1e7 --- /dev/null +++ b/src/data/line.rs @@ -0,0 +1,100 @@ +use data::coordinates::Coordinates; +use data::error::InvalidConfigurationError; +use data::station::Station; + +use std::rc::Rc; +use std::collections::HashMap; + +#[derive(Debug, Copy, Clone)] +pub enum PathType { + Rail, + Walk +} + +impl PathType { + fn from_config(path_type: Option) -> Result { + Ok(match path_type.as_ref().map(|s| &s[..]) { + Some("rail") => PathType::Rail, + Some("walk") => PathType::Walk, + Some(other) => Err(InvalidConfigurationError::InvalidPathType { name: other.to_string() })?, + None => PathType::Rail + }) + } +} + +#[derive(Debug, Clone)] +pub struct LinePoint { + station: Rc, + path_type: PathType, + path_secure: bool, + path_to_next: Vec, +} + +impl LinePoint { + pub fn station(&self) -> &Station { + &self.station + } + + pub fn path_type(&self) -> PathType { + self.path_type + } + + pub fn path_secure(&self) -> bool { + self.path_secure + } + + pub fn path_to_next(&self) -> &[Coordinates] { + &self.path_to_next + } + + pub fn from_config(line_point: ::config::LinePoint, stations: &HashMap>) -> Result { + Ok(match line_point { + ::config::LinePoint::Simple(station) => LinePoint { + station: stations.get(&station).cloned().ok_or(InvalidConfigurationError::StationNotFound { name: station })?, + path_type: PathType::Rail, + path_secure: true, + path_to_next: Vec::new(), + }, + ::config::LinePoint::WithMetadata { station, path_type, path_secure, path_to_next } => LinePoint { + station: stations.get(&station).cloned().ok_or(InvalidConfigurationError::StationNotFound { name: station })?, + path_type: PathType::from_config(path_type)?, + path_secure: path_secure.unwrap_or(true), + path_to_next: match path_to_next { + Some(vec_coordinates) => vec_coordinates.into_iter().map(|c| c.into()).collect(), + None => Vec::new() + } + } + }) + } +} + +#[derive(Debug, Clone)] +pub struct Line { + name: String, + color: String, + path: Vec, +} + +impl Line { + pub fn name(&self) -> &str { + &self.name + } + + pub fn color(&self) -> &str { + &self.color + } + + pub fn path(&self) -> &[LinePoint] { + &self.path + } + + pub fn from_config(line: ::config::Line, stations: &HashMap>) -> Result { + let path = line.path.into_iter().map(|p| LinePoint::from_config(p, stations)).collect::>()?; + + Ok(Line { + name: line.name, + color: line.color, + path + }) + } +} diff --git a/src/data/mod.rs b/src/data/mod.rs new file mode 100644 index 0000000..128059a --- /dev/null +++ b/src/data/mod.rs @@ -0,0 +1,13 @@ + +pub mod coordinates; +pub mod line; +pub mod network; +pub mod network_connection; +pub mod station; +pub mod universe; +pub mod error; + +pub use self::coordinates::Coordinates; +pub use self::network::Network; +pub use self::universe::Universe; +pub use self::station::Station; diff --git a/src/data/network.rs b/src/data/network.rs new file mode 100644 index 0000000..830bd8a --- /dev/null +++ b/src/data/network.rs @@ -0,0 +1,69 @@ +use data::station::Station; +use data::line::Line; +use data::error::InvalidConfigurationError; + +use std::collections::HashMap; +use std::collections::hash_map::Values; +use std::rc::Rc; + +#[derive(Debug)] +pub struct Network { + minecraft_world_name: String, + display_name: String, + coordinates_factor: f64, + + stations: HashMap>, + + lines: Vec +} + +impl Network { + pub fn stations(&self) -> Stations { + Stations { iter: self.stations.values() } + } + + pub fn station(&self, station_code: &String) -> Option> { + self.stations.get(station_code).cloned() + } + + pub fn display_name(&self) -> &str { + &self.display_name + } + + pub fn world_name(&self) -> &str { + &self.minecraft_world_name + } + + pub fn coordinates_factor(&self) -> f64 { + self.coordinates_factor + } + + pub fn from_config(network: ::config::Network) -> Result { + let stations = network.stations.into_iter().map(|(k, v)| (k, Rc::new(v.into()))).collect(); + let lines = network.lines.into_iter().map(|l| Line::from_config(l, &stations)).collect::>()?; + + Ok(Network { + minecraft_world_name: network.world, + display_name: network.name, + + stations, + lines, + + coordinates_factor: network.coordinates_factor + .or(network.is_nether.map(|is_nether| if is_nether { 0.125 } else { 1.0 })) + .unwrap_or(1.0) + }) + } +} + +pub struct Stations<'a> { + iter: Values<'a, String, Rc> +} + +impl<'a> Iterator for Stations<'a> { + type Item = &'a Rc; + + fn next(&mut self) -> Option { + self.iter.next() + } +} diff --git a/src/data/network_connection.rs b/src/data/network_connection.rs new file mode 100644 index 0000000..84253f3 --- /dev/null +++ b/src/data/network_connection.rs @@ -0,0 +1,47 @@ +use std::collections::HashMap; +use std::rc::Rc; + +use data::network::Network; +use data::error::InvalidConfigurationError; + +#[derive(Debug)] +pub struct NetworkConnection { + network_1: Rc, + network_2: Rc, + autoconnect_by_name: bool, + autoconnect_by_proximity: u64, + connections: Vec<(String,String)>, +} + +impl NetworkConnection { + pub fn from_config(connection: ::config::NetworkConnection, networks_map: &HashMap>) -> Result { + let network_1 = networks_map.get(&connection.networks.0).cloned() + .ok_or(InvalidConfigurationError::NetworkNotFound {name: connection.networks.0})?; + let network_2 = networks_map.get(&connection.networks.1).cloned() + .ok_or(InvalidConfigurationError::NetworkNotFound {name: connection.networks.1})?; + + let mut connections: Vec<(String,String)> = Vec::new(); + + if let Some(config_connections) = connection.connections { + for conn in config_connections { + // Checks if the references are valid + network_1.station(&conn.0).ok_or(InvalidConfigurationError::StationNotFound { name: conn.0.clone() })?; + network_2.station(&conn.1).ok_or(InvalidConfigurationError::StationNotFound { name: conn.1.clone() })?; + + connections.push((conn.0.clone(), conn.1.clone())); + } + } + + let connections = connections; + + Ok(NetworkConnection { + network_1, + network_2, + + autoconnect_by_name: connection.autoconnect_by_name.unwrap_or(false), + autoconnect_by_proximity: connection.autoconnect_by_proximity.unwrap_or(0), + + connections + }) + } +} diff --git a/src/data/station.rs b/src/data/station.rs new file mode 100644 index 0000000..1298254 --- /dev/null +++ b/src/data/station.rs @@ -0,0 +1,30 @@ +use data::coordinates::Coordinates; + +#[derive(Debug)] +pub struct Station { + name: String, + sub_name: String, + description: String, + coordinates: Coordinates, + real_coordinates: Coordinates, + is_main: bool, + has_fast_access: bool, + fast_access_time: f64, + is_hidden: bool, +} + +impl From<::config::Station> for Station { + fn from(station: ::config::Station) -> Station { + Station { + name: station.name, + sub_name: station.sub_name, + description: station.description, + coordinates: station.coordinates.clone().into(), + real_coordinates: station.real_coordinates.unwrap_or(station.coordinates).into(), + is_main: station.is_main, + has_fast_access: station.has_fast_access, + fast_access_time: station.fast_access_time, + is_hidden: station.is_hidden.unwrap_or(false) + } + } +} diff --git a/src/data/universe.rs b/src/data/universe.rs new file mode 100644 index 0000000..b57ca94 --- /dev/null +++ b/src/data/universe.rs @@ -0,0 +1,85 @@ +use std::collections::HashMap; +use std::collections::hash_map::Values; +use std::rc::Rc; + +use data::station::Station; +use data::network::Network; +use data::network_connection::NetworkConnection; +use data::error::InvalidConfigurationError; + +pub struct Universe { + display_name: String, + networks: HashMap>, + network_connections: Vec, +} + +impl Universe { + pub fn stations(&self) -> Stations { + Stations { + iter: self.networks.values(), + inner_iter: None, + } + } + + pub fn display_name(&self) -> &str { + &self.display_name + } + + pub fn get_network(&self, connection_name: &str) -> Option<&Network> { + self.networks.get(connection_name).map(|x| x.as_ref()) + } + + pub fn get_network_handle(&self, connection_name: &str) -> Option> { + self.networks.get(connection_name).cloned() + } + + pub fn get_connections(&self) -> &[NetworkConnection] { + &self.network_connections + } + + pub fn from_config(universe: ::config::Universe) -> Result { + let mut networks: HashMap> = HashMap::new(); + + for network in universe.networks.into_iter().map(|(k, v)| (k, Network::from_config(v))) { + match network.1 { + Ok(n) => networks.insert(network.0, Rc::new(n)), + Err(e) => return Err(e) + }; + } + + let networks = networks; + + let network_connections = universe.networks_connections.into_iter() + .map(|c| NetworkConnection::from_config(c, &networks)).collect::>()?; + + Ok(Universe { + display_name: universe.name, + networks, + network_connections, + }) + + } +} + +pub struct Stations<'a> { + iter: Values<'a, String, Rc>, + inner_iter: Option<::data::network::Stations<'a>>, +} + +impl<'a> Iterator for Stations<'a> { + type Item = &'a Rc; + + fn next(&mut self) -> Option { + loop { + if let Some(ref mut inner) = self.inner_iter { + if let Some(x) = inner.by_ref().next() { + return Some(x) + } + } + match self.iter.next().map(|x| x.as_ref()).map(Network::stations) { + None => return None, + next => self.inner_iter = next, + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..ea274f2 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,27 @@ +extern crate serde; +extern crate serde_json; +extern crate failure; + +#[macro_use] extern crate serde_derive; +#[macro_use] extern crate failure_derive; + +pub mod config; +pub mod data; + +pub use data::Universe; + +use std::fs::File; +use std::io::Read; +use std::path::Path; + +use failure::Error; +use failure::ResultExt; + +pub fn read_universe(reader: R) -> Result { + Ok(Universe::from_config(config::read_universe(reader)?)?) +} + +pub fn read_universe_from_file>(path: P) -> Result { + let file = File::open(&path).with_context(|_| format!("Unable to open universe data file '{}'", path.as_ref().to_string_lossy()))?; + Ok(read_universe(file).with_context(|_| format!("Unable to load universe data file '{}'", path.as_ref().to_string_lossy()))?) +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..7488140 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,37 @@ +extern crate zeps; +extern crate failure; + +use std::io::Write; +use failure::Error; +use zeps::data::universe::Universe; + +fn print_error(e: &Error) { + let seriously_dude = "Unable to write to standard error output (stderr)!"; + let stderr = &mut ::std::io::stderr(); + let mut stderr = stderr.lock(); + + writeln!(stderr, " [!] Error: {}", e).expect(seriously_dude); + + for cause in e.causes().skip(1) { + writeln!(stderr, " | Cause: \t{}", cause).expect(seriously_dude); + } + + if cfg!(debug_assertions) { + writeln!(stderr, "\n\n [?] Backtrace: {:#?}", e.backtrace()).expect(seriously_dude); + } +} + + +fn main() { + if let Err(ref e) = run() { + print_error(e); + ::std::process::exit(1); + } +} + +fn run() -> Result<(), Error> { + let u: Universe = zeps::read_universe_from_file("./tests/fixtures/with_data.json")?; + let s: Vec<_> = u.stations().collect(); + println!("Stations: {:#?}", s); + Ok(()) +} diff --git a/src/main/java/me/cassayre/florian/netherrail/Direction.java b/src/main/java/me/cassayre/florian/netherrail/Direction.java deleted file mode 100644 index e24ba88..0000000 --- a/src/main/java/me/cassayre/florian/netherrail/Direction.java +++ /dev/null @@ -1,58 +0,0 @@ -package me.cassayre.florian.netherrail; - -/** - * Represents a cardinal direction. - */ -public enum Direction -{ - NORTH(0, "Nord"), - EAST(1, "Est"), - SOUTH(2, "Sud"), - WEST(3, "Ouest"); - - private final int INDEX; - private final String NAME; - - private Direction(final int index, final String name) - { - INDEX = index; - NAME = name; - } - - /** - * Get the opposite side of this direction. - * @return the opposite direction - */ - public Direction opposite() - { - if(this == NORTH) - return SOUTH; - if(this == EAST) - return WEST; - if(this == SOUTH) - return NORTH; - if(this == WEST) - return EAST; - - throw new IllegalStateException("No opposite found!"); - } - - /** - * Get the index of this direction. - * @return the index - */ - public int getIndex() - { - return INDEX; - } - - /** - * Get the french name for this direction, begining with a capital. - * @return the name of the direction - */ - @Override - public String toString() - { - return NAME; - } -} diff --git a/src/main/java/me/cassayre/florian/netherrail/Main.java b/src/main/java/me/cassayre/florian/netherrail/Main.java deleted file mode 100644 index 4a32631..0000000 --- a/src/main/java/me/cassayre/florian/netherrail/Main.java +++ /dev/null @@ -1,104 +0,0 @@ -package me.cassayre.florian.netherrail; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; - -public class Main -{ - - public static void main(String[] args) - { - final JsonObject error = new JsonObject(); - - error.addProperty("time", 0); - error.addProperty("result", "failed"); - - // TODO Something cleaner here. - - try - { - switch (args[0].toLowerCase()) - { - case "pathfinder": - System.out.println(new PathFinder(Station.values()[Integer.parseInt(args[1])], Station.values()[Integer.parseInt(args[2])], args.length >= 4 ? Boolean.valueOf(args[3]) : true, args.length >= 5 ? Boolean.valueOf(args[4]) : true).find()); - return; - - case "list": - boolean withNetwork = false; - - if (args.length >= 2) - { - withNetwork = Boolean.parseBoolean(args[1]); - } - - final JsonObject listRoot = new JsonObject(); - - listRoot.addProperty("result", "success"); - listRoot.addProperty("time", 0); - - listRoot.addProperty("withNetwork", withNetwork); - - final JsonArray stations = new JsonArray(); - - for (Station station : Station.getStationsAlphabetically()) - { - stations.add(station.toJson(withNetwork)); - } - - listRoot.add("stations", stations); - - System.out.print(listRoot); - return; - - case "colors": - System.out.println(NetworkAreas.toJson()); - return; - - case "map": - MapCreator.saveMap(args.length > 2 ? args[2] : "netherrail_map.png", args.length > 1 ? Integer.parseInt(args[1]) : 2); - return; - - default: - throw new IllegalArgumentException(args[0]); - } - } - - // TODO Create a REAL error catcher. - - catch(ArrayIndexOutOfBoundsException ex) - { - error.add("cause", new JsonPrimitive("Not enough arguments.")); - } - catch(NumberFormatException ex) - { - error.add("cause", new JsonPrimitive("Invalid station id.")); - } - catch(PathImpossibleException ex) - { - error.add("cause", new JsonPrimitive("Path not found.")); - } - catch(IllegalArgumentException ex) - { - error.add("cause", new JsonPrimitive("Invalid argument.")); - } - catch(Exception ex) - { - error.add("cause", new JsonPrimitive("Unknown internal error.")); - } - - System.out.print(error); - } - - /* - (Ancien) - - Paramètres : - - - Chemin officiel OU non officiel - - Chemins accessibles OU en travaux - - Distance la plus courte OU trajet le plus rapide - - Descente en cours de route OU descente à un arrêt officiel - - */ -} diff --git a/src/main/java/me/cassayre/florian/netherrail/MapCreator.java b/src/main/java/me/cassayre/florian/netherrail/MapCreator.java deleted file mode 100644 index 6a93641..0000000 --- a/src/main/java/me/cassayre/florian/netherrail/MapCreator.java +++ /dev/null @@ -1,107 +0,0 @@ -package me.cassayre.florian.netherrail; - -import javax.imageio.ImageIO; -import java.awt.*; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; - -public final class MapCreator -{ - private MapCreator() {} - - private static int zoomLevel = 2; - - private static int toImageX(int mapX) - { - return (mapX + 837) / 2 * zoomLevel; - } - - private static int toImageY(int mapY) - { - return (mapY + 1763) / 2 * zoomLevel; - } - - /** - * Creates a basic map rendering to help correcting indexation issues. - * @param location the path to save the image - * @throws IOException - */ - public static void saveMap(String location, int zoomLevel) throws IOException - { - MapCreator.zoomLevel = zoomLevel; - - BufferedImage img = new BufferedImage(798 * zoomLevel, 1194 * zoomLevel, BufferedImage.TYPE_INT_ARGB); - - Graphics2D g = img.createGraphics(); - - for(Station station : Station.values()) - { - for(Direction direction : Direction.values()) - { - Station connection = station.getSubStation(direction); - - if(connection == null) - continue; - - PathType pathType = station.getPathType(direction); - - if(pathType == PathType.OFFICIAL_RAIL) - g.setColor(new Color(157, 221, 255)); - else if(pathType == PathType.OFFICIAL_WALKING) - g.setColor(new Color(57, 151, 147)); - else if(pathType == PathType.UNOFFICIAL_RAIL) - g.setColor(new Color(82, 123, 248)); - else if(pathType == PathType.UNOFFICIAL_WALKING) - g.setColor(new Color(136, 87, 255)); - - g.setStroke(new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); - - g.drawLine(toImageX(station.getX()), toImageY(station.getY()), toImageX(connection.getX()), toImageY(connection.getY())); - } - } - - - for(Station station : Station.values()) - { - if (station.isIntersection()) - { - g.setColor(Color.GREEN); - if(station.isDangerous()) - g.setColor(new Color(41, 156, 27)); - - if(!station.isVisible()) - g.setColor(new Color(206, 227, 194)); - - g.fillOval(toImageX(station.getX()) - 10, toImageY(station.getY()) - 10, 20, 20); - } - - if (station.isPortal()) g.setColor(new Color(159, 87, 209)); - if (station.isDangerous()) g.setColor(new Color(156, 69, 108)); - - if (!station.isVisible()) g.setColor(new Color(227, 194, 226)); - - g.fillOval(toImageX(station.getX()) - 8, toImageY(station.getY()) - 8, 16, 16); - - if (station.isVisible()) - { - g.setColor(Color.DARK_GRAY); - - AffineTransform fontAT = new AffineTransform(); - fontAT.setToScale(2, 2); - Font theFont = g.getFont(); - fontAT.rotate(-Math.PI / 4.0); - Font theDerivedFont = theFont.deriveFont(fontAT); - g.setFont(theDerivedFont); - - g.drawString(station.toString(), toImageX(station.getX() + 20), toImageY(station.getY()) - 20); - - g.setFont(theFont); - } - - } - - ImageIO.write(img, "png", new File(location)); - } -} diff --git a/src/main/java/me/cassayre/florian/netherrail/NetworkAreas.java b/src/main/java/me/cassayre/florian/netherrail/NetworkAreas.java deleted file mode 100644 index a862e8b..0000000 --- a/src/main/java/me/cassayre/florian/netherrail/NetworkAreas.java +++ /dev/null @@ -1,141 +0,0 @@ -package me.cassayre.florian.netherrail; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; - -import java.awt.Color; -import java.util.*; - -public class NetworkAreas -{ - private final static List areas = new ArrayList<>(); - - static - { - registerX(new Color(255, 236, 39), -714); - registerX(new Color(119, 98, 40), -570); - registerX(new Color(255, 189, 206), -529); - registerX(new Color(255, 122, 238), -485, 688); - registerX(new Color(221, 72, 70), -378, -286, 425); - registerX(new Color(94, 116, 255), -341); - registerX(new Color(110, 244, 5), -414, -234); - registerX(new Color(255, 116, 8), -251, -184); - registerX(new Color(165, 178, 255), 30, 142, 148, 259); - registerX(new Color(255, 170, 20), 294); - registerX(new Color(64, 168, 186), 540); - - registerY(new Color(110, 176, 86), 539); - registerY(new Color(255, 116, 8), 254); - registerY(new Color(221, 72, 70), 47, 251); - registerY(new Color(165, 178, 255), -84, -94, -120, -408); - registerY(new Color(0, 0, 0), -260, -301, -342); - registerY(new Color(255, 170, 20), -702); - registerY(new Color(64, 168, 186), -780, -1160); - registerY(new Color(255, 236, 39), -823); - registerY(new Color(255, 189, 206), -853); - registerY(new Color(165, 178, 255), -863); - registerY(new Color(119, 98, 40), -1069); - registerY(new Color(94, 116, 255), -1208); - registerY(new Color(255, 122, 238), -1436); - registerY(new Color(110, 244, 5), -1740); - } - - public static void registerX(Color color, int... coordinates) - { - register(Area.Orientation.VERTICAL, color, coordinates); - } - - public static void registerY(Color color, int... coordinates) - { - register(Area.Orientation.HORIZONTAL, color, coordinates); - } - - private static void register(Area.Orientation orientation, Color color, int... coordinates) - { - if(orientation == null) - throw new IllegalArgumentException("Orientation cannot be null."); - - if(color == null) - throw new IllegalArgumentException("Color cannot be null."); - - areas.add(new Area(orientation, color, coordinates)); - } - - public static List getAreas(Area.Orientation orientation) - { - List list = new ArrayList<>(); - - for(Area area : areas) - { - if(area.ORIENTATION == orientation) - list.add(area); - } - - return list; - } - - public static JsonObject toJson() - { - JsonObject object = new JsonObject(); - - JsonArray arrayX = new JsonArray(); - JsonArray arrayY = new JsonArray(); - - for(Area area : areas) - { - JsonObject areaObject = new JsonObject(); - - JsonArray array = new JsonArray(); - - for(Integer value : area.COORDINATES) - array.add(new JsonPrimitive(value)); - - areaObject.add("coordinates", array); - - areaObject.add("color", colorToJson(area.COLOR)); - - if(area.ORIENTATION == Area.Orientation.VERTICAL) - arrayX.add(areaObject); - else if(area.ORIENTATION == Area.Orientation.HORIZONTAL) - arrayY.add(areaObject); - } - - object.add("northsouth", arrayX); - - object.add("eastwest", arrayY); - - return object; - } - - public static JsonObject colorToJson(Color color) - { - JsonObject object = new JsonObject(); - - object.add("red", new JsonPrimitive(color.getRed())); - object.add("green", new JsonPrimitive(color.getGreen())); - object.add("blue", new JsonPrimitive(color.getBlue())); - - return object; - } -} - -class Area -{ - public final Orientation ORIENTATION; - public final int[] COORDINATES; - public final Color COLOR; - - public Area(Orientation orientation, Color color, int... coordinates) - { - ORIENTATION = orientation; - COORDINATES = coordinates; - COLOR = color; - } - - enum Orientation - { - VERTICAL, - HORIZONTAL - } -} diff --git a/src/main/java/me/cassayre/florian/netherrail/PathFinder.java b/src/main/java/me/cassayre/florian/netherrail/PathFinder.java deleted file mode 100644 index 19f1fab..0000000 --- a/src/main/java/me/cassayre/florian/netherrail/PathFinder.java +++ /dev/null @@ -1,178 +0,0 @@ -package me.cassayre.florian.netherrail; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; - -import java.util.*; - -public class PathFinder -{ - private final Station BEGIN, END; - private final boolean LEGAL, ACCESSIBLE; - - private final Map weights = new HashMap(); - private final Map before = new HashMap(); - private final Set went = new HashSet(); - - private final static double WALKING_SPEED = 1.35; - private final static int DIRECTION_CHANGE_TIME = 15; - private final static int INTERSECTION_TIME = 30; - - /** - * Creates a new pathfinder object. - * @param begin the station to begin at - * @param end the station to go to - * @param legal if official stations only should be used - * @param accessible if safe stations only should be used - */ - public PathFinder(Station begin, Station end, final boolean legal, final boolean accessible) - { - BEGIN = begin; - END = end; - - LEGAL = legal; - ACCESSIBLE = accessible; - } - - /** - * Finds the shorter path with the given parameters. - * @return the path to follow - * @throws PathImpossibleException if no path has been found - */ - public JsonObject find() throws PathImpossibleException - { - long t1 = System.currentTimeMillis(); - - weights.put(BEGIN, 0); - - for(Station minWeight = getMinWeight(); minWeight != END; minWeight = getMinWeight()) - { - for(Direction direction : Direction.values()) - { - if(minWeight == null) - throw new PathImpossibleException("Cannot find a valid path for " + BEGIN + " to " + END); - - Station sub = minWeight.getSubStation(direction); - - if(sub == null) - continue; - - if(went.contains(sub)) - continue; - - - if((weights.get(sub) == null || weights.get(minWeight) + minWeight.getDistanceFrom(sub) < weights.get(sub)) && (!LEGAL || minWeight.getPathType(sub) == PathType.OFFICIAL_RAIL) && (!ACCESSIBLE || !sub.isDangerous())) - { - - weights.put(sub, (int) (weights.get(minWeight) + minWeight.getDistanceFrom(sub))); - before.put(sub, minWeight); - - if(minWeight.getPathType(sub) == PathType.UNOFFICIAL_WALKING) - { - weights.put(sub, (int) (weights.get(sub) * WALKING_SPEED)); - } - - Station ant = before.get(minWeight); - if(ant != null) - { - Direction dir1 = ant.getDirection(minWeight); - Direction dir2 = minWeight.getDirection(sub); - - if(dir1 != dir2) - weights.put(sub, weights.get(sub) + DIRECTION_CHANGE_TIME); - } - - if(sub.isIntersection()) - weights.put(sub, weights.get(sub) + INTERSECTION_TIME); - } - - } - - went.add(minWeight); - } - - - final List path = createPath(); - - - JsonObject object = new JsonObject(); - - long t2 = System.currentTimeMillis(); - - object.add("result", new JsonPrimitive("success")); - - object.add("time", new JsonPrimitive(t2 - t1)); - - object.add("begin", new JsonPrimitive(BEGIN.name().toLowerCase())); - - object.add("end", new JsonPrimitive(END.name().toLowerCase())); - - object.add("travel_time", new JsonPrimitive((int) Math.ceil(weights.get(END) / 7))); - - - JsonArray array = new JsonArray(); - - // Old stuff - int distance = 0; - - for(int i = 0; i < path.size(); i++) - { - boolean hasNext = i < path.size() - 1; - - JsonObject objectStation = Station.buildStationPathObject(path.get(i), hasNext ? path.get(i + 1) : null); - - if(hasNext) - distance += path.get(i).getDistanceFrom(path.get(i + 1)); - - array.add(objectStation); - } - - object.add("path", array); - - return object; - } - - /** - * Get the station with the lowest weight that has not been explored yet. - * Can return null if no station was found. - * @return the station with the lowest weight - */ - public Station getMinWeight() - { - Station min = null; - - for(Station station : weights.keySet()) - { - if(!went.contains(station) && (min == null || weights.get(station) < weights.get(min))) - { - min = station; - } - } - - return min; - } - - /** - * Creates a list representing the path to follow. - * @return a list of stations - */ - public List createPath() - { - List path = new ArrayList(); - - Station current = END; - - path.add(current); - - while(current != BEGIN) - { - current = before.get(current); - path.add(current); - } - - Collections.reverse(path); - - return path; - } -} diff --git a/src/main/java/me/cassayre/florian/netherrail/PathImpossibleException.java b/src/main/java/me/cassayre/florian/netherrail/PathImpossibleException.java deleted file mode 100644 index 9fb2196..0000000 --- a/src/main/java/me/cassayre/florian/netherrail/PathImpossibleException.java +++ /dev/null @@ -1,22 +0,0 @@ -package me.cassayre.florian.netherrail; - -/** - * This exception should be thrown when no valid path has been found. - */ -public class PathImpossibleException extends Exception -{ - public PathImpossibleException() - { - super(); - } - - public PathImpossibleException(String ex) - { - super(ex); - } - - public PathImpossibleException(String ex, Throwable throwable) - { - super(ex, throwable); - } -} diff --git a/src/main/java/me/cassayre/florian/netherrail/PathType.java b/src/main/java/me/cassayre/florian/netherrail/PathType.java deleted file mode 100644 index 7b2f7b4..0000000 --- a/src/main/java/me/cassayre/florian/netherrail/PathType.java +++ /dev/null @@ -1,22 +0,0 @@ -package me.cassayre.florian.netherrail; - -/** - * Represents a path type between two stations. - */ -public enum PathType -{ - OFFICIAL_RAIL, - OFFICIAL_WALKING, - UNOFFICIAL_RAIL, - UNOFFICIAL_WALKING; - - public boolean isRail() - { - return this == OFFICIAL_RAIL || this == UNOFFICIAL_RAIL; - } - - public boolean isOfficial() - { - return this == OFFICIAL_RAIL || this == OFFICIAL_WALKING; - } -} \ No newline at end of file diff --git a/src/main/java/me/cassayre/florian/netherrail/Station.java b/src/main/java/me/cassayre/florian/netherrail/Station.java deleted file mode 100644 index 6af58a7..0000000 --- a/src/main/java/me/cassayre/florian/netherrail/Station.java +++ /dev/null @@ -1,821 +0,0 @@ -package me.cassayre.florian.netherrail; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * Represents an intersection, a portal or a point of interest. - */ -public enum Station -{ - NOUVEA(-714, -702, "Nouvéa", StationType.INTERSECTION_AND_PORTAL), - ZIG_ZAG(-529, -702, "Zig Zag", StationType.INTERSECTION_ONLY), - PEPINIERE_OUEST(-714, -582, "Pépinière Ouest", StationType.INTERSECTION_AND_PORTAL), - FJORDS(-529, -823, "Fjords", StationType.INTERSECTION_ONLY), - FLEURS(-714, -823, "Fleurs", StationType.INTERSECTION_ONLY), - PEPINIERE_EST(-529, -582, "Pépinière Est", StationType.INTERSECTION_AND_PORTAL), - PERE_DODUE(-714, -865, "Chez PèreDodue"), - PKTEDDYB(-714, -895, "Chez PkTeddyB"), - PINPINB(-714, -943, "Chez Pinpin'b"), - CAMOUIL(-714, -1027, "Chez Camouil"), - VERTICALE(-714, -1069, "Verticale des fous", StationType.INTERSECTION_ONLY), - UZINE(-756, -1069, "UZine", StationType.INTERSECTION_AND_PORTAL), - CARBONE(-570, -1069, "Carbone", StationType.INTERSECTION_ONLY), - SIGICOAL_TITAN(-570, -1002, "Sigicoal Titan", StationType.INTERSECTION_AND_PORTAL), - RESERVE(-341, -702, "Réserve de chasse", StationType.INTERSECTION_AND_PORTAL), - PUMPKIN_VINES(-714, -1306, "Pumpkin Vines"), - KRAVEN(-714, -1222, "Kraven", StationType.INTERSECTION_AND_PORTAL), - MIDNIGHT_CITY(-714, -1200, "Midnight City"), - CHESNATOWN(-714, -1351, "Chesnatown", StationType.INTERSECTION_AND_PORTAL), - SEPTENTRION_OCCIDENTAL(-714, -1436, "Bout Septentrional du monde", StationType.INTERSECTION_ONLY), - PIC_MARECAGE(-779, -1436, "Pic du marécage", StationType.INTERSECTION_AND_PORTAL), - TARDIS(-800, -1435, "T.A.R.D.I.S", StationType.INTERSECTION_AND_PORTAL), - TOUR_KIFEPEUR(-714, -1507, "La Tour Kifépeur", StationType.INTERSECTION_AND_PORTAL), - VEKTOR(-714, -1585, "Chez Vektor", StationType.INTERSECTION_AND_PORTAL), - PIERIRO_BILLGATESARDECHE(-714, -1633, "Chez Pieriro et BillGatesardeche", StationType.INTERSECTION_AND_PORTAL), - HURLENEIGE(-540, -1436, "Hurleneige", StationType.INTERSECTION_AND_PORTAL), - FROSTBORN_CANYON(-485, -1436, "Frostborn Canyon", StationType.INTERSECTION_ONLY), - VOYAGE_ECLAIR(-485, -1675, "Voyage-Éclair (Sanctuary)", StationType.INTERSECTION_AND_PORTAL), - GARDIENS(-413, -1436, "Chute de gardiens", StationType.INTERSECTION_AND_PORTAL), - FORET_COUVERTE(-570, -1129, "Forêt couverte et Marais montagneux"), - BASTION_DU_CACTUS_GIVRE(-714, -451, "Bastion du cactus givré"), - MOINTAGNE(-714, -397, "Mointagne"), - ISLA_NUBLAR(-529, -520, "Isla Nublar"), - COLLINE_BOULEAUX(-485, -853, "Colline des bouleaux géants"), - AEROPORT(-436, -853, "Aéroport"), - SOURCE(-419, -853, "Source miraculeuse", StationType.INTERSECTION_AND_PORTAL), - ELERIA(-341, -823, "Eléria", StationType.INTERSECTION_AND_PORTAL), - SORCIERES(-341, -871, "Usine à sorcières"), - ATLANTIS(-341, -913, "Atlantis", StationType.INTERSECTION_AND_PORTAL), - ENGORIA(-341, -961, "Engoria"), - DOGGO(-341, -1015, "République Souterraine Doggo"), - BOREE(-234, -1436, "Borée", StationType.INTERSECTION_ONLY), - KERSUB(-414, -1700, "Kersub", StationType.INTERSECTION_AND_PORTAL), - GHAST(-341, -1069, "Ghast taquin", StationType.INTERSECTION_ONLY), - MOREA(-473, -1069, "Îles de la Moréa"), - PIC_ASSAUT(-234, -1069, "Pic Assaut", StationType.INTERSECTION_ONLY), - ILE_FLEURS(-234, -1130, "Île aux fleurs"), - WITHER(-234, -1232, "Lande du Wither", StationType.INTERSECTION_AND_PORTAL), - CREVASSES(-234, -1315, "Croisée des crevasses"), - LAC_AMOUREUX(-234, -1351, "Lac des amoureux"), - SEPTENTRION(30, -1436, "Septentrion", StationType.INTERSECTION_AND_PORTAL), - TENTACLES(206, -1436, "Tentaclès", StationType.INTERSECTION_AND_PORTAL), - MESAPLAYA(30, -1278, "Mesaplaya", StationType.INTERSECTION_AND_PORTAL), - RIVE_BLANCHE(30, -1207, "Rive Blanche", StationType.INTERSECTION_AND_PORTAL), - FALAISIE(30, -1069, "Falaisie", StationType.INTERSECTION_ONLY), - TUX(108, -1069, "Tux concursus", StationType.INTERSECTION_AND_PORTAL), - PIC_MORIPLAY(195, -1069, "Pic Moriplay"), - CHESLAND(275, -1069, "Chesland", StationType.INTERSECTION_AND_PORTAL), - SAINT_KEHAINSYS(540, -1069, "Saint-Kéhainsys", StationType.INTERSECTION_ONLY), - CHASSEUR(540, -1160, "Chasseur", StationType.INTERSECTION_ONLY), - PLATYPUS(570, -1160, "Platypus", StationType.INTERSECTION_AND_PORTAL), - WITHER_DESAFFECTE(430, -1160, "Wither desaffecté", StationType.INTERSECTION_AND_PORTAL), - REFUGE_ARCTIQUE(540, -1248, "Refuge Arctique"), - BASE_MILITAIRE_MEUDON(540, -1275, "Base militaire et château de Meudon"), - MONTAGNE_SOLITAIRE(540, -1302, "Montagne solitaire"), - POUTLARD(540, -1391, "Poutlard", StationType.INTERSECTION_AND_PORTAL), - IVUJIVIK(540, -1363, "Ivujivik", StationType.PORTAL_ONLY), - NORDET(540, -1436, "Nordet", StationType.INTERSECTION_ONLY), - D_MONSTRATOR(688, -1677, "D-Monstrator", StationType.INTERSECTION_AND_PORTAL), - INTERSECT_33(688, -1436, "Intersection", StationType.INTERSECTION_ONLY, true, false), - CAPITALE_ADMINISTRATIVE_FEDERALE(638, -1436, "Capitale Administrative Fédérale", StationType.INTERSECTION_AND_PORTAL), - GLACIER(-529, -342, "Glacier", StationType.INTERSECTION_AND_PORTAL), - UNKNOWN_1(-714, -342, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - NOT_FINISHED_1(-529, -301, "En travaux", StationType.INTERSECTION_ONLY, false, true), - NOT_FINISHED_2(-714, -301, "En travaux", StationType.INTERSECTION_ONLY, false, true), - BIRDY(-714, -241, "Palais de Birdy"), - CHEZ_SQUALL(-714, -103, "Chez Squall"), - GRAND_OUEST(-714, 47, "Aiguillage du Grand Ouest", StationType.INTERSECTION_ONLY), - AMAZONIA(-804, 47, "Amazonia", StationType.INTERSECTION_AND_PORTAL), - VILLAGE_CORROMPU(-655, 47, "Village corrompu", StationType.INTERSECTION_AND_PORTAL), - PERE_MORIEL(-621, 47, "Père Moriel", StationType.INTERSECTION_AND_PORTAL), - SOMONITES(-529, 47, "Désert des Somonites", StationType.INTERSECTION_ONLY), - FALLEN_KINGDOM(-714, 267, "Fallen Kingdom", StationType.INTERSECTION_AND_PORTAL), - OCEAN_GAUCHE(-714, 539, "Océan du côté gauche", StationType.INTERSECTION_ONLY), - NAILA(-804, 539, "Naila"), - DEPOT(-529, 539, "Dépôt", StationType.INTERSECTION_ONLY), - KERLAM(-529, 421, "Kerlam", StationType.INTERSECTION_AND_PORTAL), - ALEXANDRIE(-529, 292, "Alexandrie", StationType.INTERSECTION_AND_PORTAL), - GUET(-529, 598, "Tour de guet"), - ACADEMIE(-219, -702, "Académie des Mages"), - BLAZE_ROAD(-145, -702, "Blaze Road", StationType.INTERSECTION_ONLY), - MER_ADIEUX(30, -702, "Mer des Adieux", StationType.INTERSECTION_ONLY), - FERME_VILLAGEOIS(30, -829, "Ferme à Villageois", StationType.INTERSECTION_AND_PORTAL), - POINT_CENTRAL(30, -863, "Point Central", StationType.INTERSECTION_AND_PORTAL), - MONUMENT_DE_POINT_CENTRAL(-21, -863, "Monument de Point Central", StationType.INTERSECTION_AND_PORTAL), - ARCHIPEL_TROPE(142,-863, "Archipel Trope", StationType.INTERSECTION_AND_PORTAL), - PINK_TOWER(142,-907, "Pink Tower", StationType.INTERSECTION_AND_PORTAL), - JONCTION(121, -702, "Jonction des continents"), - MARAYA(294, -702, "Maraya Toumismo", StationType.INTERSECTION_ONLY), - SPERANZA_PRISTINE(540, -702, "Speranza Pristine", StationType.INTERSECTION_ONLY), - COL_AIGUES(540, -780, "Col Aigues", StationType.INTERSECTION_ONLY), - AIGUES_CHAUDES(668, -780, "Aigues chaudes", StationType.INTERSECTION_AND_PORTAL), - PICS_PRECIPICES(-234, -1183, "Pics et précipices"), - VYNCIS(294, -661, "Vyncis", StationType.INTERSECTION_AND_PORTAL), - TECI_TARZAN(294, -637, "La téci d'Tarzan"), - CARTOUME(294, -604, "Cartoume", StationType.INTERSECTION_AND_PORTAL), - VENICE(294, -529, "Venice", StationType.INTERSECTION_AND_PORTAL), - PROJETZ(30, -613, "ProjetZ", StationType.INTERSECTION_AND_PORTAL), - UNKNOWN_2(30, -408, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - VILLAGE_MAYA(30, -318, "Village Maya"), - AIGUILLAGE_BAZAR(30, -301, "Aiguillage du Bazar bizarre", StationType.INTERSECTION_ONLY), - BAZAR(-113, -301, "Bazar bizarre", StationType.INTERSECTION_AND_PORTAL), - WALL_STREET(-144, -301, "Wall Street"), - CONSTRUCTEURS(212, -408, "Constructeurs de l'extrême", StationType.INTERSECTION_AND_PORTAL), - UNKNOWN_3(259, -408, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - UNKNOWN_4(259, -301, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - UNKNOWN_5(259, -260, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - ETHERNIA(259, -271, "Ethernia", StationType.INTERSECTION_AND_PORTAL), - CART_TOON(540, -260, "Cart Toon", StationType.INTERSECTION_ONLY), - SPERANZA(518, -702, "Sperenza"), - ILE_PRISTINE(540, -672, "Île Pristine"), - ORDOGRAD(540, -558, "Ordograd", StationType.PORTAL_ONLY), - CENTRE_SPATIAL(540, -469, "Centre Spatial", StationType.PORTAL_ONLY), - GOULAG(582, -260, "Goulag et Usine à fer", StationType.INTERSECTION_AND_PORTAL), - HALDA(684, -260, "Halda", StationType.INTERSECTION_AND_PORTAL), - TASSE(714, -260, "La tasse", StationType.INTERSECTION_AND_PORTAL), - EURAZIE(259, 47, "EuraZie", StationType.INTERSECTION_ONLY), - SECTEUR_GHASTS(295, 47, "Secteur Ghasts", StationType.INTERSECTION_ONLY), - CLEM(425, 47, "Secteur Clem", StationType.INTERSECTION_ONLY), - LAPUTA(425, 200, "Laputa", StationType.INTERSECTION_AND_PORTAL), - MELBURNE(540, 47, "Melburne", StationType.INTERSECTION_ONLY), - MACCRAGE(30, -202, "Secteur Maccrage", StationType.INTERSECTION_AND_PORTAL), - BALADE(30, -146, "Balade", StationType.INTERSECTION_AND_PORTAL), - UNKNOWN_7(30, -120, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - UNKNOWN_8(148, -120, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - ARENE_BLAZIQUE(148, -32, "Arène blazique"), - FORTERESSE_LOUL(175, -120, "Forteresse de Sire Loul"), - UNKNOWN_9(30, -94, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - UNKNOWN_10(148, -94, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - CITE_SCIENCES(190, -94, "Cité des sciences"), - GRAND_TEMPLE(30, -84, "Grand temple de May"), - COIN_NATURISTES(93, -84, "Le coin des naturistes"), - CHEZ_Z(30, -65, "Chez Z"), - VILLAGE_ELFIQUE(30, -54, "Village elfique"), - FORTERESSE_2(30, -41, "Forteresse 2"), - FLANGORIA(30, -24, "Flangoria"), - ATTRACTION(30, -3, "Attractions"), - UZINE_COCHON(30, 23, "UZine à cochons"), - VAALON(30, 47, "Vaalon", StationType.INTERSECTION_AND_PORTAL), - MOBY_DICK(89, 47, "New Libery & Moby Dick"), - AGRISUB_1(132, 47, "Agrisub I", StationType.INTERSECTION_AND_PORTAL), - UNKNOWN_11(148, 47, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - AZIE(221, 47, "Azie", StationType.INTERSECTION_AND_PORTAL), - SILVERISLAND(276, 47, "Silverisland"), - COLLINE_JAMBES(-46, 47, "La colline a des jambes"), - GRANDE_LOTTERIE(-73, 47, "La grande lotterie"), - FORTERESSE_1(-110, 47, "Forteresse 1"), - OCTOPUSSY(-129, 47, "Octopussy", StationType.INTERSECTION_AND_PORTAL), - AIGUILLAGE_CHATEAUNOIR(-251, 47, "Aiguillage Château Noir", StationType.INTERSECTION_ONLY), - CARROUSEL_HOLERIBUS(-251, 254, "Carrousel Holeribus"), - UNKNOWN_17(-184, 254, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - CHATEAU_NOIR(-184, 293, "Château Noir", StationType.INTERSECTION_AND_PORTAL), - CHATEAU_GLACES(-242, 47, "Château des glaces"), - ARRAKIS(-251, 65, "Arrakis"), - PIXEL_ART(-286, 47, "Pixel Art", StationType.INTERSECTION_ONLY), - MUSEE_PIXEL(-286, -93, "Musée du pixel art"), - BANANEROSE(-361, 47, "Ville de bananerose"), - CIUDAD(-378, 47, "Ciudad Esmeralda", StationType.INTERSECTION_AND_PORTAL), - BLAZES_POINT(-378, -152, "Blazes point"), - UNKNOWN_12(-341, -1208, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - USINE_OR(-527, -1208, "Usine à or et à XP"), - POSEIDOPOLIS_EST(540, 251, "Poseidopolis Est", StationType.INTERSECTION_AND_PORTAL), - POSEIDOPOLIS(450, 251, "Poseidopolis", StationType.INTERSECTION_AND_PORTAL), - INTERSECT_34(425, 251, "Intersection", StationType.INTERSECTION_ONLY, true, false), - ILE_PARADISIAQUE_BOBBIX(540, 366, "Île paradisiaque (Bobbix)", StationType.PORTAL_ONLY), - SUDET(540, 539, "Sudet", StationType.INTERSECTION_ONLY, false, false), - CARDINALE_EST(708, 539, "Cardinale Est", StationType.INTERSECTION_AND_PORTAL), - SURET(540, 600, "Suret", StationType.INTERSECTION_AND_PORTAL), - USINE_GARDIENS(426, 539, "Usine à gardiens", StationType.INTERSECTION_AND_PORTAL), - FORTERESSE_MYSTERIEUSE(-132, 539, "Mystérieuse forteresse", StationType.INTERSECTION_AND_PORTAL), - HASHTAG(-348, 539, "HashTag", StationType.INTERSECTION_AND_PORTAL), - ILE_ZACQUES(-480, 539, "Île de Zâcques"), - UNKNOWN_13(-529, -853, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - UNKNOWN_14(-234, -1740, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - UNKNOWN_15(-414, -1740, "Inconnue", StationType.INTERSECTION_ONLY, true, false), - ILE_VOLCANIQUE(-714, 384, "Île volcanique"), - FJORD_SUD(-529, -763, "Fjord Sud"), - FJORD_CENTRAL(-529, -786, "Fjord Central"), - FJORD_NORD(-529, -795, "Fjord Nord"), - LAGON_DE_FLUM(-575, -823, "Lagon de Flum"), - FORTERESSE_DES_FLEURS(-611, -823, "Forteresse des fleurs"), - FLEURS_CREVASSES(-636, -823, "Des fleurs et des crevasses"), - ISLA_SOMA(-529, -680, "Isla Soma"), - CHEZ_CARANDOOM(-529, -564, "Chez Carandoom"), - CHEZ_CANTIN(-529, -403, "Chez Cantin"), - ISLA_PENA(-431, -702, "Isla Pena"), - TENTACLES_PORT(158, -1436, "Port-Tentaclès", StationType.INTERSECTION_AND_PORTAL), - NOT_FINISHED_4(30, -1682, "Station inconnue", StationType.INTERSECTION_AND_PORTAL), // Portail ne menant nulle part - KAAMELOTT(-234, -1454, "Kaamelott"), - POMMACROBATICS(-234, -1604, "PommAcrobatics", StationType.INTERSECTION_AND_PORTAL), - CHEZ_NAGAIWA(-234, -1706, "Chez Nagaiwa"), - - // Old foot-based network (so-called « Netherroutes ») - - INTERSECT_18(30, 64, "Intersection", StationType.INTERSECTION_ONLY, true, false), - ADELLIA(30, 76, "Adellia"), - RAZIEL(30, 92, "Raziel"), - INTERSECT_19(30, 112, "Intersection", StationType.INTERSECTION_ONLY, true, false), - FORTERESSE_3(30, 128, "Forteresse 3"), - ARBRE_BIBLIOTHEQUE(30, 152, "Arbre bibliothèque"), - SIGICOAL(30, 189, "Sigicoal III"), - - MORZAN(-40, 64, "Morzan"), - SMASTEN(-40, 98, "Smasten"), - INTERSECT_21(-98, 64, "Intersection", StationType.INTERSECTION_ONLY, true, false), - JUNGLE_PAUMEE(-98, 117, "Jungle paumée"), - - TAVERNE_BUNKER(22, 112, "Taverne Bunker"), - INTERSECT_22(22, 140, "Intersection", StationType.INTERSECTION_ONLY, true, false), - INTERSECT_23(55, 140, "Intersection", StationType.INTERSECTION_ONLY, true, false), - ELEVAGE_DE_MEUH(155, 140, "Élevage de Meuh"), - AMPHIPOLIS(55, 164, "Amphipolis"), - REZERVE(55, 184, "RéZerve"), - INTERSECT_26(55, 206, "Intersection", StationType.INTERSECTION_ONLY, true, false), //ok - INTERSECT_27(108, 206, "Intersection", StationType.INTERSECTION_ONLY, true, false), //ok - FOREST_OF_MAGIC_ISLAND(108, 296, "Forest of Magic Island"), - ILE_PARADISIAQUE(108, 345, "Île paradisiaque"), - INTERSECT_30(108, 460, "Intersection", StationType.INTERSECTION_ONLY, true, false), - MONTAGNES_CREUSES(108, 481, "Montagnes creuses"), - BAIE_HA_LONG(295, 460, "Baie d'Ha-Long", StationType.INTERSECTION_AND_PORTAL), - MASTER_PWEL(343, 460, "Master Pwel"), - STEP_31(295, 326, "Étape", StationType.INTERSECTION_ONLY, true, true), - STEP_32(295, 304, "Étape", StationType.INTERSECTION_ONLY, true, true), - FORT_BOYAUX(295, 133, "Fort Boyaux"), - SANATORIUM_VERT(295, 61, "Sanatorium Vert"), - - KASTOU(221, 74, "Kastou"), - SWAG_ISLAND(221, 186, "Swag island"), - - TOUR_INFERNALE(259, 164, "Tour Infernale") - - ; - - static - { - register(NOUVEA, FLEURS, ZIG_ZAG, PEPINIERE_OUEST, null); // - register(ZIG_ZAG, FJORD_SUD, ISLA_PENA, ISLA_SOMA, NOUVEA); // - register(PEPINIERE_OUEST, NOUVEA, null, BASTION_DU_CACTUS_GIVRE, null); // - register(FJORDS, UNKNOWN_13, null, FJORD_NORD, LAGON_DE_FLUM); // - register(LAGON_DE_FLUM, null, FJORDS, null, FORTERESSE_DES_FLEURS); // - register(FORTERESSE_DES_FLEURS, null, LAGON_DE_FLUM, null, FLEURS_CREVASSES); - register(FLEURS, PERE_DODUE, FLEURS_CREVASSES, NOUVEA, null); // - register(PEPINIERE_EST, ISLA_SOMA, null, CHEZ_CARANDOOM, null); // - register(PERE_DODUE, PKTEDDYB, null, FLEURS, null); // - register(PKTEDDYB, PINPINB, null, PERE_DODUE, null); // - register(PINPINB, CAMOUIL, null, PKTEDDYB, null); // - register(CAMOUIL, VERTICALE, null, PINPINB, null); // - register(VERTICALE, MIDNIGHT_CITY, CARBONE, CAMOUIL, UZINE); // - register(UZINE, null, VERTICALE, null, null); // - register(CARBONE, FORET_COUVERTE, MOREA, SIGICOAL_TITAN, VERTICALE); // - register(SIGICOAL_TITAN, CARBONE, null, null, null); // - register(RESERVE, ELERIA, ACADEMIE, null, ISLA_PENA); - register(MIDNIGHT_CITY, KRAVEN, null, VERTICALE, null); // - register(KRAVEN, PUMPKIN_VINES, null, MIDNIGHT_CITY, null); // - register(PUMPKIN_VINES, CHESNATOWN, null, KRAVEN, null); // - register(CHESNATOWN, SEPTENTRION_OCCIDENTAL, null, PUMPKIN_VINES, null); // - register(SEPTENTRION_OCCIDENTAL, TOUR_KIFEPEUR, HURLENEIGE, CHESNATOWN, PIC_MARECAGE); // - register(TOUR_KIFEPEUR, VEKTOR, null, SEPTENTRION_OCCIDENTAL, null); - register(VEKTOR, PIERIRO_BILLGATESARDECHE, null, TOUR_KIFEPEUR, null); - register(PIERIRO_BILLGATESARDECHE, null, null, VEKTOR, null); - register(PIC_MARECAGE, null, SEPTENTRION_OCCIDENTAL, null, TARDIS); // - register(TARDIS, null, PIC_MARECAGE, null, null); // - register(HURLENEIGE, null, FROSTBORN_CANYON, null, SEPTENTRION_OCCIDENTAL); // - register(FROSTBORN_CANYON, VOYAGE_ECLAIR, GARDIENS, null, HURLENEIGE); // - register(VOYAGE_ECLAIR, null, null, FROSTBORN_CANYON, null); // - register(GARDIENS, null, BOREE, null, FROSTBORN_CANYON); // - register(FORET_COUVERTE, null, null, CARBONE, null); // - register(BASTION_DU_CACTUS_GIVRE, PEPINIERE_OUEST, null, MOINTAGNE, null); // - register(MOINTAGNE, BASTION_DU_CACTUS_GIVRE, null, UNKNOWN_1, null); // - register(ISLA_NUBLAR, CHEZ_CARANDOOM, null, CHEZ_CANTIN, null); // - register(COLLINE_BOULEAUX, null, AEROPORT, null, UNKNOWN_13); // - register(AEROPORT, null, SOURCE, null, COLLINE_BOULEAUX); // - register(SOURCE, null, null, null, AEROPORT); // - register(ELERIA, SORCIERES, null, RESERVE, null); // - register(SORCIERES, ATLANTIS, null, ELERIA, null); // - register(ATLANTIS, ENGORIA, null, SORCIERES, null); // - register(ENGORIA, DOGGO, null, ATLANTIS, null); // - register(DOGGO, GHAST, null, ENGORIA, null); // - register(BOREE, KAAMELOTT, SEPTENTRION, LAC_AMOUREUX, GARDIENS); // - register(KAAMELOTT, POMMACROBATICS, null, BOREE, null); // - register(POMMACROBATICS, CHEZ_NAGAIWA, null, KAAMELOTT, null); // - register(CHEZ_NAGAIWA, UNKNOWN_14, null, POMMACROBATICS, null); // - register(KERSUB, UNKNOWN_15, null, null, null); // - register(GHAST, UNKNOWN_12, PIC_ASSAUT, DOGGO, MOREA); - register(MOREA, null, GHAST, null, CARBONE); // - register(PIC_ASSAUT, ILE_FLEURS, FALAISIE, null, GHAST); - register(ILE_FLEURS, PICS_PRECIPICES, null, PIC_ASSAUT, null); // - register(WITHER, CREVASSES, null, PICS_PRECIPICES, null); // - register(CREVASSES, LAC_AMOUREUX, null, WITHER, null); // - register(LAC_AMOUREUX, BOREE, null, CREVASSES, null); // - register(SEPTENTRION, NOT_FINISHED_4, TENTACLES_PORT, MESAPLAYA, BOREE); // - register(TENTACLES_PORT, null, TENTACLES, null, SEPTENTRION); // - register(TENTACLES, null, NORDET, null, TENTACLES_PORT); // - register(MESAPLAYA, SEPTENTRION, null, RIVE_BLANCHE, null); // - register(RIVE_BLANCHE, MESAPLAYA, null, FALAISIE, null); // - register(FALAISIE, RIVE_BLANCHE, TUX, POINT_CENTRAL, PIC_ASSAUT); - register(TUX, null, PIC_MORIPLAY, null, FALAISIE); // - register(PIC_MORIPLAY, null, CHESLAND, null, TUX); // - register(CHESLAND, null, SAINT_KEHAINSYS, null, PIC_MORIPLAY); // - register(SAINT_KEHAINSYS, CHASSEUR, null, COL_AIGUES, CHESLAND); - register(CHASSEUR, REFUGE_ARCTIQUE, PLATYPUS, SAINT_KEHAINSYS, WITHER_DESAFFECTE); // - register(WITHER_DESAFFECTE, null, CHASSEUR, null, null); // - register(PLATYPUS, null, null, null, CHASSEUR); // - register(REFUGE_ARCTIQUE, BASE_MILITAIRE_MEUDON, null, CHASSEUR, null); // - register(BASE_MILITAIRE_MEUDON, MONTAGNE_SOLITAIRE, null, REFUGE_ARCTIQUE, null); // - register(MONTAGNE_SOLITAIRE, IVUJIVIK, null, BASE_MILITAIRE_MEUDON, null); // - register(IVUJIVIK, POUTLARD, null, MONTAGNE_SOLITAIRE, null); // - register(POUTLARD, NORDET, null, IVUJIVIK, null); // - register(NORDET, null, CAPITALE_ADMINISTRATIVE_FEDERALE, POUTLARD, TENTACLES); - register(CAPITALE_ADMINISTRATIVE_FEDERALE, null, INTERSECT_33, null, NORDET); - register(INTERSECT_33, D_MONSTRATOR, null, null, CAPITALE_ADMINISTRATIVE_FEDERALE); - register(D_MONSTRATOR, null, null, INTERSECT_33, null);; - register(GLACIER, new Station[] {CHEZ_CANTIN, null, NOT_FINISHED_1, UNKNOWN_1}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.UNOFFICIAL_WALKING}); - register(UNKNOWN_1, new Station[] {MOINTAGNE, GLACIER, NOT_FINISHED_2, null}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.UNOFFICIAL_WALKING, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL}); - register(NOT_FINISHED_1, GLACIER, WALL_STREET, SOMONITES, NOT_FINISHED_2); - register(NOT_FINISHED_2, UNKNOWN_1, NOT_FINISHED_1, BIRDY, null); - register(BIRDY, NOT_FINISHED_2, null, CHEZ_SQUALL, null); // - register(CHEZ_SQUALL, BIRDY, null, GRAND_OUEST, null); - register(GRAND_OUEST, CHEZ_SQUALL, VILLAGE_CORROMPU, FALLEN_KINGDOM, AMAZONIA); - register(AMAZONIA, null, GRAND_OUEST, null, null); // - register(VILLAGE_CORROMPU, null, PERE_MORIEL, null, GRAND_OUEST); // - register(PERE_MORIEL, null, SOMONITES, null, VILLAGE_CORROMPU); // - register(SOMONITES, NOT_FINISHED_1, CIUDAD, ALEXANDRIE, PERE_MORIEL); - register(FALLEN_KINGDOM, GRAND_OUEST, null, ILE_VOLCANIQUE, null); // - register(OCEAN_GAUCHE, ILE_VOLCANIQUE, DEPOT, null, NAILA); // - register(NAILA, null, OCEAN_GAUCHE, null, null); // - register(DEPOT, KERLAM, ILE_ZACQUES, GUET, OCEAN_GAUCHE); - register(KERLAM, ALEXANDRIE, null, DEPOT, null); // - register(ALEXANDRIE, SOMONITES, null, KERLAM, null); - register(ACADEMIE, null, BLAZE_ROAD, null, RESERVE); - register(BLAZE_ROAD, null, MER_ADIEUX, null, ACADEMIE); // - register(MER_ADIEUX, FERME_VILLAGEOIS, JONCTION, PROJETZ, BLAZE_ROAD); // - register(FERME_VILLAGEOIS, POINT_CENTRAL, null, MER_ADIEUX, null); // - register(POINT_CENTRAL, FALAISIE, ARCHIPEL_TROPE, FERME_VILLAGEOIS, MONUMENT_DE_POINT_CENTRAL); // - register(MONUMENT_DE_POINT_CENTRAL, null, POINT_CENTRAL, null, null); // - register(ARCHIPEL_TROPE, PINK_TOWER, null, null, POINT_CENTRAL); // - register(PINK_TOWER, null, null, ARCHIPEL_TROPE, null); // - register(GUET, DEPOT, null, null, null); // - register(JONCTION, null, MARAYA, null, MER_ADIEUX); // *** - register(MARAYA, null, SPERANZA, VYNCIS, JONCTION); - register(SPERANZA_PRISTINE, COL_AIGUES, null, ILE_PRISTINE, SPERANZA); - register(COL_AIGUES, SAINT_KEHAINSYS, AIGUES_CHAUDES, SPERANZA_PRISTINE, null); - register(AIGUES_CHAUDES, null, null, null, COL_AIGUES); - register(PICS_PRECIPICES, WITHER, null, ILE_FLEURS, null); - register(VYNCIS, MARAYA, null, TECI_TARZAN, null); - register(TECI_TARZAN, VYNCIS, null, CARTOUME, null); - register(CARTOUME, TECI_TARZAN, null, VENICE, null); - register(VENICE, CARTOUME, null, null, null); - register(PROJETZ, MER_ADIEUX, null, UNKNOWN_2, null); - register(UNKNOWN_2, new Station[] {PROJETZ, CONSTRUCTEURS, VILLAGE_MAYA, null}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL}); - register(VILLAGE_MAYA, UNKNOWN_2, null, AIGUILLAGE_BAZAR, null); - register(AIGUILLAGE_BAZAR, VILLAGE_MAYA, UNKNOWN_4, MACCRAGE, BAZAR); - register(BAZAR, null, AIGUILLAGE_BAZAR, null, WALL_STREET); - register(WALL_STREET, null, BAZAR, null, NOT_FINISHED_1); - register(CONSTRUCTEURS, new Station[] {null, UNKNOWN_3, null, UNKNOWN_2}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_WALKING}); - register(UNKNOWN_3, null, null, UNKNOWN_4, CONSTRUCTEURS); - register(UNKNOWN_4, UNKNOWN_3, null, ETHERNIA, AIGUILLAGE_BAZAR); - register(UNKNOWN_5, new Station[] {ETHERNIA, CART_TOON, EURAZIE, null}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_RAIL}); - register(ETHERNIA, UNKNOWN_4, null, UNKNOWN_5, null); - register(CART_TOON, CENTRE_SPATIAL, GOULAG, MELBURNE, UNKNOWN_5); - register(CENTRE_SPATIAL, ORDOGRAD, null, CART_TOON, null); - register(ORDOGRAD, ILE_PRISTINE, null, CENTRE_SPATIAL, null); - register(SPERANZA, null, SPERANZA_PRISTINE, null, MARAYA); - register(ILE_PRISTINE, SPERANZA_PRISTINE, null, ORDOGRAD, null); - register(GOULAG, null, HALDA, null, CART_TOON); - register(HALDA, null, TASSE, null, GOULAG); - register(TASSE, null, null, null, HALDA); - register(EURAZIE, new Station[] {UNKNOWN_5, SILVERISLAND, TOUR_INFERNALE, AZIE}, new PathType[] {PathType.OFFICIAL_WALKING, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_RAIL}); // - register(SECTEUR_GHASTS, new Station[] {null, CLEM, SANATORIUM_VERT, SILVERISLAND}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_RAIL}); - register(CLEM, new Station[] {null, MELBURNE, LAPUTA, SECTEUR_GHASTS}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.UNOFFICIAL_RAIL, PathType.OFFICIAL_RAIL}); - register(LAPUTA, new Station[] {CLEM, null, INTERSECT_34, null}, new PathType[] {PathType.UNOFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.UNOFFICIAL_RAIL, PathType.OFFICIAL_RAIL}); - register(INTERSECT_34, new Station[] {LAPUTA, POSEIDOPOLIS, null, null}, new PathType[] {PathType.UNOFFICIAL_RAIL, PathType.UNOFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL}); - register(POSEIDOPOLIS, new Station[] {null, POSEIDOPOLIS_EST, null, INTERSECT_34}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.UNOFFICIAL_RAIL}); - register(MELBURNE, CART_TOON, null, POSEIDOPOLIS_EST, CLEM); - register(MACCRAGE, AIGUILLAGE_BAZAR, null, BALADE, null); - register(BALADE, MACCRAGE, null, UNKNOWN_7, null); - register(UNKNOWN_7, BALADE, UNKNOWN_8, UNKNOWN_9, null); - register(UNKNOWN_8, ARENE_BLAZIQUE, FORTERESSE_LOUL, UNKNOWN_10, UNKNOWN_7); - register(ARENE_BLAZIQUE, null, null, UNKNOWN_8, null); - register(FORTERESSE_LOUL, null, null, null, UNKNOWN_8); - register(UNKNOWN_9, UNKNOWN_7, UNKNOWN_10, GRAND_TEMPLE, null); - register(UNKNOWN_10, UNKNOWN_8, CITE_SCIENCES, null, UNKNOWN_9); - register(CITE_SCIENCES, null, null, null, UNKNOWN_10); - register(GRAND_TEMPLE, UNKNOWN_9, COIN_NATURISTES, CHEZ_Z, null); - register(COIN_NATURISTES, null, null, null, GRAND_TEMPLE); - register(CHEZ_Z, GRAND_TEMPLE, null, VILLAGE_ELFIQUE, null); - register(VILLAGE_ELFIQUE, CHEZ_Z, null, FORTERESSE_2, null); - register(FORTERESSE_2, VILLAGE_ELFIQUE, null, FLANGORIA, null); - register(FLANGORIA, FORTERESSE_2, null, ATTRACTION, null); - register(ATTRACTION, FLANGORIA, null, UZINE_COCHON, null); - register(UZINE_COCHON, ATTRACTION, null, VAALON, null); - register(VAALON, new Station[] {UZINE_COCHON, MOBY_DICK, INTERSECT_18, COLLINE_JAMBES}, new PathType[] {PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_RAIL}); - register(MOBY_DICK, null, AGRISUB_1, null, VAALON); - register(AGRISUB_1, null, UNKNOWN_11, null, MOBY_DICK); - register(UNKNOWN_11, null, AZIE, null, AGRISUB_1); - register(AZIE, new Station[] {null, EURAZIE, KASTOU, UNKNOWN_11}, new PathType[]{PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_RAIL}); - register(SILVERISLAND, null, SECTEUR_GHASTS, null, EURAZIE); - register(COLLINE_JAMBES, null, VAALON, null, GRANDE_LOTTERIE); - register(GRANDE_LOTTERIE, null, COLLINE_JAMBES, null, FORTERESSE_1); - register(FORTERESSE_1, null, GRANDE_LOTTERIE, null, OCTOPUSSY); - register(OCTOPUSSY, null, FORTERESSE_1, null, CHATEAU_GLACES); - register(AIGUILLAGE_CHATEAUNOIR, null, CHATEAU_GLACES, ARRAKIS, PIXEL_ART); - register(CARROUSEL_HOLERIBUS, ARRAKIS, UNKNOWN_17, null, null); - register(UNKNOWN_17, null, null, CHATEAU_NOIR, CARROUSEL_HOLERIBUS); - register(CHATEAU_NOIR, UNKNOWN_17, null, null, null); - register(CHATEAU_GLACES, null, OCTOPUSSY, null, AIGUILLAGE_CHATEAUNOIR); - register(ARRAKIS, AIGUILLAGE_CHATEAUNOIR, null, CARROUSEL_HOLERIBUS, null); - register(PIXEL_ART, MUSEE_PIXEL, AIGUILLAGE_CHATEAUNOIR, null, BANANEROSE); - register(MUSEE_PIXEL, null, null, PIXEL_ART, null); - register(BANANEROSE, null, PIXEL_ART, null, CIUDAD); - register(CIUDAD, BLAZES_POINT, BANANEROSE, null, SOMONITES); - register(BLAZES_POINT, null, null, CIUDAD, null); - register(UNKNOWN_12, null, null, GHAST, USINE_OR); - register(USINE_OR, null, UNKNOWN_12, null, null); - register(POSEIDOPOLIS_EST, MELBURNE, null, ILE_PARADISIAQUE_BOBBIX, POSEIDOPOLIS); - register(ILE_PARADISIAQUE_BOBBIX, POSEIDOPOLIS_EST, null, SUDET, null); - register(SUDET, ILE_PARADISIAQUE_BOBBIX, CARDINALE_EST, SURET, USINE_GARDIENS); - register(CARDINALE_EST, null, null, null, SUDET); - register(SURET, SUDET, null, null, null); - register(USINE_GARDIENS, null, SUDET, null, FORTERESSE_MYSTERIEUSE); - register(FORTERESSE_MYSTERIEUSE, null, USINE_GARDIENS, null, HASHTAG); - register(HASHTAG, null, FORTERESSE_MYSTERIEUSE, null, ILE_ZACQUES); - register(ILE_ZACQUES, null, HASHTAG, null, DEPOT); - register(UNKNOWN_13, null, COLLINE_BOULEAUX, FJORDS, null); - register(UNKNOWN_14, null, null, CHEZ_NAGAIWA, UNKNOWN_15); - register(UNKNOWN_15, null, UNKNOWN_14, KERSUB, null); - register(ILE_VOLCANIQUE, FALLEN_KINGDOM, null, OCEAN_GAUCHE, null); - register(FJORD_SUD, FJORD_CENTRAL, null, ZIG_ZAG, null); - register(FJORD_CENTRAL, FJORD_NORD, null, FJORD_SUD, null); - register(FJORD_NORD, FJORDS, null, FJORD_CENTRAL, null); - register(FLEURS_CREVASSES, null, FORTERESSE_DES_FLEURS, null, FLEURS); - register(ISLA_SOMA, ZIG_ZAG, null, PEPINIERE_EST, null); - register(CHEZ_CARANDOOM, PEPINIERE_EST, null, ISLA_NUBLAR, null); - register(CHEZ_CANTIN, ISLA_NUBLAR, null, GLACIER, null); - register(ISLA_PENA, null, RESERVE, null, ZIG_ZAG); - register(NOT_FINISHED_4, null, null, SEPTENTRION, null); - - // Old foot-based network (so-called « Netherroutes ») - - registerWalk(INTERSECT_18, VAALON, null, ADELLIA, MORZAN); - registerWalk(ADELLIA, INTERSECT_18, null, RAZIEL, null); - registerWalk(RAZIEL, ADELLIA, null, INTERSECT_19, null); - registerWalk(INTERSECT_19, RAZIEL, null, FORTERESSE_3, TAVERNE_BUNKER); - registerWalk(FORTERESSE_3, INTERSECT_19, null, ARBRE_BIBLIOTHEQUE, null); - registerWalk(ARBRE_BIBLIOTHEQUE, FORTERESSE_3, null, SIGICOAL, null); - registerWalk(SIGICOAL, ARBRE_BIBLIOTHEQUE, null, null, null); - - registerWalk(MORZAN, null, INTERSECT_18, SMASTEN, INTERSECT_21); - registerWalk(SMASTEN, MORZAN, null, null, null); - registerWalk(INTERSECT_21, null, MORZAN, JUNGLE_PAUMEE, null); - registerWalk(JUNGLE_PAUMEE, INTERSECT_21, null, null, null); - - registerWalk(TAVERNE_BUNKER, null, INTERSECT_19, INTERSECT_22, null); - registerWalk(INTERSECT_22, TAVERNE_BUNKER, INTERSECT_23, null, null); - registerWalk(INTERSECT_23, null, ELEVAGE_DE_MEUH, AMPHIPOLIS, INTERSECT_22); - registerWalk(ELEVAGE_DE_MEUH, null, null, null, INTERSECT_23); - registerWalk(AMPHIPOLIS, INTERSECT_23, null, REZERVE, null); - registerWalk(REZERVE, AMPHIPOLIS, null, INTERSECT_26, null); - registerWalk(INTERSECT_26, REZERVE, INTERSECT_27, null, null); - registerWalk(INTERSECT_27, null, null, FOREST_OF_MAGIC_ISLAND, INTERSECT_26); - registerWalk(FOREST_OF_MAGIC_ISLAND, INTERSECT_27, null, ILE_PARADISIAQUE, null); - register(ILE_PARADISIAQUE, new Station[]{FOREST_OF_MAGIC_ISLAND, null, INTERSECT_30, null}, new PathType[] {PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.UNOFFICIAL_WALKING, PathType.OFFICIAL_WALKING}); - register(INTERSECT_30, new Station[]{ILE_PARADISIAQUE, BAIE_HA_LONG, MONTAGNES_CREUSES, null}, new PathType[] {PathType.UNOFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING}); - registerWalk(MONTAGNES_CREUSES, INTERSECT_30, null, null, null); - - registerWalk(BAIE_HA_LONG, STEP_31, MASTER_PWEL, null, INTERSECT_30); - registerWalk(MASTER_PWEL, null, null, null, BAIE_HA_LONG); - register(STEP_31, new Station[]{STEP_32, null, BAIE_HA_LONG, null}, new PathType[] {PathType.UNOFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING}); - register(STEP_32, new Station[]{FORT_BOYAUX, null, STEP_31, null}, new PathType[] {PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.UNOFFICIAL_WALKING, PathType.OFFICIAL_WALKING}); - registerWalk(FORT_BOYAUX, SANATORIUM_VERT, null, STEP_32, null); - registerWalk(SANATORIUM_VERT, SECTEUR_GHASTS, null, FORT_BOYAUX, null); - - registerWalk(KASTOU, AZIE, null, SWAG_ISLAND, null); - registerWalk(SWAG_ISLAND, KASTOU, null, null, null); - - registerWalk(TOUR_INFERNALE, EURAZIE, null, null, null); - - // check(); - } - - - private final static int STATIONS_COUNT = 4; - - private final int X, Y; - private final String NAME; - private final boolean HIDDEN; - private final boolean DANGER; - private Station[] SUB_STATIONS; - private double[] DISTANCES = new double[STATIONS_COUNT]; - private PathType[] PATH_TYPES; - private final StationType TYPE; - - Station(final int x, final int y) - { - this(x, y, null); - } - - Station(final int x, final int y, final String name) - { - this(x, y, name, StationType.PORTAL_ONLY); - } - - Station(final int x, final int y, final String name, final StationType type) - { - this(x, y, name, type, false, false); - } - - Station(final int x, final int y, final String name, final StationType type, final boolean isHidden, final boolean danger) - { - X = x; - Y = y; - - NAME = name; - - TYPE = type; - - HIDDEN = isHidden; - DANGER = danger; - } - - public static void register(final Station station, final Station... stations) - { - register(station, stations, new PathType[]{PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL, PathType.OFFICIAL_RAIL}); - } - - public static void registerWalk(final Station station, final Station... stations) - { - register(station, stations, new PathType[]{PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING, PathType.OFFICIAL_WALKING}); - } - - public static void register(final Station station, final Station[] stations, final PathType[] paths) - { - if(stations.length != STATIONS_COUNT || paths.length != STATIONS_COUNT) - throw new IllegalArgumentException(String.format("Arrays sizes must be %s for %s", STATIONS_COUNT, station.name())); - - station.SUB_STATIONS = stations; - - station.PATH_TYPES = paths; - - for(int i = 0; i < STATIONS_COUNT; i++) - { - Station sub = station.SUB_STATIONS[i]; - if(sub == null) - continue; - - if(sub == station) - throw new IllegalArgumentException("Array contains itself"); - - station.DISTANCES[i] = Math.sqrt((station.X - sub.X) * (station.X - sub.X) + (station.Y - sub.Y) * (station.Y - sub.Y)); - } - } - - public static void check() - { - for(Station station : values()) - { - - for(Direction direction : Direction.values()) - { - if(!station.hasSubStation(direction)) - continue; - - Station next = station.getSubStation(direction); - Station assertion = next.getSubStation(direction.opposite()); - - if(assertion == null || assertion != station) - { - throw new IllegalArgumentException("Stations " + station + " and " + next + " does not verify themselves for direction " + direction); - } - } - } - } - - public Station getSubStation(Direction direction) - { - if(direction == null) - throw new IllegalArgumentException("Direction cannot be null"); - - return SUB_STATIONS[direction.getIndex()]; - } - - public Direction getDirection(Station sub) - { - for(Direction direction : Direction.values()) - if(getSubStation(direction) == sub) - return direction; - - throw new IllegalArgumentException("Station " + sub + " was not found in station " + name()); - } - - public boolean hasSubStation(Direction direction) - { - return getSubStation(direction) != null; - } - - public double getDistanceFrom(Direction direction) - { - if(direction == null) - throw new IllegalArgumentException("Direction cannot be null"); - - return DISTANCES[direction.getIndex()]; - } - - public double getDistanceFrom(Station station) - { - return getDistanceFrom(getDirection(station)); - } - - public boolean isVisible() - { - return !HIDDEN; - } - - public PathType getPathType(Direction direction) - { - return PATH_TYPES[direction.getIndex()]; - } - - public PathType getPathType(Station station) - { - return getPathType(getDirection(station)); - } - - public boolean isDangerous() - { - return DANGER; - } - - public static List getStationsAlphabetically() - { - List stations = Arrays.asList(Station.values()); - Collections.sort(stations, new StationComparator()); - - return stations; - } - - @Override - public String toString() - { - if(!isVisible() || isDangerous()) - return "Station inconnue"; - - if(NAME == null) - { - String[] split = name().toLowerCase().split("_"); - - for(int i = 0; i < split.length; i++) - { - split[i] = split[i].substring(0, 1).toUpperCase() + split[i].substring(1); - } - - return Utils.join(Arrays.asList(split), " "); - } - - - return NAME; - } - - public static int getId(Station station) - { - for(int i = 0; i < values().length; i++) - { - if(station == values()[i]) - return i; - } - - throw new Error("Not found : " + station); - } - - public int getX() - { - return X; - } - - public int getY() - { - return Y; - } - - public boolean isPortal() - { - return TYPE == StationType.PORTAL_ONLY || TYPE == StationType.INTERSECTION_AND_PORTAL; - } - - public boolean isIntersection() - { - return TYPE == StationType.INTERSECTION_ONLY || TYPE == StationType.INTERSECTION_AND_PORTAL; - } - - public JsonObject toJson(boolean withNetwork) - { - JsonObject objectStation = new JsonObject(); - - objectStation.add("id", new JsonPrimitive(Station.getId(this))); - objectStation.add("code_name", new JsonPrimitive(this.name().toLowerCase())); - objectStation.add("full_name", new JsonPrimitive(this.toString())); - - objectStation.add("x", new JsonPrimitive(this.getX())); - objectStation.add("y", new JsonPrimitive(this.getY())); - - objectStation.add("is_visible", new JsonPrimitive(this.isVisible())); - objectStation.add("is_safe", new JsonPrimitive(!this.isDangerous())); - - objectStation.add("is_portal", new JsonPrimitive(this.isPortal())); - objectStation.add("is_intersection", new JsonPrimitive(this.isIntersection())); - - JsonArray network = new JsonArray(); - - if(withNetwork) - { - for(Direction direction : Direction.values()) - { - Station sub = this.getSubStation(direction); - - String key = direction.name().toLowerCase(); - - if(sub != null) - network.add(buildConnectionObject(this, sub)); - } - - objectStation.add("network", network); - } - - return objectStation; - } - - - /** - * Creates a json object representing this station and its path. The last station does not have any path. - * @param station the station - * @param next the next station - * @return a json object - */ - public static JsonObject buildStationPathObject(Station station, Station next) - { - JsonObject object = new JsonObject(); - - JsonObject objectStation = station.toJson(false); - - object.add("station", objectStation); - - if(next != null) - { - JsonObject connection = Station.buildConnectionObject(station, next); - - object.add("connection", connection); - } - - return object; - } - - /** - * Creates a json object representing a connection between two stations. - * @param station the main station - * @param sub the sub station - * @return a json object - */ - public static JsonObject buildConnectionObject(Station station, Station sub) - { - JsonObject object = new JsonObject(); - - object.add("from", new JsonPrimitive(Station.getId(station))); - object.add("to", new JsonPrimitive(Station.getId(sub))); - - object.add("direction", new JsonPrimitive(station.getDirection(sub).name().toLowerCase())); - - object.add("length", new JsonPrimitive((int) station.getDistanceFrom(sub))); - - PathType pathType = station.getPathType(sub); - - object.add("is_official", new JsonPrimitive(pathType.isOfficial())); - - object.add("is_rail", new JsonPrimitive(pathType.isRail())); - - return object; - } -} - -/** - * The type of station. - */ -enum StationType -{ - INTERSECTION_ONLY, - INTERSECTION_AND_PORTAL, - PORTAL_ONLY -} - -class StationComparator implements Comparator -{ - @Override - public int compare(Station station1, Station station2) { - return Utils.stripAccents(station1.toString()).compareTo(Utils.stripAccents(station2.toString())); - } -} diff --git a/src/main/java/me/cassayre/florian/netherrail/Utils.java b/src/main/java/me/cassayre/florian/netherrail/Utils.java deleted file mode 100644 index 7f9f283..0000000 --- a/src/main/java/me/cassayre/florian/netherrail/Utils.java +++ /dev/null @@ -1,31 +0,0 @@ -package me.cassayre.florian.netherrail; - -import java.text.Normalizer; -import java.util.Collection; -import java.util.Iterator; - -public final class Utils -{ - private Utils() - { - } - - public static String stripAccents(String s) - { - s = Normalizer.normalize(s, Normalizer.Form.NFD); - s = s.replaceAll("[\\p{InCombiningDiacriticalMarks}]", ""); - return s; - } - - public static String join(Collection var0, String var1) { - StringBuffer var2 = new StringBuffer(); - - for(Iterator var3 = var0.iterator(); var3.hasNext(); var2.append((String)var3.next())) { - if(var2.length() != 0) { - var2.append(var1); - } - } - - return var2.toString(); - } -} diff --git a/tests/config.rs b/tests/config.rs new file mode 100644 index 0000000..49d7d0c --- /dev/null +++ b/tests/config.rs @@ -0,0 +1,83 @@ +extern crate zeps; +extern crate failure; + +use zeps::data::universe::Universe; +use failure::Error; + +fn load_from_fixture(fixture: &str) -> Result { + zeps::read_universe_from_file(format!("./tests/fixtures/{}.json", fixture)) +} + +#[test] +fn it_fails_from_nothing() { + assert!(load_from_fixture("empty").is_err()); +} + +#[test] +fn it_loads_without_data() { + let universe = load_from_fixture("no_data").unwrap(); + assert_eq!(universe.stations().into_iter().fold(0, |acc, _| acc + 1), 0); +} + +#[test] +fn it_loads_with_data() { + let _ = load_from_fixture("with_data").unwrap(); +} + +#[test] +fn stations_are_all_there() { + let universe = load_from_fixture("with_data").unwrap(); + assert_eq!(universe.stations().into_iter().fold(0, |acc, _| acc + 1), 5); + assert_eq!(universe.get_network("netherrail").unwrap().stations().into_iter().fold(0, |acc, _| acc + 1), 3); + assert_eq!(universe.get_network("overworld").unwrap().stations().into_iter().fold(0, |acc, _| acc + 1), 2); +} + + +// TODO for the following reference tests: test if the correct error is returned too. + +#[test] +fn it_fails_if_a_line_references_an_unknown_station() { + assert!(load_from_fixture("lines_invalid_ref").is_err()); +} + +#[test] +fn it_fails_if_a_line_references_an_unknown_station_in_expanded_mode() { + assert!(load_from_fixture("lines_invalid_ref_expanded").is_err()); +} + +#[test] +fn it_fails_if_a_connection_references_an_unknown_network() { + assert!(load_from_fixture("connections_invalid_ref_network").is_err()); +} + +#[test] +fn it_fails_if_a_connection_references_an_unknown_station() { + assert!(load_from_fixture("connections_invalid_ref_station").is_err()); +} + +#[test] +fn it_fails_if_a_connection_references_an_unknown_station_valid_in_the_other_network() { + assert!(load_from_fixture("connections_invalid_ref_station_but_exists_in_other_network").is_err()); +} + + +#[test] +fn the_coordinates_factor_defaults_to_one() { + let universe = load_from_fixture("coordinates_factor_default").unwrap(); + let network = universe.get_network("netherrail").unwrap(); + assert_eq!(network.coordinates_factor(), 1.0); +} + +#[test] +fn the_coordinates_factor_defaults_to_point_125_if_nether() { + let universe = load_from_fixture("coordinates_factor_default_nether").unwrap(); + let network = universe.get_network("netherrail").unwrap(); + assert_eq!(network.coordinates_factor(), 0.125); +} + +#[test] +fn the_coordinates_factor_overrides_is_nether_if_explicit() { + let universe = load_from_fixture("coordinates_factor_overridden").unwrap(); + let network = universe.get_network("netherrail").unwrap(); + assert_eq!(network.coordinates_factor(), 1.84); +} diff --git a/tests/fixtures/connections_invalid_ref_network.json b/tests/fixtures/connections_invalid_ref_network.json new file mode 100644 index 0000000..58e8efd --- /dev/null +++ b/tests/fixtures/connections_invalid_ref_network.json @@ -0,0 +1,23 @@ +{ + "name": "Vessinque", + "networks": { + "netherrail": { + "name": "Netherrail", + "world": "v5_nether", + + "is_nether": true, + + "coordinates_factor": 0.125, + + "stations": {}, + "lines": [] + } + }, + "networks_connections": [ + { + "networks": ["netherrail", "overworld"], + "autoconnect_by_name": true, + "autoconnect_by_proximity": 10 + } + ] +} diff --git a/tests/fixtures/connections_invalid_ref_station.json b/tests/fixtures/connections_invalid_ref_station.json new file mode 100644 index 0000000..177cedb --- /dev/null +++ b/tests/fixtures/connections_invalid_ref_station.json @@ -0,0 +1,63 @@ +{ + "name": "Vessinque", + "networks": { + "netherrail": { + "name": "Netherrail", + "world": "v5_nether", + + "is_nether": true, + + "coordinates_factor": 0.125, + + "stations": { + "station_code_name": { + "name": "Displayed station name", + "sub_name": "For stations with a main name and another pomf", + "description": "If needed, displayed in the map balloon. Can be omitted.", + "coordinates": [0, 0, 0], + "real_coordinates": [0, 0, 0], + + "is_main": true, + + "has_fast_access": true, + "fast_access_time": 10 + } + }, + + "lines": [] + }, + + "overworld": { + "name": "Surface", + "world": "V5", + + "stations": { + "overworld_station": { + "name": "Displayed station name", + "sub_name": "For stations with a main name and another pomf", + "description": "If needed, displayed in the map balloon. Can be omitted.", + "coordinates": [0, 0, 0], + "real_coordinates": [0, 0, 0], + + "is_main": true, + + "has_fast_access": true, + "fast_access_time": 10 + } + }, + + "lines": [] + } + }, + + "networks_connections": [ + { + "networks": ["netherrail", "overworld"], + "autoconnect_by_name": true, + "autoconnect_by_proximity": 10, + "connections": [ + ["station_code_name", "unknown_station"] + ] + } + ] +} diff --git a/tests/fixtures/connections_invalid_ref_station_but_exists_in_other_network.json b/tests/fixtures/connections_invalid_ref_station_but_exists_in_other_network.json new file mode 100644 index 0000000..8572391 --- /dev/null +++ b/tests/fixtures/connections_invalid_ref_station_but_exists_in_other_network.json @@ -0,0 +1,75 @@ +{ + "name": "Vessinque", + "networks": { + "netherrail": { + "name": "Netherrail", + "world": "v5_nether", + + "is_nether": true, + + "coordinates_factor": 0.125, + + "stations": { + "station_code_name": { + "name": "Displayed station name", + "sub_name": "For stations with a main name and another pomf", + "description": "If needed, displayed in the map balloon. Can be omitted.", + "coordinates": [0, 0, 0], + "real_coordinates": [0, 0, 0], + + "is_main": true, + + "has_fast_access": true, + "fast_access_time": 10 + }, + "station_code_name_2": { + "name": "Displayed station name", + "sub_name": "For stations with a main name and another pomf", + "description": "If needed, displayed in the map balloon. Can be omitted.", + "coordinates": [0, 0, 0], + "real_coordinates": [0, 0, 0], + + "is_main": true, + + "has_fast_access": true, + "fast_access_time": 10 + } + }, + + "lines": [] + }, + + "overworld": { + "name": "Surface", + "world": "V5", + + "stations": { + "overworld_station": { + "name": "Displayed station name", + "sub_name": "For stations with a main name and another pomf", + "description": "If needed, displayed in the map balloon. Can be omitted.", + "coordinates": [0, 0, 0], + "real_coordinates": [0, 0, 0], + + "is_main": true, + + "has_fast_access": true, + "fast_access_time": 10 + } + }, + + "lines": [] + } + }, + + "networks_connections": [ + { + "networks": ["netherrail", "overworld"], + "autoconnect_by_name": true, + "autoconnect_by_proximity": 10, + "connections": [ + ["station_code_name", "station_code_name_2"] + ] + } + ] +} diff --git a/tests/fixtures/coordinates_factor_default.json b/tests/fixtures/coordinates_factor_default.json new file mode 100644 index 0000000..a1452a8 --- /dev/null +++ b/tests/fixtures/coordinates_factor_default.json @@ -0,0 +1,13 @@ +{ + "name": "Empty universe", + "networks": { + "netherrail": { + "name": "Netherrail", + "world": "V5_nether", + + "stations": {}, + "lines": [] + } + }, + "networks_connections": [] +} diff --git a/tests/fixtures/coordinates_factor_default_nether.json b/tests/fixtures/coordinates_factor_default_nether.json new file mode 100644 index 0000000..674f8ab --- /dev/null +++ b/tests/fixtures/coordinates_factor_default_nether.json @@ -0,0 +1,15 @@ +{ + "name": "Empty universe", + "networks": { + "netherrail": { + "name": "Netherrail", + "world": "V5_nether", + + "is_nether": true, + + "stations": {}, + "lines": [] + } + }, + "networks_connections": [] +} diff --git a/tests/fixtures/coordinates_factor_overridden.json b/tests/fixtures/coordinates_factor_overridden.json new file mode 100644 index 0000000..041bd87 --- /dev/null +++ b/tests/fixtures/coordinates_factor_overridden.json @@ -0,0 +1,16 @@ +{ + "name": "Empty universe", + "networks": { + "netherrail": { + "name": "Netherrail", + "world": "V5_nether", + + "is_nether": true, + "coordinates_factor": 1.84, + + "stations": {}, + "lines": [] + } + }, + "networks_connections": [] +} diff --git a/tests/fixtures/empty.json b/tests/fixtures/empty.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/tests/fixtures/empty.json @@ -0,0 +1 @@ +{} diff --git a/tests/fixtures/lines_invalid_ref.json b/tests/fixtures/lines_invalid_ref.json new file mode 100644 index 0000000..e5af20d --- /dev/null +++ b/tests/fixtures/lines_invalid_ref.json @@ -0,0 +1,39 @@ +{ + "name": "Vessinque", + "networks": { + "netherrail": { + "name": "Netherrail", + "world": "v5_nether", + + "is_nether": true, + + "coordinates_factor": 0.125, + + "stations": { + "station_code_name": { + "name": "Displayed station name", + "sub_name": "For stations with a main name and another pomf", + "description": "If needed, displayed in the map balloon. Can be omitted.", + "coordinates": [0, 0, 0], + "real_coordinates": [0, 0, 0], + + "is_main": true, + + "has_fast_access": true, + "fast_access_time": 10 + } + }, + + "lines": [ + { + "name": "(can be left empty or removed)", + "color": "#rrggbb", + "path": [ + "station_code_name_unknown" + ] + } + ] + } + }, + "networks_connections": [] +} diff --git a/tests/fixtures/lines_invalid_ref_expanded.json b/tests/fixtures/lines_invalid_ref_expanded.json new file mode 100644 index 0000000..82087c7 --- /dev/null +++ b/tests/fixtures/lines_invalid_ref_expanded.json @@ -0,0 +1,45 @@ +{ + "name": "Vessinque", + "networks": { + "netherrail": { + "name": "Netherrail", + "world": "v5_nether", + + "is_nether": true, + + "coordinates_factor": 0.125, + + "stations": { + "station_code_name": { + "name": "Displayed station name", + "sub_name": "For stations with a main name and another pomf", + "description": "If needed, displayed in the map balloon. Can be omitted.", + "coordinates": [0, 0, 0], + "real_coordinates": [0, 0, 0], + + "is_main": true, + + "has_fast_access": true, + "fast_access_time": 10 + } + }, + + "lines": [ + { + "name": "(can be left empty or removed)", + "color": "#rrggbb", + "path": [ + "station_code_name", + { + "station": "station_code_name_unknown", + "path_type": "walk", + "path_secure": false, + "path_to_next": [[0, 0,0], [0, 0], [0, 0, 0]] + } + ] + } + ] + } + }, + "networks_connections": [] +} diff --git a/tests/fixtures/no_data.json b/tests/fixtures/no_data.json new file mode 100644 index 0000000..2001d27 --- /dev/null +++ b/tests/fixtures/no_data.json @@ -0,0 +1,5 @@ +{ + "name": "Empty universe", + "networks": {}, + "networks_connections": [] +} diff --git a/tests/fixtures/with_data.json b/tests/fixtures/with_data.json new file mode 100644 index 0000000..2159401 --- /dev/null +++ b/tests/fixtures/with_data.json @@ -0,0 +1,112 @@ +{ + "name": "Vessinque", + "networks": { + "netherrail": { + "name": "Netherrail", + "world": "v5_nether", + + "is_nether": true, + + "coordinates_factor": 0.125, + + "stations": { + "station_code_name": { + "name": "Displayed station name", + "sub_name": "For stations with a main name and another pomf", + "description": "If needed, displayed in the map balloon. Can be omitted.", + "coordinates": [0, 0, 0], + "real_coordinates": [0, 0, 0], + + "is_main": true, + + "has_fast_access": true, + "fast_access_time": 10 + }, + "station_code_name_2": { + "name": "Displayed station name", + "sub_name": "For stations with a main name and another pomf", + "description": "If needed, displayed in the map balloon. Can be omitted.", + "coordinates": [0, 0, 0], + "real_coordinates": [0, 0, 0], + + "is_main": true, + + "has_fast_access": true, + "fast_access_time": 10 + }, + "station_code_name_3": { + "name": "Displayed station name", + "sub_name": "For stations with a main name and another pomf", + "description": "If needed, displayed in the map balloon. Can be omitted.", + "coordinates": [0, 0, 0], + "real_coordinates": [0, 0, 0], + + "is_main": true, + + "has_fast_access": true, + "fast_access_time": 10 + } + }, + + "lines": [ + { + "name": "(can be left empty or removed)", + "color": "#rrggbb", + "path": [ + "station_code_name", + "station_code_name_2", + { + "station": "station_code_name_3", + "path_type": "walk", + "path_secure": false, + "path_to_next": [[0, 0,0], [0, 0], [0, 0, 0]] + } + ] + } + ] + }, + + "overworld": { + "name": "Surface", + "world": "V5", + "stations": { + "overworld_station": { + "name": "Displayed station name", + "sub_name": "For stations with a main name and another pomf", + "description": "If needed, displayed in the map balloon. Can be omitted.", + "coordinates": [0, 0, 0], + "real_coordinates": [0, 0, 0], + + "is_main": true, + + "has_fast_access": true, + "fast_access_time": 10 + }, + "overworld_station_2": { + "name": "Displayed station name", + "sub_name": "For stations with a main name and another pomf", + "description": "If needed, displayed in the map balloon. Can be omitted.", + "coordinates": [0, 0, 0], + "real_coordinates": [0, 0, 0], + + "is_main": true, + + "has_fast_access": true, + "fast_access_time": 10 + } + }, + "lines": [] + } + }, + "networks_connections": [ + { + "networks": ["netherrail", "overworld"], + "autoconnect_by_name": true, + "autoconnect_by_proximity": 10, + "connections": [ + ["station_code_name", "overworld_station"], + ["station_code_name_2", "overworld_station_2"] + ] + } + ] +}