diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 000000000..f8f6764cc --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/server/.bsp/sbt.json b/server/.bsp/sbt.json new file mode 100644 index 000000000..54fa0fe21 --- /dev/null +++ b/server/.bsp/sbt.json @@ -0,0 +1 @@ +{"name":"sbt","version":"1.5.5","bspVersion":"2.0.0-M5","languages":["scala"],"argv":["C:\\Program Files\\Java\\jdk1.8.0_261\\jre/bin/java","-Xms100m","-Xmx100m","-classpath","C:\\Users\\Nikolas\\AppData\\Roaming\\JetBrains\\IntelliJIdea2020.2\\plugins\\Scala\\launcher\\sbt-launch.jar","xsbt.boot.Boot","-bsp","--sbt-launch-jar=C:\\Users\\Nikolas\\AppData\\Roaming\\JetBrains\\IntelliJIdea2020.2\\plugins\\Scala\\launcher\\sbt-launch.jar"]} \ No newline at end of file diff --git a/server/.idea/.gitignore b/server/.idea/.gitignore new file mode 100644 index 000000000..14b191c65 --- /dev/null +++ b/server/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/../../../../../../../../:\Users\Nikolas\Documents\GitHub\anyplace\server\.idea/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/server/.idea/.name b/server/.idea/.name new file mode 100644 index 000000000..a7447d6d2 --- /dev/null +++ b/server/.idea/.name @@ -0,0 +1 @@ +Anyplace \ No newline at end of file diff --git a/server/.idea/codeStyles/codeStyleConfig.xml b/server/.idea/codeStyles/codeStyleConfig.xml index a55e7a179..df5f35dcc 100644 --- a/server/.idea/codeStyles/codeStyleConfig.xml +++ b/server/.idea/codeStyles/codeStyleConfig.xml @@ -1,5 +1,5 @@ - - - + + + \ No newline at end of file diff --git a/server/.idea/compiler.xml b/server/.idea/compiler.xml new file mode 100644 index 000000000..34ba83953 --- /dev/null +++ b/server/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/server/.idea/misc.xml b/server/.idea/misc.xml new file mode 100644 index 000000000..d6f42db8f --- /dev/null +++ b/server/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/server/.idea/play2_project_settings.xml b/server/.idea/play2_project_settings.xml new file mode 100644 index 000000000..bd1c0ebaf --- /dev/null +++ b/server/.idea/play2_project_settings.xml @@ -0,0 +1,47 @@ + + + + + + \ No newline at end of file diff --git a/server/.idea/play2_settings.xml b/server/.idea/play2_settings.xml new file mode 100644 index 000000000..d729c0123 --- /dev/null +++ b/server/.idea/play2_settings.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/server/.idea/sbt.xml b/server/.idea/sbt.xml index 201874354..9f64c101e 100644 --- a/server/.idea/sbt.xml +++ b/server/.idea/sbt.xml @@ -1,6 +1,17 @@ - - - - + + + + + \ No newline at end of file diff --git a/server/.idea/scala_compiler.xml b/server/.idea/scala_compiler.xml new file mode 100644 index 000000000..39958b5b6 --- /dev/null +++ b/server/.idea/scala_compiler.xml @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/server/.idea/vcs.xml b/server/.idea/vcs.xml index 6c0b86358..2e3f6920d 100644 --- a/server/.idea/vcs.xml +++ b/server/.idea/vcs.xml @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/server/CHANGELOG.md b/server/CHANGELOG.md new file mode 100644 index 000000000..e3ec4ad56 --- /dev/null +++ b/server/CHANGELOG.md @@ -0,0 +1,87 @@ + +# Version 4.20 +
+ +Details.. + + +
+ +New features + + +- Fingerprint cache-collections: + Instead of recalculating and waste resources we are caching fingerprint groupping. There are in total 3 zoom levels and the possibility to select a date span to see fingerprints, thus there are in total 6 collections. Those are heatmaps1,2,3 and heatmapTimestamp1,2,3. + - on heatmap/Wifi-Coverage request, depends on the zoom level the heatmap cache collections are created for the requested floor. + - on heatmap-timestamp request all zoom levels are created for the requested floor. + - on delete all cached objects that are related to that floor are deleted. + - on update all cached objects that are related to that floor are deleted. + - on fingerprint insertion cache collections are NOT affected. + - on space/floor deletion, cache collections are also deleted. +- Fingerprints groupping: + + level 1: Approximately 3 meters + + level 2: 1.11 meters + + level 3: No groupping +- New login/register feature: + - Register + In the past users could only use the system with Google Accounts. Now they can create Anyplace accounts and interact with the system through them. + - Login + User provides username and password in order to login. +- Changed how API key is generated and authenticates + Since the former way of interacting with Anyplace was with Google we were using Google API-key. + Now we generate our own API-keys and authenticate the endpoints with them. +- Added space type + Buildings are renamed to Spaces. There are two types of spaces: + + building + + vessel +- Rebuilding /developers with swagger-ui + New api interface using swagger. Still on develop stage. + +
+ +
+ +Bug fixes + + +- Crossfilter: + The feature where a user could see fingerprints on a time span was not working. + - Reset button was also fixed. + The feature is now working properly and supports: + - Wi-Fi coverage + - Heatmaps +
+ +
+ +Known Bugs + + +- On space deletion directory path/radiomaps_frozen/building/floor remained +- Show access points feature shows wrong location +- Problematic features when logged with local account: + + Update space + + Add campus + + Update campus + + Search pois + +
+ +
+ +Endpoints renaming + + +- /admin/accounts_all -> /user/admin/accounts_all +- /anyplace/version -> /api/version +- /anyplace/mapping/building/add -> /anyplace/mapping/space/add +- /anyplace/mapping/building/update -> /anyplace/mapping/space/update +- /anyplace/mapping/building/delete -> /anyplace/mapping/space/delete +- /anyplace/mapping/building/all -> /anyplace/mapping/space/all +- /anyplace/mapping/building/all_owner -> /anyplace/mapping/space/all_owner +- /anyplace/mapping/building/coordinates -> /anyplace/mapping/space/coordinates +- /anyplace/mapping/building/get -> /anyplace/mapping/space/get + +
+ +
\ No newline at end of file diff --git a/server/DEVELOP.md b/server/DEVELOP.md index d83dac956..7c174a918 100644 --- a/server/DEVELOP.md +++ b/server/DEVELOP.md @@ -1,25 +1,23 @@ -# Deploy a development instance +# Remote Deploy during develop: -Idea: -1. code for the backend locally -2. sync sources to remote, compile them, and view from browser. +Workflow: +1. Write code locally +2. Sync code to remote for compilation, and view the result from the browser -# Run on different port: -sbt "run 9001" +See [deploy](./deploy) +## Run on different port: +`sbt "run 9001"` -# Troubleshooting: +## Troubleshooting: - `Can't connect to X11 window server using ':0' as the value of the DISPLAY variable.` - Try: +Try: `unset DISPLAY` - -# keystore - +## keystore ``` keytool -genkey -alias MyKey -keyalg RSA -keysize 2048 -keystore keystore.jks play -Dhttps.port=9443 -Dhttps.keyStore=keystore.jks -Dhttps.keyStorePassword=password run ``` - add dummy value to this diff --git a/server/README.md b/server/README.md index 5b98ac9dd..0b68e47f1 100644 --- a/server/README.md +++ b/server/README.md @@ -1,11 +1,11 @@ -# Anyplace v4.x Installation Notes +# Installation: This is a latest version of the Anyplace backend, which has been ported to tha scala language and that also supports all the latest versions of its underlying software layers (i.e., it has been tested with couchbase 4.5 and play framework 2.8). In case you want a precompiled release of the latest Anyplace, please check the docker folder (anyplace/docker) -# Anyplace v4.x for administrators +# For administrators ## Setup/Configuration diff --git a/server/TODO.md b/server/TODO.md index 56a3394d9..16f27daf2 100644 --- a/server/TODO.md +++ b/server/TODO.md @@ -1,15 +1,14 @@ -# TODO Release mechanism -The private Jenkins server should build a version and put it in the APFS. -Then, server should have an endpoint to fetch the versions, and maybe also a file viewer -(for all the compiled versions). +# TODO:PM remove ACCES map +Either Deprecation and removal, or update it's sources. + +# TODO update Scala, sbt, Play # TODO MongoDB * MongoDB driver * Edit parts in code for Mongo * Update docker for that -# TODO ACCES map -Either Deprecation and removal, or update it's sources. + # Cleanup if no issues arise then delete public/javascript/ flurry and jquery diff --git a/server/app/Anyplace.scala b/server/app/Anyplace.scala new file mode 100644 index 000000000..fc1781787 --- /dev/null +++ b/server/app/Anyplace.scala @@ -0,0 +1,33 @@ +import com.dmurph.tracking.JGoogleAnalyticsTracker.GoogleAnalyticsVersion +import com.dmurph.tracking.{AnalyticsConfigData, JGoogleAnalyticsTracker} +import datasources.{CouchbaseDatasource, MongodbDatasource} +import javax.inject.{Inject, Singleton} +import play.api.Configuration +import play.api.inject.ApplicationLifecycle +import utils.LPLogger + +import scala.concurrent.Future + +@Singleton +class Anyplace @Inject() (conf: Configuration) (appLifecycle: ApplicationLifecycle) { + // ON APPLICATION START (ctor): + //ifxDB.getStaticInstance(conf) + CouchbaseDatasource.initialize(conf) + MongodbDatasource.initialize(conf) + logAnalyticsInstallation() + + appLifecycle.addStopHook({ () => + Future.successful { + LPLogger.D2("onStart") + } + }) + + def logAnalyticsInstallation(): Unit = { + // Log the entry point from server installation + JGoogleAnalyticsTracker.setProxy(System.getenv("http_proxy")) + val config = new AnalyticsConfigData("UA-61313158-2") + val tracker = new JGoogleAnalyticsTracker(config, GoogleAnalyticsVersion.V_4_7_2) + tracker.trackEvent("Anyplace Installation", "Anyplace Server start", "Anyplace logging") + } + +} \ No newline at end of file diff --git a/server/app/ErrorHandler.scala b/server/app/ErrorHandler.scala index 1b6f64283..33c681698 100644 --- a/server/app/ErrorHandler.scala +++ b/server/app/ErrorHandler.scala @@ -48,9 +48,9 @@ import utils.{LPLogger, LPUtils} class ErrorHandler extends HttpErrorHandler { def infoGithub(eid: String) : String = { - "\n\n\nIf you think this is an error, open a new issue at:" + - "\nhttps://github.com/dmsl/anyplace/issues" + - "\n\nReference ErrorID:" + eid + //"\n\n\nIf you think this is an error, open a new issue at:" + + //"\nhttps://github.com/dmsl/anyplace/issues" + + "ErrorID:" + eid } def errorMsg(request: RequestHeader): String = { diff --git a/server/app/Global.scala b/server/app/Global.scala index 00c2339a8..c5d3b71c6 100644 --- a/server/app/Global.scala +++ b/server/app/Global.scala @@ -1,96 +1,133 @@ -/* - * Anyplace: A free and open Indoor Navigation Service with superb accuracy! - * - * Anyplace is a first-of-a-kind indoor information service offering GPS-less - * localization, navigation and search inside buildings using ordinary smartphones. - * - * Author(s): Constantinos Costa, Kyriakos Georgiou, Lambros Petrou, Paschalis Mpeis - * - * Supervisor: Demetrios Zeinalipour-Yazti - * - * URL: https://anyplace.cs.ucy.ac.cy - * Contact: anyplace@cs.ucy.ac.cy - * - * Copyright (c) 2016, Data Management Systems Lab (DMSL), University of Cyprus. - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the “Software”), to deal in the - * Software without restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -import java.text.SimpleDateFormat -import java.util.Date - -import com.dmurph.tracking.JGoogleAnalyticsTracker.GoogleAnalyticsVersion -import com.dmurph.tracking.{AnalyticsConfigData, JGoogleAnalyticsTracker} -import datasources.{CouchbaseDatasource, DatasourceException, InfluxdbDatasource, MongodbDatasource} -import play.{Application, GlobalSettings, Logger} -import utils.LPLogger - -// TODO Should be deprecated once we update. -class Global extends GlobalSettings { - def _date () = { - val date_format = "dd/MM/YY HH:mm:ss"; - new SimpleDateFormat(date_format).format(new Date) - } - - override def onStart(app: Application) { - LPLogger.info(_date + " | Global::onStart():: Anyplace Application started: ") - // TODO PM: store const: upTime - // and if ap-dev: display it somewhere - // or figure out a way to find which version is used) - // ls /build/server-zip creation time? - // or restart service time? - - InfluxdbDatasource.getStaticInstance - CouchbaseDatasource.getStaticInstance - MongodbDatasource.getStaticInstance - logAnalyticsInstallation() - } - - // CHECK this - override def onStop(app: Application) { - Logger.info(_date + " | Global::onStop():: Anyplace Application stopped ") - try { - InfluxdbDatasource.getStaticInstance.disconnect() - CouchbaseDatasource.getStaticInstance.disconnect() - MongodbDatasource.getStaticInstance.disconnect() - } catch { - case e: DatasourceException => Logger.error("Global::onStop():: Exception while disconnecting from the couchbase server: " + - e.getMessage) - } - } - - def logAnalyticsInstallation(): Unit = { - /** - * Log the entry point from server installation - */ - JGoogleAnalyticsTracker.setProxy(System.getenv("http_proxy")) - val config = new AnalyticsConfigData("UA-61313158-2") - val tracker = new JGoogleAnalyticsTracker(config, GoogleAnalyticsVersion.V_4_7_2) - tracker.trackEvent("Anyplace Installation", "Anyplace Server start", "Anyplace logging") - /** - * End - */ - } - -// override def onHandlerNotFound(request: RequestHeader) = { -// Future.successful(NotFound(Json.obj("error" -> "Not Found"))) -// } -} +///* +// * Anyplace: A free and open Indoor Navigation Service with superb accuracy! +// * +// * Anyplace is a first-of-a-kind indoor information service offering GPS-less +// * localization, navigation and search inside buildings using ordinary smartphones. +// * +// * Author(s): Constantinos Costa, Kyriakos Georgiou, Lambros Petrou, Paschalis Mpeis +// * +// * Supervisor: Demetrios Zeinalipour-Yazti +// * +// * URL: https://anyplace.cs.ucy.ac.cy +// * Contact: anyplace@cs.ucy.ac.cy +// * +// * Copyright (c) 2016, Data Management Systems Lab (DMSL), University of Cyprus. +// * All rights reserved. +// * +// * Permission is hereby granted, free of charge, to any person obtaining a copy of +// * this software and associated documentation files (the “Software”), to deal in the +// * Software without restriction, including without limitation the rights to use, copy, +// * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +// * and to permit persons to whom the Software is furnished to do so, subject to the +// * following conditions: +// * +// * The above copyright notice and this permission notice shall be included in all +// * copies or substantial portions of the Software. +// * +// * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +// * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// * DEALINGS IN THE SOFTWARE. +// * +// */ +// +//import java.text.SimpleDateFormat +//import java.util.Date +// +//import com.dmurph.tracking.JGoogleAnalyticsTracker.GoogleAnalyticsVersion +//import com.dmurph.tracking.{AnalyticsConfigData, JGoogleAnalyticsTracker} +//import datasources.{CouchbaseDatasource, DatasourceException, InfluxdbDatasource, MongodbDatasource} +////import play.{Application, GlobalSettings, Logger} +//import utils.LPLogger +// +////// TODO:PM Should be deprecated once we update. +////class Global extends GlobalSettings { +//// def _date () = { / TODO:NN move below +//// val date_format = "dd/MM/YY HH:mm:ss"; +//// new SimpleDateFormat(date_format).format(new Date) +//// } +//// +//// override def onStart(app: Application) { +//// LPLogger.info(_date + " | Global::onStart():: Anyplace Application started: ") +//// // TODO PM: store const: upTime +//// // and if ap-dev: display it somewhere +//// // or figure out a way to find which version is used) +//// // ls /build/server-zip creation time? +//// // or restart service time? +//// +//// InfluxdbDatasource.getStaticInstance +//// CouchbaseDatasource.getStaticInstance +//// MongodbDatasource.getStaticInstance +//// logAnalyticsInstallation() +//// } +//// +//// // CHECK this +//// override def onStop(app: Application) { +//// Logger.info(_date + " | Global::onStop():: Anyplace Application stopped ") +//// try { +//// InfluxdbDatasource.getStaticInstance.disconnect() +//// CouchbaseDatasource.getStaticInstance.disconnect() +//// MongodbDatasource.getStaticInstance.disconnect() +//// } catch { +//// case e: DatasourceException => Logger.error("Global::onStop():: Exception while disconnecting from the couchbase server: " + +//// e.getMessage) +//// } +//// } +//// +//// def logAnalyticsInstallation(): Unit = { +//// /** +//// * Log the entry point from server installation +//// */ +//// JGoogleAnalyticsTracker.setProxy(System.getenv("http_proxy")) +//// val config = new AnalyticsConfigData("UA-61313158-2") +//// val tracker = new JGoogleAnalyticsTracker(config, GoogleAnalyticsVersion.V_4_7_2) +//// tracker.trackEvent("Anyplace Installation", "Anyplace Server start", "Anyplace logging") +//// /** +//// * End +//// */ +//// } +//// +////// override def onHandlerNotFound(request: RequestHeader) = { +////// Future.successful(NotFound(Json.obj("error" -> "Not Found"))) +////// } +////} +// +//import java.time.{Clock, Instant} +//import javax.inject._ +//import play.api.Logger +//import play.api.inject.ApplicationLifecycle +//import scala.concurrent.Future +// +///** +// * This class demonstrates how to run code when the +// * application starts and stops. It starts a timer when the +// * application starts. When the application stops it prints out how +// * long the application was running for. +// * +// * This class is registered for Guice dependency injection in the +// * [[Module]] class. We want the class to start when the application +// * starts, so it is registered as an "eager singleton". See the code +// * in the [[Module]] class to see how this happens. +// * +// * This class needs to run code when the server stops. It uses the +// * application's [[ApplicationLifecycle]] to register a stop hook. +// */ +//@Singleton +//object @Inject() Global(appLifecycle: ApplicationLifecycle) { +// // This code is called when the application start +// InfluxdbDatasource.getStaticInstance +// CouchbaseDatasource.getStaticInstance +// MongodbDatasource.getStaticInstance +// //logAnalyticsInstallation() +// +// +// +// +// //// Runs when the application stops. +// //appLifecycle.addStopHook { () => +// // // TODO .... +// //} +//} \ No newline at end of file diff --git a/server/app/Module.scala b/server/app/Module.scala new file mode 100644 index 000000000..cdd25ecb6 --- /dev/null +++ b/server/app/Module.scala @@ -0,0 +1,7 @@ +import com.google.inject.AbstractModule + +class Module extends AbstractModule { + override def configure() = { + bind(classOf[Anyplace]).asEagerSingleton() + } +} diff --git a/server/app/acces/ACCES_RBF.scala b/server/app/acces/ACCES_RBF.scala deleted file mode 100644 index 4a5b6db28..000000000 --- a/server/app/acces/ACCES_RBF.scala +++ /dev/null @@ -1,527 +0,0 @@ -package acces - -import java.io.PrintWriter - -import breeze.linalg.{*, DenseMatrix, DenseVector, argsort, diag, max, min, sum, svd} -import breeze.numerics.exp -import breeze.stats.meanAndVariance -import dk.gp.cov.CovSEiso -import dk.gp.gpr.{GprModel, gpr} - -import scala.math.{log, pow, sqrt} -import scala.util.control.Breaks.{break, breakable} - -/** - * Calculates CRLB <=> ACCES score for measurement map using RBF kernel - * Due to the nature of CRLB, score goes to infinity if measurements are collected in lines - * or if supremum points are present. Lines are handled with pseudo-inverse, but supremums are not. - * @param X - Matrix of independent variables, e.g., coordinates. - * Rows - different points (1, 2, ...). Columns - different coordinates (x, y, ...) - * @param Y - Matrix of measurements, e.g., RSSI values. - * Rows - different зщштеы (1, 2, ...). Columns - different measurements (AP1, AP2, ...) - * @param Ms - Not used. - * @param sfs - multiplier in RBF kernel. Provide to use previously estimated parameters. - * @param noises - additive noise of measurements. Provide to use previously estimated parameters. - * @param gammas - multiplier in exponent in RBF kernel. Provide to use previously estimated parameters. - * @param cut_k_features - whether to consider only k best features (e.g., APs). - * Improves performance, but results could be different. - * @param drop_redundant_features - whether to drop features with zero variance, - * e.g., ignore distant Wi-Fi APs. Default - true. - * @param X_min - minimum value of X from prior knowledge (not needed if normalize_x = false) - * @param X_max - maximum value of X from prior knowledge (not needed if normalize_x = false) - * @param Y_min - minimum values of Y. Recommended to specify for each particular component of Y - * as it will affect which features to drop if cut_k_features is provided. - * @param Y_max - maximum values of Y - * @param Y_means - fixed means of Y from prior knowledge - * @param normalize_x - whether to normalize X (false recommended if X is coordinates). Default - false. - * @param normalize_y - whether to normalize Y, i.e., subtract means before fitting (true recommended). Default - true. - */ -class AccesRBF( - X: DenseMatrix[Double], Y: DenseMatrix[Double], - Ms: Option[Array[DenseMatrix[Double]]] = None, - sfs: Option[DenseVector[Double]] = None, - noises: Option[DenseVector[Double]] = None, - gammas: Option[DenseVector[Double]] = None, - cut_k_features: Option[Int] = None, - drop_redundant_features: Boolean = true, - X_min: Option[DenseVector[Double]] = None, - X_max: Option[DenseVector[Double]] = None, - Y_min: Option[DenseVector[Double]] = None, - Y_max: Option[DenseVector[Double]] = None, - Y_means: Option[DenseVector[Double]] = None, - normalize_x: Boolean = false, - normalize_y: Boolean = true) { - - val _X_min: DenseVector[Double] = X_min.getOrElse(min(X(::, *)).t) - val _X_max: DenseVector[Double] = X_max.getOrElse(max(X(::, *)).t) - val _X_normed: DenseMatrix[Double] = if (normalize_x) { - normalize_X(X=X, X_min=_X_min, X_max=_X_max) - } else { - X - } - //Attention: if use different sources, then y_min and y_max could be incorrect - //if not provided in advance, e.g., for Wi-Fi could be [-110, 0], but for magnetic could be [30, 90] - val _Y_min: DenseVector[Double] = Y_min.getOrElse(min(Y) * DenseVector.ones[Double](Y.cols)) - val _Y_max: DenseVector[Double] = Y_max.getOrElse(max(Y) * DenseVector.ones[Double](Y.cols)) - if (max(_Y_min) > min(Y) || min(_Y_max) < max(Y)) { - throw new IllegalArgumentException("Invalid Y_max, Y_min values") - } - val _Y_means: DenseVector[Double] = if (normalize_y) { - Y_means.getOrElse(get_column_means(A=Y)) - } else { - DenseVector.zeros(Y.cols) - } - val _selected_features: IndexedSeq[Int] = select_features(Y=Y, Y_min=_Y_min, Y_max=_Y_max, - cut_k_features.getOrElse(Y.cols), drop_redundant = drop_redundant_features) - val _Y_normed = normalize_Y( Y=Y, Y_means=_Y_means) - -// LPLogger.debug("x_min", _X_min) -// LPLogger.debug("x_max", _X_max) -// LPLogger.debug("X_normed\n", _X_normed.toDenseVector) -// LPLogger.debug("Y_min", _Y_min) -// LPLogger.debug("Y_max", _Y_max) -// LPLogger.debug("Y_means", _Y_means) -// LPLogger.debug("Y_normed", _Y_normed.toDenseVector) - - var _Ms = Ms - var _gammas = gammas - var _noises = noises - var _sfs = sfs - - def normalize_X(X: DenseMatrix[Double], X_min: DenseVector[Double], X_max: DenseVector[Double]): DenseMatrix[Double] = { - val tmp = X(*, ::) - X_min - return tmp(*, ::) / (X_max - X_min) - } - - def denormalize_X(X: DenseMatrix[Double], X_min: DenseVector[Double], X_max: DenseVector[Double]): DenseMatrix[Double] = { - val tmp: DenseMatrix[Double] = X(*, ::) :* (X_max - X_min) - return (tmp(*, ::) + X_min).toDenseMatrix - } - - def normalize_Y(Y: DenseMatrix[Double], Y_means: DenseVector[Double]): DenseMatrix[Double] = { - // Only change mean values to get better prior - //Need to accout for it during predictions - return Y(*, ::) - Y_means - } - - def denormalize_Y(Y: DenseMatrix[Double], Y_means: DenseVector[Double]): DenseMatrix[Double] = { - return Y(*, ::) + Y_means - } - - def select_features(Y: DenseMatrix[Double], Y_min: DenseVector[Double], Y_max: DenseVector[Double], - k_features: Int, drop_redundant: Boolean = true, - rtol: Double = 0.01, atol: Double = 0.00001): IndexedSeq[Int] = { - if (k_features <= 0) { throw new IllegalArgumentException("k_features must be positive")} - val k = if (k_features > Y.cols) Y.cols else k_features - - // LPLogger.debug("select_features: k", k) - // LPLogger.debug("select_features: Y_min", Y_min) - // LPLogger.debug("select_features: Y_max", Y_max) - val scores = DenseVector.zeros[Double](k) - for (i <- 0 to k - 1) { - scores(i) = sqrt(meanAndVariance(Y(::, i)).variance) / (Y_max(i) - Y_min(i)) - } - var inds = argsort(scores).reverse - // LPLogger.debug("scores", scores) - // LPLogger.debug("inds", inds) - // LPLogger.debug("drop", drop_redundant) - if (drop_redundant) { - breakable { - //LPLogger.debug("inds length", inds.length - 1) - for (i <- 0 to inds.length - 1) { - val ind = inds(i) - // LPLogger.debug("ind", ind, "var", scores(i)) - if (~=(scores(ind), 0, atol) || scores(ind) / scores(inds(0)) < rtol) { - inds = inds.slice(0, i) - // LPLogger.debug(inds) - break - } - // if (~=(scores(ind), 0.0, 0.00001)) { - // inds = inds.slice(0, i) - // LPLogger.debug(inds) - // break - // } - } - } - } - inds = inds.slice(0, min(inds.length, k)) - inds = inds.sorted - - // LPLogger.debug("new inds", inds) - // LPLogger.debug("new scores", scores(inds).toDenseVector) - - return inds - } - - def fit_gpr(estimate: Boolean = false, use_default_params: Boolean = false) = { - val X: DenseMatrix[Double] = this._X_normed - val Y: DenseMatrix[Double] = this._Y_normed(::, this._selected_features).toDenseMatrix - val X_min = min(X(::, *)).t - val X_max = max(X(::, *)).t - val Y_min = this._Y_min(this._selected_features).toDenseVector - val Y_max = this._Y_max(this._selected_features).toDenseVector - - val n = X.rows - val d = X.cols - val m = Y.cols - - // LPLogger.debug("X.rows, Y.rows: ", X.rows, Y.rows) - assert(X.rows == Y.rows) - - if(estimate) { - assert(this._sfs == None && this._gammas == None && this._noises == None) - } else if (!use_default_params) { - assert(this._sfs != None && this._gammas != None && this._noises != None) - assert(this._gammas.get.length == this._noises.get.length && this._noises.get.length == this._sfs.get.length) - } - -// LPLogger.debug("estimate", estimate) -// LPLogger.debug("use default parameters", use_default_params) - - val sf_0: DenseVector[Double] = 0.01 * (Y_max - Y_min) - val l_0: DenseVector[Double] = 0.1 * breeze.linalg.norm(X_max - X_min) * DenseVector.ones[Double](m) - val noise_0: DenseVector[Double] = sf_0.copy - -// LPLogger.debug("Default parameters") -// LPLogger.debug("sf_0", sf_0) -// LPLogger.debug("l_0", l_0) -// LPLogger.debug("gamma_0", 0.5 / (l_0 :* l_0)) -// LPLogger.debug("noise_0", noise_0) - - val sfs: DenseVector[Double] = this._sfs.getOrElse(sf_0) - // var gammas = sfs - val gammas: DenseVector[Double] = this._gammas.getOrElse(0.5 / (l_0 :* l_0)) - val noises: DenseVector[Double] = this._noises.getOrElse(noise_0) - -// LPLogger.debug("sfs", sfs) -// LPLogger.debug("ls", breeze.numerics.sqrt(0.5 / gammas)) -// LPLogger.debug("gammas", gammas) -// LPLogger.debug("noises", noises) - - val Ms = Array.ofDim[DenseMatrix[Double]](Y.cols) - - for (i <- 0 to Y.cols - 1) { - var covFunc = CovSEiso() - var covFuncParams = DenseVector( - log(sfs(i)), - log(sqrt( 0.5 / gammas(i))) - ) - var noiseLogStdDev: Double = log(noises(i)) - - val model = if (estimate) { - // LPLogger.debug("estimate") - // LPLogger.debug("estimate: X", X.toDenseVector) - // LPLogger.debug("estimate: Y", (Y(::, i)).toDenseVector) - var model_est = gpr(X, (Y(::, i)).toDenseVector, covFunc, covFuncParams, noiseLogStdDev) - // LPLogger.debug("estimate: covFuncParams", model_est.covFuncParams) - // LPLogger.debug("estimate: noiseLogStdDev", model_est.noiseLogStdDev) - // LPLogger.debug("estimate: sf", exp(model_est.covFuncParams(0))) - model_est - } else { - // LPLogger.debug("no estimate") - GprModel(X, (Y(::, i)).toDenseVector, covFunc, covFuncParams, noiseLogStdDev) - } - - val v = DenseVector.zeros[Double](1) - v(0) = 10 - // LPLogger.debug("v", v) - - sfs(i) = exp(model.covFuncParams(0)) - gammas(i) = 0.5 / pow(exp(model.covFuncParams(1)), 2.0) - noises(i) = exp(model.noiseLogStdDev) - - Ms(i) = { - val kXX = model.calcKXX() - // LPLogger.debug("kXX", kXX.toDenseVector) - // try{ - val kXXInv = model.calcKXXInv(kXX) - kXXInv - // } catch { - // case _ : breeze.linalg.MatrixSingularException => { - // LPLogger.debug("Singular kXX matrix!") - // diag(DenseVector.ones[Double](n)*Double.PositiveInfinity) - // } - // } - } - } - - // LPLogger.debug("new parameters for col 0") - // LPLogger.debug("new Ms", Ms(0).toDenseVector) - // LPLogger.debug("new sfs", sfs(0)) - // LPLogger.debug("new gammas", gammas(0)) - // LPLogger.debug("new ls", sqrt(0.5 / gammas(0))) - // LPLogger.debug("new noises", noises(0)) - - this._Ms = Option(Ms) - this._sfs = Option(sfs) - this._gammas = Option(gammas) - this._noises = Option(noises) - } - - def predict_gpr_scalar(X: DenseMatrix[Double], component: Int): (DenseVector[Double],DenseVector[Double]) = { - // WRONG INDEXING HERE, component for M and data is not the same, need to fix - if (!this._selected_features.contains(component)) { - throw new IllegalArgumentException("Feature %d is ignored".format(component)) - } - val X_train_normed: DenseMatrix[Double] = this._X_normed - val y_train_normed: DenseVector[Double] = this._Y_normed(::, component) - val M: DenseMatrix[Double] = this._Ms.get(component) - val gamma: Double = this._gammas.get(component) - val sf: Double = this._sfs.get(component) - - val X_normed: DenseMatrix[Double] = if (this.normalize_x) { - normalize_X(X, this._X_min, this._X_max) - } else { - X - } - - val n = X.rows - val y_test = DenseVector.zeros[Double](n) - val std_test = DenseVector.zeros[Double](n) - for (i <- 0 to n - 1) { - val k = get_k(X_train_normed, X_normed(i, ::).t, gamma=gamma, sf=sf) - y_test(i) = get_u(M=M, y=y_train_normed, k=k) - std_test(i) = get_s(M=M, k=k, sf=sf) - } - return if (normalize_y) { - (denormalize_Y(DenseMatrix(y_test).t, this._Y_means(component to component)).toDenseVector, std_test) - } else { - (y_test, std_test) - } - } - - def eucl_sqr(X: DenseMatrix[Double], x: DenseVector[Double]): DenseVector[Double] = { - var dif = X(*, ::) - x - dif = dif :* dif - var d2 = sum(dif(*, ::)) - return d2 - } - - def rbf(d2: DenseVector[Double], gamma: Double, sf: Double): DenseVector[Double] = { - return scala.math.pow(sf, 2.0)*exp(-gamma*d2) - } - - def get_k(d2: DenseVector[Double], gamma: Double, sf: Double): DenseVector[Double] = { - return rbf(d2, gamma, sf) - } - - def get_k(X: DenseMatrix[Double], x: DenseVector[Double], gamma: Double, sf: Double): DenseVector[Double] ={ - return get_k(eucl_sqr(X, x), gamma, sf) - } - - def get_grad_k(k: DenseVector[Double], gamma: Double, X: DenseMatrix[Double], x: DenseVector[Double]) : DenseMatrix[Double] = { - var tmp = X(*, ::) - x - tmp = tmp(::, *) :* k - return 2*gamma*tmp - } - - def get_H_k(ki: Double, gamma: Double, Xi: DenseVector[Double], x: DenseVector[Double]): DenseMatrix[Double] = { - return 2*gamma*ki*(2*gamma*(Xi - x)*(Xi-x).t - DenseMatrix.eye[Double](x.length)) - } - - def get_u(M: DenseMatrix[Double], y: DenseVector[Double], k: DenseVector[Double]) : Double = { - return (k.t * M) * y - } - - def get_grad_u(M: DenseMatrix[Double], y: DenseVector[Double], grad_k: DenseMatrix[Double]): DenseVector[Double] = { - return grad_k.t * (M * y) - } - - def get_H_u(M: DenseMatrix[Double], y: DenseVector[Double], H_ks: Array[DenseMatrix[Double]]): DenseMatrix[Double] = { - val n = M.rows - val d = H_ks(0).rows - assert(H_ks(0).rows == H_ks(0).cols) - val c = M * y - var H_u = DenseMatrix.zeros[Double](d,d) - for (i <- 0 to n - 1) { - H_u += c(i)*H_ks(i) - } - return H_u - } - - def get_s(M: DenseMatrix[Double], k: DenseVector[Double], sf: Double): Double = { - return sqrt(pow(sf, 2.0) - k.t * (M * k)) - } - - def get_grad_s(M: DenseMatrix[Double], s: Double, k: DenseVector[Double], grad_k: DenseMatrix[Double]): DenseVector[Double] = { - var tmp = - grad_k.t * (M * k) / 2.0 / s - //M is symmetric - tmp *= 2.0 - return tmp - - // return - grad_k.t * (M * k) - ((k.t * M) * grad_k).t - } - - def get_H_s(M: DenseMatrix[Double], k: DenseVector[Double], - s: Double, grad_s: DenseVector[Double], - grad_k: DenseMatrix[Double], H_ks: Array[DenseMatrix[Double]]): DenseMatrix[Double] = { - val n = M.rows - val d = H_ks(0).rows - assert(H_ks(0).rows == H_ks(0).cols) - var H_s2 = DenseMatrix.zeros[Double](d,d) - //M is symmetric => 2* - // Grad term - H_s2 += - 2.0 * (M * grad_k).t * grad_k - // Hessian term - val c = - 2.0 * M * k - for (i <- 0 to n - 1) { - H_s2 += c(i)*H_ks(i) - } - val H_s = (H_s2 - 2.0 * grad_s * grad_s.t) / (2.0 * s) - return H_s - } - - def get_H_1_s2(s: Double, grad_s: DenseVector[Double], H_s: DenseMatrix[Double]): DenseMatrix[Double] = { - return 2.0 / scala.math.pow(s, 3.0) * (3.0 * grad_s * grad_s.t / s - H_s) - } - - def get_H_u_1_s2(u: Double, s: Double, - grad_u: DenseVector[Double], grad_s: DenseVector[Double], - H_u: DenseMatrix[Double], H_1_s2: DenseMatrix[Double]): DenseMatrix[Double] = { - var ret = H_u / scala.math.pow(s, 2.0) - ret += - 2.0 / scala.math.pow(s, 3.0) * (grad_s * grad_u.t + grad_u * grad_s.t) - ret += u * H_1_s2 - return ret - } - - def get_H_u2_1_s2(u: Double, s: Double, - grad_u: DenseVector[Double], grad_s: DenseVector[Double], - H_1_s2: DenseMatrix[Double], H_u_1_s2: DenseMatrix[Double]): DenseMatrix[Double] = { - - var ret = 2.0 * u * H_u_1_s2 - ret += 2.0 / scala.math.pow(s, 2.0) * grad_u * grad_u.t - ret += - scala.math.pow(u, 2.0) * H_1_s2 - return ret - } - - def get_H_logs(s: Double, grad_s: DenseVector[Double], H_s: DenseMatrix[Double]): DenseMatrix[Double] = { - return (H_s - grad_s * grad_s.t / s) / s - } - - def get_FIM(x: DenseVector[Double]): DenseMatrix[Double] = { - val x_normed = if (normalize_x) { - normalize_X(x.toDenseMatrix, this._X_min, this._X_max).toDenseVector - } else x - val X_normed = this._X_normed - val Y_normed = this._Y_normed(::, this._selected_features).toDenseMatrix - val m = Y_normed.cols - val n = X_normed.rows - val d = X_normed.cols - val d2 = eucl_sqr(X=X_normed, x=x_normed) - - // var FIM = DenseMatrix.zeros[Double](d,d) - val FIMs: Array[DenseMatrix[Double]] = Array.ofDim[DenseMatrix[Double]](this._selected_features.length) - - for (i <- 0 until Y_normed.cols) { - var FIM = DenseMatrix.zeros[Double](d,d) - val M = this._Ms.get(i) - val gamma = this._gammas.get(i) - val sf = this._sfs.get(i) - val mean = this._Y_means(i) - - // LPLogger.debug("gamma", gamma) - // LPLogger.debug("sf", sf) - // LPLogger.debug("mean", mean) - // LPLogger.debug("M", M) - - val k = get_k(d2=d2, gamma=gamma, sf=sf) - val y = Y_normed(::,i) - //Account for possibly subtracted mean - val u = mean + get_u(M=M, y=y, k=k) - val s = get_s(M=M, k=k, sf=sf) - val grad_k = get_grad_k(k=k, gamma=gamma, X=X_normed, x=x_normed) - val grad_u = get_grad_u(M=M, y=y, grad_k=grad_k) - val grad_s = get_grad_s(M=M, s=s, k=k, grad_k=grad_k) - - var H_ks = Array.ofDim[DenseMatrix[Double]](n) - for (j <- 0 to n-1) { - H_ks(j) = get_H_k(ki = k(j), gamma=gamma, Xi = X_normed(j, ::).t, x = x_normed) - } - - val H_u = get_H_u(M=M, y=y, H_ks=H_ks) - val H_s = get_H_s(M=M, k=k, s=s, grad_s=grad_s, grad_k=grad_k, H_ks=H_ks) - val H_1_s2 = get_H_1_s2(s=s, grad_s=grad_s, H_s=H_s) - val H_u_1_s2 = get_H_u_1_s2(u=u, s=s, grad_u=grad_u, grad_s=grad_s, H_u=H_u, H_1_s2=H_1_s2) - val H_u2_1_s2 = get_H_u2_1_s2(u=u, s=s, grad_u=grad_u, grad_s=grad_s, H_1_s2=H_1_s2, H_u_1_s2=H_u_1_s2) - val H_logs = get_H_logs(s=s, grad_s=grad_s, H_s=H_s) - - FIM += (scala.math.pow(u, 2.0) + scala.math.pow(s, 2.0))*H_1_s2 - FIM += H_u2_1_s2 - FIM += - 2.0 * u * H_u_1_s2 - FIM += 2.0 * H_logs - FIM *= 0.5 - FIMs(i) = FIM - // LPLogger.debug("Feature %d: FIM: %d x %d:\n".format(this._selected_features(i), FIM.rows, FIM.cols), FIM) - } - var FIM_total = DenseMatrix.zeros[Double](d,d) - for (i <- 0 to FIMs.length - 1) { - FIM_total += FIMs(i) - } - FIM_total - } - - /** - * Returns error bound from CRLB (root of trace of inverse Fisher Information Matrix) - * @param x - vector of coordinates - * @param pinv_cond - cut singular values Si (i=1, 2, ...) smaller (in modulus) than S0*pinv_cond. - * If topolgy is corridor-like, but in 2D, then should cut small singular values in order - * to avoid infinite CRLB. - * @return - */ - def get_CRLB(x: DenseVector[Double], pinv_cond: Double = 1e-15): Double = { - // return try { - // val svd = breeze.linalg.svd() - // sqrt(breeze.linalg.trace(breeze.linalg.inv(get_FIM(x=x)))) - // } catch { - // case _ : breeze.linalg.MatrixSingularException => { - // Double.PositiveInfinity - // } - // } - return { - val FIM = get_FIM(x=x) - val breeze.linalg.svd.SVD(u, s, vt) = svd(FIM) - var k: Int = 1 - for (i <- 1 to s.length - 1) { - if (scala.math.abs(s(i)) >= scala.math.abs(s(0)*pinv_cond)) k += 1 - } - val Uk = u(::, 0 to k - 1) - val sk = s(0 to k - 1) - val Vtk = vt(0 to k - 1, ::) - val FIMinv = Vtk.t * diag(1.0 / sk) * Uk.t - sqrt(breeze.linalg.trace(FIMinv)) - } - } - - /** - * @param X - matrix of coordinates - * @return - */ - def get_CRLB(X: DenseMatrix[Double], pinv_cond: Double): DenseVector[Double] = { - val crlbs = DenseVector.zeros[Double](X.rows) - // LPLogger.debug("lsolea01: ACCES",X.rows) - for (i <- 0 until X.rows) { - crlbs(i) = get_CRLB(X(i, ::).t, pinv_cond) - } - - // lsolea01 x write to file - // val file_io = new PrintWriter("X_floor_2.txt") - // for (i <- 0 until X.rows) { - // file_io.LPLogger.debug(X(i,::)) - // } - // file_io.close() - crlbs - } - - def ~=(x: Double, y: Double, precision: Double) = { - if ((x - y).abs < precision) true else false - } - - def get_column_means(A: DenseMatrix[Double]): DenseVector[Double] = { - val means = DenseVector.zeros[Double](A.cols) - for (i <- 0 to A.cols - 1) { - val mv = meanAndVariance(A(::, i)) - means(i) = mv.mean - } - return means - } -} diff --git a/server/app/acces/GeoUtils.scala b/server/app/acces/GeoUtils.scala deleted file mode 100644 index 53a75cd11..000000000 --- a/server/app/acces/GeoUtils.scala +++ /dev/null @@ -1,207 +0,0 @@ -package acces - -import breeze.linalg.{DenseMatrix, DenseVector, linspace} - -import scala.math._ -import java.util.{ArrayList, List} -import utils.{GeoJSONMultiPoint, GeoPoint} -object GeoUtils { - - val R_eq: Double = 6356.752 - val R_pl: Double = 6371.001 - - def radius(lat: Double): Double = { - if (lat > Pi / 2.0 || lat < -Pi / 2.0) { - throw new IllegalArgumentException("Most probably, lat is in degrees, must be in radians") - } - val r1 = R_eq - val r2 = R_pl - val sinB = sin(lat) - val cosB = cos(lat) - val radius = sqrt( (pow(pow(r1, 2.0)*cosB, 2.0) + pow(pow(r2, 2.0)*sinB, 2.0)) / (pow(r1*cosB, 2.0) + pow(r2*sinB, 2.0 ))) - radius - } - - def dist(latlng_deg_1: DenseVector[Double], latlng_deg_2: DenseVector[Double]): Double = { - if (latlng_deg_1.length != 2 || latlng_deg_2.length != 2) { - throw new IllegalArgumentException("Incorrect latlng sizes") - } - val (lat1, lng1) = (toRadians(latlng_deg_1(0)), toRadians(latlng_deg_1(1))) - val (lat2, lng2) = (toRadians(latlng_deg_2(0)), toRadians(latlng_deg_2(1))) - - val a = pow(sin((lat1 - lat2)/2.0), 2.0) + cos(lat1)*cos(lat2)*pow(sin((lng1-lng2)/2.0), 2.0) - val c = 2.0*atan2( sqrt(a), sqrt(1.0-a) ) - val d = radius((lat1 + lat2)/2.0)*c - return d*1000.0 - } - - def latlng2xy(latlng_deg: DenseVector[Double], - latlng_deg_bl: DenseVector[Double], - latlng_deg_ur: DenseVector[Double]): DenseVector[Double] = { - if (latlng_deg.length != 2 || latlng_deg_bl.length != 2 || latlng_deg_ur.length != 2) { - throw new IllegalArgumentException("Incorrect latlng sizes") - } - val latlng_deg_left = DenseVector[Double]( - (latlng_deg_bl(0) + latlng_deg_ur(0)) / 2.0, - latlng_deg_bl(1) - ) - val latlng_deg_right = DenseVector[Double]( - (latlng_deg_bl(0) + latlng_deg_ur(0)) / 2.0, - latlng_deg_ur(1) - ) - val latlng_deg_bottom = DenseVector[Double]( - latlng_deg_bl(0), - (latlng_deg_bl(1) + latlng_deg_ur(1)) / 2.0 - ) - val latlng_deg_top = DenseVector[Double]( - latlng_deg_ur(0), - (latlng_deg_bl(1) + latlng_deg_ur(1)) / 2.0 - ) - val width = dist(latlng_deg_left, latlng_deg_right) - val height = dist(latlng_deg_bottom, latlng_deg_top) - - //Latitude of point, longitude of left - val latlng_deg_x = DenseVector[Double](latlng_deg(0), latlng_deg_bl(1)) - val d_x = dist(latlng_deg_x, latlng_deg) * {if (latlng_deg(1) < latlng_deg_x(1)) -1.0 else 1.0} - - //Longitude of point, latitude of bottom - val latlng_deg_y = DenseVector[Double](latlng_deg_bl(0), latlng_deg(1)) - val d_y = dist(latlng_deg_y, latlng_deg) * {if (latlng_deg(0) < latlng_deg_y(0)) -1.0 else 1.0} - - DenseVector[Double](d_x, d_y) - } - - def latlng2xy(point: GeoPoint, - bl: GeoPoint, - ur: GeoPoint): DenseVector[Double] = { - val latlng_deg = DenseVector[Double](point.dlat, point.dlon) - val latlng_deg_bl = DenseVector[Double](bl.dlat, bl.dlon) - val latlng_deg_ur = DenseVector[Double](ur.dlat, ur.dlon) - latlng2xy(latlng_deg, latlng_deg_bl, latlng_deg_ur) - } - - def latlng2xy(latlng_deg: DenseMatrix[Double], - latlng_deg_bl: DenseVector[Double], - latlng_deg_ur: DenseVector[Double]): DenseMatrix[Double] = { - if (latlng_deg.cols != 2 || latlng_deg_bl.length != 2 || latlng_deg_ur.length != 2) { - throw new IllegalArgumentException("Incorrect latlng sizes") - } - val xy: DenseMatrix[Double] = DenseMatrix.zeros[Double](latlng_deg.rows, latlng_deg.cols) - for (i <- 0 to xy.rows - 1) { - xy(i, ::) := latlng2xy(latlng_deg(i, ::).t, latlng_deg_bl, latlng_deg_ur).t - } - xy - } - - def latlng2xy(points: GeoJSONMultiPoint, bl: GeoPoint, ur: GeoPoint): DenseMatrix[Double] = { - val n = points.points.size() - val latlng_deg = DenseMatrix.zeros[Double](n, 2) - for (i <- 0 to n - 1) { - val point = points.points.get(i) - latlng_deg(i, ::) := DenseVector[Double](point.dlat, point.dlon).t - } - val latlng_deg_bl = DenseVector[Double](bl.dlat, bl.dlon) - val latlng_deg_ur = DenseVector[Double](ur.dlat, ur.dlon) - latlng2xy(latlng_deg, latlng_deg_bl, latlng_deg_ur) - } - - - def xy2latlng(xy: DenseVector[Double], - latlng_deg_bl: DenseVector[Double], - latlng_deg_ur: DenseVector[Double]): DenseVector[Double] = { - if (xy.length != 2 || latlng_deg_bl.length != 2 || latlng_deg_ur.length != 2) { - throw new IllegalArgumentException("Incorrect latlng or xy sizes") - } - val latlng_deg_left = DenseVector[Double]( - (latlng_deg_bl(0) + latlng_deg_ur(0)) / 2.0, - latlng_deg_bl(1) - ) - val latlng_deg_right = DenseVector[Double]( - (latlng_deg_bl(0) + latlng_deg_ur(0)) / 2.0, - latlng_deg_ur(1) - ) - val latlng_deg_bottom = DenseVector[Double]( - latlng_deg_bl(0), - (latlng_deg_bl(1) + latlng_deg_ur(1)) / 2.0 - ) - val latlng_deg_top = DenseVector[Double]( - latlng_deg_ur(0), - (latlng_deg_bl(1) + latlng_deg_ur(1)) / 2.0 - ) - val width = dist(latlng_deg_left, latlng_deg_right) - val height = dist(latlng_deg_bottom, latlng_deg_top) - - val (x, y) = (xy(0), xy(1)) - val lat = latlng_deg_bl(0) + y / height * (latlng_deg_top(0) - latlng_deg_bottom(0)) - val lng = latlng_deg_bl(1) + x / width * (latlng_deg_right(1) - latlng_deg_left(1)) - - DenseVector[Double](lat, lng) - } - - def xy2latlng(xy: DenseVector[Double], - bl: GeoPoint, - ur: GeoPoint): DenseVector[Double] = { - xy2latlng(xy, - latlng_deg_bl = DenseVector[Double](bl.dlat, bl.dlon), - latlng_deg_ur = DenseVector[Double](ur.dlat, ur.dlon)) - } - - def xy2latlng(xy: DenseMatrix[Double], - latlng_deg_bl: DenseVector[Double], - latlng_deg_ur: DenseVector[Double]): DenseMatrix[Double] = { - if (xy.cols != 2 || latlng_deg_bl.length != 2 || latlng_deg_ur.length != 2) { - throw new IllegalArgumentException("Incorrect latlng sizes") - } - val latlng = DenseMatrix.zeros[Double](xy.rows, xy.cols) - for (i <- 0 to latlng.rows - 1) { - latlng(i, ::) := xy2latlng(xy(i, ::).t, latlng_deg_bl, latlng_deg_ur).t - } - latlng - } - - def xy2latlng(xy: DenseMatrix[Double], - bl: GeoPoint, - ur: GeoPoint): DenseMatrix[Double] = { - xy2latlng(xy, - latlng_deg_bl = DenseVector[Double](bl.dlat, bl.dlon), - latlng_deg_ur = DenseVector[Double](ur.dlat, ur.dlon)) - } - - def dv2GeoPoint(latlng: DenseVector[Double]): GeoPoint = { - if (latlng.length != 2) { - throw new IllegalArgumentException("Incorrect latlng sizes") - } - return new GeoPoint(lat=latlng(0), lon=latlng(1)) - } - - def dm2GeoJSONMultiPoint(latlng: DenseMatrix[Double]): GeoJSONMultiPoint = { - if (latlng.cols != 2) { - throw new IllegalArgumentException("Incorrect latlng sizes") - } - val n = latlng.rows - val geoJSONMultiPoint = new GeoJSONMultiPoint() - for (i <- 0 to n - 1) { - val point = new GeoPoint(lat=latlng(i, 0), lon=latlng(i, 1)) - geoJSONMultiPoint.points.add(point) - } - geoJSONMultiPoint - } - - def grid_2D(bl: DenseVector[Double], ur: DenseVector[Double], h: Double): DenseMatrix[Double] = { - assert(h > 0.0) - assert(bl.length == ur.length && bl.length == 2) - val Nx = scala.math.max( 1 + scala.math.ceil( (ur(0) - bl(0)) / h ).toInt, 2) - val Ny = scala.math.max( 1 + scala.math.ceil( (ur(1) - bl(1)) / h ).toInt, 2) - val lin_x = linspace(bl(0), ur(0), Nx) - val lin_y = linspace(bl(1), ur(1), Ny) - val grid = DenseMatrix.zeros[Double](Nx*Ny, 2) - for (i <- 0 until Nx) { - for (j <- 0 until Ny) { - val k = Ny*i + j - grid(k, ::) := DenseVector[Double](lin_x(i), lin_y(j)).t - } - } - return grid - } - -} diff --git a/server/app/accounts/ProxyAccountService.scala b/server/app/accounts/ProxyAccountService.scala index 0994346aa..fd9b17b7d 100644 --- a/server/app/accounts/ProxyAccountService.scala +++ b/server/app/accounts/ProxyAccountService.scala @@ -33,57 +33,52 @@ * DEALINGS IN THE SOFTWARE. * */ -package accounts - -import datasources.CouchbaseDatasource - -import oauth.provider.v2.models.AccessTokenModel - -import oauth.provider.v2.models.AccountModel - -import oauth.provider.v2.models.AuthInfo - -object ProxyAccountService { - -private var sInstance: ProxyAccountService = _ - - def getInstance(): ProxyAccountService = { - if (sInstance == null) { - sInstance = new ProxyAccountService() - } - sInstance - } - - } - -/** - * This class acts as a proxy to the User Service implementation. - */ -class ProxyAccountService private () extends IAccountService { - -private var mCouchbase: CouchbaseDatasource = - CouchbaseDatasource.getStaticInstance - - override def validateClient(clientId: String, - clientSecret: String, - grantType: String): AccountModel = - mCouchbase.validateClient(clientId, clientSecret, grantType) - - override def validateAccount(account: AccountModel, - username: String, - password: String): Boolean = - mCouchbase.validateAccount(account, username, password) - - override def createOrUpdateAuthInfo(account: AccountModel, - clientId: String, - scope: String): AuthInfo = - mCouchbase.createOrUpdateAuthInfo(account, clientId, scope) - - override def getAuthInfoByRefreshToken(refreshToken: String): AuthInfo = - mCouchbase.getAuthInfoByRefreshToken(refreshToken) - - override def createOrUpdateAccessToken( - authInfo: AuthInfo): AccessTokenModel = - mCouchbase.createOrUpdateAccessToken(authInfo) - - } +//package accounts +// +//import datasources.CouchbaseDatasource +//import oauth.provider.v2.models.{AccessTokenModel, AccountModel, AuthInfo} +// +//object ProxyAccountService { +// +// private var sInstance: ProxyAccountService = _ +// +// def getInstance(): ProxyAccountService = { +// if (sInstance == null) { +// sInstance = new ProxyAccountService() +// } +// sInstance +// } +// +//} +// +///** +// * This class acts as a proxy to the User Service implementation. +// */ +//class ProxyAccountService private() extends IAccountService { +// +// private var mCouchbase: CouchbaseDatasource = +// CouchbaseDatasource.getStaticInstance() +// +// override def validateClient(clientId: String, +// clientSecret: String, +// grantType: String): AccountModel = +// mCouchbase.validateClient(clientId, clientSecret, grantType) +// +// override def validateAccount(account: AccountModel, +// username: String, +// password: String): Boolean = +// mCouchbase.validateAccount(account, username, password) +// +// override def createOrUpdateAuthInfo(account: AccountModel, +// clientId: String, +// scope: String): AuthInfo = +// mCouchbase.createOrUpdateAuthInfo(account, clientId, scope) +// +// override def getAuthInfoByRefreshToken(refreshToken: String): AuthInfo = +// mCouchbase.getAuthInfoByRefreshToken(refreshToken) +// +// override def createOrUpdateAccessToken( +// authInfo: AuthInfo): AccessTokenModel = +// mCouchbase.createOrUpdateAccessToken(authInfo) +// +//} diff --git a/server/app/controllers/Admin.scala b/server/app/controllers/Admin.scala index 59dad5d1f..8936f5f81 100644 --- a/server/app/controllers/Admin.scala +++ b/server/app/controllers/Admin.scala @@ -1,13 +1,20 @@ package controllers -import controllers.AnyplaceMapping.{appendGoogleIdIfNeeded, verifyId} import datasources.{DatasourceException, MongodbDatasource, ProxyDataSource, SCHEMA} +import javax.inject.{Inject, Singleton} +import json.VALIDATE import oauth.provider.v2.models.OAuth2Request import play.api.libs.json.{JsValue, Json} -import play.api.mvc.{Action, AnyContent, Request, Result} -import utils.{AnyResponseHelper, JsonUtils, LPLogger} +import play.api.mvc._ +import utils.LPUtils.appendGoogleIdIfNeeded +import utils.{AnyResponseHelper, LPLogger} -object Admin extends play.api.mvc.Controller { +@Singleton +class Admin @Inject()(cc: ControllerComponents, + mdb: MongodbDatasource, + pds: ProxyDataSource, + user: helper.User) + extends AbstractController(cc) { def migrateToMongoDB() = Action { implicit request => @@ -17,18 +24,15 @@ object Admin extends play.api.mvc.Controller { // generate heatmaps val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if ((json \ SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - val owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + val json = anyReq.getJsonBody() + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fAccessToken) + if (checkRequirements != null) return checkRequirements + val owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - - // use oAuth2.verifyAdmin (anyReq.verifyAdmin) if (!MongodbDatasource.loadAdmins().contains(appendGoogleIdIfNeeded(owner_id))) { return AnyResponseHelper.forbidden("Unauthorized. Only admins can generate heatmaps.") } - if (!ProxyDataSource.getIDatasource().generateHeatmaps()) + if (!pds.getIDatasource.generateHeatmaps()) return AnyResponseHelper.internal_server_error("Couldn't generate Heatmaps") return AnyResponseHelper.ok("Generated heatmaps successfully") } @@ -42,37 +46,25 @@ object Admin extends play.api.mvc.Controller { */ def fetchAllAccounts() = Action { implicit request => - def inner(request: Request[AnyContent]): Result = { - LPLogger.info("AnyplaceAccounts::fetchAllAccounts(): ") + LPLogger.info("fetchAllAccounts(): ") val anyReq: OAuth2Request = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) { - return AnyResponseHelper.bad_request( - AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - } - val json = anyReq.getJsonBody - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if ((json \ SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) - if (owner_id == null) - return AnyResponseHelper.forbidden("Unauthorized") - + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + val json = anyReq.getJsonBody() + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fAccessToken) + if (checkRequirements != null) return checkRequirements + val owner_id = user.authorize(json) + if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") + if (!MongodbDatasource.loadAdmins().contains(owner_id)) + return AnyResponseHelper.forbidden("Only admin users can see all accounts.") try { - val users: List[JsValue] = ProxyDataSource.getIDatasource().getAllAccounts() - val res: JsValue = Json.obj( - "users_num" -> users.length, - SCHEMA.cUsers -> Json.arr(users) - ) + val users: List[JsValue] = pds.getIDatasource.getAllAccounts() + val res: JsValue = Json.obj("users_num" -> users.length, SCHEMA.cUsers -> Json.arr(users)) AnyResponseHelper.ok(res, "Successfully retrieved all accounts!") } catch { - case e: DatasourceException => - return AnyResponseHelper.internal_server_error( - "500: " + e.getMessage) - + case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) } } - inner(request) } diff --git a/server/app/controllers/AnyplaceAccounts.scala b/server/app/controllers/AnyplaceAccounts.scala deleted file mode 100644 index 9e37dbf0f..000000000 --- a/server/app/controllers/AnyplaceAccounts.scala +++ /dev/null @@ -1,507 +0,0 @@ -/* - * AnyPlace: A free and open Indoor Navigation Service with superb accuracy! - * - * Anyplace is a first-of-a-kind indoor information service offering GPS-less - * localization, navigation and search inside buildings using ordinary smartphones. - * - * Author(s): Nikolas Neofytou, Constantinos Costa, Kyriakos Georgiou, Lambros Petrou - * - * Co-Supervisor: Paschalis Mpeis - * Supervisor: Demetrios Zeinalipour-Yazti - * - * URL: https://anyplace.cs.ucy.ac.cy - * Contact: anyplace@cs.ucy.ac.cy - * - * Copyright (c) 2016, Data Management Systems Lab (DMSL), University of Cyprus. - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the “Software”), to deal in the - * Software without restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ -package controllers - - -import com.couchbase.client.java.document.json.JsonObject -import datasources.{DatasourceException, ProxyDataSource, SCHEMA} -import json.VALIDATE -import oauth.provider.v2.granttype.GrantHandlerFactory -import oauth.provider.v2.models.{AccountModel, OAuth2Request} -import play.api.libs.json._ -import play.api.mvc.{Action, AnyContent, Request, Result} -import play.mvc.Controller -import utils.JsonUtils.toCouchObject -import utils.{AnyResponseHelper, JsonUtils, LPLogger} - - -object AnyplaceAccounts extends Controller { - - /** - * Fetches the account with the AUID passed in. - * The account document is returned in the Json response. - * - * @return - */ - def fetchAccount(auid_in: String) = Action { - implicit request => - - def inner(request: Request[AnyContent]): Result = { - var auid: String = auid_in - // create the Request and check it - val anyReq: OAuth2Request = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) { - return AnyResponseHelper.bad_request( - AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - } - val json = anyReq.getJsonBody() - LPLogger.info("AnyplaceAccounts::fetchAccount():: " + json.toString) - // check if there is any required parameter missing - val notFound: java.util.List[String] = - JsonUtils.hasProperties(json, "auid") - if (!notFound.isEmpty && (auid == null || auid.trim().isEmpty)) { - return AnyResponseHelper.requiredFieldsMissing(notFound) - } - // if the auid in the route is empty then try to get the one from the POST json body - if (auid == null || auid.trim().isEmpty) - auid = json.\\("auid").mkString - try { - var storedAccount: JsonObject = null - storedAccount = - toCouchObject(ProxyDataSource.getIDatasource.getFromKeyAsJson(auid)) - if (storedAccount == - null) { - return AnyResponseHelper.bad_request("Account could not be found!") - } - return AnyResponseHelper.ok(storedAccount, - "Successfully created account!") - } catch { - case e: DatasourceException => - return AnyResponseHelper.internal_server_error( - "500: " + e.getMessage) - - } - } - - inner(request) - } - - /** - * Deletes the account with the AUID passed in. - * The result of the action is returned in the Json response. - * - * @return - */ - def deleteAccount(auid_in: String) = Action { - implicit request => - - def inner(request: Request[AnyContent]): Result = { - var auid: String = auid_in - // create the Request and check it - val anyReq: OAuth2Request = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) { - return AnyResponseHelper.bad_request( - AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - } - val json = anyReq.getJsonBody() - LPLogger.info("AnyplaceAccounts::deleteAccount():: " + json.toString) - // check if there is any required parameter missing - val notFound: java.util.List[String] = - JsonUtils.hasProperties(json, "auid") - if (!notFound.isEmpty && (auid == null || auid.trim().isEmpty)) { - return AnyResponseHelper.requiredFieldsMissing(notFound) - } - // if the auid in the route is empty then try to get the one from the POST json body - if (auid == null || auid.trim().isEmpty) - auid = json.\\("auid").mkString - try { - if (!ProxyDataSource.getIDatasource.deleteFromKey(auid)) { - return AnyResponseHelper.bad_request("Account could not be deleted!") - } - return AnyResponseHelper.ok("Successfully deleted account!") - } catch { - case e: DatasourceException => - return AnyResponseHelper.internal_server_error( - "500: " + e.getMessage) - - } - } - - inner(request) - } - - /** - * Updates the account specified by the AUID. - * The result of the update is returned in the Json response. - * - * @return - */ - def UpdateAccount(auid: String)(auid_in: String) = Action { - implicit request => - - def inner(request: Request[AnyContent]): Result = { - var auid: String = auid_in - // create the Request and check it - val anyReq: OAuth2Request = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) { - return AnyResponseHelper.bad_request( - AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - } - val json = anyReq.getJsonBody() - LPLogger.info("AnyplaceAccounts::updateAccount():: " + json.toString) - // check if there is any required parameter missing - val notFound: java.util.List[String] = - JsonUtils.hasProperties(json, "auid") - if (!notFound.isEmpty && (auid == null || auid.trim().isEmpty)) { - return AnyResponseHelper.requiredFieldsMissing(notFound) - } - // if the auid in the route is empty then try to get the one from the POST json body - if (auid == null || auid.trim().isEmpty) - auid = json.\\("auid").mkString - try { - // fetch the stored object - var storedAccount: JsonObject = null - storedAccount = toCouchObject(ProxyDataSource.getIDatasource().getFromKeyAsJson(auid)) - if (storedAccount == null) { - return AnyResponseHelper.bad_request( - "Account could not be updated! Try again...") - } - // apply any change made - val updateableFields: Array[String] = - AccountModel.getChangeableProperties() - for (s <- updateableFields) { - val value = json.\\(s) - if (value.asInstanceOf[Boolean]) { - storedAccount.put(s, value.asInstanceOf[Boolean]) - } else { - val nv: String = value.mkString - if (nv == null || nv.trim().isEmpty) //continue - storedAccount.put(s, nv) - } - } - // save the changes - if (!ProxyDataSource.getIDatasource().replaceJsonDocument(auid, 0, storedAccount.toString)) { - return AnyResponseHelper.bad_request( - "Account could not be updated! Try again...") - } - return AnyResponseHelper.ok("Successfully updated account!") - } catch { - case e: DatasourceException => - return AnyResponseHelper.internal_server_error( - "500: " + e.getMessage) - - } - } - - inner(request) - } - - // check if there is any required parameter missing - // check if there is any required parameter missing - - /** - * Returns the list of clients for this account - * - * @param auid The account for which the clients are to be returned - * @return - */ - def fetchAccountClients(auid: String)(auid_in: String) = Action { - implicit request => - - def inner(request: Request[AnyContent]): Result = { - var auid: String = auid_in - // create the Request and check it - val anyReq: OAuth2Request = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) { - return AnyResponseHelper.bad_request( - AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - } - val json = anyReq.getJsonBody() - LPLogger.info("AnyplaceAccounts::fetchAccountClients():: " + json.toString) - // check if there is any required parameter missing - val notFound: java.util.List[String] = - JsonUtils.hasProperties(json, "auid") - if (!notFound.isEmpty && (auid == null || auid.trim().isEmpty)) { - return AnyResponseHelper.requiredFieldsMissing(notFound) - } - // if the auid in the route is empty then try to get the one from the POST json body - if (auid == null || auid.trim().isEmpty) - auid = json.\\("auid").mkString - try { - var storedAccount: JsonObject = null - storedAccount = - toCouchObject(ProxyDataSource.getIDatasource().getFromKeyAsJson(auid)) - if (storedAccount == null) { - return AnyResponseHelper.bad_request("Account could not be found!") - } - val json_clients = storedAccount.getArray("clients") - val resp: JsonObject = JsonObject.empty() - resp.put("clients", json_clients) - return AnyResponseHelper.ok(resp, "Successfully fetched account clients!") - } catch { - case e: DatasourceException => - return AnyResponseHelper.internal_server_error( - "500: " + e.getMessage) - - } - } - - inner(request) - } - - /** - * Adds a new client for this account - * - * @param auid The account the new account belongs to - * @return - */ - def addAccountClient(auid: String)(auid_in: String) = Action { - implicit request => - - def inner(request: Request[AnyContent]): Result = { - var auid: String = auid_in - // create the Request and check it - val anyReq: OAuth2Request = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) { - return AnyResponseHelper.bad_request( - AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - } - val json = anyReq.getJsonBody() - LPLogger.info("AnyplaceAccounts::addAccountClient():: " + json.toString) - // check if there is any required parameter missing - val notFound: java.util.List[String] = - JsonUtils.hasProperties(json, "auid", "grant_type") - if (!notFound.isEmpty && (auid == null || auid.trim().isEmpty)) { - return AnyResponseHelper.requiredFieldsMissing(notFound) - } - // if the auid in the route is empty then try to get the one from the POST json body - if (auid == null || auid.trim().isEmpty) - auid = json.\\("auid").mkString - val grant_type: String = json.\\("grant_type").mkString - val scope: String = json.\\("scope").mkString - val redirect_uri: String = json.\\("redirect_uri").mkString - if (!GrantHandlerFactory.isGrantTypeSupported(grant_type)) { - return AnyResponseHelper.bad_request("grant_type specified is not supported!") - } - try { - var storedAccount: JsonObject = null - storedAccount = toCouchObject(ProxyDataSource.getIDatasource().getFromKeyAsJson(auid)) - if (storedAccount == null) { - return AnyResponseHelper.bad_request("Account could not be found!") - } - val account: AccountModel = new AccountModel(storedAccount) - account.addNewClient(grant_type, scope, redirect_uri) - // save the changes - if (!ProxyDataSource.getIDatasource().replaceJsonDocument( - auid, - 0, - account.toJson().toString)) { - return AnyResponseHelper.bad_request( - "Account could not be updated! Try again...") - } - return AnyResponseHelper.ok("Successfully added account client!") - } catch { - case e: DatasourceException => - return AnyResponseHelper.internal_server_error( - "500: " + e.getMessage) - - } - } - - inner(request) - } - - /** - * Fetches the account client with the AUID and client_id passed in. - * The client document is returned in the Json response. - * - * @return - */ - def fetchAccountClient(auid: String, client_id: String)(auid_in: String) = Action { - implicit request => - - def inner(request: Request[AnyContent]): Result = { - var auid: String = auid_in - // create the Request and check it - val anyReq: OAuth2Request = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) { - return AnyResponseHelper.bad_request( - AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - } - val json = anyReq.getJsonBody - LPLogger.info("AnyplaceAccounts::fetchAccount():: " + json.toString) - // check the arguments - if ((auid == null || auid.trim().isEmpty)) { - return AnyResponseHelper.bad_request("Invalid account id provided!") - } - if ((client_id == null || client_id.trim().isEmpty)) { - AnyResponseHelper.bad_request("Invalid client id provided!") - } - try { - var storedAccount: JsonObject = null - storedAccount = toCouchObject(ProxyDataSource.getIDatasource.getFromKeyAsJson(auid)) - if (storedAccount == null) { - return AnyResponseHelper.bad_request("Account could not be found!") - } - val account: AccountModel = new AccountModel(storedAccount) - val client: AccountModel.ClientModel = account.getClient(client_id) - if (client == null) { - return AnyResponseHelper.bad_request("Account client could not be found!") - } - return AnyResponseHelper.ok(client.toJson(), - "Successfully fetched account client!") - } catch { - case e: DatasourceException => - return AnyResponseHelper.internal_server_error( - "500: " + e.getMessage) - - } - } - - inner(request) - } - - /** - * Fetches the account client with the AUID and client_id passed in. - * The client document is returned in the Json response. - * - * @return - */ - def deleteAccountClient(auid: String, client_id: String)(auid_in: String) = Action { - implicit request => - - def inner(request: Request[AnyContent]): Result = { - var auid: String = auid_in - // create the Request and check it - val anyReq: OAuth2Request = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) { - return AnyResponseHelper.bad_request( - AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - } - val json = anyReq.getJsonBody - LPLogger.info("AnyplaceAccounts::deleteAccount():: " + json.toString) - // check the arguments - if ((auid == null || auid.trim().isEmpty)) { - return AnyResponseHelper.bad_request("Invalid account id provided!") - } - if ((client_id == null || client_id.trim().isEmpty)) { - return AnyResponseHelper.bad_request("Invalid client id provided!") - } - try { - var storedAccount: JsonObject = null - storedAccount = - toCouchObject(ProxyDataSource.getIDatasource.getFromKeyAsJson(auid)) - if (storedAccount == null) { - return AnyResponseHelper.bad_request("Account could not be found!") - } - val account: AccountModel = new AccountModel(storedAccount) - if (!account.deleteClient(client_id)) { - return AnyResponseHelper.bad_request("Account client could not be found!") - } - // save the changes - if (!ProxyDataSource.getIDatasource.replaceJsonDocument( - auid, - 0, - account.toJson().toString)) { - return AnyResponseHelper.bad_request( - "Account could not be updated! Try again...") - } - return AnyResponseHelper.ok("Successfully deleted account client!") - } catch { - case e: DatasourceException => - return AnyResponseHelper.internal_server_error( - "500: " + e.getMessage) - - } - } - - inner(request) - } - - def login() = Action { - implicit request => - - def inner(request: Request[AnyContent]): Result = { - val anyReq: OAuth2Request = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) { - return AnyResponseHelper.bad_request( - AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - } - val json = anyReq.getJsonBody - LPLogger.D2("json = " + json) - - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fUsername, SCHEMA.fPassword) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fUsername, SCHEMA.fPassword) - if (validation.failed()) return validation.response() - - val username = (json \ SCHEMA.fUsername).as[String] - val password = (json \ SCHEMA.fPassword).as[String] - val storedUser = ProxyDataSource.getIDatasource().login(SCHEMA.cUsers, username, password) - if (storedUser == null) return AnyResponseHelper.bad_request("User doesn't exist!") - if (storedUser.size > 1) return AnyResponseHelper.bad_request("More than one users were found!") - val accessToken = (storedUser(0) \ SCHEMA.fAccessToken).as[String] - if (accessToken == null) return AnyResponseHelper.bad_request("User doesn't have access token!") - - val user = storedUser(0).as[JsObject] - SCHEMA.fPassword - val res = Json.obj("user" -> user) - return AnyResponseHelper.ok(res, "Successfully found user.") - } - - inner(request) - } - - def register() = Action { - implicit request => - - def inner(request: Request[AnyContent]): Result = { - val anyReq: OAuth2Request = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) { - return AnyResponseHelper.bad_request( - AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - } - val json = anyReq.getJsonBody - LPLogger.D2("json = " + json) - - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fUsername, SCHEMA.fPassword, SCHEMA.fName, SCHEMA.fEmail) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fUsername, SCHEMA.fPassword, SCHEMA.fName, SCHEMA.fEmail) - if (validation.failed()) return validation.response() - - val name = (json \ SCHEMA.fName).as[String] - val email = (json \ SCHEMA.fEmail).as[String] - val username = (json \ SCHEMA.fUsername).as[String] - val password = (json \ SCHEMA.fPassword).as[String] - val external = "anyplace" - val accType = "user" - - val storedUsername = ??? - - val storedEmail = ??? - - // TODO: check username uniqueness - val storedUser = ProxyDataSource.getIDatasource().login(SCHEMA.cUsers, username, password) - if (storedUser != null) return AnyResponseHelper.bad_request("User already exist!") - - val newUser = ProxyDataSource.getIDatasource().register(SCHEMA.cUsers, name, email, username, password, external, accType) - - return AnyResponseHelper.ok("Succefully registered!") - } - - inner(request) - } -} diff --git a/server/app/controllers/AnyplaceAndroid.scala b/server/app/controllers/AnyplaceAndroid.scala deleted file mode 100644 index d700292f6..000000000 --- a/server/app/controllers/AnyplaceAndroid.scala +++ /dev/null @@ -1,93 +0,0 @@ -/* - * AnyPlace: A free and open Indoor Navigation Service with superb accuracy! - * - * Anyplace is a first-of-a-kind indoor information service offering GPS-less - * localization, navigation and search inside buildings using ordinary smartphones. - * - * Author(s): Constantinos Costa, Kyriakos Georgiou, Lambros Petrou - * - * Supervisor: Demetrios Zeinalipour-Yazti - * - * URL: https://anyplace.cs.ucy.ac.cy - * Contact: anyplace@cs.ucy.ac.cy - * - * Copyright (c) 2016, Data Management Systems Lab (DMSL), University of Cyprus. - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the “Software”), to deal in the - * Software without restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ -package controllers - -import play.api.mvc.{Action, Result} -import play.mvc.Security -import utils.{AndroidAPKFile, AnyplaceServerAPI, LPLogger} - -/** - * Created by costantinos on 25/6/2017. - */ - -import java.io.File -import java.util.{ArrayList, Collections, List} - - -object AnyplaceAndroid extends play.api.mvc.Controller { - - val ANDROID_APKS_ROOT_DIRECTORY_LOCAL: String = "anyplace_android" + File.separatorChar + "apk" + File.separatorChar - - val ANDROID_APk_DOWNLOAD: String = AnyplaceServerAPI.ANDROID_API_ROOT + "apk/" - - // the action for the Anyplce Architect - @Security.Authenticated(classOf[Secured]) - def getApks = Action { - def inner(): Result = { - if (true) - return BadRequest("Android disabled!") - val dirApks: File = new File(ANDROID_APKS_ROOT_DIRECTORY_LOCAL) - if (!dirApks.isDirectory || !dirApks.canExecute() || !dirApks.canRead()) { - return BadRequest("No Android apk available!") - } - var apk: AndroidAPKFile = null - val apks: List[AndroidAPKFile] = new ArrayList[AndroidAPKFile]() - for (fileApk <- dirApks.listFiles()) { - if (!fileApk.isFile) //continue - apk = new AndroidAPKFile(fileApk) - apk.setDownloadUrl(ANDROID_APk_DOWNLOAD + apk.getFilePathBasename) - apks.add(apk) - } - Collections.sort(apks, new AndroidAPKFile.AndroidAPKComparator()) - Ok(views.html.anyplace_android.render(apks)) - } - inner() - } - - def downloadApk(file: String) = Action { - - def inner(): Result = { - val fileApk: File = new File(ANDROID_APKS_ROOT_DIRECTORY_LOCAL, file) - LPLogger.debug("requested: " + fileApk) - if (!fileApk.exists() || !fileApk.canRead()) { - return BadRequest("Requested APK does not exist on our database!") - } - Ok.sendFile(fileApk) - } - inner() - } - -} diff --git a/server/app/controllers/AnyplaceAssets.scala b/server/app/controllers/AnyplaceAssets.scala index 761cc883f..4b80d858d 100644 --- a/server/app/controllers/AnyplaceAssets.scala +++ b/server/app/controllers/AnyplaceAssets.scala @@ -36,11 +36,14 @@ package controllers import datasources.SCHEMA -import play.api.mvc.Action +import javax.inject.{Inject, Singleton} +import play.api.mvc._ -object AnyplaceAssets extends play.api.mvc.Controller { +@Singleton +class AnyplaceAssets @Inject()(cc: ControllerComponents, + assets: Assets) extends AbstractController(cc) { - def at(path: String, file: String) = Action.async { + def at(path: String, file: String): Action[AnyContent] = Action.async { implicit request => // Assets.at(path+"/anyplace_viewer_campus", file) val uri = request.headers.get("referer").getOrElse("") @@ -51,7 +54,10 @@ object AnyplaceAssets extends play.api.mvc.Controller { } else { viewerDir = "/anyplace_viewer_campus/" } - Assets.at(path + viewerDir, file).apply(request) - + // assets.a + //play.api.controllers.AnyplaceAssets.super.at + assets.at(path + viewerDir, file).apply(request) + //.apply(request) } + } diff --git a/server/app/controllers/AnyplaceInfluxdb.scala b/server/app/controllers/AnyplaceInfluxdb.scala index 355063922..f36fee2e4 100644 --- a/server/app/controllers/AnyplaceInfluxdb.scala +++ b/server/app/controllers/AnyplaceInfluxdb.scala @@ -1,153 +1,155 @@ -/* - * AnyPlace: A free and open Indoor Navigation Service with superb accuracy! - * - * Anyplace is a first-of-a-kind indoor information service offering GPS-less - * localization, navigation and search inside buildings using ordinary smartphones. - * - * Author(s): Stefanos Kyriakou, Panayiotis Leontiou, Stelios Tymvios - * - * Supervisor: Demetrios Zeinalipour-Yazti - * - * URL: https://anyplace.cs.ucy.ac.cy - * Contact: anyplace@cs.ucy.ac.cy - * - * Copyright (c) 2016, Data Management Systems Lab (DMSL), University of Cyprus. - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the “Software”), to deal in the - * Software without restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ -package controllers - -import java.util - -import com.google.gson.JsonParseException -import datasources.{DatasourceException, InfluxdbDatasource, SCHEMA} -import io.razem.influxdbclient.Point -import oauth.provider.v2.models.OAuth2Request -import play.api.libs.json._ -import play.api.mvc.{Action, AnyContent} -import utils.{AnyResponseHelper, _} - -import scala.concurrent.ExecutionContext.Implicits.global - -object AnyplaceInfluxdb extends play.api.mvc.Controller { - - - def locationLookup: Action[AnyContent] = Action.async { - implicit request => - - var notFound: util.List[String] = new util.ArrayList[String]() - try { - val anyReq = new OAuth2Request(request) - - if (!anyReq.assertJsonBody()) - throw new JsonParseException("OATH parse error.") - val json = anyReq.getJsonBody() - - var gp1: GeoPoint = new GeoPoint() - var gp2: GeoPoint = new GeoPoint() - val base = JsonUtils.hasProperties(json, "deviceID", "beginTime", "endTime") - val twoPoints = JsonUtils.hasProperties(json, "point1", "point2") - val onePoint = JsonUtils.hasProperties(json, "point", "distance") - - ( - base isEmpty, - twoPoints isEmpty, - onePoint isEmpty) match { - // when base input validation failed - case (false, _, _) => - notFound = base - throw new NoSuchFieldException() - - // when none of two apis validate raise error - case (true, false, false) => - notFound = twoPoints - throw new NoSuchFieldException() - - // BoxByRange, i.e. two points is preferred over bounding box with distance - // due to better floating point behavior as the distance is a floating point in KM - // eg. "0.13".toFloat is not exactly 0.13 due to floating point precision - case (true, true, _) => - val bb = GeoPoint.getGeoBoundingBoxByRange((json \ "point1").as[GeoPoint], (json \ "point2").as[GeoPoint]) - gp1 = bb(1) - gp2 = bb(0) - - case (true, false, true) => - val bb = GeoPoint.getGeoBoundingBox((json \ "point").as[GeoPoint], (json \ "distance").as[String].toDouble) - gp1 = bb(0) - gp2 = bb(1) - } - - val deviceID = (json \ "deviceID").as[String] - val beginTime = (json \ "beginTime").as[Long] - val endTime = (json \ "endTime").as[Long] - - val infdb = InfluxdbDatasource.getStaticInstance - infdb.devicePointsInBoundingBox(gp1, gp2, List(deviceID), beginTime, endTime) - .map { m=> Ok(Json.toJson(m)) } - - } - catch { - case e: DatasourceException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request(e getMessage) } - case e: NullPointerException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request(e getMessage) } - case _: JsonParseException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - case _: NoSuchFieldException => scala.concurrent.Future {} map { _ => AnyResponseHelper.requiredFieldsMissing(notFound) } - case _: JsResultException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request("Json validation failed") } - } - } - - def insertInfluxdb(): Action[AnyContent] = Action.async { - implicit request => - - var notFound: util.List[String] = new util.ArrayList[String]() - try { - val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) - throw new JsonParseException("OATH parse error.") - val json = anyReq.getJsonBody() - - notFound = JsonUtils.hasProperties(json, "point","deviceID",SCHEMA.fTimestamp) - if (!notFound.isEmpty) - throw new NoSuchFieldException() - - - val infdb = InfluxdbDatasource.getStaticInstance - val deviceID = (json \ "deviceID").as[String] - val timestamp = (json \ SCHEMA.fTimestamp).as[Float] - val gp = (json \ "point").as[GeoPoint] - - val point = Point(SCHEMA.fLocation) - .addTag("deviceID", deviceID) - // using config defined (or default) precision - .addTag("geohash", gp asGeohash infdb.stored_precision) - .addField(SCHEMA.fTimestamp, timestamp) - .addField("latitude", gp dlat) - .addField("longitude", gp dlon) - infdb.write(point) map { _ => AnyResponseHelper.ok("Point Written") } - } - catch { - case e: DatasourceException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request(e getMessage) } - case e: NullPointerException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request(e getMessage) } - case _: JsonParseException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - case _: NoSuchFieldException => scala.concurrent.Future {} map { _ => AnyResponseHelper.requiredFieldsMissing(notFound) } - case e: JsResultException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request(e getMessage) } - } - } -} \ No newline at end of file +///* +// * AnyPlace: A free and open Indoor Navigation Service with superb accuracy! +// * +// * Anyplace is a first-of-a-kind indoor information service offering GPS-less +// * localization, navigation and search inside buildings using ordinary smartphones. +// * +// * Author(s): Stefanos Kyriakou, Panayiotis Leontiou, Stelios Tymvios +// * +// * Supervisor: Demetrios Zeinalipour-Yazti +// * +// * URL: https://anyplace.cs.ucy.ac.cy +// * Contact: anyplace@cs.ucy.ac.cy +// * +// * Copyright (c) 2016, Data Management Systems Lab (DMSL), University of Cyprus. +// * All rights reserved. +// * +// * Permission is hereby granted, free of charge, to any person obtaining a copy of +// * this software and associated documentation files (the “Software”), to deal in the +// * Software without restriction, including without limitation the rights to use, copy, +// * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +// * and to permit persons to whom the Software is furnished to do so, subject to the +// * following conditions: +// * +// * The above copyright notice and this permission notice shall be included in all +// * copies or substantial portions of the Software. +// * +// * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +// * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// * DEALINGS IN THE SOFTWARE. +// * +// */ +//package controllers +// +//import java.util +// +//import com.google.gson.JsonParseException +//import datasources.{DatasourceException, InfluxdbDatasource, SCHEMA} +//import io.razem.influxdbclient.Point +//import javax.inject.{Inject, Singleton} +//import oauth.provider.v2.models.OAuth2Request +//import play.api.libs.json._ +//import play.api.mvc.{AbstractController, Action, AnyContent, ControllerComponents} +//import utils.{AnyResponseHelper, _} +//import scala.language.postfixOps +// +//import scala.concurrent.ExecutionContext.Implicits.global +//// TODO:PM CLR +//@Singleton +//class AnyplaceInfluxdb @Inject()(cc: ControllerComponents) extends AbstractController(cc) { +// +// def locationLookup: Action[AnyContent] = Action.async { +// implicit request => +// +// var notFound: util.List[String] = new util.ArrayList[String]() +// try { +// val anyReq = new OAuth2Request(request) +// +// if (!anyReq.assertJsonBody()) +// throw new JsonParseException("OATH parse error.") +// val json = anyReq.getJsonBody() +// +// var gp1: GeoPoint = new GeoPoint() +// var gp2: GeoPoint = new GeoPoint() +// val base = JsonUtils.hasProperties(json, "deviceID", "beginTime", "endTime") +// val twoPoints = JsonUtils.hasProperties(json, "point1", "point2") +// val onePoint = JsonUtils.hasProperties(json, "point", "distance") +// +// ( +// base isEmpty, +// twoPoints isEmpty, +// onePoint isEmpty) match { +// // when base input validation failed +// case (false, _, _) => +// notFound = base +// throw new NoSuchFieldException() +// +// // when none of two apis validate raise error +// case (true, false, false) => +// notFound = twoPoints +// throw new NoSuchFieldException() +// +// // BoxByRange, i.e. two points is preferred over bounding box with distance +// // due to better floating point behavior as the distance is a floating point in KM +// // eg. "0.13".toFloat is not exactly 0.13 due to floating point precision +// case (true, true, _) => +// val bb = GeoPoint.getGeoBoundingBoxByRange((json \ "point1").as[GeoPoint], (json \ "point2").as[GeoPoint]) +// gp1 = bb(1) +// gp2 = bb(0) +// +// case (true, false, true) => +// val bb = GeoPoint.getGeoBoundingBox((json \ "point").as[GeoPoint], (json \ "distance").as[String].toDouble) +// gp1 = bb(0) +// gp2 = bb(1) +// } +// +// val deviceID = (json \ "deviceID").as[String] +// val beginTime = (json \ "beginTime").as[Long] +// val endTime = (json \ "endTime").as[Long] +// +// //val infdb = InfluxdbDatasource.getStaticInstance +// //infdb.devicePointsInBoundingBox(gp1, gp2, List(deviceID), beginTime, endTime) +// // .map { m=> Ok(Json.toJson(m)) } +// +// } +// catch { +// case e: DatasourceException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request(e getMessage) } +// case e: NullPointerException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request(e getMessage) } +// case _: JsonParseException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } +// case _: NoSuchFieldException => scala.concurrent.Future {} map { _ => AnyResponseHelper.requiredFieldsMissing(notFound) } +// case _: JsResultException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request("Json validation failed") } +// } +// } +// +// def insertInfluxdb(): Action[AnyContent] = Action.async { +// implicit request => +// +// var notFound: util.List[String] = new util.ArrayList[String]() +// try { +// val anyReq = new OAuth2Request(request) +// if (!anyReq.assertJsonBody()) +// throw new JsonParseException("OATH parse error.") +// val json = anyReq.getJsonBody() +// +// notFound = JsonUtils.hasProperties(json, "point","deviceID",SCHEMA.fTimestamp) +// if (!notFound.isEmpty) +// throw new NoSuchFieldException() +// +// +// //val infdb = InfluxdbDatasource.getStaticInstance() +// val deviceID = (json \ "deviceID").as[String] +// val timestamp = (json \ SCHEMA.fTimestamp).as[Float] +// val gp = (json \ "point").as[GeoPoint] +// +// val point = Point(SCHEMA.fLocation) +// .addTag("deviceID", deviceID) +// // using config defined (or default) precision +// .addTag("geohash", gp asGeohash infdb.stored_precision) +// .addField(SCHEMA.fTimestamp, timestamp) +// .addField("latitude", gp dlat) +// .addField("longitude", gp dlon) +// infdb.write(point) map { _ => AnyResponseHelper.ok("Point Written") } +// } +// catch { +// case e: DatasourceException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request(e getMessage) } +// case e: NullPointerException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request(e getMessage) } +// case _: JsonParseException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } +// case _: NoSuchFieldException => scala.concurrent.Future {} map { _ => AnyResponseHelper.requiredFieldsMissing(notFound) } +// case e: JsResultException => scala.concurrent.Future {} map { _ => AnyResponseHelper.bad_request(e getMessage) } +// } +// } +//} \ No newline at end of file diff --git a/server/app/controllers/AnyplaceMapping.scala b/server/app/controllers/AnyplaceMapping.scala index fd3f88901..db62d2881 100644 --- a/server/app/controllers/AnyplaceMapping.scala +++ b/server/app/controllers/AnyplaceMapping.scala @@ -38,48 +38,62 @@ package controllers import java.io._ import java.net.{HttpURLConnection, URL} -import java.nio.file.{Files, Paths} import java.text.{NumberFormat, ParseException} -import java.time.Instant import java.time.temporal.{ChronoUnit, TemporalUnit} import java.util import java.util.Locale import java.util.zip.GZIPOutputStream -import acces.{AccesRBF, GeoUtils} -import breeze.linalg.{DenseMatrix, DenseVector} -import com.couchbase.client.java.document.json.{JsonArray, JsonObject} -import datasources.MongodbDatasource.convertJson -import datasources.{DatasourceException, MongodbDatasource, ProxyDataSource, SCHEMA} +import com.couchbase.client.java.document.json.JsonObject +import datasources.ProxyDataSource +import org.apache.commons.codec.binary.Base64 +import org.mongodb.scala.model.Filters.equal +import play.api.{Configuration, Environment} +import radiomapserver.RadioMap.RadioMap +import utils.LPUtils.appendGoogleIdIfNeeded + +import scala.concurrent.Future +//import breeze.linalg.{DenseMatrix, DenseVector} + +import datasources.{DatasourceException, MongodbDatasource, SCHEMA} import db_models.ExternalType.ExternalType import db_models._ import json.VALIDATE -import json.VALIDATE.{Coordinate, String, StringNumber} +import json.VALIDATE.String import location.Algorithms import oauth.provider.v2.models.OAuth2Request -import org.apache.commons.codec.binary.Base64 import org.mongodb.scala.MongoDatabase -import org.mongodb.scala.model.Filters.equal -import play.Play import play.api.libs.json.Reads._ import play.api.libs.json.{JsObject, JsValue, Json, _} import play.api.mvc._ -import play.libs.F -import radiomapserver.RadioMap.RadioMap import radiomapserver.RadioMapMean -import utils.JsonUtils.{isNullOrEmpty, toCouchArray} +import utils.JsonUtils.isNullOrEmpty import utils._ -import scala.collection.JavaConversions._ -import scala.collection.mutable.ListBuffer +// import scala.collection.JavaConversions._ +import javax.inject.{Inject, Singleton} + import scala.concurrent.Await import scala.concurrent.duration.Duration -import scala.io.Source +import scala.jdk.CollectionConverters._ import scala.util.control.Breaks -object AnyplaceMapping extends play.api.mvc.Controller { - // CHECK Why is this hardcoded here? +@Singleton +class AnyplaceMapping @Inject()(cc: ControllerComponents, + env: Environment, + conf: Configuration, + api: AnyplaceServerAPI, + mapHelper: helper.Mapping, + tilerHelper: AnyPlaceTilerHelper, + mongoDB: MongodbDatasource, + pds: ProxyDataSource, + user: helper.User) + extends AbstractController(cc) { + implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global +//object AnyplaceMapping extends play.api.mvc.Controller { + + // CHECK:NN CHECK:PM Why is this hardcoded here? private val ADMIN_ID = "112997031510415584062_google" val ACCES_RETRY_AMOUNT = 2 val ACCES_RETRY_UNIT: TemporalUnit = ChronoUnit.HOURS @@ -94,7 +108,6 @@ object AnyplaceMapping extends play.api.mvc.Controller { } // TODO:PM TODO:NN local accounts - @deprecated("Will use oAuth2.verifyUsers") // query (find) the user by api_key def verifyId(authToken: String): String = { // remove the double string quotes due to json processing @@ -104,13 +117,11 @@ object AnyplaceMapping extends play.api.mvc.Controller { res = sendGet(gURL) } catch { case e: Exception => { - LPLogger.error("verifyId: " + e.toString) null } } if (res != null) try { - // CHECK:PM CHECK:NN bug on main branch (JsonObject.fromJson()) val json = Json.parse(res) val uid = (json \ "user_id") @@ -126,15 +137,6 @@ object AnyplaceMapping extends play.api.mvc.Controller { null } - def appendGoogleIdIfNeeded(id: String) = { - if (id.contains("_local")) - id - else if (id.contains("_google")) - id - else - id + "_google" - } - private def sendGet(url: String) = { val obj = new URL(url) val con = obj.openConnection().asInstanceOf[HttpURLConnection] @@ -152,9 +154,9 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - LPLogger.info("AnyplaceMapping::getRadioHeatmap(): " + stripJson(anyReq.getJsonBody)) + LPLogger.info("AnyplaceMapping::getRadioHeatmap(): " + stripJson(anyReq.getJsonBody())) try { - val radioPoints = ProxyDataSource.getIDatasource.getRadioHeatmap + val radioPoints = pds.getIDatasource.getRadioHeatmap() if (radioPoints == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") val res = JsonObject.empty() res.put("radioPoints", (radioPoints)) @@ -174,17 +176,14 @@ object AnyplaceMapping extends play.api.mvc.Controller { // --- val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("getHeatmapByFloorAVG1: " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloor) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fFloor, SCHEMA.fBuid) - if (validation.failed()) return validation.response() - + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloor) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] val floor = (json \ SCHEMA.fFloor).as[String] try { - val radioPoints = ProxyDataSource.getIDatasource.getRadioHeatmapByBuildingFloorAverage1(buid, floor) + val radioPoints = pds.getIDatasource.getRadioHeatmapByBuildingFloorAverage1(buid, floor) if (radioPoints == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") val res: JsValue = Json.obj("radioPoints" -> radioPoints) try { @@ -207,17 +206,14 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.D2("getRadioHeatmapRSS2(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloor) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fFloor, SCHEMA.fBuid) - if (validation.failed()) return validation.response() - + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fFloor, SCHEMA.fBuid) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] val floor = (json \ SCHEMA.fFloor).as[String] try { - val radioPoints = ProxyDataSource.getIDatasource.getRadioHeatmapByBuildingFloorAverage2(buid, floor) + val radioPoints = pds.getIDatasource.getRadioHeatmapByBuildingFloorAverage2(buid, floor) if (radioPoints == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") val res: JsValue = Json.obj("radioPoints" -> radioPoints) try { @@ -245,16 +241,14 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.D2("getHeatmapByFloorAVG3: " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloor) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fFloor, SCHEMA.fBuid) - if (validation.failed()) return validation.response() + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloor) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] val floor = (json \ SCHEMA.fFloor).as[String] try { - val radioPoints = ProxyDataSource.getIDatasource.getRadioHeatmapByBuildingFloorAverage3(buid, floor) + val radioPoints = pds.getIDatasource.getRadioHeatmapByBuildingFloorAverage3(buid, floor) if (radioPoints == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") val res: JsValue = Json.obj("radioPoints" -> radioPoints) try { @@ -281,20 +275,17 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.D2("getHeatmapByFloorAVG3Tiles: " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloor, SCHEMA.fX, SCHEMA.fY, "z") - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fFloor, SCHEMA.fBuid, SCHEMA.fX, SCHEMA.fY, "z") - if (validation.failed()) return validation.response() - + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloor, SCHEMA.fX, SCHEMA.fY, "z") + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] val floor = (json \ SCHEMA.fFloor).as[String] val tileX = (json \ SCHEMA.fX).as[Int] val tileY = (json \ SCHEMA.fY).as[Int] val zoomLevel = (json \ "z").as[Int] try { - val radioPoints = ProxyDataSource.getIDatasource.getRadioHeatmapByBuildingFloorAverage3(buid, floor) + val radioPoints = pds.getIDatasource.getRadioHeatmapByBuildingFloorAverage3(buid, floor) if (radioPoints == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") val radioPointsInXY: util.ArrayList[JsValue] = new util.ArrayList[JsValue]() @@ -307,7 +298,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { radioPointsInXY.add(radioPoint) } } - val res = Json.obj("radioPoints" -> radioPointsInXY.toList) + val res = Json.obj("radioPoints" -> radioPointsInXY.asScala) try { gzippedJSONOk(res.toString) } catch { @@ -330,20 +321,17 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.D2("heatmapByFloorTimestampAVG3: " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloor, SCHEMA.fTimestampX, SCHEMA.fTimestampY) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fFloor, SCHEMA.fBuid, SCHEMA.fTimestampX, SCHEMA.fTimestampY) - if (validation.failed()) return validation.response() - + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fFloor, SCHEMA.fBuid, SCHEMA.fTimestampX, SCHEMA.fTimestampY) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] val floor = (json \ SCHEMA.fFloor).as[String] val timestampX = (json \ SCHEMA.fTimestampX).as[String] val timestampY = (json \ SCHEMA.fTimestampY).as[String] try { - val radioPoints = ProxyDataSource.getIDatasource.getRadioHeatmapByFloorTimestamp(buid, floor, timestampX, timestampY) + val radioPoints = pds.getIDatasource.getRadioHeatmapByFloorTimestamp(buid, floor, timestampX, timestampY) if (radioPoints == null) return AnyResponseHelper.bad_request("Fingerprints does not exist or could not be retrieved!") val res: JsValue = Json.obj("radioPoints" -> radioPoints) try { @@ -385,14 +373,11 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.D3("heatmapByFloorTimestampTiles: " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloor, SCHEMA.fTimestampX, SCHEMA.fTimestampY, SCHEMA.fX, SCHEMA.fY, "z") - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fFloor, SCHEMA.fBuid, SCHEMA.fTimestampX, SCHEMA.fTimestampY, - SCHEMA.fX, SCHEMA.fY, "z") - if (validation.failed()) return validation.response() - + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloor, SCHEMA.fTimestampX, + SCHEMA.fTimestampY, SCHEMA.fX, SCHEMA.fY, "z") + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] val floor = (json \ SCHEMA.fFloor).as[String] val timestampX = (json \ SCHEMA.fTimestampX).as[String] @@ -402,7 +387,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { val z = (json \ "z").as[Int] try { - val radioPoints = ProxyDataSource.getIDatasource.getRadioHeatmapByFloorTimestamp(buid, floor, timestampX, timestampY) + val radioPoints = pds.getIDatasource.getRadioHeatmapByFloorTimestamp(buid, floor, timestampX, timestampY) if (radioPoints == null) return AnyResponseHelper.bad_request("Fingerprints does not exist or could not be retrieved!") val radioPointsInXY: util.ArrayList[JsValue] = new util.ArrayList[JsValue]() @@ -413,7 +398,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { if (xyConverter(0) == x && xyConverter(1) == y) radioPointsInXY.add(radioPoint) } - val res: JsValue = Json.obj("radioPoints" -> radioPointsInXY.toList) + val res: JsValue = Json.obj("radioPoints" -> radioPointsInXY.asScala) try { gzippedJSONOk(res.toString) } catch { @@ -434,19 +419,16 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("heatmapByFloorTimestampAVG1: " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloor, SCHEMA.fTimestampX, SCHEMA.fTimestampY) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fFloor, SCHEMA.fBuid, SCHEMA.fTimestampX, SCHEMA.fTimestampY) - if (validation.failed()) return validation.response() - + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloor, SCHEMA.fTimestampX, SCHEMA.fTimestampY) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] val floor = (json \ SCHEMA.fFloor).as[String] val timestampX = (json \ SCHEMA.fTimestampX).as[String] val timestampY = (json \ SCHEMA.fTimestampY).as[String] try { - val radioPoints = ProxyDataSource.getIDatasource.getRadioHeatmapByBuildingFloorTimestampAverage1(buid, floor, timestampX, timestampY) + val radioPoints = pds.getIDatasource.getRadioHeatmapByBuildingFloorTimestampAverage1(buid, floor, timestampX, timestampY) if (radioPoints == null) return AnyResponseHelper.bad_request("Fingerprints does not exist or could not be retrieved!") val res: JsValue = Json.obj("radioPoints" -> radioPoints) try { @@ -469,19 +451,16 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("heatmapByFloorTimestampAVG2: " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloor, SCHEMA.fTimestampX, SCHEMA.fTimestampY) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fFloor, SCHEMA.fBuid, SCHEMA.fTimestampX, SCHEMA.fTimestampY) - if (validation.failed()) return validation.response() - + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloor, SCHEMA.fTimestampX, SCHEMA.fTimestampY) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] val floor = (json \ SCHEMA.fFloor).as[String] val timestampX = (json \ SCHEMA.fTimestampX).as[String] val timestampY = (json \ SCHEMA.fTimestampY).as[String] try { - val radioPoints = ProxyDataSource.getIDatasource.getRadioHeatmapByBuildingFloorTimestampAverage2(buid, floor, timestampX, timestampY) + val radioPoints = pds.getIDatasource.getRadioHeatmapByBuildingFloorTimestampAverage2(buid, floor, timestampX, timestampY) if (radioPoints == null) return AnyResponseHelper.bad_request("Fingerprints does not exist or could not be retrieved!") val res: JsValue = Json.obj("radioPoints" -> radioPoints) try { @@ -507,24 +486,21 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::getAPs(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloor) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fFloor, SCHEMA.fBuid) - if (validation.failed()) return validation.response() - + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloor) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] val floor = (json \ SCHEMA.fFloor).as[String] - val APs = ProxyDataSource.getIDatasource().getCachedAPsByBuildingFloor(buid, floor) + val APs = pds.getIDatasource.getCachedAPsByBuildingFloor(buid, floor) // if cached return it if (APs != null) { val res = Json.obj("accessPoints" -> (APs \ "accessPoints").as[List[JsValue]]) return gzippedJSONOk(res, "Fetched precompute of accessPointsWifi") } else { try { - var accessPoints = ProxyDataSource.getIDatasource.getAPsByBuildingFloor(buid, floor) - val apcdb = ProxyDataSource.getIDatasource.getAPsByBuildingFloorcdb(buid, floor) + var accessPoints = pds.getIDatasource.getAPsByBuildingFloor(buid, floor) + val apcdb = pds.getIDatasource.getAPsByBuildingFloorcdb(buid, floor) LPLogger.debug("mdb " + accessPoints.size) LPLogger.debug("cdb " + apcdb.size()) @@ -533,7 +509,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { // val newAP = fromCouchObject(ap) // newList.add(newAP) //} - //accessPoints = newList.toList + //accessPoints = newList.asScala val uniqueAPs: util.HashMap[String, JsValue] = new util.HashMap() for (accessPoint <- accessPoints) { var tempAP = accessPoint @@ -567,9 +543,9 @@ object AnyplaceMapping extends play.api.mvc.Controller { } if (accessPoints == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") - val newAccessPoint = Json.obj(SCHEMA.fBuid -> buid, SCHEMA.fFloor -> floor, "accessPoints" -> uniqueAPs.values().toList) - ProxyDataSource.getIDatasource().addJsonDocument(SCHEMA.cAccessPointsWifi, newAccessPoint.toString()) - val res: JsValue = Json.obj("accessPoints" -> new util.ArrayList[JsValue](uniqueAPs.values()).toList) + val newAccessPoint = Json.obj(SCHEMA.fBuid -> buid, SCHEMA.fFloor -> floor, "accessPoints" -> uniqueAPs.values().asScala) + pds.getIDatasource.addJsonDocument(SCHEMA.cAccessPointsWifi, newAccessPoint.toString()) + val res: JsValue = Json.obj("accessPoints" -> new util.ArrayList[JsValue](uniqueAPs.values()).asScala) try { gzippedJSONOk(res, "Generated precompute of accessPointsWifi") } catch { @@ -594,11 +570,11 @@ object AnyplaceMapping extends play.api.mvc.Controller { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() val accessPointsOfReq = (json \ "ids").as[List[String]] try { val reqFile = "public/anyplace_architect/ids.json" - val file = Play.application().resourceAsStream(reqFile) + val file = env.classLoader.getResourceAsStream(reqFile) var accessPointsOfFile: List[JsObject] = null if (file != null) { @@ -637,7 +613,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { sameBits += 1 } else { - inner_loop.break + inner_loop.break() } } } @@ -648,7 +624,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { sameBits = 0 if (firstBitFound) { firstBitFound = false - loop.break + loop.break() } } @@ -692,16 +668,15 @@ object AnyplaceMapping extends play.api.mvc.Controller { implicit request => def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody) + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("FingerPrintsDelete: " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloor, "lat1", "lon1", "lat2", "lon2", SCHEMA.fOwnerId) - if (!requiredMissing.isEmpty) - return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fFloor, SCHEMA.fBuid, "lat1", "lon1", "lat2", "lon2") - if (validation.failed()) return validation.response() - + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloor, "lat1", "lon1", "lat2", + "lon2", SCHEMA.fAccessToken) + if (checkRequirements != null) return checkRequirements + val owner_id = user.authorize(json) + if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") val buid = (json \ SCHEMA.fBuid).as[String] val floor_number = (json \ SCHEMA.fFloor).as[String] val lat1 = (json \ "lat1").as[String] @@ -709,24 +684,20 @@ object AnyplaceMapping extends play.api.mvc.Controller { val lat2 = (json \ "lat2").as[String] val lon2 = (json \ "lon2").as[String] try { - val fingerprints: List[JsValue] = ProxyDataSource.getIDatasource.getFingerPrintsBBox( + val fingerprints: List[JsValue] = pds.getIDatasource.getFingerPrintsBBox( buid, floor_number, lat1, lon1, lat2, lon2) if (fingerprints.isEmpty) return AnyResponseHelper.bad_request("Fingerprints does not exist or could not be retrieved!") LPLogger.D2("FingerPrintsDelete: will delete " + fingerprints.size + " fingerprints.") for (fingerprint <- fingerprints) { - ProxyDataSource.getIDatasource.deleteFingerprint(fingerprint) + pds.getIDatasource.deleteFingerprint(fingerprint) } - ProxyDataSource.getIDatasource().deleteAffectedHeatmaps(buid,floor_number) + pds.getIDatasource.deleteAffectedHeatmaps(buid,floor_number) val res: JsValue = Json.obj("fingerprints" -> fingerprints) - val strPromise = F.Promise.pure("10") - val intPromise = strPromise.map(new F.Function[String, Integer]() { - override def apply(arg0: String): java.lang.Integer = { - AnyplacePosition.updateFrozenRadioMap(buid, floor_number) - 0 - } - }) + Future { + mapHelper.updateFrozenRadioMap(buid, floor_number) + }(ec) return gzippedJSONOk(res, "Deleted " + fingerprints.size + " fingerprints and returning them.") } catch { case e: Exception => @@ -742,17 +713,13 @@ object AnyplaceMapping extends play.api.mvc.Controller { implicit request => def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody) + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::FingerPrintsTimestampDelete(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloor, "lat1", "lon1", "lat2", "lon2", - SCHEMA.fTimestampX, SCHEMA.fTimestampY) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fBuid, SCHEMA.fFloor, "lat1", "lon1", "lat2", "lon2", + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloor, "lat1", "lon1", "lat2", "lon2", SCHEMA.fTimestampX, SCHEMA.fTimestampY) - if (validation.failed()) return validation.response() - + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] val floor_number = (json \ SCHEMA.fFloor).as[String] val lat1 = (json \ "lat1").as[String] @@ -762,24 +729,19 @@ object AnyplaceMapping extends play.api.mvc.Controller { val timestampX = (json \ SCHEMA.fTimestampX).as[String] val timestampY = (json \ SCHEMA.fTimestampY).as[String] try { - val fingerprints: List[JsValue] = ProxyDataSource.getIDatasource.getFingerPrintsTimestampBBox(buid, floor_number, lat1, lon1, lat2, lon2, timestampX, timestampY) + val fingerprints: List[JsValue] = pds.getIDatasource.getFingerPrintsTimestampBBox(buid, floor_number, lat1, lon1, lat2, lon2, timestampX, timestampY) if (fingerprints.isEmpty) return AnyResponseHelper.bad_request("FingerPrints does not exist or could not be retrieved!") for (fingerprint <- fingerprints) - ProxyDataSource.getIDatasource.deleteFingerprint(fingerprint) - ProxyDataSource.getIDatasource().deleteAffectedHeatmaps(buid,floor_number) + pds.getIDatasource.deleteFingerprint(fingerprint) + pds.getIDatasource.deleteAffectedHeatmaps(buid,floor_number) // TODO:do also 1 and 2 - ProxyDataSource.getIDatasource().createTimestampHeatmap(SCHEMA.cHeatmapWifiTimestamp3, buid, floor_number, 3) + pds.getIDatasource.createTimestampHeatmap(SCHEMA.cHeatmapWifiTimestamp3, buid, floor_number, 3) val res: JsValue = Json.obj("radioPoints" -> fingerprints) try { - //Regenerate the radiomap files - val strPromise = F.Promise.pure("10") - val intPromise = strPromise.map(new F.Function[String, Integer]() { - override def apply(arg0: String): java.lang.Integer = { - AnyplacePosition.updateFrozenRadioMap(buid, floor_number) - 0 - } - }) + Future { + mapHelper.updateFrozenRadioMap(buid, floor_number) + }(ec) gzippedJSONOk(res.toString) } catch { case ioe: IOException => @@ -805,25 +767,22 @@ object AnyplaceMapping extends play.api.mvc.Controller { implicit request => def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody) + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.D2("FingerprintsByTime: " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloor) - if (!requiredMissing.isEmpty) - return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fBuid, SCHEMA.fFloor) - if (validation.failed()) return validation.response() - + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloor) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] val floor_number = (json \ SCHEMA.fFloor).as[String] - ProxyDataSource.getIDatasource().createTimestampHeatmap(SCHEMA.cHeatmapWifiTimestamp1, buid, floor_number, 1) - ProxyDataSource.getIDatasource().createTimestampHeatmap(SCHEMA.cHeatmapWifiTimestamp2, buid, floor_number, 2) - ProxyDataSource.getIDatasource().createTimestampHeatmap(SCHEMA.cHeatmapWifiTimestamp3, buid, floor_number, 3) + // create cache-collections + pds.getIDatasource.createTimestampHeatmap(SCHEMA.cHeatmapWifiTimestamp1, buid, floor_number, 1) + pds.getIDatasource.createTimestampHeatmap(SCHEMA.cHeatmapWifiTimestamp2, buid, floor_number, 2) + pds.getIDatasource.createTimestampHeatmap(SCHEMA.cHeatmapWifiTimestamp3, buid, floor_number, 3) try { - val radioPoints: List[JsValue] = ProxyDataSource.getIDatasource.getFingerprintsByTime(buid, floor_number) + val radioPoints: List[JsValue] = pds.getIDatasource.getFingerprintsByTime(buid, floor_number) if (radioPoints.isEmpty) return AnyResponseHelper.bad_request("Fingerprints do not exist.") val res: JsValue = Json.obj("radioPoints" -> radioPoints) try { @@ -845,9 +804,9 @@ object AnyplaceMapping extends play.api.mvc.Controller { implicit request => def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody) + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::findPosition(): " + stripJson(json)) //val requiredMissing = JsonUtils.requirePropertiesInJson(json, SCHEMA.fBuid, SCHEMA.fFloor,"APs","algorithm_choice") // LPLogger.debug("json: "+json) @@ -879,30 +838,31 @@ object AnyplaceMapping extends play.api.mvc.Controller { case s: JsSuccess[String] => { if (s.get != null && s.get.trim != "") Integer.parseInt(s.get) - else - Play.application().configuration().getInt("defaultPositionAlgorithm") + else { + conf.get[Int]("defaultPositionAlgorithm") + } } case e: JsError => - Play.application().configuration().getInt("defaultPositionAlgorithm") + conf.get[Int]("defaultPositionAlgorithm") } //FeatureAdd : Configuring location for server generated files - val radioMapsFrozenDir = Play.application().configuration().getString("radioMapFrozenDir") + val radioMapsFrozenDir = conf.get[String]("radioMapFrozenDir") /* * REVIEWLS . Leaving bugfix from develop val floor_number = (json \ SCHEMA.fFloor).as[String] val jsonstr=(json\"APs").as[String] val accessPoints= Json.parse(jsonstr).as[List[JsValue]] - val floors: Array[JsonObject] = ProxyDataSource.getIDatasource.floorsByBuildingAsJson(buid).iterator().toArray + val floors: Array[JsonObject] = pds.getIDatasource.floorsByBuildingAsJson(buid).iterator().toArray val algorithm_choice = (json\"algorithm_choice").as[String].toInt */ - val rmapFile = new File(radioMapsFrozenDir + AnyplaceServerAPI.URL_SEP + buid + AnyplaceServerAPI.URL_SEP + - floor_number + AnyplaceServerAPI.URL_SEP + "indoor-radiomap-mean.txt") + val rmapFile = new File(radioMapsFrozenDir + api.URL_SEP + buid + api.URL_SEP + + floor_number + api.URL_SEP + "indoor-radiomap-mean.txt") if (!rmapFile.exists()) { //Regenerate the radiomap files if not exist - AnyplacePosition.updateFrozenRadioMap(buid, floor_number) + mapHelper.updateFrozenRadioMap(buid, floor_number) } /* * BuxFix : Server side localization API @@ -943,9 +903,9 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody) + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplacePosition::radioDownloadFloor(): " + stripJson(json)) val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fCoordinatesLat, SCHEMA.fCoordinatesLon, SCHEMA.fFloor, SCHEMA.fBuid, "range") if (!requiredMissing.isEmpty) @@ -959,9 +919,9 @@ object AnyplaceMapping extends play.api.mvc.Controller { val range = strRange.toInt try { var radioPoints: util.List[JsonObject] = null - if (weight.compareTo("false") == 0) radioPoints = ProxyDataSource.getIDatasource.getRadioHeatmapBBox2(lat, lon, buid, floor_number, range) - else if (weight.compareTo("true") == 0) radioPoints = ProxyDataSource.getIDatasource.getRadioHeatmapBBox(lat, lon, buid, floor_number, range) - else if (weight.compareTo("no spatial") == 0) radioPoints = ProxyDataSource.getIDatasource.getRadioHeatmapByBuildingFloor2(lat, lon, buid, floor_number, range) + if (weight.compareTo("false") == 0) radioPoints = pds.getIDatasource.getRadioHeatmapBBox2(lat, lon, buid, floor_number, range) + else if (weight.compareTo("true") == 0) radioPoints = pds.getIDatasource.getRadioHeatmapBBox(lat, lon, buid, floor_number, range) + else if (weight.compareTo("no spatial") == 0) radioPoints = pds.getIDatasource.getRadioHeatmapByBuildingFloor2(lat, lon, buid, floor_number, range) if (radioPoints == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") val res = JsonObject.empty() @@ -989,10 +949,10 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::deleteRadiosInBox(): " + stripJson(json)) try { - if (!ProxyDataSource.getIDatasource.deleteRadiosInBox()) return AnyResponseHelper.bad_request("Building already exists or could not be added!") + if (!pds.getIDatasource.deleteRadiosInBox()) return AnyResponseHelper.bad_request("Building already exists or could not be added!") return AnyResponseHelper.ok("Success") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) @@ -1007,17 +967,13 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody - LPLogger.info("AnyplaceMapping::spaceAdd(): " + stripJson(json)) - - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fIsPublished, SCHEMA.fName, SCHEMA.fDescription, + var json = anyReq.getJsonBody() + LPLogger.D2("spaceAdd: " + stripJson(json)) + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fIsPublished, SCHEMA.fName, SCHEMA.fDescription, SCHEMA.fURL, SCHEMA.fAddress, SCHEMA.fCoordinatesLat, SCHEMA.fCoordinatesLon, SCHEMA.fAccessToken, SCHEMA.fSpaceType) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if ((json \ SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + if (checkRequirements != null) return checkRequirements + val owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - - owner_id = appendGoogleIdIfNeeded(owner_id) json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) try { var space: Space = null @@ -1027,8 +983,8 @@ object AnyplaceMapping extends play.api.mvc.Controller { } catch { case e: NumberFormatException => return AnyResponseHelper.bad_request("Building coordinates are invalid!") } - if (!ProxyDataSource.getIDatasource.addJsonDocument(SCHEMA.cSpaces, space.toGeoJSON())) return AnyResponseHelper.bad_request("Building already exists or could not be added!") - val res: JsValue = Json.obj(SCHEMA.fBuid -> space.getId) + if (!pds.getIDatasource.addJsonDocument(SCHEMA.cSpaces, space.toGeoJSON())) return AnyResponseHelper.bad_request("Building already exists or could not be added!") + val res: JsValue = Json.obj(SCHEMA.fBuid -> space.getId()) return AnyResponseHelper.ok(res, "Successfully added space!") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) @@ -1049,20 +1005,20 @@ object AnyplaceMapping extends play.api.mvc.Controller { val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fAccessToken, SCHEMA.fCoOwners) if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) if (json.\\(SCHEMA.fAccessToken) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + var owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) val validation = VALIDATE.fields(json, SCHEMA.fBuid) if (validation.failed()) return validation.response() val buid = (json \ SCHEMA.fBuid).as[String] try { - val stored_space: JsValue = ProxyDataSource.getIDatasource().getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + + val stored_space: JsValue = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_space == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (!isBuildingOwner(stored_space, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") val space = new Space(stored_space) - if (!ProxyDataSource.getIDatasource.replaceJsonDocument(SCHEMA.cSpaces, SCHEMA.fBuid, space.getId, space.appendCoOwners(json))) + if (!pds.getIDatasource.replaceJsonDocument(SCHEMA.cSpaces, SCHEMA.fBuid, space.getId(), space.appendCoOwners(json))) return AnyResponseHelper.bad_request("Building could not be updated!") return AnyResponseHelper.ok("Successfully updated space!") } catch { @@ -1078,14 +1034,13 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::spaceUpdateOwner(): " + stripJson(json)) val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fAccessToken, "new_owner") if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + var owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) val validation = VALIDATE.fields(json, SCHEMA.fBuid, "new_owner") if (validation.failed()) return validation.response() @@ -1094,11 +1049,11 @@ object AnyplaceMapping extends play.api.mvc.Controller { var newOwner = (json \ "new_owner").as[String] newOwner = appendGoogleIdIfNeeded(newOwner) try { - val stored_space = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + val stored_space = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_space == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (!isBuildingOwner(stored_space, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") val space = new Space(stored_space) - if (!ProxyDataSource.getIDatasource.replaceJsonDocument(SCHEMA.cSpaces, SCHEMA.fBuid, space.getId, space.changeOwner(newOwner))) return AnyResponseHelper.bad_request("Building could not be updated!") + if (!pds.getIDatasource.replaceJsonDocument(SCHEMA.cSpaces, SCHEMA.fBuid, space.getId(), space.changeOwner(newOwner))) return AnyResponseHelper.bad_request("Building could not be updated!") return AnyResponseHelper.ok("Successfully updated space!") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) @@ -1113,21 +1068,16 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::spaceUpdateX(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fAccessToken) + if (checkRequirements != null) return checkRequirements + val owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) - val validation = VALIDATE.fields(json, SCHEMA.fBuid) - if (validation.failed()) return validation.response() val buid = (json \ SCHEMA.fBuid).as[String] - try { - var stored_space = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + var stored_space = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_space == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (!isBuildingOwner(stored_space, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") if (json.\(SCHEMA.fIsPublished).getOrElse(null) != null) { @@ -1150,7 +1100,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { if (json.\(SCHEMA.fCoordinatesLon).getOrElse(null) != null) stored_space = stored_space.as[JsObject] + (SCHEMA.fCoordinatesLon -> JsString((json \ SCHEMA.fCoordinatesLon).as[String])) val space = new Space(stored_space) - if (!ProxyDataSource.getIDatasource.replaceJsonDocument(SCHEMA.cSpaces, SCHEMA.fBuid, space.getId, space.toGeoJSON())) return AnyResponseHelper.bad_request("Building could not be updated!") + if (!pds.getIDatasource.replaceJsonDocument(SCHEMA.cSpaces, SCHEMA.fBuid, space.getId(), space.toGeoJSON())) return AnyResponseHelper.bad_request("Building could not be updated!") return AnyResponseHelper.ok("Successfully updated space!") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) @@ -1165,60 +1115,32 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) - - // TODO:NN this could be ONE method. with arguments: properties: - /*e.g. val reqResult=anyReq.checkAuthRequest(CHEMA.fBUid); // THIS will replace the lines below.. after these comments.. - if(reqRes not null) return it..; - - // these will be implemneted somewher else... - OAht2Request::checkAuthRequest( varargs...): Response { - return checkRequest(true, vargargs) - } - - Oauth2Request::checkRequest(auth: boolean, varargs...): Response { - - if auth: varargs.append(fAccessToekn) - JUtils.HasProperties(varargs) - - if(auth) { - vreifyId(..) - } - - if all ok: return null - } - */ - // TODO:NN if the request is wrong must reply json if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::spaceDelete(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) - if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") // TODO:NN OAuthReponse::Unauthorized() - owner_id = appendGoogleIdIfNeeded(owner_id) - // up to here will be in the method in the comments.... - - + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fAccessToken) + if (checkRequirements != null) return checkRequirements + val owner_id = user.authorize(json) + if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) if (String(json, SCHEMA.fBuid) == null) return AnyResponseHelper.bad_request("Buid field must be String!") val buid = (json \ SCHEMA.fBuid).as[String] try { - val stored_space = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + val stored_space = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_space == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (!isBuildingOwner(stored_space, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) } try { - val deleted = ProxyDataSource.getIDatasource.deleteAllByBuilding(buid) + val deleted = pds.getIDatasource.deleteAllByBuilding(buid) if (deleted == false) return AnyResponseHelper.bad_request("Some items related to the deleted space could not be deleted.") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) } - val filePath = AnyPlaceTilerHelper.getRootFloorPlansDirFor(buid) + val filePath = tilerHelper.getRootFloorPlansDirFor(buid) try { val buidfile = new File(filePath) if (buidfile.exists()) HelperMethods.recDeleteDirFile(buidfile) @@ -1238,10 +1160,10 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("spaceAll: " + stripJson(json)) try { - val spaces = ProxyDataSource.getIDatasource.getAllBuildings + val spaces = pds.getIDatasource.getAllBuildings() val res: JsValue = Json.obj(SCHEMA.cSpaces -> spaces) try { gzippedJSONOk(res.toString) @@ -1268,15 +1190,13 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::spaceGet(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, SCHEMA.fBuid) - if (validation.failed()) return validation.response() + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] try { - var space = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + var space = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (space != null && (space \ SCHEMA.fBuid) != JsDefined(JsNull) && (space \ SCHEMA.fCoordinatesLat) != JsDefined(JsNull) && (space \ SCHEMA.fCoordinatesLon) != JsDefined(JsNull) && @@ -1305,19 +1225,15 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("spaceAllByOwner: " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fAccessToken) + if (checkRequirements != null) return checkRequirements + val owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) - json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) - if (owner_id == null || owner_id.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) try { LPLogger.debug("owner_id = " + owner_id) - val spaces = ProxyDataSource.getIDatasource.getAllBuildingsByOwner(owner_id) + val spaces = pds.getIDatasource.getAllBuildingsByOwner(owner_id) val res: JsValue = Json.obj("spaces" -> spaces) try { gzippedJSONOk(res.toString) @@ -1339,13 +1255,13 @@ object AnyplaceMapping extends play.api.mvc.Controller { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("spaceByBucode: " + stripJson(json)) val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuCode) if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) val bucode = (json \ SCHEMA.fBuCode).as[String] try { - val spaces = ProxyDataSource.getIDatasource.getAllBuildingsByBucode(bucode) + val spaces = pds.getIDatasource.getAllBuildingsByBucode(bucode) val res: JsValue = Json.obj(SCHEMA.cSpaces -> spaces) try { gzippedJSONOk(res.toString) @@ -1366,11 +1282,10 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("spaceCoordinates(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fAccessToken, SCHEMA.fCoordinatesLat, SCHEMA.fCoordinatesLon) + if (checkRequirements != null) return checkRequirements var range = NEARBY_BUILDINGS_RANGE if (JsonUtils.hasProperty(json, "range")) { if ((json \ "range").validate[Int].isError) { @@ -1386,22 +1301,13 @@ object AnyplaceMapping extends play.api.mvc.Controller { } } - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) - if (owner_id == null) owner_id = "" - owner_id = appendGoogleIdIfNeeded(owner_id) + val owner_id = user.authorize(json) + if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) - requiredMissing.addAll(JsonUtils.hasProperties(json, SCHEMA.fCoordinatesLat, SCHEMA.fCoordinatesLon)) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) try { - if (Coordinate(json, SCHEMA.fCoordinatesLat) == null) - return AnyResponseHelper.bad_request("coordinates_lat field must be String containing a float!") val lat = java.lang.Double.parseDouble((json \ SCHEMA.fCoordinatesLat).as[String]) - - if (Coordinate(json, SCHEMA.fCoordinatesLon) == null) - return AnyResponseHelper.bad_request("coordinates_lon field must be String containing a float!") val lon = java.lang.Double.parseDouble((json \ SCHEMA.fCoordinatesLon).as[String]) - - val spaces = ProxyDataSource.getIDatasource.getAllBuildingsNearMe(lat, lon, range, owner_id) + val spaces = pds.getIDatasource.getAllBuildingsNearMe(lat, lon, range, owner_id) val res: JsValue = Json.obj(SCHEMA.cSpaces -> spaces) try { gzippedJSONOk(res.toString) @@ -1426,17 +1332,15 @@ object AnyplaceMapping extends play.api.mvc.Controller { implicit request => def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody) - return AnyResponseHelper - .bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + if (!anyReq.assertJsonBody()) + return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + val json = anyReq.getJsonBody() LPLogger.info("buildingSetAll: " + stripJson(json)) - var cuid = request.getQueryString(SCHEMA.fCampusCuid).orNull - if (String(json, SCHEMA.fCampusCuid) == null) - return AnyResponseHelper.bad_request("cuid field must be String!") - if (cuid == null) cuid = (json \ SCHEMA.fCampusCuid).as[String] + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fCampusCuid) + if (checkRequirements != null) return checkRequirements + val cuid = (json \ SCHEMA.fCampusCuid).as[String] try { - val campus = ProxyDataSource.getIDatasource.getBuildingSet(cuid) + val campus = pds.getIDatasource.getBuildingSet(cuid) if (campus.size == 0) { return AnyResponseHelper.not_found("Campus '" + cuid + "' not found!") } else if (campus.size > 1) { @@ -1451,13 +1355,13 @@ object AnyplaceMapping extends play.api.mvc.Controller { } } val buildings = new util.ArrayList[JsValue] - for (b <- buids) { - val building = ProxyDataSource.getIDatasource().getFromKey(SCHEMA.cSpaces, SCHEMA.fBuid, b) + for (b <- buids.asScala) { + val building = pds.getIDatasource.getFromKey(SCHEMA.cSpaces, SCHEMA.fBuid, b) if (building != null) // some buildings are deleted but still exist in buids[] of a campus buildings.add(building.as[JsObject] - SCHEMA.fId - SCHEMA.fSchema - SCHEMA.fCoOwners - SCHEMA.fGeometry - SCHEMA.fType - SCHEMA.fOwnerId) } - val res = campus.get(0).as[JsObject] - SCHEMA.fBuids - SCHEMA.fOwnerId - SCHEMA.fId - SCHEMA.fSchema - SCHEMA.fCampusCuid - SCHEMA.fDescription + - (SCHEMA.cSpaces -> Json.toJson(buildings.toList)) + val res = campus(0).as[JsObject] - SCHEMA.fBuids - SCHEMA.fOwnerId - SCHEMA.fId - SCHEMA.fSchema - SCHEMA.fCampusCuid - SCHEMA.fDescription + + (SCHEMA.cSpaces -> Json.toJson(buildings.asScala)) try gzippedJSONOk(res.toString) catch { @@ -1483,25 +1387,19 @@ object AnyplaceMapping extends play.api.mvc.Controller { implicit request => def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody) + if (!anyReq.assertJsonBody()) return AnyResponseHelper .bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::buildingSetAdd(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fDescription, SCHEMA.fName, SCHEMA.fBuids, SCHEMA.fGreeklish) - if (!requiredMissing.isEmpty) - return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - // get access token from url and check it against google's service - if (json.\\(SCHEMA.fAccessToken) == null) - return AnyResponseHelper.forbidden("Unauthorized1") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) - if (owner_id == null) - return AnyResponseHelper.forbidden("Unauthorized2") - owner_id = appendGoogleIdIfNeeded(owner_id) + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fDescription, SCHEMA.fName, SCHEMA.fBuids, SCHEMA.fGreeklish) + if (checkRequirements != null) return checkRequirements + var owner_id = user.authorize(json) + if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized2") json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) - SCHEMA.fAccessToken try { val cuid = (json \ SCHEMA.fCampusCuid).as[String] - val campus = ProxyDataSource.getIDatasource.BuildingSetsCuids(cuid) + val campus = pds.getIDatasource.BuildingSetsCuids(cuid) if (campus) return AnyResponseHelper.bad_request("Building set already exists!") else { var buildingset: BuildingSet = null @@ -1511,9 +1409,9 @@ object AnyplaceMapping extends play.api.mvc.Controller { case e: NumberFormatException => return AnyResponseHelper.bad_request("Building coordinates are invalid!") } - if (!ProxyDataSource.getIDatasource.addJsonDocument(SCHEMA.cCampuses, buildingset.addBuids())) + if (!pds.getIDatasource.addJsonDocument(SCHEMA.cCampuses, buildingset.addBuids())) return AnyResponseHelper.bad_request("Building set already exists or could not be added!") - val res: JsValue = Json.obj(SCHEMA.fCampusCuid -> buildingset.getId) + val res: JsValue = Json.obj(SCHEMA.fCampusCuid -> buildingset.getId()) return AnyResponseHelper.ok(res, "Successfully added building Set!") } } catch { @@ -1535,26 +1433,18 @@ object AnyplaceMapping extends play.api.mvc.Controller { implicit request => def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody) + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::campusUpdate(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fCampusCuid, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) - return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - // get access token from url and check it against google's service - if (json.\\(SCHEMA.fAccessToken) == null) - return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) - if (owner_id == null) - return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fCampusCuid, SCHEMA.fAccessToken) + if (checkRequirements != null) return checkRequirements + var owner_id = user.authorize(json) + if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) - if (String(json, SCHEMA.fCampusCuid) == null) - return AnyResponseHelper.bad_request("cuid field must be String!") val cuid = (json \ SCHEMA.fCampusCuid).as[String] try { - var stored_campus = ProxyDataSource.getIDatasource().getFromKeyAsJson(SCHEMA.cCampuses, SCHEMA.fCampusCuid, cuid) + var stored_campus = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cCampuses, SCHEMA.fCampusCuid, cuid) if (stored_campus == null) return AnyResponseHelper.bad_request("Campus does not exist or could not be retrieved!") if (!isCampusOwner(stored_campus, owner_id)) @@ -1591,7 +1481,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { stored_campus = stored_campus.as[JsObject] + (SCHEMA.fBuids -> Json.toJson(buidsList.toList)) } val campus = new BuildingSet(stored_campus) - if (!ProxyDataSource.getIDatasource().replaceJsonDocument(SCHEMA.cCampuses, SCHEMA.fCampusCuid, campus.getId(), campus.toGeoJSON())) + if (!pds.getIDatasource.replaceJsonDocument(SCHEMA.cCampuses, SCHEMA.fCampusCuid, campus.getId(), campus.toGeoJSON())) return AnyResponseHelper.bad_request("Campus could not be updated!") return AnyResponseHelper.ok("Successfully updated campus!") } catch { @@ -1606,7 +1496,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { import java.io.IOException - import datasources.{DatasourceException, ProxyDataSource} + import datasources.{DatasourceException} import oauth.provider.v2.models.OAuth2Request import utils.{AnyResponseHelper, JsonUtils, LPLogger} @@ -1614,25 +1504,16 @@ object AnyplaceMapping extends play.api.mvc.Controller { implicit request => def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody) - return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody - LPLogger.info("AnyplaceMapping::buildingSetAll(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) - return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - // get access token from url and check it against google's service - if (json.\\(SCHEMA.fAccessToken) == null) - return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) - if (owner_id == null) - return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + var json = anyReq.getJsonBody() + LPLogger.info("buildingsetAllByOwner: " + stripJson(json)) + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fAccessToken) + if (checkRequirements != null) return checkRequirements + val owner_id = user.authorize(json) + if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) - if (owner_id == null || owner_id.isEmpty) - return AnyResponseHelper.requiredFieldsMissing(requiredMissing) try { - val buildingsets = ProxyDataSource.getIDatasource().getAllBuildingsetsByOwner(owner_id) + val buildingsets = pds.getIDatasource.getAllBuildingsetsByOwner(owner_id) val res: JsValue = Json.obj("buildingsets" -> buildingsets) try gzippedJSONOk(res.toString) @@ -1658,31 +1539,23 @@ object AnyplaceMapping extends play.api.mvc.Controller { implicit request => def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody) + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::campusDelete(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fCampusCuid, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) - return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - // get access token from url and check it against google's service - if (json.\\(SCHEMA.fAccessToken) == null) - return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) - if (owner_id == null) - return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fCampusCuid, SCHEMA.fAccessToken) + if (checkRequirements != null) return checkRequirements + var owner_id = user.authorize(json) + if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) - if (String(json, SCHEMA.fCampusCuid) == null) - return AnyResponseHelper.bad_request("cuid field must be String!") val cuid = (json \ SCHEMA.fCampusCuid).as[String] try { - val stored_campus = ProxyDataSource.getIDatasource().getFromKeyAsJson(SCHEMA.cCampuses, SCHEMA.fCampusCuid, cuid) + val stored_campus = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cCampuses, SCHEMA.fCampusCuid, cuid) if (stored_campus == null) return AnyResponseHelper.bad_request("Campus does not exist or could not be retrieved!") if (!isCampusOwner(stored_campus, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") - if (!ProxyDataSource.getIDatasource().deleteFromKey(SCHEMA.cCampuses, SCHEMA.fCampusCuid, cuid)) + if (!pds.getIDatasource.deleteFromKey(SCHEMA.cCampuses, SCHEMA.fCampusCuid, cuid)) return AnyResponseHelper.internal_server_error("500: Failed to delete Campus") } catch { case e: DatasourceException => @@ -1709,23 +1582,17 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.D2("AnyplaceMapping::floorAdd(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fIsPublished, SCHEMA.fBuid, SCHEMA.fFloorName, + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fIsPublished, SCHEMA.fBuid, SCHEMA.fFloorName, SCHEMA.fDescription, SCHEMA.fFloorNumber, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + if (checkRequirements != null) return checkRequirements + val owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) - if (String(json, SCHEMA.fBuid) == null) - return AnyResponseHelper.bad_request("buid field must be String!") - if (StringNumber(json, SCHEMA.fFloorNumber) == null) - return AnyResponseHelper.bad_request("floor_number field must be String, containing a number!") val buid = (json \ SCHEMA.fBuid).as[String] try { - val stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + val stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (!isBuildingOwner(stored_building, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") } catch { @@ -1736,7 +1603,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { try { json = json.as[JsObject] - SCHEMA.fAccessToken val floor = new Floor(json) - if (!ProxyDataSource.getIDatasource.addJsonDocument(SCHEMA.cFloorplans, stripJson(floor.toValidMongoJson()))) return AnyResponseHelper.bad_request("Floor already exists or could not be added!") + if (!pds.getIDatasource.addJsonDocument(SCHEMA.cFloorplans, stripJson(floor.toValidMongoJson()))) return AnyResponseHelper.bad_request("Floor already exists or could not be added!") return AnyResponseHelper.ok("Successfully added floor " + floor_number + "!") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) @@ -1752,18 +1619,17 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::floorUpdate(): " + stripJson(json)) val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloorNumber, SCHEMA.fAccessToken) if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + var owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) val buid = (json \ SCHEMA.fBuid).as[String] try { - val stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + val stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (!isBuildingOwner(stored_building, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") } catch { @@ -1773,7 +1639,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { if (!Floor.checkFloorNumberFormat(floor_number)) return AnyResponseHelper.bad_request("Floor number cannot contain whitespace!") try { val fuid = Floor.getId(buid, floor_number) - var stored_floor = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cFloorplans, SCHEMA.fFuid, fuid) + var stored_floor = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cFloorplans, SCHEMA.fFuid, fuid) if (stored_floor == null) return AnyResponseHelper.bad_request("Floor does not exist or could not be retrieved!") if (json.\(SCHEMA.fIsPublished).getOrElse(null) != null) stored_floor = stored_floor.as[JsObject] + (SCHEMA.fIsPublished -> JsString((json \ SCHEMA.fIsPublished).as[String])) @@ -1782,7 +1648,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { if (json.\(SCHEMA.fDescription).getOrElse(null) != null) stored_floor = stored_floor.as[JsObject] + (SCHEMA.fDescription, JsString((json \ SCHEMA.fDescription).as[String])) val floor = new Floor(stored_floor) - if (!ProxyDataSource.getIDatasource.replaceJsonDocument(SCHEMA.cFloorplans, SCHEMA.fFuid, floor.getId, floor.toValidMongoJson().toString)) + if (!pds.getIDatasource.replaceJsonDocument(SCHEMA.cFloorplans, SCHEMA.fFuid, floor.getId(), floor.toValidMongoJson().toString)) return AnyResponseHelper.bad_request("Floor could not be updated!") return AnyResponseHelper.ok("Successfully updated floor!") } catch { @@ -1793,68 +1659,62 @@ object AnyplaceMapping extends play.api.mvc.Controller { inner(request) } - /** - * Deletes the ACCES data (CRLB) for a space. - */ - def deleteAccesSpaceData() = Action { - implicit request => - def inner(request: Request[AnyContent]): Result = { - val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val buid = (json \ SCHEMA.fBuid).as[String] - val floor_number = (json \ SCHEMA.fFloor).as[String] - val file_path = new File( - Play.application().configuration().getString("crlbsDir") + - File.separatorChar + buid + File.separator + "fl_" + floor_number + ".txt") - if (file_path.exists()) { - if (file_path.delete) { - return AnyResponseHelper.ok("Deleted floor :" + floor_number) - } - } - return AnyResponseHelper.bad_request("ERROR: while deleting: " + floor_number) - } - - inner(request) - } + ///** + // * Deletes the ACCES data (CRLB) for a space. + // */ + //def deleteAccesSpaceData() = Action { + // implicit request => + // def inner(request: Request[AnyContent]): Result = { + // val anyReq = new OAuth2Request(request) + // if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + // val json = anyReq.getJsonBody() + // val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid) + // if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) + // val buid = (json \ SCHEMA.fBuid).as[String] + // val floor_number = (json \ SCHEMA.fFloor).as[String] + // val file_path = new File( + // Play.application().configuration().getString("crlbsDir") + + // File.separatorChar + buid + File.separator + "fl_" + floor_number + ".txt") + // if (file_path.exists()) { + // if (file_path.delete) { + // return AnyResponseHelper.ok("Deleted floor :" + floor_number) + // } + // } + // return AnyResponseHelper.bad_request("ERROR: while deleting: " + floor_number) + // } + // + // inner(request) + //} def floorDelete() = Action { implicit request => def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::floorDelete(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloorNumber, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloorNumber, SCHEMA.fAccessToken) + if (checkRequirements != null) return checkRequirements + var owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) - if (String(json, SCHEMA.fBuid) == null) - return AnyResponseHelper.bad_request("buid field must be String!") val buid = (json \ SCHEMA.fBuid).as[String] - if (StringNumber(json, SCHEMA.fFloorNumber) == null) - return AnyResponseHelper.bad_request("floor_number field must be String, containing a number!") val floor_number = (json \ SCHEMA.fFloorNumber).as[String] try { - val stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + val stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (!isBuildingOwner(stored_building, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) } try { - val deleted = ProxyDataSource.getIDatasource.deleteAllByFloor(buid, floor_number) + val deleted = pds.getIDatasource.deleteAllByFloor(buid, floor_number) if (deleted == false) return AnyResponseHelper.bad_request("Some items related to the floor could not be deleted.") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) } - val filePath = AnyPlaceTilerHelper.getFloorPlanFor(buid, floor_number) + val filePath = tilerHelper.getFloorPlanFor(buid, floor_number) try { val floorfile = new File(filePath) /* @@ -1877,16 +1737,14 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::floorAll(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (String(json, SCHEMA.fBuid) == null) - return AnyResponseHelper.bad_request("buid field must be String!") + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] try { - val floors = ProxyDataSource.getIDatasource.floorsByBuildingAsJson(buid) - val res: JsValue = Json.obj("floors" -> floors.toList) + val floors = pds.getIDatasource.floorsByBuildingAsJson(buid) + val res: JsValue = Json.obj("floors" -> floors.asScala) try { gzippedJSONOk(res.toString) } catch { @@ -1905,22 +1763,19 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::poisAdd(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fIsPublished, SCHEMA.fBuid, SCHEMA.fFloorName, + if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fIsPublished, SCHEMA.fBuid, SCHEMA.fFloorName, SCHEMA.fFloorNumber, SCHEMA.fName, SCHEMA.fPoisType, SCHEMA.fIsDoor, SCHEMA.fIsBuildingEntrance, SCHEMA.fCoordinatesLat, SCHEMA.fCoordinatesLon, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + if (checkRequirements != null) return checkRequirements + val owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) - SCHEMA.fAccessToken - if (String(json, SCHEMA.fBuid) == null) - return AnyResponseHelper.bad_request("Buid field must be String!") val buid = (json \ SCHEMA.fBuid).as[String] try { - val stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + val stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (!isBuildingOwner(stored_building, owner_id) && !isBuildingCoOwner(stored_building, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") } catch { @@ -1928,8 +1783,8 @@ object AnyplaceMapping extends play.api.mvc.Controller { } try { val poi = new Poi(json) - if (!ProxyDataSource.getIDatasource.addJsonDocument(SCHEMA.cPOIS, poi.toGeoJSON())) return AnyResponseHelper.bad_request("Poi already exists or could not be added!") - val res: JsValue = Json.obj(SCHEMA.fPuid -> poi.getId) + if (!pds.getIDatasource.addJsonDocument(SCHEMA.cPOIS, poi.toGeoJSON())) return AnyResponseHelper.bad_request("Poi already exists or could not be added!") + val res: JsValue = Json.obj(SCHEMA.fPuid -> poi.getId()) return AnyResponseHelper.ok(res, "Successfully added poi!") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) @@ -1944,23 +1799,17 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::poisUpdate(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fPuid, SCHEMA.fBuid, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fPuid, SCHEMA.fBuid, SCHEMA.fAccessToken) + if (checkRequirements != null) return checkRequirements + val owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) - if (String(json, SCHEMA.fPuid) == null) - return AnyResponseHelper.bad_request("Puid field must be String!") val puid = (json \ SCHEMA.fPuid).as[String] - if (String(json, SCHEMA.fBuid) == null) - return AnyResponseHelper.bad_request("Buid field must be String!") val buid = (json \ SCHEMA.fBuid).as[String] try { - val stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + val stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (!isBuildingOwner(stored_building, owner_id) && !isBuildingCoOwner(stored_building, owner_id)) { return AnyResponseHelper.unauthorized("Unauthorized") @@ -1969,7 +1818,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) } try { - var stored_poi = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cPOIS, SCHEMA.fPuid, puid) + var stored_poi = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cPOIS, SCHEMA.fPuid, puid) if (stored_poi == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (json.\(SCHEMA.fIsPublished).getOrElse(null) != null) { val is_published = (json \ SCHEMA.fIsPublished).as[String] @@ -2001,7 +1850,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { if (json.\(SCHEMA.fCoordinatesLon).getOrElse(null) != null) stored_poi = stored_poi.as[JsObject] + (SCHEMA.fCoordinatesLon, JsString((json \ SCHEMA.fCoordinatesLon).as[String])) val poi = new Poi(stored_poi) - if (!ProxyDataSource.getIDatasource.replaceJsonDocument(SCHEMA.cPOIS, SCHEMA.fPuid, poi.getId, poi.toGeoJSON())) + if (!pds.getIDatasource.replaceJsonDocument(SCHEMA.cPOIS, SCHEMA.fPuid, poi.getId(), poi.toGeoJSON())) return AnyResponseHelper.bad_request("Poi could not be updated!") return AnyResponseHelper.ok("Successfully updated poi!") } catch { @@ -2017,23 +1866,17 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::poiDelete(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fPuid, SCHEMA.fBuid, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fPuid, SCHEMA.fBuid, SCHEMA.fAccessToken) + if (checkRequirements != null) return checkRequirements + val owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) - if (String(json, SCHEMA.fBuid) == null) - return AnyResponseHelper.bad_request("Buid field must be String!") val buid = (json \ SCHEMA.fBuid).as[String] - if (String(json, SCHEMA.fPuid) == null) - return AnyResponseHelper.bad_request("Puid field must be String!") val puid = (json \ SCHEMA.fPuid).as[String] try { - val stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + val stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (!isBuildingOwner(stored_building, owner_id) && !isBuildingCoOwner(stored_building, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") @@ -2041,7 +1884,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) } try { - val all_items_failed = ProxyDataSource.getIDatasource.deleteAllByPoi(puid) + val all_items_failed = pds.getIDatasource.deleteAllByPoi(puid) if (all_items_failed.size > 0) { val obj = JsonObject.empty() obj.put("ids", (all_items_failed)) @@ -2064,20 +1907,16 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::poisByFloor(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloorNumber) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (String(json, SCHEMA.fBuid) == null) - return AnyResponseHelper.bad_request("Buid field must be String!") + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloorNumber) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] - if (StringNumber(json, SCHEMA.fFloorNumber) == null) - return AnyResponseHelper.bad_request("Floor_number field must be String, containing a number!") val floor_number = (json \ SCHEMA.fFloorNumber).as[String] try { - val stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + val stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") - val pois = ProxyDataSource.getIDatasource.poisByBuildingFloorAsJson(buid, floor_number) + val pois = pds.getIDatasource.poisByBuildingFloorAsJson(buid, floor_number) val res: JsValue = Json.obj(SCHEMA.cPOIS -> pois) try { gzippedJSONOk(res.toString) @@ -2098,18 +1937,16 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::poisByBuid(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (String(json, SCHEMA.fBuid) == null) - return AnyResponseHelper.bad_request("Buid field must be String!") + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] try { - val stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + val stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") - val pois = ProxyDataSource.getIDatasource.poisByBuildingAsJson(buid) - val res: JsValue = Json.obj(SCHEMA.cPOIS -> pois.toList) + val pois = pds.getIDatasource.poisByBuildingAsJson(buid) + val res: JsValue = Json.obj(SCHEMA.cPOIS -> pois.asScala) try { gzippedJSONOk(res.toString) } catch { @@ -2134,9 +1971,9 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { LPLogger.D2("searchPois") // ALWAYS: a D2 on the endpoint method with method name val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody) + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.debug("json = " + json) var cuid = request.getQueryString(SCHEMA.fConCuid).orNull if (cuid == null) cuid = (json \ SCHEMA.fConCuid).as[String] @@ -2145,16 +1982,15 @@ object AnyplaceMapping extends play.api.mvc.Controller { var buid = request.getQueryString(SCHEMA.fBuid).orNull if (buid == null) buid = (json \ SCHEMA.fBuid).as[String] var greeklish = request.getQueryString(SCHEMA.fGreeklish).orNull - LPLogger.debug("greeklish = " + greeklish) if (greeklish == null) greeklish = (json \ SCHEMA.fGreeklish).as[String] try { var result: List[JsValue] = null if (cuid.compareTo("") == 0) - result = ProxyDataSource.getIDatasource.poisByBuildingAsJson3(buid, letters) + result = pds.getIDatasource.poisByBuildingAsJson3(buid, letters) else if (greeklish.compareTo("true") == 0) - result = ProxyDataSource.getIDatasource.poisByBuildingAsJson2GR(cuid, letters) + result = pds.getIDatasource.poisByBuildingAsJson2GR(cuid, letters) else - result = ProxyDataSource.getIDatasource.poisByBuildingAsJson2(cuid, letters) + result = pds.getIDatasource.poisByBuildingAsJson2(cuid, letters) val res: JsValue = Json.obj(SCHEMA.cPOIS -> result) try gzippedJSONOk(res.toString) @@ -2181,9 +2017,9 @@ object AnyplaceMapping extends play.api.mvc.Controller { implicit request => def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody) + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::poisByBuidincConnectors(): " + stripJson(json)) val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid) if (!requiredMissing.isEmpty) @@ -2192,7 +2028,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { return AnyResponseHelper.bad_request("buid field must be String!") val buid = (json \ SCHEMA.fBuid).as[String] try { - val pois = ProxyDataSource.getIDatasource.poisByBuildingIDAsJson(buid) + val pois = pds.getIDatasource.poisByBuildingIDAsJson(buid) val res: JsValue = Json.obj(SCHEMA.cPOIS -> pois) try gzippedJSONOk(res.toString) @@ -2214,39 +2050,27 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::connectionAdd(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fIsPublished, SCHEMA.fPoisA, SCHEMA.fFloorA, + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fIsPublished, SCHEMA.fPoisA, SCHEMA.fFloorA, SCHEMA.fBuidA, SCHEMA.fPoisB, SCHEMA.fFloorB, SCHEMA.fBuidB, SCHEMA.fBuid, SCHEMA.fEdgeType, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + if (checkRequirements != null) return checkRequirements + var owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) - if (String(json, SCHEMA.fBuid) == null) - return AnyResponseHelper.bad_request("buid field must be String!") val buid = (json \ SCHEMA.fBuid).as[String] - if (String(json, SCHEMA.fBuidA) == null) - return AnyResponseHelper.bad_request("buid_a field must be String!") val buid1 = (json \ SCHEMA.fBuidA).as[String] - if (String(json, SCHEMA.fBuidB) == null) - return AnyResponseHelper.bad_request("buid_b field must be String!") val buid2 = (json \ SCHEMA.fBuidB).as[String] - if (StringNumber(json, SCHEMA.fFloorA) == null) - return AnyResponseHelper.bad_request("floor_a field must be String, containing a number!") - if (StringNumber(json, SCHEMA.fFloorB) == null) - return AnyResponseHelper.bad_request("floor_b field must be String, containing a number!") try { - var stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid1) + var stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid1) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (!isBuildingOwner(stored_building, owner_id) && !isBuildingCoOwner(stored_building, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") - stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid2) + stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid2) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (!isBuildingOwner(stored_building, owner_id) && !isBuildingCoOwner(stored_building, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") - stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) @@ -2259,9 +2083,9 @@ object AnyplaceMapping extends play.api.mvc.Controller { val pois_a = (json \ SCHEMA.fPoisA).as[String] val pois_b = (json \ SCHEMA.fPoisB).as[String] - if (!ProxyDataSource.getIDatasource().poiByBuidFloorPuid(buid1, (json \ SCHEMA.fFloorA).as[String], (json \ SCHEMA.fPoisA).as[String])) + if (!pds.getIDatasource.poiByBuidFloorPuid(buid1, (json \ SCHEMA.fFloorA).as[String], (json \ SCHEMA.fPoisA).as[String])) return AnyResponseHelper.bad_request("pois_a does not exist or could not be retrieved!") - if (!ProxyDataSource.getIDatasource().poiByBuidFloorPuid(buid2, (json \ SCHEMA.fFloorB).as[String], (json \ SCHEMA.fPoisB).as[String])) + if (!pds.getIDatasource.poiByBuidFloorPuid(buid2, (json \ SCHEMA.fFloorB).as[String], (json \ SCHEMA.fPoisB).as[String])) return AnyResponseHelper.bad_request("pois_b does not exist or could not be retrieved!") try { val weight = calculateWeightOfConnection(pois_a, pois_b) @@ -2269,9 +2093,9 @@ object AnyplaceMapping extends play.api.mvc.Controller { if (edge_type == Connection.EDGE_TYPE_ELEVATOR || edge_type == Connection.EDGE_TYPE_STAIR) { } val conn = new Connection(json) - if (!ProxyDataSource.getIDatasource.addJsonDocument(SCHEMA.cEdges, conn.toValidMongoJson().toString)) + if (!pds.getIDatasource.addJsonDocument(SCHEMA.cEdges, conn.toValidMongoJson().toString)) return AnyResponseHelper.bad_request("Connection already exists or could not be added!") - val res: JsValue = Json.obj(SCHEMA.fConCuid -> conn.getId) + val res: JsValue = Json.obj(SCHEMA.fConCuid -> conn.getId()) return AnyResponseHelper.ok(res, "Successfully added new connection!") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) @@ -2294,25 +2118,24 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::connectionUpdate(): " + stripJson(json)) val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fPoisA, SCHEMA.fPoisB, SCHEMA.fBuidA, SCHEMA.fBuidB, SCHEMA.fAccessToken) if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + var owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) val buid1 = (json \ SCHEMA.fBuidA).as[String] val buid2 = (json \ SCHEMA.fBuidB).as[String] try { - var stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid1) + var stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid1) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (!isBuildingOwner(stored_building, owner_id) && !isBuildingCoOwner(stored_building, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") - stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid2) + stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid2) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") if (!isBuildingOwner(stored_building, owner_id) && !isBuildingCoOwner(stored_building, owner_id)) @@ -2324,7 +2147,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { val pois_a = (json \ SCHEMA.fPoisA).as[String] val pois_b = (json \ SCHEMA.fPoisB).as[String] val cuid = Connection.getId(pois_a, pois_b) - var stored_conn = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cEdges, SCHEMA.fConCuid, cuid) + var stored_conn = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cEdges, SCHEMA.fConCuid, cuid) if (stored_conn == null) return AnyResponseHelper.bad_request("Connection does not exist or could not be retrieved!") if (json.\(SCHEMA.fIsPublished).getOrElse(null) != null) { @@ -2341,7 +2164,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { stored_conn = stored_conn.as[JsObject] + (SCHEMA.fEdgeType -> JsString(edge_type)) } val conn = new Connection(stored_conn) - if (!ProxyDataSource.getIDatasource.replaceJsonDocument(SCHEMA.cEdges, SCHEMA.fConCuid, conn.getId, conn.toValidMongoJson().toString)) + if (!pds.getIDatasource.replaceJsonDocument(SCHEMA.cEdges, SCHEMA.fConCuid, conn.getId(), conn.toValidMongoJson().toString)) return AnyResponseHelper.bad_request("Connection could not be updated!") return AnyResponseHelper.ok("Successfully updated connection!") } catch { @@ -2358,49 +2181,39 @@ object AnyplaceMapping extends play.api.mvc.Controller { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::poiDelete(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fPoisA, SCHEMA.fPoisB, SCHEMA.fBuidA, SCHEMA.fBuidB, + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fPoisA, SCHEMA.fPoisB, SCHEMA.fBuidA, SCHEMA.fBuidB, SCHEMA.fAccessToken) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") - var owner_id = verifyId((json \ SCHEMA.fAccessToken).as[String]) + if (checkRequirements != null) return checkRequirements + val owner_id = user.authorize(json) if (owner_id == null) return AnyResponseHelper.forbidden("Unauthorized") - owner_id = appendGoogleIdIfNeeded(owner_id) json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(owner_id)) - if (String(json, SCHEMA.fBuidA) == null) - return AnyResponseHelper.bad_request("buid_a field must be String!") val buid1 = (json \ SCHEMA.fBuidA).as[String] - if (String(json, SCHEMA.fBuidB) == null) - return AnyResponseHelper.bad_request("buid_b field must be String!") val buid2 = (json \ SCHEMA.fBuidB).as[String] try { - var stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid1) + var stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid1) if (stored_building == null) return AnyResponseHelper.bad_request("Building_a does not exist or could not be retrieved!") if (!isBuildingOwner(stored_building, owner_id) && !isBuildingCoOwner(stored_building, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") - stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid2) + stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid2) if (stored_building == null) return AnyResponseHelper.bad_request("Building_b does not exist or could not be retrieved!") if (!isBuildingOwner(stored_building, owner_id) && !isBuildingCoOwner(stored_building, owner_id)) return AnyResponseHelper.unauthorized("Unauthorized") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) } - if (String(json, SCHEMA.fPoisA) == null) - return AnyResponseHelper.bad_request("pois_a field must be String!") val pois_a = (json \ SCHEMA.fPoisA).as[String] - if (String(json, SCHEMA.fPoisB) == null) - return AnyResponseHelper.bad_request("pois_b field must be String!") val pois_b = (json \ SCHEMA.fPoisB).as[String] try { val cuid = Connection.getId(pois_a, pois_b) - val all_items_failed = ProxyDataSource.getIDatasource.deleteAllByConnection(cuid) + val all_items_failed = pds.getIDatasource.deleteAllByConnection(cuid) if (all_items_failed == null) { LPLogger.info("AnyplaceMapping::connectionDelete(): " + cuid + " not found.") return AnyResponseHelper.bad_request("POI Connection not found") } if (all_items_failed.size > 0) { - val obj: JsValue = Json.obj("ids" -> all_items_failed.toList) + val obj: JsValue = Json.obj("ids" -> all_items_failed.asScala) return AnyResponseHelper.bad_request(obj, "Some items related to the deleted connection could not be deleted: " + all_items_failed.size + " items.") } @@ -2418,27 +2231,23 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::poisByFloor(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloorNumber) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (String(json, SCHEMA.fBuid) == null) - return AnyResponseHelper.bad_request("buid field must be String!") + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloorNumber) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] - if (StringNumber(json, SCHEMA.fFloorNumber) == null) - return AnyResponseHelper.bad_request("Floor_number field must be String, containing a number!") val floor_number = (json \ SCHEMA.fFloorNumber).as[String] try { - val stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + val stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") - val stored_floors = ProxyDataSource.getIDatasource.floorsByBuildingAsJson(buid) + val stored_floors = pds.getIDatasource.floorsByBuildingAsJson(buid) var floorExists = false - for (floor <- stored_floors) + for (floor <- stored_floors.asScala) if ((floor \ SCHEMA.fFloorNumber).as[String] == floor_number) floorExists = true if (!floorExists) return AnyResponseHelper.bad_request("Floor does not exist or could not be retrieved!") - val pois = ProxyDataSource.getIDatasource.connectionsByBuildingFloorAsJson(buid, floor_number) + val pois = pds.getIDatasource.connectionsByBuildingFloorAsJson(buid, floor_number) val res: JsValue = Json.obj("connections" -> pois) try { gzippedJSONOk(res.toString) @@ -2456,7 +2265,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { import java.io.IOException - import datasources.{DatasourceException, ProxyDataSource} + import datasources.{DatasourceException} import oauth.provider.v2.models.OAuth2Request import utils.{AnyResponseHelper, JsonUtils, LPLogger} @@ -2470,20 +2279,17 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody) + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::connectionsByallFloors(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid) - if (!requiredMissing.isEmpty) - return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (String(json, SCHEMA.fBuid) == null) - return AnyResponseHelper.bad_request("buid field must be String!") + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] try { - val stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) + val stored_building = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid) if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") - val pois = ProxyDataSource.getIDatasource.connectionsByBuildingAllFloorsAsJson(buid) + val pois = pds.getIDatasource.connectionsByBuildingAllFloorsAsJson(buid) val res: JsValue = Json.obj("connections" -> pois) try gzippedJSONOk(res.toString) @@ -2506,7 +2312,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { var lat_b = 0.0 var lon_b = 0.0 val nf = NumberFormat.getInstance(Locale.ENGLISH) - val pa = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cPOIS, SCHEMA.fPuid, pois_a) + val pa = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cPOIS, SCHEMA.fPuid, pois_a) if (pa == null) { lat_a = 0.0 lon_a = 0.0 @@ -2516,7 +2322,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { } catch { case e: ParseException => e.printStackTrace() } - val pb = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cPOIS, SCHEMA.fPuid, pois_b) + val pb = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cPOIS, SCHEMA.fPuid, pois_b) if (pb == null) { lat_b = 0.0 lon_b = 0.0 @@ -2535,9 +2341,9 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::serveFloorPlan(): " + stripJson(json)) - val filePath = AnyPlaceTilerHelper.getFloorPlanFor(buid, floor_number) + val filePath = tilerHelper.getFloorPlanFor(buid, floor_number) LPLogger.info("requested: " + filePath) try { val file = new File(filePath) @@ -2560,10 +2366,10 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::serveFloorPlanTilesZip(): " + stripJson(json)) if (!Floor.checkFloorNumberFormat(floor_number)) return AnyResponseHelper.bad_request("Floor number cannot contain whitespace!") - val filePath = AnyPlaceTilerHelper.getFloorTilesZipFor(buid, floor_number) + val filePath = tilerHelper.getFloorTilesZipFor(buid, floor_number) LPLogger.info("requested: " + filePath) try { val file = new File(filePath) @@ -2585,16 +2391,16 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::serveFloorPlanTilesZipLink(): " + stripJson(json)) if (!Floor.checkFloorNumberFormat(floor_number)) return AnyResponseHelper.bad_request("Floor number cannot contain whitespace!") - val filePath = AnyPlaceTilerHelper.getFloorTilesZipFor(buid, floor_number) + val filePath = tilerHelper.getFloorTilesZipFor(buid, floor_number) LPLogger.info("requested: " + filePath) val file = new File(filePath) if (!file.exists()) return AnyResponseHelper.bad_request("Requested floor plan does not exist"); if (!file.canRead()) return AnyResponseHelper.bad_request("Requested floor plan cannot be read: " + floor_number) - val res: JsValue = Json.obj("tiles_archive" -> AnyPlaceTilerHelper.getFloorTilesZipLinkFor(buid, floor_number)) + val res: JsValue = Json.obj("tiles_archive" -> tilerHelper.getFloorTilesZipLinkFor(buid, floor_number)) return AnyResponseHelper.ok(res, "Successfully fetched link for the tiles archive!") } @@ -2608,8 +2414,8 @@ object AnyplaceMapping extends play.api.mvc.Controller { buid.trim().isEmpty || floor_number.trim().isEmpty) NotFound(

Page not found

) var filePath: String = null - filePath = if (path == AnyPlaceTilerHelper.FLOOR_TILES_ZIP_NAME) AnyPlaceTilerHelper.getFloorTilesZipFor(buid, - floor_number) else AnyPlaceTilerHelper.getFloorTilesDirFor(buid, floor_number) + + filePath = if (path == tilerHelper.FLOOR_TILES_ZIP_NAME) tilerHelper.getFloorTilesZipFor(buid, + floor_number) else tilerHelper.getFloorTilesDirFor(buid, floor_number) + path try { val file = new File(filePath) @@ -2630,9 +2436,9 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::serveFloorPlanBase64(): " + stripJson(json)) - val filePath = AnyPlaceTilerHelper.getFloorPlanFor(buid, floor_number) + val filePath = tilerHelper.getFloorPlanFor(buid, floor_number) LPLogger.info("requested: " + filePath) val file = new File(filePath) try { @@ -2673,9 +2479,9 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody) + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::serveFloorPlanBase64all(): " + stripJson(json) + " " + floor_number) val floors = floor_number.split(" ") val all_floors = new util.ArrayList[String] @@ -2683,7 +2489,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { while ( { z < floors.length }) { - val filePath = AnyPlaceTilerHelper.getFloorPlanFor(buid, floors(z)) + val filePath = tilerHelper.getFloorPlanFor(buid, floors(z)) LPLogger.info("requested: " + filePath) val file = new File(filePath) try @@ -2707,7 +2513,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { z - 1 } } - val res: JsValue = Json.obj("all_floors" -> all_floors.toList) + val res: JsValue = Json.obj("all_floors" -> all_floors.asScala) try gzippedJSONOk(res.toString) catch { @@ -2780,27 +2586,27 @@ object AnyplaceMapping extends play.api.mvc.Controller { val top_right_lng = (json \ SCHEMA.fLonTopRight).as[String] val fuid = Floor.getId(buid, floor_number) try { - var stored_floor = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cFloorplans, SCHEMA.fFuid, fuid) + var stored_floor = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cFloorplans, SCHEMA.fFuid, fuid) if (stored_floor == null) return AnyResponseHelper.bad_request("Floor does not exist or could not be retrieved!") stored_floor = stored_floor.as[JsObject] + (SCHEMA.fLatBottomLeft -> JsString(bottom_left_lat)) stored_floor = stored_floor.as[JsObject] + (SCHEMA.fLonBottomLeft -> JsString(bottom_left_lng)) stored_floor = stored_floor.as[JsObject] + (SCHEMA.fLatTopRight -> JsString(top_right_lat)) stored_floor = stored_floor.as[JsObject] + (SCHEMA.fLonTopRight -> JsString(top_right_lng)) - if (!ProxyDataSource.getIDatasource.replaceJsonDocument(SCHEMA.cFloorplans, SCHEMA.fFuid, fuid, stored_floor.toString)) + if (!pds.getIDatasource.replaceJsonDocument(SCHEMA.cFloorplans, SCHEMA.fFuid, fuid, stored_floor.toString)) return AnyResponseHelper.bad_request("Floor plan could not be updated in the database!") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("Error while reading from our backend service!") } var floor_file: File = null try { - floor_file = AnyPlaceTilerHelper.storeFloorPlanToServer(buid, floor_number, floorplan.ref.file) + floor_file = tilerHelper.storeFloorPlanToServer(buid, floor_number, floorplan.ref.file) } catch { case e: AnyPlaceException => return AnyResponseHelper.bad_request("Cannot save floor plan on the server!") } val top_left_lat = top_right_lat val top_left_lng = bottom_left_lng try { - AnyPlaceTilerHelper.tileImage(floor_file, top_left_lat, top_left_lng) + tilerHelper.tileImage(floor_file, top_left_lat, top_left_lng) } catch { case e: AnyPlaceException => return AnyResponseHelper.bad_request("Could not create floor plan tiles on the server!") } @@ -2830,19 +2636,16 @@ object AnyplaceMapping extends play.api.mvc.Controller { } catch { case e: IOException => return AnyResponseHelper.bad_request("Cannot parse json in the request!") } - LPLogger.info("Floorplan Request[json]: " + json.toString) - LPLogger.info("Floorplan Request[floorplan]: " + floorplan.filename) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, SCHEMA.fFloorNumber, SCHEMA.fLatBottomLeft, + //LPLogger.info("Floorplan Request[json]: " + json.toString) + //LPLogger.info("Floorplan Request[floorplan]: " + floorplan.filename) + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloorNumber, SCHEMA.fLatBottomLeft, SCHEMA.fLonBottomLeft, SCHEMA.fLatTopRight, SCHEMA.fLonTopRight, SCHEMA.fZoom) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - if (String(json, SCHEMA.fBuid) == null) - return AnyResponseHelper.bad_request("buid field must be String!") + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] val zoom = (json \ SCHEMA.fZoom).as[String] val zoom_number = zoom.toInt if (zoom_number < 20) return AnyResponseHelper.bad_request("You have provided zoom level " + zoom + ". You have to zoom at least to level 20 to upload the floorplan.") - val floor_number = (json \ SCHEMA.fFloorNumber).as[String] val bottom_left_lat = (json \ SCHEMA.fLatBottomLeft).as[String] val bottom_left_lng = (json \ SCHEMA.fLonBottomLeft).as[String] @@ -2850,14 +2653,14 @@ object AnyplaceMapping extends play.api.mvc.Controller { val top_right_lng = (json \ SCHEMA.fLonTopRight).as[String] val fuid = Floor.getId(buid, floor_number) try { - var stored_floor = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cFloorplans, SCHEMA.fFuid, fuid) + var stored_floor = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cFloorplans, SCHEMA.fFuid, fuid) if (stored_floor == null) return AnyResponseHelper.bad_request("Floor does not exist or could not be retrieved!") stored_floor = stored_floor.as[JsObject] + (SCHEMA.fZoom -> JsString(zoom)) stored_floor = stored_floor.as[JsObject] + (SCHEMA.fLatBottomLeft -> JsString(bottom_left_lat)) stored_floor = stored_floor.as[JsObject] + (SCHEMA.fLonBottomLeft -> JsString(bottom_left_lng)) stored_floor = stored_floor.as[JsObject] + (SCHEMA.fLatTopRight -> JsString(top_right_lat)) stored_floor = stored_floor.as[JsObject] + (SCHEMA.fLonTopRight -> JsString(top_right_lng)) - if (!ProxyDataSource.getIDatasource.replaceJsonDocument(SCHEMA.cFloorplans, SCHEMA.fFuid, fuid, stored_floor.toString)) { + if (!pds.getIDatasource.replaceJsonDocument(SCHEMA.cFloorplans, SCHEMA.fFuid, fuid, stored_floor.toString)) { return AnyResponseHelper.bad_request("Floor plan could not be updated in the database!") } } catch { @@ -2865,14 +2668,14 @@ object AnyplaceMapping extends play.api.mvc.Controller { } var floor_file: File = null try { - floor_file = AnyPlaceTilerHelper.storeFloorPlanToServer(buid, floor_number, floorplan.ref.file) + floor_file = tilerHelper.storeFloorPlanToServer(buid, floor_number, floorplan.ref.path.toFile) } catch { case e: AnyPlaceException => return AnyResponseHelper.bad_request("Cannot save floor plan on the server!") } val top_left_lat = top_right_lat val top_left_lng = bottom_left_lng try { - AnyPlaceTilerHelper.tileImageWithZoom(floor_file, top_left_lat, top_left_lng, zoom) + tilerHelper.tileImageWithZoom(floor_file, top_left_lat, top_left_lng, zoom) } catch { case e: AnyPlaceException => return AnyResponseHelper.bad_request("Could not create floor plan tiles on the server!") } @@ -2894,28 +2697,28 @@ object AnyplaceMapping extends play.api.mvc.Controller { def isFirstUser(): Boolean = { - val mdb: MongoDatabase = MongodbDatasource.getMDB + val mdb: MongoDatabase = mongoDB.getMDB val collection = mdb.getCollection(SCHEMA.cUsers) val users = collection.find() - var awaited = Await.result(users.toFuture, Duration.Inf) + var awaited = Await.result(users.toFuture(), Duration.Inf) var res = awaited.toList return (res.size == 0) } def getUser(json: JsValue): JsValue = { - val mdb: MongoDatabase = MongodbDatasource.getMDB + val mdb: MongoDatabase = mongoDB.getMDB val collection = mdb.getCollection(SCHEMA.cUsers) var user: JsValue = null getAccountType(json) match { case ExternalType.GOOGLE => { - val mdb: MongoDatabase = MongodbDatasource.getMDB + val mdb: MongoDatabase = mongoDB.getMDB val collection = mdb.getCollection(SCHEMA.cUsers) val ownerId = (json \ SCHEMA.fOwnerId).as[String] val userLookUp = collection.find(equal(SCHEMA.fOwnerId, ownerId)) - val awaited = Await.result(userLookUp.toFuture, Duration.Inf) + val awaited = Await.result(userLookUp.toFuture(), Duration.Inf) val res = awaited.toList if (res.size == 1) { - user = convertJson(res.get(0)) + user = mongoDB.convertJson(res(0)) } else if (res.size > 1) { LPLogger.error("User exists. More than one user with id: " + ownerId) } @@ -2923,11 +2726,6 @@ object AnyplaceMapping extends play.api.mvc.Controller { } case ExternalType.LOCAL => LPLogger.debug("TODO: query unique email") } - // CLR:NN - // val users = collection.find() - // var awaited = Await.result(users.toFuture, Duration.Inf) - // var res = awaited.toList - // return (res.size == 0) return user } @@ -2940,28 +2738,22 @@ object AnyplaceMapping extends play.api.mvc.Controller { implicit request => def inner(request: Request[AnyContent]): Result = { LPLogger.D1("AddAccount") - val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody - - if (isNullOrEmpty(json)) { - return AnyResponseHelper.bad_request(AnyResponseHelper.WRONG_API_USAGE) - } else { - LPLogger.D1("OK") - } - - json = appendUserType(json) + val auth = new OAuth2Request(request) + if (!auth.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + var json = auth.getJsonBody() + if (isNullOrEmpty(json)) return AnyResponseHelper.bad_request(AnyResponseHelper.WRONG_API_USAGE) + json = appendUserType(json) //# TODO auth.appendUserType() // update json directly.. inside auth object.. + // auth.isGoogleUser() // and hide the below functionality.... val external = (json \ SCHEMA.fExternal) var result: Result = null if (external.toOption.isDefined) { - result = addGoogleAccount(json) + return addGoogleAccount(auth) // auth.addGoogleAccount() } else { - // addLocalAccount() // TODO LPLogger.error("TODO: Add Local Account") null } - // LPLogger.D2("Logged in user: " + (json \ SCHEMA.fOwnerId)) - return result + //val user: JsValue = Json.obj("user" -> result) + //return AnyResponseHelper.ok(user,"ok") } inner(request) @@ -2995,10 +2787,10 @@ object AnyplaceMapping extends play.api.mvc.Controller { // call appendUserType // ---------------------------- // requirePropertiesInJson: email, username, password - val mdb: MongoDatabase = MongodbDatasource.getMDB + val mdb: MongoDatabase = mongoDB.getMDB val collection = mdb.getCollection(SCHEMA.cUsers) val userLookUp = collection.find(equal("username", (json \ "username").as[String])) - val awaited = Await.result(userLookUp.toFuture, Duration.Inf) + val awaited = Await.result(userLookUp.toFuture(), Duration.Inf) val res = awaited.toList if (res.size != 0) { // TODO user must have unique username (query username in mongo) @@ -3006,33 +2798,32 @@ object AnyplaceMapping extends play.api.mvc.Controller { null } - def addGoogleAccount(obj: JsValue): Result = { - LPLogger.info("AnyplaceAccounts::addGoogleAccount()") - var json = obj - val notFound = JsonUtils.hasProperties(json, SCHEMA.fAccessToken, SCHEMA.fExternal) // TODO + def addGoogleAccount(auth: OAuth2Request): Result = { + LPLogger.info("addGoogleAccount") + var json = auth.getJsonBody() + val notFound = JsonUtils.hasProperties(json, SCHEMA.fExternal) // TODO if (!notFound.isEmpty) return AnyResponseHelper.requiredFieldsMissing(notFound) - if (json.\(SCHEMA.fAccessToken).getOrElse(null) == null) return AnyResponseHelper.forbidden("Unauthorized") + var id = verifyId((json \ SCHEMA.fAccessToken).as[String]) if (id == null) return AnyResponseHelper.forbidden("Unauthorized") id = appendGoogleIdIfNeeded(id) json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(id)) - LPLogger.D2("Logged in user: " + (json \ SCHEMA.fOwnerId)) - LPLogger.debug("type = " + (json \ SCHEMA.fType).as[String]) - val user = getUser(json) + + var user = getUser(json) + if (!(user \ SCHEMA.fAccessToken).toOption.isDefined && user != null) { // add access_token to db if !exists + user = user.as[JsObject] + (SCHEMA.fAccessToken -> JsString(MongodbDatasource.generateAccessToken(false))) + + (SCHEMA.fSchema -> JsNumber(MongodbDatasource.__SCHEMA)) + pds.getIDatasource.replaceJsonDocument(SCHEMA.cUsers, SCHEMA.fOwnerId, + (json \ SCHEMA.fOwnerId).as[String], user.toString()) + } + json = json.as[JsObject] + (SCHEMA.fOwnerId -> Json.toJson(id)) if (user != null) { - val jsonRes = Json.obj(SCHEMA.fType -> JsString((user \ SCHEMA.fType).as[String])) - LPLogger.D2("User already exists") // CLR:nn - AnyResponseHelper.ok(jsonRes, "User Exists.") // its not AnyResponseHelperok + user = user.as[JsObject] + (SCHEMA.fType -> JsString((user \ SCHEMA.fType).as[String])) + return AnyResponseHelper.ok(user, "User Exists.") // its not AnyResponseHelperok } else { - val jsonRes = Json.obj(SCHEMA.fType -> JsString((json \ SCHEMA.fType).as[String])) - val newAccount = new Account(json) - try { - ProxyDataSource.getIDatasource.addJsonDocument(SCHEMA.cUsers, newAccount.toString()) - LPLogger.D2("Added google user") // CLR:nn - AnyResponseHelper.ok(jsonRes, "Added google user.") - } catch { - case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) - } + val user = new Account(json) + pds.getIDatasource.addJsonDocument(SCHEMA.cUsers, user.toString()) + return AnyResponseHelper.ok(user.toJson(), "Added google user.") } } @@ -3078,13 +2869,13 @@ object AnyplaceMapping extends play.api.mvc.Controller { private def gzippedJSONOk(body: String): Result = { val gzipv = gzip(body) Ok(gzipv.toByteArray).withHeaders(("Content-Encoding", "gzip"), - ("Content-Length", gzipv.size + ""), + ("Content-Length", gzipv.size.toString), ("Content-Type", "application/json")) } private def gzippedOk(body: String): Result = { val gzipv = gzip(body) - Ok(gzipv.toByteArray).withHeaders(("Content-Encoding", "gzip"), ("Content-Length", gzipv.size + "")) + Ok(gzipv.toByteArray).withHeaders(("Content-Encoding", "gzip"), ("Content-Length", gzipv.size.toString)) } private def gzip(input: String) = { @@ -3103,79 +2894,81 @@ object AnyplaceMapping extends play.api.mvc.Controller { stringOutputStream } - def getAccesHeatmapByBuildingFloor() = Action { - implicit request => - - def inner(request: Request[AnyContent]): Result = { - val anyReq = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) { - LPLogger.info("getAccesHeatmapByBuildingFloor: assert json anyreq") - return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - } - val json = anyReq.getJsonBody - LPLogger.info("getAccesHeatmapByBuildingFloor(): " + stripJson(json)) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fFloor, SCHEMA.fBuid) - if (!requiredMissing.isEmpty) { - return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - } - val floor_number = (json \ SCHEMA.fFloor).as[String] - val buid = (json \ SCHEMA.fBuid).as[String] - val cut_k_features = (json \ "cut_k_features").asOpt[Int] - //Default 5 meter grid step - val h = (json \ "h").asOpt[Double].getOrElse(5.0) - - if (!Floor.checkFloorNumberFormat(floor_number)) { - return AnyResponseHelper.bad_request("Floor number cannot contain whitespace!") - } - try { - val rm = getRadioMapMeanByBuildingFloor(buid = buid, floor_number = floor_number) - if (rm.isEmpty) { - return AnyResponseHelper.bad_request("Area not supported yet!") - } else { - val (latlon_predict, crlbs) = getAccesMap(rm = rm.get, buid = buid, floor_number = floor_number, - cut_k_features = cut_k_features, h = h) - if (latlon_predict == null) { - - val crlb_filename = Play.application().configuration().getString("crlbsDir") + - File.separatorChar + buid + File.separatorChar + "fl_" + floor_number + ".txt" - val crlb_filename_lock = crlb_filename + ".lock" - - val lockInstant = - Files.getLastModifiedTime(Paths.get(crlb_filename_lock)).toInstant - val requestExpired = lockInstant. - plus(ACCES_RETRY_AMOUNT, ACCES_RETRY_UNIT) isBefore Instant.now - var msg = "" - if (requestExpired) { - // TODO if ACCES generation happens asynchronously we can skip the extra step - // This is just to show a warning message to the user. - val file_lock = new File(crlb_filename_lock) - file_lock.delete() - msg = "Generating ACCES has previously failed. Please retry." - } else { - msg = "Generating ACCES map in another background thread!" - } - - return AnyResponseHelper.bad_request(msg) - } - - val res = JsonObject.empty() - res.put("geojson", JsonObject.fromJson(latlon_predict.toGeoJSON().toString)) - res.put("crlb", JsonArray.from(new util.ArrayList[Double](crlbs.toArray.toList))) - return AnyResponseHelper.ok(res, "Successfully served ACCES map.") - } - } catch { - case e: FileNotFoundException => return AnyResponseHelper.internal_server_error( - "Cannot create radiomap:mapping:FNFE:" + e.getMessage) - case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) - case e: IOException => return AnyResponseHelper.internal_server_error( - "Cannot create radiomap:IOE:" + e.getMessage) - case e: Exception => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) - case _: Throwable => return AnyResponseHelper.internal_server_error("500: ") - } - } - - inner(request) - } + // CLR:NN + //@deprecated("Removing acces") + //def getAccesHeatmapByBuildingFloor() = Action { + // implicit request => + // + // def inner(request: Request[AnyContent]): Result = { + // val anyReq = new OAuth2Request(request) + // if (!anyReq.assertJsonBody()) { + // LPLogger.info("getAccesHeatmapByBuildingFloor: assert json anyreq") + // return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + // } + // val json = anyReq.getJsonBody() + // LPLogger.info("getAccesHeatmapByBuildingFloor(): " + stripJson(json)) + // val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fFloor, SCHEMA.fBuid) + // if (!requiredMissing.isEmpty) { + // return AnyResponseHelper.requiredFieldsMissing(requiredMissing) + // } + // val floor_number = (json \ SCHEMA.fFloor).as[String] + // val buid = (json \ SCHEMA.fBuid).as[String] + // val cut_k_features = (json \ "cut_k_features").asOpt[Int] + // //Default 5 meter grid step + // val h = (json \ "h").asOpt[Double].getOrElse(5.0) + // + // if (!Floor.checkFloorNumberFormat(floor_number)) { + // return AnyResponseHelper.bad_request("Floor number cannot contain whitespace!") + // } + // try { + // val rm = getRadioMapMeanByBuildingFloor(buid = buid, floor_number = floor_number) + // if (rm.isEmpty) { + // return AnyResponseHelper.bad_request("Area not supported yet!") + // } else { + // val (latlon_predict, crlbs) = getAccesMap(rm = rm.get, buid = buid, floor_number = floor_number, + // cut_k_features = cut_k_features, h = h) + // if (latlon_predict == null) { + // + // // TODO:PM : update application.conf + // val crlb_filename = Play.application().configuration().getString("crlbsDir") + + // File.separatorChar + buid + File.separatorChar + "fl_" + floor_number + ".txt" + // val crlb_filename_lock = crlb_filename + ".lock" + // val lockInstant = + // Files.getLastModifiedTime(Paths.get(crlb_filename_lock)).toInstant + // val requestExpired = lockInstant. + // plus(ACCES_RETRY_AMOUNT, ACCES_RETRY_UNIT) isBefore Instant.now + // var msg = "" + // if (requestExpired) { + // // TODO if ACCES generation happens asynchronously we can skip the extra step + // // This is just to show a warning message to the user. + // val file_lock = new File(crlb_filename_lock) + // file_lock.delete() + // msg = "Generating ACCES has previously failed. Please retry." + // } else { + // msg = "Generating ACCES map in another background thread!" + // } + // + // return AnyResponseHelper.bad_request(msg) + // } + // + // val res = JsonObject.empty() + // res.put("geojson", JsonObject.fromJson(latlon_predict.toGeoJSON().toString)) + // res.put("crlb", JsonArray.from(new util.ArrayList[Double](crlbs.toArray.asScala))) + // return AnyResponseHelper.ok(res, "Successfully served ACCES map.") + // } + // } catch { + // case e: FileNotFoundException => return AnyResponseHelper.internal_server_error( + // "Cannot create radiomap:mapping:FNFE:" + e.getMessage) + // case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) + // case e: IOException => return AnyResponseHelper.internal_server_error( + // "Cannot create radiomap:IOE:" + e.getMessage) + // case e: Exception => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) + // case _: Throwable => return AnyResponseHelper.internal_server_error("500: ") + // } + // } + // + // inner(request) + //} @deprecated("NotNeeded") def maintenance() = Action { @@ -3184,10 +2977,10 @@ object AnyplaceMapping extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - var json = anyReq.getJsonBody + var json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::deleteNotValidDocuments(): " + stripJson(json)) try { - if (!ProxyDataSource.getIDatasource.deleteNotValidDocuments()) return AnyResponseHelper.bad_request("None valid documents!") + if (!pds.getIDatasource.deleteNotValidDocuments()) return AnyResponseHelper.bad_request("None valid documents!") return AnyResponseHelper.ok("Success") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) @@ -3197,159 +2990,159 @@ object AnyplaceMapping extends play.api.mvc.Controller { inner(request) } - - private def getAccesMap(rm: RadioMapMean, - buid: String, floor_number: String, - cut_k_features: Option[Int], h: Double): (GeoJSONMultiPoint, DenseVector[Double]) = { - - // TODO this should be asynchronous. and display warning that it will take time - // Especially if it runs on radiomap upload - - val folder = new File( - Play.application().configuration().getString("crlbsDir") + - File.separatorChar + buid) - if (!folder.exists()) { - LPLogger.debug("getAccesMap: mkdir: " + folder.getCanonicalPath) - folder.mkdirs() - } - - // REVIEWLS use option for this - val crlb_filename = Play.application().configuration().getString("crlbsDir") + - File.separatorChar + buid + File.separatorChar + "fl_" + floor_number + ".txt" - - val crlb_filename_lock = crlb_filename + ".lock" - LPLogger.debug("getAccesMap:" + crlb_filename) - - val file_path = new File(crlb_filename) - val file_lock = new File(crlb_filename_lock) - - if (file_lock.exists()) { - val lockInstant = - Files.getLastModifiedTime(Paths.get(crlb_filename_lock)).toInstant - val requestExpired = lockInstant. - plus(ACCES_RETRY_AMOUNT, ACCES_RETRY_UNIT) isBefore Instant.now - if (requestExpired) { - // This is to give user some feedback too.. - LPLogger.info("getAccesMap: Previous request failed and expired." + - "Will retry on next request.\nFile: " + crlb_filename) - // lock will be deleted at the callsite of this method - } else { - LPLogger.debug("getAccesMap: Ignoring request. Another process is already building: " + crlb_filename) - } - - return (null, null) - } - - val hm = rm.getGroupLocationRSS_HashMap() - val keys = hm.keySet() - - val list_latlon = ListBuffer[GeoPoint]() - val list_rss = ListBuffer[DenseVector[Double]]() - - val m = rm.getMacAdressList().size() - for (key <- keys) { - val lrhm = hm.get(key) - for (loc: String <- lrhm.keySet()) { - val rss: util.List[String] = lrhm.get(loc) - val rss_vec = DenseVector.zeros[Double](m) - for (i <- 0 until rss.size()) { - rss_vec(i) = rss.get(i).toDouble - } - val slat_slon = loc.split(" ") - val point = new GeoPoint(lat = slat_slon(0), lon = slat_slon(1)) - list_latlon.append(point) - list_rss.append(rss_vec) - } - } - val n = rm.getOrderList().size() - val multipoint = new GeoJSONMultiPoint() - for (i <- 0 until n) { - multipoint.points.add(list_latlon(i)) - } - LPLogger.info("AnyplaceMapping::getAccesHeatmapByBuildingFloor(): fingerprints, APs: " - + n.toString + ", " + m.toString) - - //LPLogger.info("AnyplaceMapping::getAccesHeatmapByBuildingFloor(): multipoint: " + multipoint.toGeoJSON().toString) - - val floors: Array[JsonObject] = toCouchArray(ProxyDataSource.getIDatasource.floorsByBuildingAsJson(buid).iterator().toArray) - val floor = floors.filter((js: JsonObject) => js.getString(SCHEMA.fFloorNumber) == floor_number)(0) - val bl = new GeoPoint(lat = floor.getString(SCHEMA.fLatBottomLeft), lon = floor.getString(SCHEMA.fLonBottomLeft)) - val ur = new GeoPoint(lat = floor.getString(SCHEMA.fLatTopRight), lon = floor.getString(SCHEMA.fLonTopRight)) - val X = GeoUtils.latlng2xy(multipoint, bl = bl, ur = ur) - val Y = DenseMatrix.zeros[Double](n, m) - for (i <- 0 until n) { - Y(i, ::) := list_rss.get(i).t - } - - val X_min = GeoUtils.latlng2xy(point = bl, bl = bl, ur = ur) - val X_max = GeoUtils.latlng2xy(point = ur, bl = bl, ur = ur) - val Y_min = -110.0 * DenseVector.ones[Double](m) - val Y_max = 0.0 * DenseVector.ones[Double](m) - val acces = new AccesRBF( - X = X, Y = Y, - X_min = Option(X_min), X_max = Option(X_max), - Y_min = Option(Y_min), Y_max = Option(Y_max), - normalize_x = false, - normalize_y = true, - drop_redundant_features = true, - cut_k_features = cut_k_features - ) - - - // CLRLS - // if (!Files.exists(Paths.get(file_path))) { - // acces.fit_gpr(estimate = true, use_default_params = false) - // } - // LPLogger.debug("fit_gpr: starting") - // acces.fit_gpr(estimate = true, use_default_params = false) - // LPLogger.debug("fit_gpr: finished") - - //X_min and X_max are bl and ur in XY coordinates - val X_predict = GeoUtils.grid_2D(bl = X_min, ur = X_max, h = h) - - if (file_path.exists()) { - val crl = Source.fromFile(file_path).getLines.toArray - val crlbs = DenseVector.zeros[Double](crl.length) - - // CLRLS - // acces.fit_gpr(estimate = true, use_default_params = false) - // LPLogger.debug("crl",crl.length); - - for (k <- 0 until crlbs.length) { - crlbs(k) = crl(k).toDouble - } - val latlon_predict = GeoUtils.dm2GeoJSONMultiPoint( - GeoUtils.xy2latlng(xy = X_predict, bl = bl, ur = ur)) - - return (latlon_predict, crlbs) - } else { - file_lock.createNewFile(); - // TODO this should happen in the background. - LPLogger.info("Generating ACCES: " + crlb_filename) - acces.fit_gpr(estimate = true, use_default_params = false) - - val crlbs = acces.get_CRLB(X = X_predict, pinv_cond = 1e-6) - - LPLogger.debug("length:" + crlbs.length) - val acces_file = new PrintWriter(file_path) - for (i <- 0 until crlbs.length) { - acces_file.println(crlbs(i)) - } - acces_file.close() - file_lock.delete() - - LPLogger.debug("Generated ACCES:" + crlb_filename) - val latlon_predict = GeoUtils.dm2GeoJSONMultiPoint( - GeoUtils.xy2latlng(xy = X_predict, bl = bl, ur = ur)) - - return (latlon_predict, crlbs) - } - } + // CLR:NN + //private def getAccesMap(rm: RadioMapMean, + // buid: String, floor_number: String, + // cut_k_features: Option[Int], h: Double): (GeoJSONMultiPoint, DenseVector[Double]) = { + // + // // TODO this should be asynchronous. and display warning that it will take time + // // Especially if it runs on radiomap upload + // + // val folder = new File( + // Play.application().configuration().getString("crlbsDir") + + // File.separatorChar + buid) + // if (!folder.exists()) { + // LPLogger.debug("getAccesMap: mkdir: " + folder.getCanonicalPath) + // folder.mkdirs() + // } + // + // // REVIEWLS use option for this + // val crlb_filename = Play.application().configuration().getString("crlbsDir") + + // File.separatorChar + buid + File.separatorChar + "fl_" + floor_number + ".txt" + // + // val crlb_filename_lock = crlb_filename + ".lock" + // LPLogger.debug("getAccesMap:" + crlb_filename) + // + // val file_path = new File(crlb_filename) + // val file_lock = new File(crlb_filename_lock) + // + // if (file_lock.exists()) { + // val lockInstant = + // Files.getLastModifiedTime(Paths.get(crlb_filename_lock)).toInstant + // val requestExpired = lockInstant. + // plus(ACCES_RETRY_AMOUNT, ACCES_RETRY_UNIT) isBefore Instant.now + // if (requestExpired) { + // // This is to give user some feedback too.. + // LPLogger.info("getAccesMap: Previous request failed and expired." + + // "Will retry on next request.\nFile: " + crlb_filename) + // // lock will be deleted at the callsite of this method + // } else { + // LPLogger.debug("getAccesMap: Ignoring request. Another process is already building: " + crlb_filename) + // } + // + // return (null, null) + // } + // + // val hm = rm.getGroupLocationRSS_HashMap() + // val keys = hm.keySet() + // + // val list_latlon = ListBuffer[GeoPoint]() + // val list_rss = ListBuffer[DenseVector[Double]]() + // + // val m = rm.getMacAdressList().size() + // for (key <- keys) { + // val lrhm = hm.get(key) + // for (loc: String <- lrhm.keySet()) { + // val rss: util.List[String] = lrhm.get(loc) + // val rss_vec = DenseVector.zeros[Double](m) + // for (i <- 0 until rss.size()) { + // rss_vec(i) = rss.get(i).toDouble + // } + // val slat_slon = loc.split(" ") + // val point = new GeoPoint(lat = slat_slon(0), lon = slat_slon(1)) + // list_latlon.append(point) + // list_rss.append(rss_vec) + // } + // } + // val n = rm.getOrderList().size() + // val multipoint = new GeoJSONMultiPoint() + // for (i <- 0 until n) { + // multipoint.points.add(list_latlon(i)) + // } + // LPLogger.info("AnyplaceMapping::getAccesHeatmapByBuildingFloor(): fingerprints, APs: " + // + n.toString + ", " + m.toString) + // + // //LPLogger.info("AnyplaceMapping::getAccesHeatmapByBuildingFloor(): multipoint: " + multipoint.toGeoJSON().toString) + // + // val floors: Array[JsonObject] = toCouchArray(pds.getIDatasource.floorsByBuildingAsJson(buid).iterator().toArray) + // val floor = floors.filter((js: JsonObject) => js.getString(SCHEMA.fFloorNumber) == floor_number)(0) + // val bl = new GeoPoint(lat = floor.getString(SCHEMA.fLatBottomLeft), lon = floor.getString(SCHEMA.fLonBottomLeft)) + // val ur = new GeoPoint(lat = floor.getString(SCHEMA.fLatTopRight), lon = floor.getString(SCHEMA.fLonTopRight)) + // val X = GeoUtils.latlng2xy(multipoint, bl = bl, ur = ur) + // val Y = DenseMatrix.zeros[Double](n, m) + // for (i <- 0 until n) { + // Y(i, ::) := list_rss.get(i).t + // } + // + // val X_min = GeoUtils.latlng2xy(point = bl, bl = bl, ur = ur) + // val X_max = GeoUtils.latlng2xy(point = ur, bl = bl, ur = ur) + // val Y_min = -110.0 * DenseVector.ones[Double](m) + // val Y_max = 0.0 * DenseVector.ones[Double](m) + // val acces = new AccesRBF( + // X = X, Y = Y, + // X_min = Option(X_min), X_max = Option(X_max), + // Y_min = Option(Y_min), Y_max = Option(Y_max), + // normalize_x = false, + // normalize_y = true, + // drop_redundant_features = true, + // cut_k_features = cut_k_features + // ) + // + // + // // CLRLS + // // if (!Files.exists(Paths.get(file_path))) { + // // acces.fit_gpr(estimate = true, use_default_params = false) + // // } + // // LPLogger.debug("fit_gpr: starting") + // // acces.fit_gpr(estimate = true, use_default_params = false) + // // LPLogger.debug("fit_gpr: finished") + // + // //X_min and X_max are bl and ur in XY coordinates + // val X_predict = GeoUtils.grid_2D(bl = X_min, ur = X_max, h = h) + // + // if (file_path.exists()) { + // val crl = Source.fromFile(file_path).getLines.toArray + // val crlbs = DenseVector.zeros[Double](crl.length) + // + // // CLRLS + // // acces.fit_gpr(estimate = true, use_default_params = false) + // // LPLogger.debug("crl",crl.length); + // + // for (k <- 0 until crlbs.length) { + // crlbs(k) = crl(k).toDouble + // } + // val latlon_predict = GeoUtils.dm2GeoJSONMultiPoint( + // GeoUtils.xy2latlng(xy = X_predict, bl = bl, ur = ur)) + // + // return (latlon_predict, crlbs) + // } else { + // file_lock.createNewFile(); + // // TODO this should happen in the background. + // LPLogger.info("Generating ACCES: " + crlb_filename) + // acces.fit_gpr(estimate = true, use_default_params = false) + // + // val crlbs = acces.get_CRLB(X = X_predict, pinv_cond = 1e-6) + // + // LPLogger.debug("length:" + crlbs.length) + // val acces_file = new PrintWriter(file_path) + // for (i <- 0 until crlbs.length) { + // acces_file.println(crlbs(i)) + // } + // acces_file.close() + // file_lock.delete() + // + // LPLogger.debug("Generated ACCES:" + crlb_filename) + // val latlon_predict = GeoUtils.dm2GeoJSONMultiPoint( + // GeoUtils.xy2latlng(xy = X_predict, bl = bl, ur = ur)) + // + // return (latlon_predict, crlbs) + // } + //} private def getRadioMapMeanByBuildingFloor(buid: String, floor_number: String): Option[RadioMapMean] = { //FeatureAdd : Configuring location for server generated files - val radioMapsFrozenDir = Play.application().configuration().getString("radioMapFrozenDir") + val radioMapsFrozenDir = conf.get[String]("radioMapFrozenDir") val rmapDir = new File(radioMapsFrozenDir + File.separatorChar + buid + File.separatorChar + floor_number) val meanFile = new File(rmapDir.toString + File.separatorChar + "indoor-radiomap-mean.txt") if (rmapDir.exists() && meanFile.exists()) { @@ -3367,8 +3160,8 @@ object AnyplaceMapping extends play.api.mvc.Controller { var fout: FileOutputStream = null fout = new FileOutputStream(radio) LPLogger.debug(radio.toPath().getFileName.toString) - var floorFetched: Long = 0l - floorFetched = ProxyDataSource.getIDatasource.dumpRssLogEntriesByBuildingACCESFloor(fout, buid, floor_number) + var floorFetched: Long = 0L + floorFetched = pds.getIDatasource.dumpRssLogEntriesByBuildingACCESFloor(fout, buid, floor_number) try { fout.close() } catch { @@ -3394,7 +3187,6 @@ object AnyplaceMapping extends play.api.mvc.Controller { return Option[RadioMapMean](rm_mean) } - // private def getRadioMapMeanByBuildingFloor(buid: String, floor_number: String) : Option[RadioMapMean] = { // val rmapDir = new File("radiomaps_frozen" + File.separatorChar + buid + File.separatorChar + floor_number) // val meanFile = new File(rmapDir.toString + File.separatorChar + "indoor-radiomap-mean.txt") @@ -3421,7 +3213,7 @@ object AnyplaceMapping extends play.api.mvc.Controller { // LPLogger.debug(radio.toPath().getFileName.toString) // // var floorFetched: Long = 0l - // floorFetched = ProxyDataSource.getIDatasource.dumpRssLogEntriesByBuildingFloor(fout, buid, floor_number) + // floorFetched = pds.getIDatasource.dumpRssLogEntriesByBuildingFloor(fout, buid, floor_number) // try { // fout.close() // } catch { diff --git a/server/app/controllers/AnyplaceNavigation.scala b/server/app/controllers/AnyplaceNavigation.scala index 829fc3774..2ab4372f1 100644 --- a/server/app/controllers/AnyplaceNavigation.scala +++ b/server/app/controllers/AnyplaceNavigation.scala @@ -40,17 +40,19 @@ import java.util.{ArrayList, HashMap, List} import datasources.{DatasourceException, ProxyDataSource, SCHEMA} import db_models.NavResultPoint -import json.VALIDATE.{Coordinate, String, StringNumber} +import javax.inject.{Inject, Singleton} +import json.VALIDATE import oauth.provider.v2.models.OAuth2Request import play.api.libs.json.{JsObject, JsValue, Json} -import play.api.mvc.{Action, AnyContent, Request, Result} +import play.api.mvc._ import utils._ -//remove if not needed -import scala.collection.JavaConversions._ -object AnyplaceNavigation extends play.api.mvc.Controller { - val ROUTE_MAX_DISTANCE_ALLOWED = 5.0 +import scala.jdk.CollectionConverters.CollectionHasAsScala +//remove if not needed +// import scala.collection.JavaConversions._ +@Singleton +class AnyplaceNavigation @Inject()(cc: ControllerComponents, pds: ProxyDataSource) extends AbstractController(cc) { val ROUTE_MAX_DISTANCE_ALLOWED = 5.0 def getBuildingById() = Action { implicit request => @@ -59,17 +61,13 @@ object AnyplaceNavigation extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceNavigation::getBuildingById():: " + json.toString) - val notFound = JsonUtils.hasProperties(json, SCHEMA.fBuid) - if (!notFound.isEmpty) { - return AnyResponseHelper.requiredFieldsMissing(notFound) - } - if (String(json, SCHEMA.fBuid) == null) - return AnyResponseHelper.bad_request("Buid field must be String!") + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid) + if (checkRequirements != null) return checkRequirements val buid = (json \ SCHEMA.fBuid).as[String] try { - val doc = ProxyDataSource.getIDatasource.buildingFromKeyAsJson(buid) + val doc = pds.getIDatasource.buildingFromKeyAsJson(buid) if (doc == null) { return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!") } @@ -89,17 +87,13 @@ object AnyplaceNavigation extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceNavigation::getPoisById():: " + json.toString) - val notFound = JsonUtils.hasProperties(json, SCHEMA.cPOIS) - if (!notFound.isEmpty) { - return AnyResponseHelper.requiredFieldsMissing(notFound) - } - if (String(json, SCHEMA.cPOIS) == null) - return AnyResponseHelper.bad_request("Puid field must be String!") + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.cPOIS) + if (checkRequirements != null) return checkRequirements val puid = (json \ SCHEMA.cPOIS).as[String] try { - var doc = ProxyDataSource.getIDatasource.poiFromKeyAsJson(SCHEMA.cPOIS, SCHEMA.fPuid, puid) + var doc = pds.getIDatasource.poiFromKeyAsJson(SCHEMA.cPOIS, SCHEMA.fPuid, puid) if (doc == null) { return AnyResponseHelper.bad_request("Document does not exist or could not be retrieved!") } @@ -120,27 +114,21 @@ object AnyplaceNavigation extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceNavigation::getNavigationRoute(): " + json.toString) - val requiredMissing = JsonUtils.hasProperties(json, "pois_from", "pois_to") - if (!requiredMissing.isEmpty) { - return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - } - if (String(json, "pois_from") == null) - return AnyResponseHelper.bad_request("pois_from field must be String!") + val checkRequirements = VALIDATE.checkRequirements(json, "pois_from", "pois_to") + if (checkRequirements != null) return checkRequirements val puid_from = (json \ "pois_from").as[String] - if (String(json, "pois_to") == null) - return AnyResponseHelper.bad_request("pois_to field must be String!") val puid_to = (json \ "pois_to").as[String] if (puid_from.equalsIgnoreCase(puid_to)) { return AnyResponseHelper.bad_request("Destination and Source is the same!") } try { - val poiFrom = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cPOIS, SCHEMA.fPuid, puid_from) + val poiFrom = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cPOIS, SCHEMA.fPuid, puid_from) if (poiFrom == null) { return AnyResponseHelper.bad_request("Source POI does not exist or could not be retrieved!") } - val poiTo = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cPOIS, SCHEMA.fPuid, puid_to) + val poiTo = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cPOIS, SCHEMA.fPuid, puid_to) if (poiTo == null) { return AnyResponseHelper.bad_request("Destination POI does not exist or could not be retrieved!") } @@ -158,7 +146,7 @@ object AnyplaceNavigation extends play.api.mvc.Controller { } else { return AnyResponseHelper.bad_request("Navigation between buildings not supported yet!") } - val res: JsValue = Json.obj("num_of_pois" -> points.size, SCHEMA.cPOIS -> points.toList) + val res: JsValue = Json.obj("num_of_pois" -> points.size, SCHEMA.cPOIS -> points.asScala) return AnyResponseHelper.ok(res, "Successfully plotted navigation.") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) @@ -173,26 +161,18 @@ object AnyplaceNavigation extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceNavigation::getNavigationRouteXY():: " + json.toString) - val notFound = JsonUtils.hasProperties(json, SCHEMA.fCoordinatesLat, SCHEMA.fCoordinatesLon, SCHEMA.fFloorNumber, + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fCoordinatesLat, SCHEMA.fCoordinatesLon, SCHEMA.fFloorNumber, "pois_to") - if (!notFound.isEmpty) return AnyResponseHelper.requiredFieldsMissing(notFound) - if (Coordinate(json, SCHEMA.fCoordinatesLat) == null) - return AnyResponseHelper.bad_request("coordinates_lat field must be String containing a float!") + if (checkRequirements != null) return checkRequirements val coordinates_lat = (json \ SCHEMA.fCoordinatesLat).as[String] - if (Coordinate(json, SCHEMA.fCoordinatesLon) == null) - return AnyResponseHelper.bad_request("coordinates_lon field must be String containing a float!") val coordinates_lon = (json \ SCHEMA.fCoordinatesLon).as[String] - if (StringNumber(json, SCHEMA.fFloorNumber) == null) - return AnyResponseHelper.bad_request("Floor_number field must be String, containing a number!") val floor_number = (json \ SCHEMA.fFloorNumber).as[String] - if (String(json, "pois_to") == null) - return AnyResponseHelper.bad_request("pois_to field must be String!") val puid_to = (json \ "pois_to").as[String] var res: Result = null try { - val poiTo = ProxyDataSource.getIDatasource.getFromKeyAsJson(SCHEMA.cPOIS, SCHEMA.fPuid, puid_to) + val poiTo = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cPOIS, SCHEMA.fPuid, puid_to) if (poiTo == null) { return AnyResponseHelper.bad_request("Destination POI does not exist or could not be retrieved!") } @@ -200,7 +180,7 @@ object AnyplaceNavigation extends play.api.mvc.Controller { val floor_to = (poiTo \ SCHEMA.fFloorNumber).as[String] val dlat = java.lang.Double.parseDouble(coordinates_lat) val dlon = java.lang.Double.parseDouble(coordinates_lon) - val floorPois = ProxyDataSource.getIDatasource.poisByBuildingFloorAsJson(buid_to, floor_number) + val floorPois = pds.getIDatasource.poisByBuildingFloorAsJson(buid_to, floor_number) if (0 == floorPois.size) { return AnyResponseHelper.bad_request("Navigation is not supported on your floor!") } @@ -239,11 +219,11 @@ object AnyplaceNavigation extends play.api.mvc.Controller { LPLogger.error("Nav unsupported") return AnyResponseHelper.bad_request("Navigation between buildings not supported yet!") } - val json: JsValue = Json.obj("num_of_pois" -> points.size, SCHEMA.cPOIS -> points.toList) + val json: JsValue = Json.obj("num_of_pois" -> points.size, SCHEMA.cPOIS -> points.asScala) return AnyResponseHelper.ok(json, "Successfully plotted navigation.") } catch { //case e: DatasourceException => AnyResponseHelper.internal_server_error("500: " + e.getMessage) - case e: Exception => return AnyResponseHelper.internal_server_error(e.getClass + ": " + e.getMessage) + case e: Exception => return AnyResponseHelper.internal_server_error(e.getClass.toString + ": " + e.getMessage) } } @@ -251,19 +231,19 @@ object AnyplaceNavigation extends play.api.mvc.Controller { } private def navigateSameFloor(from: JsValue, to: JsValue): List[JsValue] = { - navigateSameFloor(from, to, ProxyDataSource.getIDatasource.poisByBuildingFloorAsMap((from \ SCHEMA.fBuid).as[String], + navigateSameFloor(from, to, pds.getIDatasource.poisByBuildingFloorAsMap((from \ SCHEMA.fBuid).as[String], (from \ SCHEMA.fFloorNumber).as[String])) } private def navigateSameFloor(from: JsValue, to: JsValue, floorPois: List[HashMap[String, String]]): List[JsValue] = { val graph = new Dijkstra.Graph() graph.addPois(floorPois) - graph.addEdges(ProxyDataSource.getIDatasource.connectionsByBuildingAsMap((from \ SCHEMA.fBuid).as[String])) + graph.addEdges(pds.getIDatasource.connectionsByBuildingAsMap((from \ SCHEMA.fBuid).as[String])) val routePois = Dijkstra.getShortestPath(graph, (from \ SCHEMA.fPuid).as[String], (to \ SCHEMA.fPuid).as[String]) val final_points = new ArrayList[JsValue]() var p: NavResultPoint = null - for (poi <- routePois) { + for (poi <- routePois.asScala) { p = new NavResultPoint() p.lat = poi.get(SCHEMA.fCoordinatesLat) p.lon = poi.get(SCHEMA.fCoordinatesLon) @@ -278,12 +258,12 @@ object AnyplaceNavigation extends play.api.mvc.Controller { private def navigateSameBuilding(from: JsValue, to: JsValue): List[JsValue] = { val graph = new Dijkstra.Graph() - graph.addPois(ProxyDataSource.getIDatasource.poisByBuildingAsMap((from \ SCHEMA.fBuid).as[String])) - graph.addEdges(ProxyDataSource.getIDatasource.connectionsByBuildingAsMap((from \ SCHEMA.fBuid).as[String])) + graph.addPois(pds.getIDatasource.poisByBuildingAsMap((from \ SCHEMA.fBuid).as[String])) + graph.addEdges(pds.getIDatasource.connectionsByBuildingAsMap((from \ SCHEMA.fBuid).as[String])) val routePois = Dijkstra.getShortestPath(graph, (from \ SCHEMA.fPuid).as[String], (to \ SCHEMA.fPuid).as[String]) val final_points = new ArrayList[JsValue]() var p: NavResultPoint = null - for (poi <- routePois) { + for (poi <- routePois.asScala) { p = new NavResultPoint() p.lat = poi.get(SCHEMA.fCoordinatesLat) p.lon = poi.get(SCHEMA.fCoordinatesLon) diff --git a/server/app/controllers/AnyplacePosition.scala b/server/app/controllers/AnyplacePosition.scala index f9847e5d5..2d8ecfcf6 100644 --- a/server/app/controllers/AnyplacePosition.scala +++ b/server/app/controllers/AnyplacePosition.scala @@ -40,32 +40,40 @@ import java.io._ import java.util.ArrayList import com.couchbase.client.java.document.json.{JsonArray, JsonObject} -import controllers.AnyplaceMapping.verifyId -import datasources.SCHEMA._ import datasources.{DatasourceException, ProxyDataSource, SCHEMA} -import db_models.RadioMapRaw.findRadioBbox import db_models.{Floor, MagneticMilestone, MagneticPath, RadioMapRaw} import floor_module.Algo1 +import javax.inject.{Inject, Singleton} import json.VALIDATE -import json.VALIDATE.{String, StringNumber} +import json.VALIDATE.StringNumber import oauth.provider.v2.models.OAuth2Request -import org.apache.commons.lang3.time.StopWatch -import play.Play +import play.api.Configuration import play.api.libs.json.{JsValue, Json} -import play.api.mvc.{Action, AnyContent, Request, Result} +import play.api.mvc._ import radiomapserver.RadioMap import radiomapserver.RadioMap.{RBF_ENABLED, RadioMap} -import utils.FileUtils._ import utils._ -import scala.collection.JavaConversions._ +import scala.jdk.CollectionConverters.CollectionHasAsScala +// import scala.collection.JavaConversions._ + + +@Singleton +class AnyplacePosition @Inject()(cc: ControllerComponents, + mapHelper: helper.Mapping, + api: AnyplaceServerAPI, + conf: Configuration, + fu: FileUtils, + proxyDataSource: ProxyDataSource, + user: helper.User) + extends AbstractController(cc) { + implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global -object AnyplacePosition extends play.api.mvc.Controller { - val BBOX_MAX = 500 /** - * Upload fingerprints to server and database. + * Upload fingerprints to server and database. + * * @return */ def radioUpload() = Action { @@ -73,12 +81,10 @@ object AnyplacePosition extends play.api.mvc.Controller { def inner(request: Request[AnyContent]): Result = { val anyReq = new OAuth2Request(request) val body = anyReq.getMultipartFormData() - if (body == null) { - return AnyResponseHelper.bad_request("Invalid request type - Not Multipart!") - } + if (body == null) {return AnyResponseHelper.bad_request("Invalid request type - Not Multipart!")} var rssLog: File = null try { - rssLog = body.file("radiomap").get.ref.file + rssLog = body.file("radiomap").get.ref.path.toFile } catch { case e: Exception => return AnyResponseHelper.bad_request("Cannot find radiomap (rss log)!") } @@ -90,19 +96,19 @@ object AnyplacePosition extends play.api.mvc.Controller { return AnyResponseHelper.bad_request("Cannot find access_token in the request!") } val access_token = body_form.get(SCHEMA.fAccessToken).get.head - if (verifyId(access_token) == null) return AnyResponseHelper.forbidden("Unauthorized") + if (user.authorize(Json.obj(SCHEMA.fAccessToken -> access_token)) == null) return AnyResponseHelper.forbidden("Unauthorized") var ret: String = "" val newBuildingsFloors = RadioMap.verifyRssLogAndGetBuildingFloors(rssLog) if (newBuildingsFloors == null) { return AnyResponseHelper.bad_request("Uploaded a corrupted rss-log file!") } else { - HelperMethods.storeRadioMapRawToServer(rssLog) + mapHelper.storeRadioMapRawToServer(rssLog) ret = storeFloorRssToDB(rssLog) LPLogger.debug("Rss values already exist: " + ret) val errors: ArrayList[JsValue] = new ArrayList[JsValue] - for (buid <- newBuildingsFloors.keySet) { - for (floor_num <- newBuildingsFloors.get(buid)) { - val res = updateFrozenRadioMap(buid, floor_num) + for (buid <- newBuildingsFloors.keySet.asScala) { + for (floor_num <- newBuildingsFloors.get(buid).asScala) { + val res = mapHelper.updateFrozenRadioMap(buid, floor_num) if (res != null) { val js = Json.obj(SCHEMA.fBuid -> buid, "floor_num" -> floor_num, "error" -> res) errors.add(js) @@ -110,7 +116,7 @@ object AnyplacePosition extends play.api.mvc.Controller { } } if (errors.size > 0) { - val json = Json.obj("errorList" -> errors.toList) + val json = Json.obj("errorList" -> errors.asScala) return AnyResponseHelper.bad_request(json, "Failed to create frozen radio maps.") } } @@ -134,14 +140,12 @@ object AnyplacePosition extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("radioDownloadFloor: " + json.toString) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fCoordinatesLat, SCHEMA.fCoordinatesLon, SCHEMA.fFloorNumber) - if (!requiredMissing.isEmpty) { - return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - } + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fCoordinatesLat, SCHEMA.fCoordinatesLon, SCHEMA.fFloorNumber) + if (checkRequirements != null) return checkRequirements // range is large enough to cover the entire floor - return findRadioBbox(json, BBOX_MAX) + return mapHelper.findRadioBbox(json, mapHelper.BBOX_MAX) } inner(request) @@ -154,19 +158,17 @@ object AnyplacePosition extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplacePosition::radioDownloadFloor(): " + json.toString) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fCoordinatesLat, SCHEMA.fCoordinatesLon, + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fCoordinatesLat, SCHEMA.fCoordinatesLon, SCHEMA.fFloorNumber, "range") - if (!requiredMissing.isEmpty) { - return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - } + if (checkRequirements != null) return checkRequirements if (StringNumber(json, "range") == null) { return AnyResponseHelper.bad_request("range field must be String, containing a number!") } var range = (json \ "range").as[String].toInt - if (range > BBOX_MAX) range = BBOX_MAX - return findRadioBbox(json, range) + if (range > mapHelper.BBOX_MAX) range = mapHelper.BBOX_MAX + return mapHelper.findRadioBbox(json, range) } inner(request) @@ -184,38 +186,32 @@ object AnyplacePosition extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("radioDownloadByBuildingFloor: " + json.toString) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fFloor, SCHEMA.fBuid) - if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - val validation = VALIDATE.fields(json, fFloor, fBuid) - if (validation.failed()) return validation.response() - + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fFloor, SCHEMA.fBuid) + if (checkRequirements != null) return checkRequirements val floor_number = (json \ SCHEMA.fFloor).as[String] val buid = (json \ SCHEMA.fBuid).as[String] - - if (!Floor.checkFloorNumberFormat(floor_number)) { return AnyResponseHelper.bad_request("Floor number cannot contain whitespace!") } - //FeatureAdd : Configuring location for server generated files - val rmapDir = getDirFrozenFloor(buid, floor_number) - val radiomapFile = getRadiomapFile(buid, floor_number) - val meanFile = getMeanFile(buid, floor_number) + val rmapDir = fu.getDirFrozenFloor(buid, floor_number) + val radiomapFile = fu.getRadiomapFile(buid, floor_number) + val meanFile = fu.getMeanFile(buid, floor_number) if (rmapDir.exists() && radiomapFile.exists() && meanFile.exists()) { try { - val radiomap_filename = getRadioMapFileName(buid, floor_number).getAbsolutePath + val radiomap_filename = fu.getRadioMapFileName(buid, floor_number).getAbsolutePath var radiomap_mean_filename = radiomap_filename.replace(".txt", "-mean.txt") var radiomap_rbf_weights_filename = radiomap_filename.replace(".txt", "-weights.txt") var radiomap_parameters_filename = radiomap_filename.replace(".txt", "-parameters.txt") - val api = AnyplaceServerAPI.SERVER_API_ROOT - var pos = getFilePos(radiomap_mean_filename) - radiomap_mean_filename = api + radiomap_mean_filename.substring(pos) - pos = getFilePos(radiomap_rbf_weights_filename) - radiomap_rbf_weights_filename = api + radiomap_rbf_weights_filename.substring(pos) - pos = getFilePos(radiomap_parameters_filename) - radiomap_parameters_filename = api + radiomap_parameters_filename.substring(pos) + val url: String = api.SERVER_API_ROOT + var pos = fu.getFilePos(radiomap_mean_filename) + radiomap_mean_filename = url + radiomap_mean_filename.substring(pos) + pos = fu.getFilePos(radiomap_rbf_weights_filename) + radiomap_rbf_weights_filename = url + radiomap_rbf_weights_filename.substring(pos) + pos = fu.getFilePos(radiomap_parameters_filename) + radiomap_parameters_filename = url + radiomap_parameters_filename.substring(pos) var res: JsValue = null if (RBF_ENABLED) { @@ -233,12 +229,12 @@ object AnyplacePosition extends play.api.mvc.Controller { if (!rmapDir.mkdirs()) { return AnyResponseHelper.internal_server_error("Error while creating Radio Map on-the-fly!") } - val radio = new File(rmapDir.getAbsolutePath + AnyplaceServerAPI.URL_SEP + "rss-log") + val radio = new File(rmapDir.getAbsolutePath + api.URL_SEP + "rss-log") var fout: FileOutputStream = null - var floorFetched: Long = 0l + var floorFetched: Long = 0L try { fout = new FileOutputStream(radio) - floorFetched = ProxyDataSource.getIDatasource.dumpRssLogEntriesByBuildingFloor(fout, buid, floor_number) + floorFetched = proxyDataSource.getIDatasource.dumpRssLogEntriesByBuildingFloor(fout, buid, floor_number) fout.close() if (floorFetched == 0) { @@ -246,7 +242,7 @@ object AnyplacePosition extends play.api.mvc.Controller { } val folder = rmapDir.toString - val radiomap_filename = new File(folder + AnyplaceServerAPI.URL_SEP + "indoor-radiomap.txt") + val radiomap_filename = new File(folder + api.URL_SEP + "indoor-radiomap.txt") .getAbsolutePath var radiomap_mean_filename = radiomap_filename.replace(".txt", "-mean.txt") var radiomap_rbf_weights_filename = radiomap_filename.replace(".txt", "-weights.txt") @@ -256,13 +252,13 @@ object AnyplacePosition extends play.api.mvc.Controller { if (resCreate != null) { return AnyResponseHelper.internal_server_error("radioDownloadByBuildingFloor: radiomap on-the-fly: " + resCreate) } - val api = AnyplaceServerAPI.SERVER_API_ROOT + val url = api.SERVER_API_ROOT var pos = radiomap_mean_filename.indexOf("radiomaps_frozen") - radiomap_mean_filename = api + radiomap_mean_filename.substring(pos) + radiomap_mean_filename = url + radiomap_mean_filename.substring(pos) pos = radiomap_rbf_weights_filename.indexOf("radiomaps_frozen") - radiomap_rbf_weights_filename = api + radiomap_rbf_weights_filename.substring(pos) + radiomap_rbf_weights_filename = url + radiomap_rbf_weights_filename.substring(pos) pos = radiomap_parameters_filename.indexOf("radiomaps_frozen") - radiomap_parameters_filename = api + radiomap_parameters_filename.substring(pos) + radiomap_parameters_filename = url + radiomap_parameters_filename.substring(pos) val res: JsValue = Json.obj("map_url_mean" -> radiomap_mean_filename, "map_url_weights" -> radiomap_rbf_weights_filename, "map_url_parameters" -> radiomap_parameters_filename) @@ -290,42 +286,35 @@ object AnyplacePosition extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("radioDownloadByBuildingFloorall: " + json.toString) - val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fFloor, SCHEMA.fBuid) - if (!requiredMissing.isEmpty) { - return AnyResponseHelper.requiredFieldsMissing(requiredMissing) - } - if (StringNumber(json, SCHEMA.fFloor) == null) - return AnyResponseHelper.bad_request("floor field must be String, containing a number!") + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fFloor, SCHEMA.fBuid) + if (checkRequirements != null) return checkRequirements val floor_number = (json \ SCHEMA.fFloor).as[String] - if (String(json, SCHEMA.fBuid) == null) - return AnyResponseHelper.bad_request("buid field must be String!") val buid = (json \ SCHEMA.fBuid).as[String] - val floors = floor_number.split(" ") val radiomap_mean_filename = new java.util.ArrayList[String]() val rss_log_files = new java.util.ArrayList[String]() for (floor_number <- floors) { //FeatureAdd : Configuring location for server generated files - val rmapDir = getDirFrozenFloor(buid, floor_number) - val radiomapFile = getRadiomapFile(buid, floor_number) - val meanFile = getMeanFile(buid, floor_number) + val rmapDir = fu.getDirFrozenFloor(buid, floor_number) + val radiomapFile = fu.getRadiomapFile(buid, floor_number) + val meanFile = fu.getMeanFile(buid, floor_number) if (rmapDir.exists() && radiomapFile.exists() && meanFile.exists()) { try { val folder = rmapDir.toString - val radiomap_filename = getRadioMapFileName(buid, floor_number).getAbsolutePath + val radiomap_filename = fu.getRadioMapFileName(buid, floor_number).getAbsolutePath var radiomap_mean_filename = radiomap_filename.replace(".txt", "-mean.txt") var radiomap_rbf_weights_filename = radiomap_filename.replace(".txt", "-weights.txt") var radiomap_parameters_filename = radiomap_filename.replace(".txt", "-parameters.txt") - val api = AnyplaceServerAPI.SERVER_API_ROOT - var pos = getFilePos(radiomap_mean_filename) - radiomap_mean_filename = api + radiomap_mean_filename.substring(pos) - pos = getFilePos(radiomap_rbf_weights_filename) - radiomap_rbf_weights_filename = api + radiomap_rbf_weights_filename.substring(pos) - pos = getFilePos(radiomap_parameters_filename) - radiomap_parameters_filename = api + radiomap_parameters_filename.substring(pos) + val url = api.SERVER_API_ROOT + var pos = fu.getFilePos(radiomap_mean_filename) + radiomap_mean_filename = url + radiomap_mean_filename.substring(pos) + pos = fu.getFilePos(radiomap_rbf_weights_filename) + radiomap_rbf_weights_filename = url + radiomap_rbf_weights_filename.substring(pos) + pos = fu.getFilePos(radiomap_parameters_filename) + radiomap_parameters_filename = url + radiomap_parameters_filename.substring(pos) } catch { case e: Exception => return AnyResponseHelper.internal_server_error("Error serving radiomap : " + e.getMessage) } @@ -334,7 +323,7 @@ object AnyplacePosition extends play.api.mvc.Controller { if (!rmapDir.mkdirs()) { return AnyResponseHelper.internal_server_error("Error while creating Radio Map on-the-fly!") } - val radio = new File(rmapDir.getAbsolutePath + AnyplaceServerAPI.URL_SEP + "rss-log") + val radio = new File(rmapDir.getAbsolutePath + api.URL_SEP + "rss-log") var fout: FileOutputStream = null try { fout = new FileOutputStream(radio) @@ -342,9 +331,9 @@ object AnyplacePosition extends play.api.mvc.Controller { case e: FileNotFoundException => return AnyResponseHelper.internal_server_error( "Cannot create radiomap:3:" + e.getMessage) } - var floorFetched: Long = 0l + var floorFetched: Long = 0L try { - floorFetched = ProxyDataSource.getIDatasource.dumpRssLogEntriesByBuildingFloor(fout, buid, floor_number) + floorFetched = proxyDataSource.getIDatasource.dumpRssLogEntriesByBuildingFloor(fout, buid, floor_number) try { fout.close() } catch { @@ -357,7 +346,7 @@ object AnyplacePosition extends play.api.mvc.Controller { try { val folder = rmapDir.toString - val radiomap_filename = getRadioMapFileName(buid, floor_number).getAbsolutePath + val radiomap_filename = fu.getRadioMapFileName(buid, floor_number).getAbsolutePath var radiomap_mean_filename = radiomap_filename.replace(".txt", "-mean.txt") var radiomap_rbf_weights_filename = radiomap_filename.replace(".txt", "-weights.txt") var radiomap_parameters_filename = radiomap_filename.replace(".txt", "-parameters.txt") @@ -366,19 +355,18 @@ object AnyplacePosition extends play.api.mvc.Controller { if (resCreate != null) { return AnyResponseHelper.internal_server_error("radioDownloadByBuildingFloorall: Error: on-the-fly radioMap: " + resCreate) } - val api = AnyplaceServerAPI.SERVER_API_ROOT - var pos = getFilePos(radiomap_mean_filename) - radiomap_mean_filename = api + radiomap_mean_filename.substring(pos) - pos = getFilePos(radiomap_rbf_weights_filename) - radiomap_rbf_weights_filename = api + radiomap_rbf_weights_filename.substring(pos) - pos = getFilePos(radiomap_parameters_filename) - radiomap_parameters_filename = api + radiomap_parameters_filename.substring(pos) + val url = api.SERVER_API_ROOT + var pos = fu.getFilePos(radiomap_mean_filename) + radiomap_mean_filename = url + radiomap_mean_filename.substring(pos) + pos = fu.getFilePos(radiomap_rbf_weights_filename) + radiomap_rbf_weights_filename = url + radiomap_rbf_weights_filename.substring(pos) + pos = fu.getFilePos(radiomap_parameters_filename) + radiomap_parameters_filename = url + radiomap_parameters_filename.substring(pos) } catch { case e: Exception => return AnyResponseHelper.internal_server_error("Error while creating Radio Map on-the-fly! : " + e.getMessage) } - - val source = scala.io.Source.fromFile(rmapDir.getAbsolutePath + AnyplaceServerAPI.URL_SEP + "indoor-radiomap.txt") + val source = scala.io.Source.fromFile(rmapDir.getAbsolutePath + api.URL_SEP + "indoor-radiomap.txt") val lines = try source.mkString finally source.close() radiomap_mean_filename.add(floor_number) rss_log_files.add(lines) @@ -388,8 +376,8 @@ object AnyplacePosition extends play.api.mvc.Controller { } } - val res: JsValue = Json.obj("map_url_mean" -> radiomap_mean_filename.toList, - "rss_log_files" -> rss_log_files.toList) + val res: JsValue = Json.obj("map_url_mean" -> radiomap_mean_filename.asScala, + "rss_log_files" -> rss_log_files.asScala) return AnyResponseHelper.ok(res, "Successfully served radio map.") } @@ -415,7 +403,7 @@ object AnyplacePosition extends play.api.mvc.Controller { LPLogger.info(rmr.toValidJson().toString) LPLogger.debug("raw[" + lineNumber + "] : " + rmr.toValidJson()) try { - if (!ProxyDataSource.getIDatasource.addJsonDocument(rmr.getId, 0, rmr.toGeoJSON())) { + if (!proxyDataSource.getIDatasource.addJsonDocument(rmr.getId(), 0, rmr.toGeoJSON())) { return "Radio Map entry could not be saved in database![could not be created]" } } catch { @@ -444,9 +432,9 @@ object AnyplacePosition extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() //LPLogger.info("AnyplacePosition::serveRadioMap(): " + json.toString) - val filePath = "radiomaps" + AnyplaceServerAPI.URL_SEP + radio_folder + AnyplaceServerAPI.URL_SEP + + val filePath = "radiomaps" + api.URL_SEP + radio_folder + api.URL_SEP + fileName LPLogger.info("requested: " + filePath) val file = new File(filePath) @@ -468,11 +456,10 @@ object AnyplacePosition extends play.api.mvc.Controller { def inner(): Result = { //FeatureAdd : Configuring location for server generated files - val radioMapsFrozenDir = Play.application().configuration().getString("radioMapFrozenDir") - - val filePath = radioMapsFrozenDir + AnyplaceServerAPI.URL_SEP + building + AnyplaceServerAPI.URL_SEP + + val radioMapsFrozenDir = conf.get[String]("radioMapFrozenDir") + val filePath = radioMapsFrozenDir + api.URL_SEP + building + api.URL_SEP + floor + - AnyplaceServerAPI.URL_SEP + + api.URL_SEP + fileName LPLogger.info("requested: " + filePath) val file = new File(filePath) @@ -519,14 +506,14 @@ object AnyplacePosition extends play.api.mvc.Controller { val fingerprintToks = values.get(0).split(" ") val tempMeasurements = new ArrayList[List[String]] // creating measurements for the currect window - for (value <- values) { + for (value <- values.asScala) { val tok = value.split(" ") val measurement = new ArrayList[String] measurement.add(tok(4)) // adding MAC measurement.add(tok(5)) // adding heading - tempMeasurements.add(measurement.toList) + tempMeasurements.add(measurement.asScala.toList) } - val measurements: List[List[String]] = tempMeasurements.toList + val measurements: List[List[String]] = tempMeasurements.asScala.toList // creating fingerprint with measurements var rmr: RadioMapRaw = null if (fingerprintToks.length >= 8) { @@ -540,17 +527,17 @@ object AnyplacePosition extends play.api.mvc.Controller { } // Before add check if already exists, if exists ignore and notify - if (ProxyDataSource.getIDatasource().fingerprintExists(SCHEMA.cFingerprintsWifi, fingerprintToks(7), + if (proxyDataSource.getIDatasource.fingerprintExists(SCHEMA.cFingerprintsWifi, fingerprintToks(7), fingerprintToks(6), fingerprintToks(1), fingerprintToks(2), fingerprintToks(3))) { - return 1 + "" + return 1.toString() } else { try { - ProxyDataSource.getIDatasource.addJsonDocument(SCHEMA.cFingerprintsWifi, rmr.addMeasurements(measurements)) - ProxyDataSource.getIDatasource().deleteAffectedHeatmaps(fingerprintToks(7), fingerprintToks(6)) + proxyDataSource.getIDatasource.addJsonDocument(SCHEMA.cFingerprintsWifi, rmr.addMeasurements(measurements)) + proxyDataSource.getIDatasource.deleteAffectedHeatmaps(fingerprintToks(7), fingerprintToks(6)) } catch { case e: DatasourceException => return "Internal server error while trying to save rss entry." } - return 0 + "" + return 0.toString() } } null @@ -606,7 +593,7 @@ object AnyplacePosition extends play.api.mvc.Controller { case e: IOException => return "Internal server error: Error while storing rss log." } } - return totalExists + "/" + totalRss + return totalExists.toString + "/" + totalRss.toString } /** @@ -621,89 +608,42 @@ object AnyplacePosition extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody - val watch = new StopWatch() - watch.start() + val json = anyReq.getJsonBody() var alg1: Algo1 = null try { alg1 = new Algo1(json) } catch { - case ex: Exception => return AnyResponseHelper.bad_request(ex.getMessage) + case ex: Exception => { + return AnyResponseHelper.bad_request(ex.getClass.toString() + ": " + ex.getMessage + ": " + ex.getCause.toString()) + } } try { val lat = json.\("dlat").as[Double] val lot = json.\("dlong").as[Double] val bbox = GeoPoint.getGeoBoundingBox(lat, lot, 100) val strongestMAC = new ArrayList[String](2) - if (json.\("first").getOrElse(null) != null) return AnyResponseHelper.bad_request("Sent first Wifi") + if (json.\("first").getOrElse(null) == null) return AnyResponseHelper.bad_request("Sent first Wifi") strongestMAC.add(json.\("first").\(SCHEMA.fMac).as[String]) if (json.\("second").getOrElse(null) != null) strongestMAC.add(json.\("second").\(SCHEMA.fMac).as[String]) + LPLogger.D2("strongestMAC " + strongestMAC) val res = JsonObject.empty() - if (ProxyDataSource.getIDatasource.predictFloor(alg1, bbox, strongestMAC.toArray(Array.ofDim[String](1)))) { - res.put(SCHEMA.fFloor, alg1.getFloor) + var msg = "" + if (proxyDataSource.getIDatasource.predictFloor(alg1, bbox, strongestMAC.toArray(Array.ofDim[String](1)))) { + res.put(SCHEMA.fFloor, alg1.getFloor()) + msg = "Successfully predicted floor." } else { res.put(SCHEMA.fFloor, "") + msg = "Could not predict floor." } - watch.stop() - LPLogger.info("Time for Algo1 is millis: " + watch.getNanoTime / 1000000) - AnyResponseHelper.ok(res, "Successfully predicted Floor.") + AnyResponseHelper.ok(res, msg) } catch { - case e: Exception => AnyResponseHelper.internal_server_error("500: " + e.getMessage) + case e: Exception => AnyResponseHelper.internal_server_error("500: " + e.getMessage + ": " + e.getCause) } } inner(request) } - /** - * Now this is synchronously called. - * - * @param buid - * @param floor_number - * @return a status regarding the frozen radio_map creation. - */ - def updateFrozenRadioMap(buid: String, floor_number: String): String = { - val cls = "updateFrozenRadioMap: " - if (!Floor.checkFloorNumberFormat(floor_number)) { - return null - } - LPLogger.info(cls + buid + ":" + floor_number) - - val radioMapsFrozenDir = Play.application().configuration().getString("radioMapFrozenDir") - - val rmapDir = new File(radioMapsFrozenDir + AnyplaceServerAPI.URL_SEP + buid + AnyplaceServerAPI.URL_SEP + - floor_number) - - if (!rmapDir.exists() && !rmapDir.mkdirs()) { - return cls + "failed to create: " + rmapDir.toString - } - val rssLogPerFloor = new File(rmapDir.getAbsolutePath + AnyplaceServerAPI.URL_SEP + "rss-log") - var fout: FileOutputStream = null - try { - fout = new FileOutputStream(rssLogPerFloor) - LPLogger.D1(cls + "Creating rss-log: " + rssLogPerFloor.toPath().getFileName.toString) - } catch { - case e: FileNotFoundException => return cls + e.getClass + ": " + e.getMessage - } - var floorFetched: Long = 0l - try { - floorFetched = ProxyDataSource.getIDatasource.dumpRssLogEntriesByBuildingFloor(fout, buid, floor_number) - fout.close() - } catch { - case e: DatasourceException => return cls + e.getClass + ": " + e.getMessage - case e: IOException => return cls + e.getClass + " Error while closing rss-log: " + e.getMessage - } - if (floorFetched == 0) { - return null - } - val radiomap_filename = new File(rmapDir.toString + AnyplaceServerAPI.URL_SEP + "indoor-radiomap.txt") - .getAbsolutePath - val rm = new RadioMap(new File(rmapDir.toString), radiomap_filename, "", -110) - val resCreate = rm.createRadioMap() - if (resCreate != null) return cls + "Failed: createRadioMap: " + resCreate - null - } - def magneticPathAdd() = Action { implicit request => def inner(request: Request[AnyContent]): Result = { @@ -711,7 +651,7 @@ object AnyplacePosition extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMagnetic::pathAdd(): " + json.toString) val requiredMissing = JsonUtils.hasProperties(json, "lat_a", "lng_a", "lat_b", "lng_b", SCHEMA.fBuid, "floor_num") @@ -725,11 +665,11 @@ object AnyplacePosition extends play.api.mvc.Controller { } catch { case e: NumberFormatException => return AnyResponseHelper.bad_request("Magnetic Path coordinates are invalid!") } - if (!ProxyDataSource.getIDatasource.addJsonDocument(mpath.getId, 0, mpath.toValidJson().toString)) { + if (!proxyDataSource.getIDatasource.addJsonDocument(mpath.getId(), 0, mpath.toValidJson().toString)) { return AnyResponseHelper.bad_request("MPath already exists or could not be added!") } val res = JsonObject.empty() - res.put("mpath", mpath.getId) + res.put("mpath", mpath.getId()) return AnyResponseHelper.ok(res, "Successfully added magnetic path!") } catch { case e: DatasourceException => return AnyResponseHelper.internal_server_error("500: " + e.getMessage) @@ -746,7 +686,7 @@ object AnyplacePosition extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMagnetic::magneticPathDelete(): " + json.toString) val requiredMissing = JsonUtils.hasProperties(json, "mpuid") if (!requiredMissing.isEmpty) { @@ -754,7 +694,7 @@ object AnyplacePosition extends play.api.mvc.Controller { } val mpuid = (json \ "mpuid").as[String] try { - val success = ProxyDataSource.getIDatasource.deleteFromKey(mpuid) + val success = proxyDataSource.getIDatasource.deleteFromKey(mpuid) if (!success) { return AnyResponseHelper.bad_request("Magnetic Path does not exist or could not be retrieved!") } @@ -774,7 +714,7 @@ object AnyplacePosition extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::poisByFloor(): " + json.toString) val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, "floor_num") if (!requiredMissing.isEmpty) { @@ -783,7 +723,7 @@ object AnyplacePosition extends play.api.mvc.Controller { val buid = (json \ SCHEMA.fBuid).as[String] val floor_number = (json \ "floor_num").as[String] try { - val mpaths = ProxyDataSource.getIDatasource.magneticPathsByBuildingFloorAsJson(buid, floor_number) + val mpaths = proxyDataSource.getIDatasource.magneticPathsByBuildingFloorAsJson(buid, floor_number) val res = JsonObject.empty() res.put("mpaths", JsonArray.from(mpaths)) return AnyResponseHelper.ok(res.toString) @@ -802,7 +742,7 @@ object AnyplacePosition extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::mpsByBuilding(): " + json.toString) val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid) if (!requiredMissing.isEmpty) { @@ -810,7 +750,7 @@ object AnyplacePosition extends play.api.mvc.Controller { } val buid = (json \ SCHEMA.fBuid).as[String] try { - val mpaths = ProxyDataSource.getIDatasource.magneticPathsByBuildingAsJson(buid) + val mpaths = proxyDataSource.getIDatasource.magneticPathsByBuildingAsJson(buid) val res = JsonObject.empty() res.put("mpaths", JsonArray.from(mpaths)) return AnyResponseHelper.ok(res.toString) @@ -829,7 +769,7 @@ object AnyplacePosition extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::mpsByBuilding(): " + json.toString) val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, "floor_num", "mpuid", "milestones") if (!requiredMissing.isEmpty) { @@ -847,7 +787,7 @@ object AnyplacePosition extends play.api.mvc.Controller { for (jn <- milestones.toList.asInstanceOf[List[JsonObject]]) { val mm = new MagneticMilestone(jn, buid, floor_num, mpuid) try { - if (!ProxyDataSource.getIDatasource.addJsonDocument(mm.getId, 0, mm.toValidJson().toString)) { + if (!proxyDataSource.getIDatasource.addJsonDocument(mm.getId(), 0, mm.toValidJson().toString)) { return AnyResponseHelper.bad_request("Milestone already exists or could not be added!") } } catch { @@ -867,7 +807,7 @@ object AnyplacePosition extends play.api.mvc.Controller { if (!anyReq.assertJsonBody()) { return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) } - val json = anyReq.getJsonBody + val json = anyReq.getJsonBody() LPLogger.info("AnyplaceMapping::milestonesByFloor(): " + json.toString) val requiredMissing = JsonUtils.hasProperties(json, SCHEMA.fBuid, "floor_num") if (!requiredMissing.isEmpty) { @@ -876,7 +816,7 @@ object AnyplacePosition extends play.api.mvc.Controller { val buid = (json \ SCHEMA.fBuid).as[String] val floor_number = (json \ "floor_num").as[String] try { - val mpaths = ProxyDataSource.getIDatasource.magneticMilestonesByBuildingFloorAsJson(buid, floor_number) + val mpaths = proxyDataSource.getIDatasource.magneticMilestonesByBuildingFloorAsJson(buid, floor_number) val res = JsonObject.empty() res.put("mpaths", JsonArray.from(mpaths)) return AnyResponseHelper.ok(res.toString) diff --git a/server/app/controllers/Application.scala b/server/app/controllers/Application.scala deleted file mode 100644 index 100cb287a..000000000 --- a/server/app/controllers/Application.scala +++ /dev/null @@ -1,45 +0,0 @@ -/* - * AnyPlace: A free and open Indoor Navigation Service with superb accuracy! - * - * Anyplace is a first-of-a-kind indoor information service offering GPS-less - * localization, navigation and search inside buildings using ordinary smartphones. - * - * Author(s): Constantinos Costa, Kyriakos Georgiou, Lambros Petrou - * - * Supervisor: Demetrios Zeinalipour-Yazti - * - * URL: https://anyplace.cs.ucy.ac.cy - * Contact: anyplace@cs.ucy.ac.cy - * - * Copyright (c) 2016, Data Management Systems Lab (DMSL), University of Cyprus. - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the “Software”), to deal in the - * Software without restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ -package controllers -import play.api.mvc._ - -class Application extends Controller { - - def index = Action { - Ok("It works!") - } - -} diff --git a/server/app/controllers/ApplicationAnyplace.scala b/server/app/controllers/ApplicationAnyplace.scala index bf7929782..b2a7e6bf9 100644 --- a/server/app/controllers/ApplicationAnyplace.scala +++ b/server/app/controllers/ApplicationAnyplace.scala @@ -35,25 +35,50 @@ */ package controllers -import com.couchbase.client.java.document.json.{JsonArray, JsonObject} -import play.Play -import play.api.data._ -import play.api.data.Forms._ -import play.api.mvc.{Action, Result} -import security.User -import utils.{AnyResponseHelper, LPLogger} +import javax.inject.{Inject, Singleton} +import play.api.Configuration +import play.api.libs.json.{JsValue, Json} +import play.api.mvc.{AbstractController, ControllerComponents} -object ApplicationAnyplace extends play.api.mvc.Controller { +@Singleton +class ApplicationAnyplace @Inject()(cc: ControllerComponents, + conf: Configuration) + extends AbstractController(cc) { def index() = Action { Redirect("/viewer") } def Version= Action { - val version = Play.application().configuration().getString("application.version") - Ok(version) + val version = conf.get[String]("application.version") + val address = conf.get[String]("server.address") + val port = conf.get[String]("server.port") + + + var variant="" + if (address.contains("dev")) { + variant = "beta" + if (port != "443" || port != "80") variant = "alpha" + } else if (address.contains("localhost")) { + variant = "local" + } + + val res: JsValue = Json.obj( + "version" -> version, + "address" -> address, + "port"-> port, + "variant" -> variant) + +// return AnyResponseHelper.ok(res) CLR:PM + Ok(res) } + def indexAny() = index() + + def indexAny(any: String) = index() + //Redirect(routes.Assets.at("/public/anyplace_viewer", "index.html")) + + // CHECK:PM CHECK:NN ?? // def Architect = Action { // Ok(views.html.architect()) // } @@ -65,68 +90,62 @@ object ApplicationAnyplace extends play.api.mvc.Controller { // def ViewerCampus(any: String) = Action { // Ok(views.html.viewer_campus()) // } - - def indexAny() = index() - - def indexAny(any: String) = Action { - Redirect(routes.Assets.at("/public/anyplace_viewer", "index.html")) - } - - /** - * AUTHORIZATION SESSION - */ - case class Login(username: String, password: String) { - var admin_mode = "" - - def validate: String = { - if (!User.authenticate(username, password)) return "Invalid user or password" - null - } - } - - // displays the login form for the architect - def login = Action { // IMPORTANT - to allow cross domain requests - LPLogger.error("ApplicationAnyplace.login() ?") - //response().setHeader("Access-Control-Allow-Origin", CORSHelper.checkOriginFromRequest(request())); - // allows session cookies to be transferred - //response().setHeader("Access-Control-Allow-Credentials", "true"); - def frm = Form(mapping("Username" -> nonEmptyText, - "Password" -> nonEmptyText)(Login.apply)(Login.unapply)) - - Ok(views.html.anyplace_login.render(frm)) - } - - // validates the username and password - def authenticate = Action { - LPLogger.error("ApplicationAnyplace.authenticate() ?") - def loginForm = Form(mapping("Username" -> nonEmptyText, "Password" -> nonEmptyText)(Login.apply)(Login.unapply)) - - if (loginForm.hasErrors) - BadRequest(views.html.anyplace_login.render(loginForm)) - else { - if (loginForm.get.admin_mode.equalsIgnoreCase("architect")) - Redirect(routes.AnyplaceWebApps.serveAdmin("index.html")).withSession(("username", loginForm.get.username)) - else if (loginForm.get.admin_mode.equalsIgnoreCase("android")) - Redirect(routes.AnyplaceAndroid.getApks).withSession(("username", loginForm.get.username)) - else if (loginForm.get.admin_mode.equalsIgnoreCase("admin")) - Redirect(routes.AnyplaceWebApps.serveAdmin("index.html")).withSession(("username", loginForm.get.username)) - else if (loginForm.get.admin_mode.equalsIgnoreCase("architect2")) - Redirect(routes.AnyplaceWebApps.serveAdmin("index.html")).withSession(("username", loginForm.get.username)) - } - - def frm = Form(mapping("Username" -> nonEmptyText, - "Password" -> nonEmptyText)(Login.apply)(Login.unapply)) - BadRequest(views.html.anyplace_login.render(frm)) - } - - /** - * Logout and clean the session. - */ - def logout = Action { - LPLogger.error("ApplicationAnyplace.logout() ?") - Redirect(routes.ApplicationAnyplace.login).withNewSession.flashing( - "success" -> "You've been logged out" - ) - } + // CLR:PM + ///** + // * AUTHORIZATION SESSION + // */ + //case class Login(username: String, password: String) { + // var admin_mode = "" + // + // def validate: String = { + // if (!User.authenticate(username, password)) return "Invalid user or password" + // null + // } + //} + // + //// displays the login form for the architect + //def login = Action { // IMPORTANT - to allow cross domain requests + // LPLogger.error("ApplicationAnyplace.login() ?") + // //response().setHeader("Access-Control-Allow-Origin", CORSHelper.checkOriginFromRequest(request())); + // // allows session cookies to be transferred + // //response().setHeader("Access-Control-Allow-Credentials", "true"); + // def frm = Form(mapping("Username" -> nonEmptyText, + // "Password" -> nonEmptyText)(Login.apply)(Login.unapply)) + // + // Ok(views.html.anyplace_login.render(frm)) + //} + // + //// validates the username and password + //def authenticate = Action { + // LPLogger.error("ApplicationAnyplace.authenticate() ?") + // def loginForm = Form(mapping("Username" -> nonEmptyText, "Password" -> nonEmptyText)(Login.apply)(Login.unapply)) + // + // if (loginForm.hasErrors) + // BadRequest(views.html.anyplace_login.render(loginForm)) + // else { + // if (loginForm.get.admin_mode.equalsIgnoreCase("architect")) + // Redirect(routes.AnyplaceWebApps.serveAdmin("index.html")).withSession(("username", loginForm.get.username)) + // else if (loginForm.get.admin_mode.equalsIgnoreCase("android")) + // Redirect(routes.AnyplaceAndroid.getApks).withSession(("username", loginForm.get.username)) + // else if (loginForm.get.admin_mode.equalsIgnoreCase("admin")) + // Redirect(routes.AnyplaceWebApps.serveAdmin("index.html")).withSession(("username", loginForm.get.username)) + // else if (loginForm.get.admin_mode.equalsIgnoreCase("architect2")) + // Redirect(routes.AnyplaceWebApps.serveAdmin("index.html")).withSession(("username", loginForm.get.username)) + // } + // + // def frm = Form(mapping("Username" -> nonEmptyText, + // "Password" -> nonEmptyText)(Login.apply)(Login.unapply)) + // BadRequest(views.html.anyplace_login.render(frm)) + //} + // + ///** + // * Logout and clean the session. + // */ + //def logout = Action { + // LPLogger.error("ApplicationAnyplace.logout() ?") + // Redirect(routes.ApplicationAnyplace.login).withNewSession.flashing( + // "success" -> "You've been logged out" + // ) + //} } diff --git a/server/app/controllers/Secured.scala b/server/app/controllers/Secured.scala deleted file mode 100644 index d83745d02..000000000 --- a/server/app/controllers/Secured.scala +++ /dev/null @@ -1,52 +0,0 @@ -/* - * AnyPlace: A free and open Indoor Navigation Service with superb accuracy! - * - * Anyplace is a first-of-a-kind indoor information service offering GPS-less - * localization, navigation and search inside buildings using ordinary smartphones. - * - * Author(s): Constantinos Costa, Kyriakos Georgiou, Lambros Petrou - * - * Supervisor: Demetrios Zeinalipour-Yazti - * - * URL: https://anyplace.cs.ucy.ac.cy - * Contact: anyplace@cs.ucy.ac.cy - * - * Copyright (c) 2016, Data Management Systems Lab (DMSL), University of Cyprus. - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the “Software”), to deal in the - * Software without restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ -package controllers - -import play.api.mvc.RequestHeader -import play.mvc.{Call, Result, Results, Security} -import play.mvc.Http.Context - -class Secured extends Security.Authenticator { - - override def getUsername(ctx: Context): String = - ctx.session().get("username") - - override def onUnauthorized(ctx: Context): Result = { - onUnauthorized(ctx._requestHeader()) - } - - def onUnauthorized(request: RequestHeader) = Results.redirect(routes.ApplicationAnyplace.login()) -} diff --git a/server/app/controllers/UserController.scala b/server/app/controllers/UserController.scala new file mode 100644 index 000000000..7b549b194 --- /dev/null +++ b/server/app/controllers/UserController.scala @@ -0,0 +1,495 @@ +/* + * AnyPlace: A free and open Indoor Navigation Service with superb accuracy! + * + * Anyplace is a first-of-a-kind indoor information service offering GPS-less + * localization, navigation and search inside buildings using ordinary smartphones. + * + * Author(s): Nikolas Neofytou, Constantinos Costa, Kyriakos Georgiou, Lambros Petrou + * + * Co-Supervisor: Paschalis Mpeis + * Supervisor: Demetrios Zeinalipour-Yazti + * + * URL: https://anyplace.cs.ucy.ac.cy + * Contact: anyplace@cs.ucy.ac.cy + * + * Copyright (c) 2016, Data Management Systems Lab (DMSL), University of Cyprus. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the “Software”), to deal in the + * Software without restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ +package controllers + + +import datasources.{DatasourceException, ProxyDataSource, SCHEMA} +import javax.inject.{Inject, Singleton} +import json.VALIDATE +import oauth.provider.v2.models.OAuth2Request +import play.api.Configuration +import play.api.libs.json._ +import play.api.mvc._ +import utils.{AnyResponseHelper, JsonUtils, LPLogger} + +@Singleton +class UserController @Inject()(cc: ControllerComponents, + pds: ProxyDataSource, + conf: Configuration) + extends AbstractController(cc) { + + /** + * Deletes the account with the AUID passed in. + * The result of the action is returned in the Json response. + * + * @return + */ + def deleteAccount(auid_in: String) = Action { + implicit request => + + def inner(request: Request[AnyContent]): Result = { + var auid: String = auid_in + // create the Request and check it + val anyReq: OAuth2Request = new OAuth2Request(request) + if (!anyReq.assertJsonBody()) { + return AnyResponseHelper.bad_request( + AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + } + val json = anyReq.getJsonBody() + LPLogger.info("UserController:deleteAccount: " + json.toString) + // check if there is any required parameter missing + val notFound: java.util.List[String] = + JsonUtils.hasProperties(json, "auid") + if (!notFound.isEmpty && (auid == null || auid.trim().isEmpty)) { + return AnyResponseHelper.requiredFieldsMissing(notFound) + } + // if the auid in the route is empty then try to get the one from the POST json body + if (auid == null || auid.trim().isEmpty) + auid = json.\\("auid").mkString + try { + if (!pds.getIDatasource.deleteFromKey(auid)) { + return AnyResponseHelper.bad_request("Account could not be deleted!") + } + return AnyResponseHelper.ok("Successfully deleted account!") + } catch { + case e: DatasourceException => + return AnyResponseHelper.internal_server_error( + "500: " + e.getMessage) + + } + } + + inner(request) + } + + ///** + // * Updates the account specified by the AUID. + // * The result of the update is returned in the Json response. + // * + // * @return + // */ + //def UpdateAccount(auid: String)(auid_in: String) = Action { + // implicit request => + // + // def inner(request: Request[AnyContent]): Result = { + // var auid: String = auid_in + // // create the Request and check it + // val anyReq: OAuth2Request = new OAuth2Request(request) + // if (!anyReq.assertJsonBody()) { + // return AnyResponseHelper.bad_request( + // AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + // } + // val json = anyReq.getJsonBody() + // LPLogger.info("AnyplaceAccounts::updateAccount():: " + json.toString) + // // check if there is any required parameter missing + // val notFound: java.util.List[String] = + // JsonUtils.hasProperties(json, "auid") + // if (!notFound.isEmpty && (auid == null || auid.trim().isEmpty)) { + // return AnyResponseHelper.requiredFieldsMissing(notFound) + // } + // // if the auid in the route is empty then try to get the one from the POST json body + // if (auid == null || auid.trim().isEmpty) + // auid = json.\\("auid").mkString + // try { + // // fetch the stored object + // var storedAccount: JsonObject = null + // storedAccount = toCouchObject(CouchbaseDatasource.getStaticInstance(conf).getFromKeyAsJson(auid)) + // if (storedAccount == null) { + // return AnyResponseHelper.bad_request( + // "Account could not be updated! Try again...") + // } + // // apply any change made + // val updateableFields: Array[String] = + // AccountModel.getChangeableProperties() + // for (s <- updateableFields) { + // val value = json.\\(s) + // if (value.asInstanceOf[Boolean]) { + // storedAccount.put(s, value.asInstanceOf[Boolean]) + // } else { + // val nv: String = value.mkString + // if (nv == null || nv.trim().isEmpty) //continue + // storedAccount.put(s, nv) + // } + // } + // // save the changes + // if (!pds.getIDatasource.replaceJsonDocument(auid, 0, storedAccount.toString)) { + // return AnyResponseHelper.bad_request( + // "Account could not be updated! Try again...") + // } + // return AnyResponseHelper.ok("Successfully updated account!") + // } catch { + // case e: DatasourceException => + // return AnyResponseHelper.internal_server_error( + // "500: " + e.getMessage) + // + // } + // } + // + // inner(request) + //} + + // check if there is any required parameter missing + // check if there is any required parameter missing + + ///** + // * Returns the list of clients for this account + // * + // * @param auid The account for which the clients are to be returned + // * @return + // */ + //def fetchAccountClients(auid: String)(auid_in: String) = Action { + // implicit request => + // def inner(request: Request[AnyContent]): Result = { + // var auid: String = auid_in + // // create the Request and check it + // val anyReq: OAuth2Request = new OAuth2Request(request) + // if (!anyReq.assertJsonBody()) { + // return AnyResponseHelper.bad_request( + // AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + // } + // val json = anyReq.getJsonBody() + // LPLogger.info("AnyplaceAccounts::fetchAccountClients():: " + json.toString) + // // check if there is any required parameter missing + // val notFound: java.util.List[String] = + // JsonUtils.hasProperties(json, "auid") + // if (!notFound.isEmpty && (auid == null || auid.trim().isEmpty)) { + // return AnyResponseHelper.requiredFieldsMissing(notFound) + // } + // // if the auid in the route is empty then try to get the one from the POST json body + // if (auid == null || auid.trim().isEmpty) + // auid = json.\\("auid").mkString + // try { + // var storedAccount: JsonObject = null + // storedAccount = + // toCouchObject(CouchbaseDatasource.getStaticInstance(conf).getFromKeyAsJson(auid)) + // if (storedAccount == null) { + // return AnyResponseHelper.bad_request("Account could not be found!") + // } + // val json_clients = storedAccount.getArray("clients") + // val resp: JsonObject = JsonObject.empty() + // resp.put("clients", json_clients) + // return AnyResponseHelper.ok(resp, "Successfully fetched account clients!") + // } catch { + // case e: DatasourceException => + // return AnyResponseHelper.internal_server_error( + // "500: " + e.getMessage) + // + // } + // } + // + // inner(request) + //} + + ///** + // * Adds a new client for this account + // * + // * @param auid The account the new account belongs to + // * @return + // */ + //def addAccountClient(auid: String)(auid_in: String) = Action { + // implicit request => + // + // def inner(request: Request[AnyContent]): Result = { + // var auid: String = auid_in + // // create the Request and check it + // val anyReq: OAuth2Request = new OAuth2Request(request) + // if (!anyReq.assertJsonBody()) { + // return AnyResponseHelper.bad_request( + // AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + // } + // val json = anyReq.getJsonBody() + // LPLogger.info("AnyplaceAccounts::addAccountClient():: " + json.toString) + // // check if there is any required parameter missing + // val notFound: java.util.List[String] = + // JsonUtils.hasProperties(json, "auid", "grant_type") + // if (!notFound.isEmpty && (auid == null || auid.trim().isEmpty)) { + // return AnyResponseHelper.requiredFieldsMissing(notFound) + // } + // // if the auid in the route is empty then try to get the one from the POST json body + // if (auid == null || auid.trim().isEmpty) + // auid = json.\\("auid").mkString + // val grant_type: String = json.\\("grant_type").mkString + // val scope: String = json.\\("scope").mkString + // val redirect_uri: String = json.\\("redirect_uri").mkString + // if (!GrantHandlerFactory.isGrantTypeSupported(grant_type)) { + // return AnyResponseHelper.bad_request("grant_type specified is not supported!") + // } + // try { + // var storedAccount: JsonObject = null + // storedAccount = toCouchObject(CouchbaseDatasource.getStaticInstance(conf).getFromKeyAsJson(auid)) + // if (storedAccount == null) { + // return AnyResponseHelper.bad_request("Account could not be found!") + // } + // val account: AccountModel = new AccountModel(storedAccount) + // account.addNewClient(grant_type, scope, redirect_uri) + // // save the changes + // if (!pds.getIDatasource.replaceJsonDocument( + // auid, + // 0, + // account.toJson().toString)) { + // return AnyResponseHelper.bad_request( + // "Account could not be updated! Try again...") + // } + // return AnyResponseHelper.ok("Successfully added account client!") + // } catch { + // case e: DatasourceException => + // return AnyResponseHelper.internal_server_error( + // "500: " + e.getMessage) + // + // } + // } + // + // inner(request) + //} + + /** + * Fetches the account client with the AUID and client_id passed in. + * The client document is returned in the Json response. + * + * @return + */ + //def fetchAccountClient(auid: String, client_id: String)(auid_in: String) = Action { + // implicit request => + // + // def inner(request: Request[AnyContent]): Result = { + // var auid: String = auid_in + // // create the Request and check it + // val anyReq: OAuth2Request = new OAuth2Request(request) + // if (!anyReq.assertJsonBody()) { + // return AnyResponseHelper.bad_request( + // AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + // } + // val json = anyReq.getJsonBody() + // LPLogger.info("AnyplaceAccounts::fetchAccount():: " + json.toString) + // // check the arguments + // if ((auid == null || auid.trim().isEmpty)) { + // return AnyResponseHelper.bad_request("Invalid account id provided!") + // } + // if ((client_id == null || client_id.trim().isEmpty)) { + // AnyResponseHelper.bad_request("Invalid client id provided!") + // } + // try { + // var storedAccount: JsonObject = null + // storedAccount = toCouchObject(CouchbaseDatasource.getStaticInstance(conf).getFromKeyAsJson(auid)) + // if (storedAccount == null) { + // return AnyResponseHelper.bad_request("Account could not be found!") + // } + // val account: AccountModel = new AccountModel(storedAccount) + // val client: AccountModel.ClientModel = account.getClient(client_id) + // if (client == null) { + // return AnyResponseHelper.bad_request("Account client could not be found!") + // } + // return AnyResponseHelper.ok(client.toJson(), + // "Successfully fetched account client!") + // } catch { + // case e: DatasourceException => + // return AnyResponseHelper.internal_server_error( + // "500: " + e.getMessage) + // + // } + // } + // + // inner(request) + //} + + /** + * Fetches the account client with the AUID and client_id passed in. + * The client document is returned in the Json response. + * + * @return + */ + //def deleteAccountClient(auid: String, client_id: String)(auid_in: String) = Action { + // implicit request => + // + // def inner(request: Request[AnyContent]): Result = { + // var auid: String = auid_in + // // create the Request and check it + // val anyReq: OAuth2Request = new OAuth2Request(request) + // if (!anyReq.assertJsonBody()) { + // return AnyResponseHelper.bad_request( + // AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + // } + // val json = anyReq.getJsonBody() + // LPLogger.info("AnyplaceAccounts::deleteAccount():: " + json.toString) + // // check the arguments + // if ((auid == null || auid.trim().isEmpty)) { + // return AnyResponseHelper.bad_request("Invalid account id provided!") + // } + // if ((client_id == null || client_id.trim().isEmpty)) { + // return AnyResponseHelper.bad_request("Invalid client id provided!") + // } + // try { + // var storedAccount: JsonObject = null + // storedAccount = + // toCouchObject(CouchbaseDatasource.getStaticInstance(conf).getFromKeyAsJson(auid)) + // if (storedAccount == null) { + // return AnyResponseHelper.bad_request("Account could not be found!") + // } + // val account: AccountModel = new AccountModel(storedAccount) + // if (!account.deleteClient(client_id)) { + // return AnyResponseHelper.bad_request("Account client could not be found!") + // } + // // save the changes + // if (!pds.getIDatasource.replaceJsonDocument( + // auid, + // 0, + // account.toJson().toString)) { + // return AnyResponseHelper.bad_request( + // "Account could not be updated! Try again...") + // } + // return AnyResponseHelper.ok("Successfully deleted account client!") + // } catch { + // case e: DatasourceException => + // return AnyResponseHelper.internal_server_error( + // "500: " + e.getMessage) + // + // } + // } + // + // inner(request) + //} + + def login() = Action { + implicit request => + + def inner(request: Request[AnyContent]): Result = { + + val anyReq: OAuth2Request = new OAuth2Request(request) + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + val json = anyReq.getJsonBody() + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fUsername, SCHEMA.fPassword) + if (checkRequirements != null) return checkRequirements + + LPLogger.D2("login = " + json) + val username = (json \ SCHEMA.fUsername).as[String] + val password = (json \ SCHEMA.fPassword).as[String] + val storedUser = pds.getIDatasource.login(SCHEMA.cUsers, username, password) + if (storedUser == null) return AnyResponseHelper.bad_request("Incorrect username or password!") + if (storedUser.size > 1) return AnyResponseHelper.bad_request("More than one users were found!") + val accessToken = (storedUser(0) \ SCHEMA.fAccessToken).as[String] + if (accessToken == null) return AnyResponseHelper.bad_request("User doesn't have access token!") + + val user = storedUser(0).as[JsObject] - SCHEMA.fPassword + val res = Json.obj("user" -> user) + return AnyResponseHelper.ok(res, "Successfully found user.") + } + + inner(request) + } + + def register() = Action { + implicit request => + def inner(request: Request[AnyContent]): Result = { + val anyReq: OAuth2Request = new OAuth2Request(request) + if (!anyReq.assertJsonBody()) return AnyResponseHelper.bad_request(AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + val json = anyReq.getJsonBody() + LPLogger.D2("register: " + json) + val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fUsername, SCHEMA.fPassword, SCHEMA.fName, SCHEMA.fEmail) + if (checkRequirements != null) return checkRequirements + val name = (json \ SCHEMA.fName).as[String] + val email = (json \ SCHEMA.fEmail).as[String] + val username = (json \ SCHEMA.fUsername).as[String] + val password = (json \ SCHEMA.fPassword).as[String] + val external = "anyplace" + var accType = "user" + if (pds.getIDatasource.isAdmin(SCHEMA.cUsers)) // if first user then assign as admin + accType = "admin" + // Check if the email is unique + val storedEmail = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cUsers, SCHEMA.fEmail, email) + if (storedEmail != null) return AnyResponseHelper.bad_request("There is already an account with this email.") + // Check if the username is unique + val storedUsername = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cUsers, SCHEMA.fUsername, username) + if (storedUsername != null) return AnyResponseHelper.bad_request("Username is already taken.") + val newUser = pds.getIDatasource.register(SCHEMA.cUsers, name, email, username, password, external, accType) + if (newUser == null) return AnyResponseHelper.bad_request("Please try again.") + // TODO:NN change return to "succesffully ... pls login.." + val res: JsValue = Json.obj("newUser" -> newUser) + return AnyResponseHelper.ok(res,"Succefully registered!") + } + inner(request) + } + + // CLR:PM + /** + * Fetches the account with the AUID passed in. + * The account document is returned in the Json response. + * + * @return + */ + //def fetchAccount(auid_in: String) = Action { + // implicit request => + // + // def inner(request: Request[AnyContent]): Result = { + // var auid: String = auid_in + // // create the Request and check it + // val anyReq: OAuth2Request = new OAuth2Request(request) + // if (!anyReq.assertJsonBody()) { + // return AnyResponseHelper.bad_request( + // AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + // } + // val json = anyReq.getJsonBody() + // LPLogger.info("AnyplaceAccounts::fetchAccount():: " + json.toString) + // // check if there is any required parameter missing + // val notFound: java.util.List[String] = + // JsonUtils.hasProperties(json, "auid") + // if (!notFound.isEmpty && (auid == null || auid.trim().isEmpty)) { + // return AnyResponseHelper.requiredFieldsMissing(notFound) + // } + // // if the auid in the route is empty then try to get the one from the POST json body + // if (auid == null || auid.trim().isEmpty) + // auid = json.\\("auid").mkString + // try { + // var storedAccount: JsonObject = null + // storedAccount = + // toCouchObject(CouchbaseDatasource.getStaticInstance(conf).getFromKeyAsJson(auid)) + // if (storedAccount == null) { + // return AnyResponseHelper.bad_request("Account could not be found!") + // } + // return AnyResponseHelper.ok(storedAccount, + // "Successfully created account!") + // } catch { + // case e: DatasourceException => + // return AnyResponseHelper.internal_server_error( + // "500: " + e.getMessage) + // + // } + // } + // + // inner(request) + //} + +} diff --git a/server/app/controllers/AnyplaceWebApps.scala b/server/app/controllers/WebAppController.scala similarity index 58% rename from server/app/controllers/AnyplaceWebApps.scala rename to server/app/controllers/WebAppController.scala index 58931b79f..382bd11e2 100644 --- a/server/app/controllers/AnyplaceWebApps.scala +++ b/server/app/controllers/WebAppController.scala @@ -36,40 +36,44 @@ package controllers import datasources.SCHEMA -import play.mvc.{Http, Security} -import play.api.mvc.{Action, Result} -import play.Play +import play.api.Environment +import play.api.mvc.{AbstractController, ControllerComponents, Result} +//import play.Play +import javax.inject.{Inject, Singleton} -object AnyplaceWebApps extends play.api.mvc.Controller { +@Singleton +class WebAppController @Inject()(cc: ControllerComponents, + env: Environment) extends AbstractController(cc) { def AddTrailingSlash() = Action { implicit request => MovedPermanently(request.path + "/") } - def serveArchitect2(file: String) = Action { + def serveArchitect(file: String) = Action { val archiDir = "public/anyplace_architect" serveFile(archiDir, file) } - def servePortal(file: String) = Action { - val viewerDir = "web_apps/anyplace_portal" - serveFile(viewerDir, file) - } - - def servePortalTos(file: String) = Action { - val viewerDir = "web_apps/anyplace_portal/tos" - serveFile(viewerDir, file) - } - - def servePortalPrivacy(file: String) = Action { - val viewerDir = "web_apps/anyplace_portal/privacy" - serveFile(viewerDir, file) - } - - def servePortalMail(file: String) = Action { - val viewerDir = "web_apps/anyplace_portal/mail" - serveFile(viewerDir, file) - } + // CLR:PM + //def servePortal(file: String) = Action { + // val viewerDir = "web_apps/anyplace_portal" + // serveFile(viewerDir, file) + //} + // + //def servePortalTos(file: String) = Action { + // val viewerDir = "web_apps/anyplace_portal/tos" + // serveFile(viewerDir, file) + //} + // + //def servePortalPrivacy(file: String) = Action { + // val viewerDir = "web_apps/anyplace_portal/privacy" + // serveFile(viewerDir, file) + //} + // + //def servePortalMail(file: String) = Action { + // val viewerDir = "web_apps/anyplace_portal/mail" + // serveFile(viewerDir, file) + //} def serveViewer(file: String) = Action { implicit request => val mode = request.getQueryString("mode").getOrElse("") @@ -91,43 +95,43 @@ object AnyplaceWebApps extends play.api.mvc.Controller { serveFile(viewerDir, file) } - def serveViewer2(file: String) = Action { request => - val mode = request.getQueryString("mode").getOrElse("") - if (mode == null || !mode.equalsIgnoreCase("widget")) { - var bid = request.getQueryString("buid").getOrElse("") - var pid = request.getQueryString("selected").getOrElse("") - var floor = request.getQueryString(SCHEMA.fFloor).getOrElse("") - } - val viewerDir = "public/anyplace_viewer_campus" - serveFile(viewerDir, file) - } + //def serveViewer2(file: String) = Action { request => + // val mode = request.getQueryString("mode").getOrElse("") + // if (mode == null || !mode.equalsIgnoreCase("widget")) { + // var bid = request.getQueryString("buid").getOrElse("") + // var pid = request.getQueryString("selected").getOrElse("") + // var floor = request.getQueryString(SCHEMA.fFloor).getOrElse("") + // } + // val viewerDir = "public/anyplace_viewer_campus" + // serveFile(viewerDir, file) + //} def serveDevelopers(file: String) = Action { - val devsDir = "public/anyplace_developers" + val devsDir = "public/developers" serveFile(devsDir, file) } - def parseCookieForUsername(request: Http.Request): String = { - val cookie = request.cookie("PLAY_SESSION").value() - val data = cookie.substring(cookie.indexOf('-') + 1) - val pairs = data.split(" ") - for (pair <- pairs) { - val dat = pair.split("%3A") - val key = dat(0) - val value = dat(1) - if (key == "username") { - return value - } - } - "" - } - - // The action that serves the Admin website - @Security.Authenticated(classOf[Secured]) - def serveAdmin(file: String) = Action { - val accountsDir = "web_apps/anyplace_accounts" - serveFile(accountsDir, file) - } + //def parseCookieForUsername(request: Http.Request): String = { + // val cookie = request.cookie("PLAY_SESSION").value() + // val data = cookie.substring(cookie.indexOf('-') + 1) + // val pairs = data.split(" ") + // for (pair <- pairs) { + // val dat = pair.split("%3A") + // val key = dat(0) + // val value = dat(1) + // if (key == "username") { + // return value + // } + // } + // "" + //} + // + //// The action that serves the Admin website + //@Security.Authenticated(classOf[Secured]) + //def serveAdmin(file: String) = Action { + // val accountsDir = "web_apps/anyplace_accounts" + // serveFile(accountsDir, file) + //} def serveFile(appDir: String, file_in: String): Result = { var header = ("", "") @@ -140,9 +144,8 @@ object AnyplaceWebApps extends play.api.mvc.Controller { file_str = "index.html" header = ("Content-Disposition", "inline") } - val reqFile = appDir + "/" + file_str - val file = Play.application().resourceAsStream(reqFile) - + val reqFile: String = appDir + "/" + file_str + val file = env.classLoader.getResourceAsStream(reqFile) if (file != null) Ok(scala.io.Source.fromInputStream(file, "UTF-8").mkString).as("text/html") else diff --git a/server/app/controllers/helper/Mapping.scala b/server/app/controllers/helper/Mapping.scala new file mode 100644 index 000000000..08a2c08f7 --- /dev/null +++ b/server/app/controllers/helper/Mapping.scala @@ -0,0 +1,197 @@ +package controllers.helper + +import java.io.{File, FileNotFoundException, FileOutputStream, IOException} +import java.nio.file.Files + +import datasources.{DatasourceException, ProxyDataSource, SCHEMA} +import db_models.Floor +import javax.inject.Inject +import json.VALIDATE.{Coordinate, StringNumber} +import play.api.Configuration +import play.api.libs.json.{JsValue, Json} +import play.api.mvc.Result +import radiomapserver.RadioMap.{RBF_ENABLED, RadioMap} +import utils.LPUtils.{MD5, generateRandomRssLogFileName} +import utils.{AnyResponseHelper, AnyplaceServerAPI, FileUtils, GeoPoint, LPLogger} +import javax.inject.Singleton + +@Singleton +class Mapping @Inject() (api: AnyplaceServerAPI, conf: Configuration, fu: FileUtils, pds: ProxyDataSource){ + val BBOX_MAX = 500 + /** + * Now this is synchronously called. + * + * @param buid + * @param floor_number + * @return a status regarding the frozen radio_map creation. + */ + def updateFrozenRadioMap(buid: String, floor_number: String): String = { + val cls = "updateFrozenRadioMap: " + if (!Floor.checkFloorNumberFormat(floor_number)) { + return null + } + LPLogger.info(cls + buid + ":" + floor_number) + + val radioMapsFrozenDir = conf.get[String]("radioMapFrozenDir") + + val rmapDir = new File(radioMapsFrozenDir + api.URL_SEP + buid + api.URL_SEP + + floor_number) + + if (!rmapDir.exists() && !rmapDir.mkdirs()) { + return cls + "failed to create: " + rmapDir.toString + } + val rssLogPerFloor = new File(rmapDir.getAbsolutePath + api.URL_SEP + "rss-log") + var fout: FileOutputStream = null + try { + fout = new FileOutputStream(rssLogPerFloor) + LPLogger.D1(cls + "Creating rss-log: " + rssLogPerFloor.toPath().getFileName.toString) + } catch { + case e: FileNotFoundException => return cls + e.getClass + ": " + e.getMessage + } + var floorFetched: Long = 0 + try { + floorFetched = pds.getIDatasource.dumpRssLogEntriesByBuildingFloor(fout, buid, floor_number) + fout.close() + } catch { + case e: DatasourceException => return cls + e.getClass + ": " + e.getMessage + case e: IOException => return cls + e.getClass + " Error while closing rss-log: " + e.getMessage + } + if (floorFetched == 0) { + return null + } + val radiomap_filename = new File(rmapDir.toString + api.URL_SEP + "indoor-radiomap.txt") + .getAbsolutePath + val rm = new RadioMap(new File(rmapDir.toString), radiomap_filename, "", -110) + val resCreate = rm.createRadioMap() + if (resCreate != null) return cls + "Failed: createRadioMap: " + resCreate + null + } + + /** + * Every time it creates a new radiomap file + * We have only coordinates and floor. We dont have a building so we download from a bounding box + * + * @param json + * @param range + * @return + */ + def findRadioBbox(json: JsValue, range: Int): Result = { + if (Coordinate(json, SCHEMA.fCoordinatesLat) == null) + return AnyResponseHelper.bad_request("coordinates_lat field must be String containing a float!") + val lat = (json \ SCHEMA.fCoordinatesLat).as[String] + if (Coordinate(json, SCHEMA.fCoordinatesLon) == null) + return AnyResponseHelper.bad_request("coordinates_lon field must be String containing a float!") + val lon = (json \ SCHEMA.fCoordinatesLon).as[String] + if (StringNumber(json, SCHEMA.fFloorNumber) == null) + return AnyResponseHelper.bad_request("floor_number field must be String, containing a number!") + val floorNumber = (json \ SCHEMA.fFloorNumber).as[String] + if (!Floor.checkFloorNumberFormat(floorNumber)) { + return AnyResponseHelper.bad_request("Floor number cannot contain whitespace!") + } else { + val bbox = GeoPoint.getGeoBoundingBox(java.lang.Double.parseDouble(lat), java.lang.Double.parseDouble(lon), + range) + LPLogger.D4("LowerLeft: " + bbox(0) + " UpperRight: " + bbox(1)) + + // create unique name for cached file based on coordinates, floor_number, range + val pathName = "radiomaps" + val hashKey = lat + lon + floorNumber + val bboxRadioDir = MD5(hashKey) + "-" + range.toString + LPLogger.debug("hashkey = " + hashKey) + LPLogger.debug("bbox_token = " + bboxRadioDir) + // store in radioMapRawDir/tmp/buid/floor/bbox_token + val fullPath = conf.get[String]("radioMapRawDir") + "/bbox/" + bboxRadioDir + val dir = new File(fullPath) + val radiomap_filename = new File(fullPath + api.URL_SEP + "indoor-radiomap.txt") + .getAbsolutePath + var msg = "" + if (!dir.exists()) { + // if the range is maximum then we are looking for the entire floor + if (range == BBOX_MAX) { + val buid = pds.getIDatasource.dumpRssLogEntriesWithCoordinates(floorNumber, lat.toDouble, lon.toDouble) + if (buid != null) { // building found. return path to file + val radiomap_mean_filename = api.SERVER_API_ROOT + val path = radiomap_mean_filename.dropRight(1) + fu.getDirFrozenFloor(buid, floorNumber) + "/indoor-radiomap-mean.txt" + val res = Json.obj("map_url_mean" -> path) + return AnyResponseHelper.ok(res, "Successfully retrieved radiomap: full-floor (according to lat lon)") + } + } + msg = "created bbox: " + fullPath + if (!dir.mkdirs()) { + return AnyResponseHelper.internal_server_error("Failed to create bbox dir: " + fullPath) + } + val rssLog = new File(dir.getAbsolutePath + api.URL_SEP + "rss-log") + var fout: FileOutputStream = null + var floorFetched: Long = 0L + try { + fout = new FileOutputStream(rssLog) + LPLogger.D5("RSS path: " + rssLog.toPath().getFileName.toString) + floorFetched = pds.getIDatasource.dumpRssLogEntriesSpatial(fout, bbox, floorNumber) + fout.close() + if (floorFetched == 0) { + return AnyResponseHelper.bad_request("Area not supported yet!") + } + val rm = new RadioMap(new File(fullPath), radiomap_filename, "", -110) + val resCreate = rm.createRadioMap() + if (resCreate != null) { + return AnyResponseHelper.internal_server_error("findRadioBbox: radiomap on-the-fly: " + resCreate) + } + } catch { + case fnfe: FileNotFoundException => return AnyResponseHelper.internal_server_error("findRadioBbox: " + + "rssLog: " + rssLog, fnfe) + case e: Exception => return AnyResponseHelper.internal_server_error("findRadioBbox" , e) + } + } else { + msg = "cached-bbox: " + fullPath + LPLogger.debug("findRadioBbox: " + msg) + } + var radiomap_mean_filename = radiomap_filename.replace(".txt", "-mean.txt") + var radiomap_rbf_weights_filename = radiomap_filename.replace(".txt", "-weights.txt") + var radiomap_parameters_filename = radiomap_filename.replace(".txt", "-parameters.txt") + val url = api.SERVER_API_ROOT + var pos = radiomap_mean_filename.indexOf(pathName) + radiomap_mean_filename = url + radiomap_mean_filename.substring(pos) + var res: JsValue = null + if (RBF_ENABLED) { + pos = radiomap_rbf_weights_filename.indexOf(pathName) + radiomap_rbf_weights_filename = url + radiomap_rbf_weights_filename.substring(pos) + pos = radiomap_parameters_filename.indexOf(pathName) + radiomap_parameters_filename = url + radiomap_parameters_filename.substring(pos) + res = Json.obj("map_url_mean" -> radiomap_mean_filename, + "map_url_weights" -> radiomap_rbf_weights_filename, "map_url_parameters" -> radiomap_parameters_filename) + } else { + res = Json.obj("map_url_mean" -> radiomap_mean_filename) + } + + AnyResponseHelper.ok(res, "Successfully retrieved radiomap: " + msg) + } + } + + def storeRadioMapRawToServer(file: File): Boolean = { + /* + * FeatureAdd : Configuring location for server generated files + */ + //val radio_dir = "radio_maps_raw/" + val radio_dir = conf.get[String]("radioMapRawDir") + val dir = new File(radio_dir) + dir.mkdirs() + if (!dir.isDirectory || !dir.canWrite() || !dir.canExecute()) { + return false + } + val name = generateRandomRssLogFileName() + //FeatureAdd : Configuring location for server generated files + val dest_f = new File(radio_dir + api.URL_SEP + name) + var fout: FileOutputStream = null + try { + fout = new FileOutputStream(dest_f) + Files.copy(file.toPath(), fout) + fout.close() + LPLogger.D1("storeRadioMapToServer: Stored raw rss-log: " + name) + } catch { + case e: IOException => { + e.printStackTrace() + return false + } + } + true + } +} diff --git a/server/app/controllers/helper/User.scala b/server/app/controllers/helper/User.scala new file mode 100644 index 000000000..e651b770f --- /dev/null +++ b/server/app/controllers/helper/User.scala @@ -0,0 +1,24 @@ +package controllers.helper + +import datasources.{ProxyDataSource, SCHEMA} +import javax.inject.Inject +import play.api.libs.json.JsValue +import javax.inject.Singleton + +@Singleton +class User @Inject()(pds: ProxyDataSource){ + + /** + * Checks in database if a user exists with the access_token of the json. + * + * @param json original request. + * @return the owner_id of the user. + */ + def authorize(json: JsValue): String = { + val token = (json \ SCHEMA.fAccessToken).as[String] + val user = pds.getIDatasource.getFromKeyAsJson(SCHEMA.cUsers, SCHEMA.fAccessToken, token) + if (user != null) + return (user \ SCHEMA.fOwnerId).as[String] + null + } +} diff --git a/server/app/datasources/CouchbaseDatasource.scala b/server/app/datasources/CouchbaseDatasource.scala index 493bc745b..546026929 100644 --- a/server/app/datasources/CouchbaseDatasource.scala +++ b/server/app/datasources/CouchbaseDatasource.scala @@ -35,7 +35,7 @@ */ package datasources -import java.io.{FileOutputStream, IOException, PrintWriter} +import java.io.{FileOutputStream, IOException} import java.util import java.util.concurrent.TimeUnit import java.util.{ArrayList, Collections, HashMap} @@ -44,43 +44,41 @@ import accounts.IAccountService import com.couchbase.client.java.document.JsonDocument import com.couchbase.client.java.document.json.{JsonArray, JsonObject} import com.couchbase.client.java.env.DefaultCouchbaseEnvironment -import com.couchbase.client.java.view.{SpatialViewQuery, ViewQuery} +import com.couchbase.client.java.view.ViewQuery import com.couchbase.client.java.{Bucket, CouchbaseCluster, PersistTo} -import db_models.{Connection, Poi, RadioMapRaw} +import db_models.Connection import floor_module.IAlgo import oauth.provider.v2.models.{AccessTokenModel, AccountModel, AuthInfo} import oauth.provider.v2.token.TokenService -import play.Play +import play.api.Configuration import play.api.libs.json.{JsValue, Json} -import utils.JsonUtils.{fromCouchList, fromCouchObject, toCouchObject} -import utils.{GeoPoint, JsonUtils, LPLogger} +import play.twirl.api.TwirlHelperImports.twirlJavaCollectionToScala +import utils.{GeoPoint, LPLogger} import scala.collection.mutable.ListBuffer -//remove if not needed -import scala.collection.JavaConversions._ - +import scala.jdk.CollectionConverters.{CollectionHasAsScala, IterableHasAsScala} object CouchbaseDatasource { - private var sInstance: CouchbaseDatasource = null - private var sLockInstance: AnyRef = new AnyRef() - - def getStaticInstance: CouchbaseDatasource = { + private val sLockInstance: AnyRef = new AnyRef() + + def initialize(conf: Configuration): CouchbaseDatasource = { sLockInstance.synchronized { if (sInstance == null) { - val clusterNodes = Play.application().configuration().getString("couchbase.clusterNodes") - val hostname = Play.application().configuration().getString("couchbase.hostname") - val port = Play.application().configuration().getString("couchbase.port") - val username = Play.application().configuration().getString("couchbase.username") - val bucket = Play.application().configuration().getString("couchbase.bucket") - val password = Play.application().configuration().getString("couchbase.password") + // It either users clusterNodes or hostname + var clusterNodes : String = null + var hostname :String = null + if (conf.has("couchbase.clusterNodes")) clusterNodes = conf.get[String]("couchbase.clusterNodes") + if (conf.has("couchbase.hostname")) hostname = conf.get[String]("couchbase.hostname") + val port = conf.get[String]("couchbase.port") + val username = conf.get[String]("couchbase.username") + val bucket = conf.get[String]("couchbase.bucket") + val password = conf.get[String]("couchbase.password") sInstance = CouchbaseDatasource.createNewInstance(hostname, clusterNodes, port, bucket, username, password) try { sInstance.init() } catch { - case e: DatasourceException => LPLogger.error("CouchbaseDatasource::getStaticInstance():: Exception while instantiating Couchbase [" + - e.getMessage + - "]") + case e: DatasourceException => LPLogger.error("CouchbaseDatasource: INIT ERROR: " + e.getMessage) } } sInstance @@ -242,7 +240,7 @@ class CouchbaseDatasource private(hostname: String, def getFromKey(collection:String, key: String, value: String): JsValue = ??? - override def getFromKey(key: String): JsonDocument = { + def getFromKey(key: String): JsonDocument = { val client = getConnection val db_res = client.get(key) db_res @@ -250,51 +248,51 @@ class CouchbaseDatasource private(hostname: String, override def getFromKeyAsJson(collection: String, key: String, value: String): JsValue = ??? - override def getFromKeyAsJson(key: String): JsValue = { - if (key == null || key.trim().isEmpty) { - throw new IllegalArgumentException("No null or empty string allowed as key!") - } - val db_res = getFromKey(key) - if (db_res == null) { - return null - } - try { - val jsonNode = db_res.content() - LPLogger.debug("json node = " + jsonNode) - fromCouchObject(jsonNode) - } catch { - case e: IOException => { - LPLogger.error("CouchbaseDatasource::getFromKeyAsJson():: Could not convert document from Couchbase into JSON!") - null - } - } - } + //def getFromKeyAsJson(key: String): JsValue = { + // if (key == null || key.trim().isEmpty) { + // throw new IllegalArgumentException("No null or empty string allowed as key!") + // } + // val db_res = getFromKey(key) + // if (db_res == null) { + // return null + // } + // try { + // val jsonNode = db_res.content() + // LPLogger.debug("json node = " + jsonNode) + // fromCouchObject(jsonNode) + // } catch { + // case e: IOException => { + // LPLogger.error("CouchbaseDatasource::getFromKeyAsJson():: Could not convert document from Couchbase into JSON!") + // null + // } + // } + //} override def fingerprintExists(collection: String, buid: String, floor: String, x: String, y: String, heading: String): Boolean = ??? // override def buildingFromKeyAsJson(key: String): JsValue = ??? - override def buildingFromKeyAsJson(key: String): JsValue = { - val building = toCouchObject(getFromKeyAsJson(key)) - if (building == null) { - return null - } - val floors = JsonArray.empty() - for (f <- floorsByBuildingAsJson(key)) { - floors.add(f) - } - building.put("floors", floors) - val pois = JsonArray.empty() - for (p <- poisByBuildingAsJson(key)) { - if (!toCouchObject(p).getString("pois_type").equalsIgnoreCase(Poi.POIS_TYPE_NONE)) //continue - pois.add(p) - } - building.put("pois", floors) - fromCouchObject(building) - } + //override def buildingFromKeyAsJson(key: String): JsValue = { + // val building = toCouchObject(getFromKeyAsJson(key)) + // if (building == null) { + // return null + // } + // val floors = JsonArray.empty() + // for (f <- floorsByBuildingAsJson(key).asScala) { + // floors.add(f) + // } + // building.put("floors", floors) + // val pois = JsonArray.empty() + // for (p <- poisByBuildingAsJson(key).asScala) { + // if (!toCouchObject(p).getString("pois_type").equalsIgnoreCase(Poi.POIS_TYPE_NONE)) //continue + // pois.add(p) + // } + // building.put("pois", floors) + // fromCouchObject(building) + //} override def poiByBuidFloorPuid(buid: String, floor_number: String, puid: String): Boolean = ??? - override def poiFromKeyAsJson(collection: String, key: String, value: String): JsValue = getFromKeyAsJson(key) + //override def poiFromKeyAsJson(collection: String, key: String, value: String): JsValue = getFromKeyAsJson(key) override def poisByBuildingFloorAsJson(buid: String, floor_number: String): List[JsValue] = ??? @@ -343,7 +341,7 @@ class CouchbaseDatasource private(hostname: String, val pois = new ArrayList[JsonObject]() var json: JsonObject = null - for (row <- res.allRows()) { + for (row <- res.allRows().asScala) { try { json = row.document().content() json.removeKey("owner_id") @@ -356,43 +354,43 @@ class CouchbaseDatasource private(hostname: String, pois } - override def poisByBuildingAsMap(buid: String): java.util.List[HashMap[String, String]] = { - val couchbaseClient = getConnection - val viewQuery = ViewQuery.from("nav", "pois_by_buid").includeDocs(true).key((buid)) - - val res = couchbaseClient.query(viewQuery) - - val pois = new ArrayList[HashMap[String, String]]() - - for (row <- res.allRows()) { - pois.add(JsonUtils.getHashMapStrStr(fromCouchObject(row.document().content()))) - } - pois - } - - override def floorsByBuildingAsJson(buid: String): java.util.List[JsValue] = { - val floors = new ArrayList[JsValue]() - val couchbaseClient = getConnection - val viewQuery = ViewQuery.from("nav", "floor_by_buid").key(buid).includeDocs(true) - - val res = couchbaseClient.query(viewQuery) - LPLogger.debug("couchbase results: " + res.totalRows()) - if (!res.success()) { - throw new DatasourceException("Error retrieving floors from database!") - } - var json: JsonObject = null + //override def poisByBuildingAsMap(buid: String): java.util.List[HashMap[String, String]] = { + // val couchbaseClient = getConnection + // val viewQuery = ViewQuery.from("nav", "pois_by_buid").includeDocs(true).key((buid)) + // + // val res = couchbaseClient.query(viewQuery) + // + // val pois = new ArrayList[HashMap[String, String]]() + // + // for (row <- res.allRows().asScala) { + // pois.add(JsonUtils.getHashMapStrStr(fromCouchObject(row.document().content()))) + // } + // pois + //} - for (row <- res.allRows()) { - try { - json = row.document().content() - json.removeKey("owner_id") - floors.add(fromCouchObject(json)) - } catch { - case e: IOException => - } - } - floors - } + //override def floorsByBuildingAsJson(buid: String): java.util.List[JsValue] = { + // val floors = new ArrayList[JsValue]() + // val couchbaseClient = getConnection + // val viewQuery = ViewQuery.from("nav", "floor_by_buid").key(buid).includeDocs(true) + // + // val res = couchbaseClient.query(viewQuery) + // LPLogger.debug("couchbase results: " + res.totalRows()) + // if (!res.success()) { + // throw new DatasourceException("Error retrieving floors from database!") + // } + // var json: JsonObject = null + // + // for (row <- res.allRows().asScala) { + // try { + // json = row.document().content() + // json.removeKey("owner_id") + // floors.add(fromCouchObject(json)) + // } catch { + // case e: IOException => + // } + // } + // floors + //} override def connectionsByBuildingAllFloorsAsJson(buid: String): List[JsValue] = ??? // @throws[DatasourceException] @@ -451,7 +449,7 @@ class CouchbaseDatasource private(hostname: String, var hm: HashMap[String, String] = null val conns = new ArrayList[HashMap[String, String]]() - for (row <- res.allRows()) { + for (row <- res.allRows().asScala) { // hm = JsonUtils.getHashMapStrStr(row.document().content()) if (!hm.get("edge_type").equalsIgnoreCase(Connection.EDGE_TYPE_OUTDOOR)) conns.add(hm) @@ -489,7 +487,7 @@ class CouchbaseDatasource private(hostname: String, val viewQuery = ViewQuery.from("nav", "all_by_buid").includeDocs(true).key((buid)) val res = couchbaseClient.query(viewQuery) - for (row <- res.allRows()) { + for (row <- res.allRows().asScala) { val id = row.id() val db_res = couchbaseClient.remove(id, PersistTo.ONE) try { @@ -501,7 +499,7 @@ class CouchbaseDatasource private(hostname: String, case e: Exception => all_items_failed.add(id) } } - all_items_failed + //all_items_failed false } @@ -546,7 +544,7 @@ class CouchbaseDatasource private(hostname: String, val res = couchbaseClient.query(viewQuery) - for (row <- res.allRows()) { + for (row <- res.allRows().asScala) { val id = row.id() val db_res = couchbaseClient.remove(id, PersistTo.ONE) try { @@ -572,7 +570,7 @@ class CouchbaseDatasource private(hostname: String, LPLogger.debug("couchbase results: " + res.totalRows) var json: JsonObject = null - for (row <- res.allRows()) { + for (row <- res.allRows().asScala) { try { json = row.key().asInstanceOf[JsonObject] json.put("weight", row.value().toString) @@ -810,7 +808,7 @@ class CouchbaseDatasource private(hostname: String, val res = couchbaseClient.query(viewQuery) var json: JsonObject = null var jsonCheck: JsonObject = null - for (row <- res.allRows()) { + for (row <- res.allRows().asScala) { try { json = JsonObject.empty() jsonCheck = JsonObject.empty() @@ -841,7 +839,7 @@ class CouchbaseDatasource private(hostname: String, val viewQuery = ViewQuery.from("heatmaps", "heatmap_by_floor_building").includeDocs(true).key((id)) val res = couchbaseClient.query(viewQuery) - for (row <- res.allRows()) { + for (row <- res.allRows().asScala) { val id = row.id() val db_res = couchbaseClient.remove(id, PersistTo.ONE) try { @@ -957,28 +955,28 @@ class CouchbaseDatasource private(hostname: String, // override def getAllBuildings(): List[JsValue] = ??? - override def getAllBuildings(): List[JsValue] = { - - val buildings = new ArrayList[JsonObject]() - val couchbaseClient = getConnection - val viewQuery = ViewQuery.from("nav", "building_all").includeDocs(true) - val res = couchbaseClient.query(viewQuery) - // - - for (row <- res.allRows()) { - try { - val json = row.document().content() - json.removeKey("geometry") - json.removeKey("owner_id") - json.removeKey("co_owners") - buildings.add(json) - - } catch { - case e: IOException => - } - } - fromCouchList(buildings) - } + //override def getAllBuildings(): List[JsValue] = { + // + // val buildings = new ArrayList[JsonObject]() + // val couchbaseClient = getConnection + // val viewQuery = ViewQuery.from("nav", "building_all").includeDocs(true) + // val res = couchbaseClient.query(viewQuery) + // // + // + // for (row <- res.allRows().asScala) { + // try { + // val json = row.document().content() + // json.removeKey("geometry") + // json.removeKey("owner_id") + // json.removeKey("co_owners") + // buildings.add(json) + // + // } catch { + // case e: IOException => + // } + // } + // fromCouchList(buildings) + //} override def getAllBuildingsByOwner(oid: String): List[JsValue] = ??? // override def getAllBuildingsByOwner(oid: String): java.util.List[JsonObject] = { @@ -1045,7 +1043,7 @@ class CouchbaseDatasource private(hostname: String, // try { // json = row.document().content() // val pub = json.getString("is_published") == null || json.getString("is_published").equalsIgnoreCase("true") - // val owner = json.getString("owner_id").equals(owner_id) || json.getArray("co_owners").toList.contains(owner_id) + // val owner = json.getString("owner_id").equals(owner_id) || json.getArray("co_owners").asScala.contains(owner_id) // if (pub || owner) { // json.removeKey("geometry") // json.removeKey("owner_id") @@ -1134,7 +1132,7 @@ class CouchbaseDatasource private(hostname: String, val viewQuery = ViewQuery.from("nav", "get_campus").includeDocs(true) val res = couchbaseClient.query(viewQuery) var json: JsonObject = null - for (row <- res.allRows()) { + for (row <- res.allRows().asScala) { try { json = row.document().content() var cuid = json.getString("cuid") @@ -1171,144 +1169,144 @@ class CouchbaseDatasource private(hostname: String, // buildingsets // } - /** - * fetch all rss entries and write them in a file - * @param outFile - * @param bbox - * @param floor_number - * @return total of rss entries of a specifi floor - */ - override def dumpRssLogEntriesSpatial(outFile: FileOutputStream, bbox: Array[GeoPoint], floor_number: String): Long = { - val writer = new PrintWriter(outFile) - val floorLimit = 100000 - val queryLimit = 5000 - var totalFetched = 0 - var currentFetched = 0 - var floorFetched = 0 - var rssEntry: JsonObject = null - val couchbaseClient = getConnection - try { - do { - val viewQuery = SpatialViewQuery.from("nav_spatial", "building_coordinates") - .startRange(JsonArray.from(new java.lang.Double(bbox(0).dlat), new java.lang.Double(bbox(0).dlon))) - .endRange(JsonArray.from(new java.lang.Double(bbox(1).dlat), new java.lang.Double(bbox(1).dlon))).includeDocs(true).limit(queryLimit).skip(totalFetched) - val res = couchbaseClient.query(viewQuery) - currentFetched = 0 - for (row <- res) { - currentFetched += 1 - rssEntry = row.document().content() - - if (rssEntry.getString("floor") == floor_number) { - floorFetched += 1 - // re-create old fingerprints in order to call that method - writer.println(RadioMapRaw.toRawRadioMapRecord(fromCouchObject(rssEntry))) - } - } - totalFetched += currentFetched - LPLogger.info("total fetched: " + totalFetched) - // check limits - } while (currentFetched >= queryLimit && floorFetched < floorLimit); - writer.flush() - writer.close() - } catch { - case e: Exception => LPLogger.error("dumpRssLogEntriesSpatial: " + e.getClass + ": " + e.getMessage)//continue - } - floorFetched - } + ///** + // * fetch all rss entries and write them in a file + // * @param outFile + // * @param bbox + // * @param floor_number + // * @return total of rss entries of a specifi floor + // */ + //override def dumpRssLogEntriesSpatial(outFile: FileOutputStream, bbox: Array[GeoPoint], floor_number: String): Long = { + // val writer = new PrintWriter(outFile) + // val floorLimit = 100000 + // val queryLimit = 5000 + // var totalFetched = 0 + // var currentFetched = 0 + // var floorFetched = 0 + // var rssEntry: JsonObject = null + // val couchbaseClient = getConnection + // try { + // do { + // val viewQuery = SpatialViewQuery.from("nav_spatial", "building_coordinates") + // .startRange(JsonArray.from(new java.lang.Double(bbox(0).dlat), new java.lang.Double(bbox(0).dlon))) + // .endRange(JsonArray.from(new java.lang.Double(bbox(1).dlat), new java.lang.Double(bbox(1).dlon))).includeDocs(true).limit(queryLimit).skip(totalFetched) + // val res = couchbaseClient.query(viewQuery) + // currentFetched = 0 + // for (row <- res.asScala) { + // currentFetched += 1 + // rssEntry = row.document().content() + // + // if (rssEntry.getString("floor") == floor_number) { + // floorFetched += 1 + // // re-create old fingerprints in order to call that method + // writer.println(RadioMapRaw.toRawRadioMapRecord(fromCouchObject(rssEntry))) + // } + // } + // totalFetched += currentFetched + // LPLogger.info("total fetched: " + totalFetched) + // // check limits + // } while (currentFetched >= queryLimit && floorFetched < floorLimit); + // writer.flush() + // writer.close() + // } catch { + // case e: Exception => LPLogger.error("dumpRssLogEntriesSpatial: " + e.getClass + ": " + e.getMessage)//continue + // } + // floorFetched + //} override def dumpRssLogEntriesWithCoordinates(floor_number: String, lat: Double, lon: Double): String = ??? - override def dumpRssLogEntriesByBuildingFloor(outFile: FileOutputStream, buid: String, floor_number: String): Long = { - val writer = new PrintWriter(outFile) - val couchbaseClient = getConnection - val queryLimit = 10000 - var totalFetched = 0 - var currentFetched: Int = 0 - var rssEntry: JsonObject = null - - var viewQuery = ViewQuery.from("radio", "raw_radio_building_floor").key(JsonArray.from(buid, floor_number)).includeDocs(true) - - do { - viewQuery = ViewQuery.from("radio", "raw_radio_building_floor").key(JsonArray.from(buid, floor_number)).includeDocs(true).limit(queryLimit).skip(totalFetched) - - val res = couchbaseClient.query(viewQuery) - if (!(res.totalRows() > 0)) return totalFetched - currentFetched = 0 - - for (row <- res.allRows()) { - currentFetched += 1 - try { - rssEntry = row.document().content() - } catch { - case e: IOException => //continue - } - writer.println(RadioMapRaw.toRawRadioMapRecord(fromCouchObject(rssEntry))) - } - totalFetched += currentFetched - LPLogger.info("total fetched: " + totalFetched) - } while (currentFetched >= queryLimit) - writer.flush() - writer.close() - totalFetched - } - - override def dumpRssLogEntriesByBuildingACCESFloor(outFile: FileOutputStream, buid: String, floor_number: String): Long = { - val writer = new PrintWriter(outFile) - val couchbaseClient = getConnection - val queryLimit = 10000 - var totalFetched = 0 - var currentFetched: Int = 0 - var rssEntry: JsonObject = null - - - do { - var viewQuery = ViewQuery.from("radio", "raw_radio_building_floor").key(JsonArray.from(buid, floor_number)).includeDocs(true).limit(queryLimit).skip(totalFetched) - val res = couchbaseClient.query(viewQuery) - if (res == null) return totalFetched - currentFetched = 0 - - var threshold = 0 - var thresholdCounter= 0 - var thresholdAction = false - val results = new java.util.ArrayList[JsonObject] - for (row <- res.allRows()) { - results.add(row.document().content()) - } - - if(results.size()>200) { - threshold = results.size() / 200 - thresholdAction=true - } + //override def dumpRssLogEntriesByBuildingFloor(outFile: FileOutputStream, buid: String, floor_number: String): Long = { + // val writer = new PrintWriter(outFile) + // val couchbaseClient = getConnection + // val queryLimit = 10000 + // var totalFetched = 0 + // var currentFetched: Int = 0 + // var rssEntry: JsonObject = null + // + // var viewQuery = ViewQuery.from("radio", "raw_radio_building_floor").key(JsonArray.from(buid, floor_number)).includeDocs(true) + // + // do { + // viewQuery = ViewQuery.from("radio", "raw_radio_building_floor").key(JsonArray.from(buid, floor_number)).includeDocs(true).limit(queryLimit).skip(totalFetched) + // + // val res = couchbaseClient.query(viewQuery) + // if (!(res.totalRows() > 0)) return totalFetched + // currentFetched = 0 + // + // for (row <- res.allRows().asScala) { + // currentFetched += 1 + // try { + // rssEntry = row.document().content() + // } catch { + // case e: IOException => //continue + // } + // writer.println(RadioMapRaw.toRawRadioMapRecord(fromCouchObject(rssEntry))) + // } + // totalFetched += currentFetched + // LPLogger.info("total fetched: " + totalFetched) + // } while (currentFetched >= queryLimit) + // writer.flush() + // writer.close() + // totalFetched + //} - for (result <- results) { - if(thresholdAction) { - thresholdCounter += 1 - if (thresholdCounter % threshold == 0) { - currentFetched += 1 - try { - rssEntry = result - } catch { - case e: IOException => //continue - } - writer.println(RadioMapRaw.toRawRadioMapRecord(fromCouchObject(rssEntry))) - } - }else{ - currentFetched += 1 - try { - rssEntry = result - } catch { - case e: IOException => //continue - } - writer.println(RadioMapRaw.toRawRadioMapRecord(fromCouchObject(rssEntry))) - } - } - totalFetched += currentFetched - LPLogger.info("total fetched: " + totalFetched) - } while (currentFetched >= queryLimit) - writer.flush() - writer.close() - totalFetched - } + //override def dumpRssLogEntriesByBuildingACCESFloor(outFile: FileOutputStream, buid: String, floor_number: String): Long = { + // val writer = new PrintWriter(outFile) + // val couchbaseClient = getConnection + // val queryLimit = 10000 + // var totalFetched = 0 + // var currentFetched: Int = 0 + // var rssEntry: JsonObject = null + // + // + // do { + // var viewQuery = ViewQuery.from("radio", "raw_radio_building_floor").key(JsonArray.from(buid, floor_number)).includeDocs(true).limit(queryLimit).skip(totalFetched) + // val res = couchbaseClient.query(viewQuery) + // if (res == null) return totalFetched + // currentFetched = 0 + // + // var threshold = 0 + // var thresholdCounter= 0 + // var thresholdAction = false + // val results = new java.util.ArrayList[JsonObject] + // for (row <- res.allRows().asScala) { + // results.add(row.document().content()) + // } + // + // if(results.size()>200) { + // threshold = results.size() / 200 + // thresholdAction=true + // } + // + // for (result <- results.asScala) { + // if(thresholdAction) { + // thresholdCounter += 1 + // if (thresholdCounter % threshold == 0) { + // currentFetched += 1 + // try { + // rssEntry = result + // } catch { + // case e: IOException => //continue + // } + // writer.println(RadioMapRaw.toRawRadioMapRecord(fromCouchObject(rssEntry))) + // } + // }else{ + // currentFetched += 1 + // try { + // rssEntry = result + // } catch { + // case e: IOException => //continue + // } + // writer.println(RadioMapRaw.toRawRadioMapRecord(fromCouchObject(rssEntry))) + // } + // } + // totalFetched += currentFetched + // LPLogger.info("total fetched: " + totalFetched) + // } while (currentFetched >= queryLimit) + // writer.flush() + // writer.close() + // totalFetched + //} override def getAllAccounts(): List[JsValue] = { LPLogger.debug("couchbase getAllAccounts: ") @@ -1326,7 +1324,7 @@ class CouchbaseDatasource private(hostname: String, } var json: JsonObject = null - for (row <- res.allRows()) { + for (row <- res.allRows().asScala) { try { if (row.document() != null) { json = row.document().content() @@ -1345,67 +1343,66 @@ class CouchbaseDatasource private(hostname: String, val viewQuery = ViewQuery.from("radio", "tempview").includeDocs(true) val res = couchbaseClient.query(viewQuery) - for (row <- res.allRows()) { + for (row <- res.allRows().asScala) { deleteFromKey(row.key().toString) } true } - override def predictFloor(algo: IAlgo, bbox: Array[GeoPoint], strongestMAC: Array[String]): Boolean = { - predictFloorFast(algo, bbox, strongestMAC) - } + override def predictFloor(algo: IAlgo, bbox: Array[GeoPoint], strongestMACs: Array[String]): Boolean = ??? + //override def predictFloor(algo: IAlgo, bbox: Array[GeoPoint], strongestMAC: Array[String]): Boolean = { + // predictFloorFast(algo, bbox, strongestMAC) + //} - private def predictFloorFast(algo: IAlgo, bbox: Array[GeoPoint], strongestMACs: Array[String]): Boolean = { - val designDoc = "floor" - val viewName = "group_wifi" - val couchbaseClient = getConnection - var totalFetched = 0 - for (strongestMAC <- strongestMACs) { - - /** - * val startkey: ComplexKey = ComplexKey.of(strongestMAC, new java.lang.Double(bbox(0).dlat), new java.lang.Double(bbox(0).dlon), null) - * val endkey: ComplexKey = ComplexKey.of(strongestMAC, new java.lang.Double(bbox(1).dlat), new java.lang.Double(bbox(1).dlon), "࿿") - *query.setRange(startkey, endkey) - */ - - val viewQuery = ViewQuery.from(designDoc, viewName) - .startKey(JsonArray.from(strongestMAC, new java.lang.Double(bbox(0).dlat), new java.lang.Double(bbox(0).dlon))) - .endKey(JsonArray.from(strongestMAC, new java.lang.Double(bbox(1).dlat), new java.lang.Double(bbox(1).dlon))).includeDocs(true).skip(totalFetched) - val response = couchbaseClient.query(viewQuery) - - - var _timestamp = "" - var _floor = "0" - val bucket = new ArrayList[JsonObject](10) - if (response.nonEmpty) - for (row <- response) { - try { - val timestamp = row.key.toString - if (timestamp == strongestMAC || timestamp == "࿿") { - val value = row.value().asInstanceOf[JsonObject] - if (_timestamp != timestamp) { - if (_timestamp != "") { - //algo.proccess(bucket, _floor) - } - bucket.clear() - _timestamp = timestamp - _floor = value.getString("floor") - } - bucket.add(value) - totalFetched += 1 - } - } catch { - case e: IOException => //continue - } - } - } - LPLogger.D3("predictFloorFast fetched: " + totalFetched) - if (totalFetched > 10) { - true - } else { - false - } - } + //private def predictFloorFast(algo: IAlgo, bbox: Array[GeoPoint], strongestMACs: Array[String]): Boolean = { + // val designDoc = "floor" + // val viewName = "group_wifi" + // val couchbaseClient = getConnection + // var totalFetched = 0 + // var count = 0 + // + // for (strongestMAC <- strongestMACs) { + // LPLogger.debug("strongestMAC = " + strongestMAC) + // /** + // * val startkey: ComplexKey = ComplexKey.of(strongestMAC, new java.lang.Double(bbox(0).dlat), new java.lang.Double(bbox(0).dlon), null) + // * val endkey: ComplexKey = ComplexKey.of(strongestMAC, new java.lang.Double(bbox(1).dlat), new java.lang.Double(bbox(1).dlon), "࿿") + // *query.setRange(startkey, endkey) + // */ + // val viewQuery = ViewQuery.from(designDoc, viewName) + // .startKey(JsonArray.from(strongestMAC, new java.lang.Double(bbox(0).dlat), new java.lang.Double(bbox(0).dlon))) + // .endKey(JsonArray.from(strongestMAC, new java.lang.Double(bbox(1).dlat), new java.lang.Double(bbox(1).dlon))).includeDocs(true).skip(totalFetched) + // val response = couchbaseClient.query(viewQuery) + // + // var _floor = "0" + // val bucket = new ArrayList[JsValue](10) + // + // for (row <- response.asScala) { + // try { + // + // val value = row.value().asInstanceOf[JsonObject] + // val MAC = value.getString(SCHEMA.fMac) + // + // if (MAC == strongestMAC) { + // count = count +1 + // algo.proccess(bucket, _floor) + // bucket.clear() + // _floor = value.getString("floor") + // bucket.add(Json.parse(value.toString())) + // totalFetched += 1 + // } + // } catch { + // case e: IOException => LPLogger.D2("" + e.getClass + ": " + e.getMessage + ": " + e.getCause) + // } + // } + // } + // LPLogger.D2("predictFloorFast fetched: " + totalFetched) + // LPLogger.D2("COUNt = " + count) + // if (totalFetched > 10) { + // true + // } else { + // false + // } + //} override def magneticPathsByBuildingFloorAsJson(buid: String, floor_number: String): java.util.List[JsonObject] = { val couchbaseClient = getConnection @@ -1418,7 +1415,7 @@ class CouchbaseDatasource private(hostname: String, val result = new ArrayList[JsonObject]() var json: JsonObject = null - for (row <- res.allRows()) { + for (row <- res.allRows().asScala) { try { json = row.document().content() result.add(json) @@ -1440,7 +1437,7 @@ class CouchbaseDatasource private(hostname: String, val result = new ArrayList[JsonObject]() var json: JsonObject = null - for (row <- res.allRows()) { + for (row <- res.allRows().asScala) { try { json = row.document().content() result.add(json) @@ -1461,7 +1458,7 @@ class CouchbaseDatasource private(hostname: String, val result = new ArrayList[JsonObject]() var json: JsonObject = null - for (row <- res.allRows()) { + for (row <- res.allRows().asScala) { try { json = row.document().content() result.add(json) @@ -1494,7 +1491,7 @@ class CouchbaseDatasource private(hostname: String, var accountJson: JsonObject = null var clients: JsonArray = null var found: Boolean = false - for (row <- res) { + for (row <- res.asScala) { try accountJson = row.document().content() catch { case e: IOException => null @@ -1525,14 +1522,14 @@ class CouchbaseDatasource private(hostname: String, false } // TODO- or even maybe salting them - if (username != account.getUsername) { + if (username != account.getUsername()) { false } - if (password == null || password.trim().isEmpty) { + if (password == null || password.trim().isEmpty()) { false } // TODO- or even maybe salting them - if (password != account.getPassword) { + if (password != account.getPassword()) { false } true @@ -1551,7 +1548,7 @@ class CouchbaseDatasource private(hostname: String, null } // TODO - IMPORTANT - no refresh token is issued at the moment - new AuthInfo(account.getAuid, clientId, scope) + new AuthInfo(account.getAuid(), clientId, scope) } // TODO - maybe the database here first in order to check @@ -1575,8 +1572,8 @@ class CouchbaseDatasource private(hostname: String, val tokenModel: AccessTokenModel = TokenService.createNewAccessToken(authInfo) val db_res = client.mapAdd( - tokenModel.getTuid, tokenModel.getTuid, - tokenModel.toJson().toString, + tokenModel.getTuid(), tokenModel.getTuid(), + tokenModel.toJson().toString(), tokenModel.getExpiresIn().toInt, TimeUnit.MILLISECONDS) try if (db_res) { @@ -1605,7 +1602,7 @@ class CouchbaseDatasource private(hostname: String, var json: JsonObject = null - import scala.collection.JavaConversions._ + // import scala.collection.JavaConversions._ for (row <- res) { // handle each building entry try { json = JsonObject.empty() @@ -1628,107 +1625,107 @@ class CouchbaseDatasource private(hostname: String, points } - override def getRadioHeatmapBBox(lat: String, lon: String, buid: String, floor: String, range: Int): java.util.List[JsonObject] = { - - val points = new java.util.ArrayList[JsonObject] - val point = new java.util.HashMap[java.util.List[String], Integer]() - val xy = new java.util.ArrayList[java.util.List[String]] - - val couchbaseClient = getConnection - - val bbox = GeoPoint.getGeoBoundingBox(lat.toDouble, lon.toDouble, range) // 50 meters radius - - val viewQuery = SpatialViewQuery.from("radio", "radio_heatmap_bbox_byxy") - .startRange(JsonArray.from(new java.lang.Double(bbox(0).dlat), new java.lang.Double(bbox(0).dlon))) - .endRange(JsonArray.from(new java.lang.Double(bbox(1).dlat), new java.lang.Double(bbox(1).dlon))).includeDocs(true) - val res = couchbaseClient.query(viewQuery) - - - LPLogger.debug("couchbase results: " + res.size) - - var json: JsonObject = null - for (row <- res) { // handle each building entry - try { - json = row.document().content() - if ((json.getString("buid").compareTo("\"" + buid + "\"") == 0) && (json.getString("floor").compareTo("\"" + floor + "\"") == 0)) { - val p = new java.util.ArrayList[String] - val x = json.getString("x") - val y = json.getString("y") - p.add(x) - p.add(y) - if (point.containsKey(p)) point.put(p, point.get(p) + 1) - else { - point.put(p, 1) - xy.add(p) - } - } - } catch { - case e: IOException => - - // skip this NOT-JSON document - } - } - while ( { - !xy.isEmpty - }) { - val p = xy.remove(0) - try { - json = JsonObject.empty() - val w = "" + point.get(p) - json.put("x", p.get(0)) - json.put("y", p.get(1)) - json.put("w", w) - points.add(json) - } catch { - case e: IOException => - - //skip this NOT-JSON document - } - } - points - } - - override def getRadioHeatmapBBox2(lat: String, lon: String, buid: String, floor: String, range: Int): java.util.List[JsonObject] = { - - val points = new java.util.ArrayList[JsonObject] - val point = new HashMap[java.util.List[String], Integer] - - val couchbaseClient = getConnection - - val bbox = GeoPoint.getGeoBoundingBox(lat.toDouble, lon.toDouble, range) // 50 meters radius - - val viewQuery = SpatialViewQuery.from("radio", "radio_heatmap_bbox_byxy") - .startRange(JsonArray.from(new java.lang.Double(bbox(0).dlat), new java.lang.Double(bbox(0).dlon))) - .endRange(JsonArray.from(new java.lang.Double(bbox(1).dlat), new java.lang.Double(bbox(1).dlon))).includeDocs(true) - val res = couchbaseClient.query(viewQuery) - - var json: JsonObject = null - var json2: JsonObject = null - for (row <- res) { // handle each building entry - try { - json = row.document().content() - if ((json.getString("buid").compareTo("\"" + buid + "\"") == 0) && (json.getString("floor").compareTo("\"" + floor + "\"") == 0)) { - val p = new ArrayList[String] - val x = json.getString("x") - val y = json.getString("y") - p.add(x) - p.add(y) - if (!point.containsKey(p)) { - json2 = JsonObject.empty() - json2.put("x", p.get(0)) - json2.put("y", p.get(1)) - points.add(json2) - point.put(p, 1) - } - } - } catch { - case e: IOException => + //override def getRadioHeatmapBBox(lat: String, lon: String, buid: String, floor: String, range: Int): java.util.List[JsonObject] = { + // + // val points = new java.util.ArrayList[JsonObject] + // val point = new java.util.HashMap[java.util.List[String], Integer]() + // val xy = new java.util.ArrayList[java.util.List[String]] + // + // val couchbaseClient = getConnection + // + // val bbox = GeoPoint.getGeoBoundingBox(lat.toDouble, lon.toDouble, range) // 50 meters radius + // + // val viewQuery = SpatialViewQuery.from("radio", "radio_heatmap_bbox_byxy") + // .startRange(JsonArray.from(new java.lang.Double(bbox(0).dlat), new java.lang.Double(bbox(0).dlon))) + // .endRange(JsonArray.from(new java.lang.Double(bbox(1).dlat), new java.lang.Double(bbox(1).dlon))).includeDocs(true) + // val res = couchbaseClient.query(viewQuery) + // + // + // LPLogger.debug("couchbase results: " + res.size) + // + // var json: JsonObject = null + // for (row <- res) { // handle each building entry + // try { + // json = row.document().content() + // if ((json.getString("buid").compareTo("\"" + buid + "\"") == 0) && (json.getString("floor").compareTo("\"" + floor + "\"") == 0)) { + // val p = new java.util.ArrayList[String] + // val x = json.getString("x") + // val y = json.getString("y") + // p.add(x) + // p.add(y) + // if (point.containsKey(p)) point.put(p, point.get(p) + 1) + // else { + // point.put(p, 1) + // xy.add(p) + // } + // } + // } catch { + // case e: IOException => + // + // // skip this NOT-JSON document + // } + // } + // while ( { + // !xy.isEmpty + // }) { + // val p = xy.remove(0) + // try { + // json = JsonObject.empty() + // val w = "" + point.get(p) + // json.put("x", p.get(0)) + // json.put("y", p.get(1)) + // json.put("w", w) + // points.add(json) + // } catch { + // case e: IOException => + // + // //skip this NOT-JSON document + // } + // } + // points + //} - // skip this NOT-JSON document - } - } - points - } + //override def getRadioHeatmapBBox2(lat: String, lon: String, buid: String, floor: String, range: Int): java.util.List[JsonObject] = { + // + // val points = new java.util.ArrayList[JsonObject] + // val point = new HashMap[java.util.List[String], Integer] + // + // val couchbaseClient = getConnection + // + // val bbox = GeoPoint.getGeoBoundingBox(lat.toDouble, lon.toDouble, range) // 50 meters radius + // + // val viewQuery = SpatialViewQuery.from("radio", "radio_heatmap_bbox_byxy") + // .startRange(JsonArray.from(new java.lang.Double(bbox(0).dlat), new java.lang.Double(bbox(0).dlon))) + // .endRange(JsonArray.from(new java.lang.Double(bbox(1).dlat), new java.lang.Double(bbox(1).dlon))).includeDocs(true) + // val res = couchbaseClient.query(viewQuery) + // + // var json: JsonObject = null + // var json2: JsonObject = null + // for (row <- res) { // handle each building entry + // try { + // json = row.document().content() + // if ((json.getString("buid").compareTo("\"" + buid + "\"") == 0) && (json.getString("floor").compareTo("\"" + floor + "\"") == 0)) { + // val p = new ArrayList[String] + // val x = json.getString("x") + // val y = json.getString("y") + // p.add(x) + // p.add(y) + // if (!point.containsKey(p)) { + // json2 = JsonObject.empty() + // json2.put("x", p.get(0)) + // json2.put("y", p.get(1)) + // points.add(json2) + // point.put(p, 1) + // } + // } + // } catch { + // case e: IOException => + // + // // skip this NOT-JSON document + // } + // } + // points + //} var lastletters = "" @@ -2142,6 +2139,10 @@ class CouchbaseDatasource private(hostname: String, true } + override def dumpRssLogEntriesSpatial(outFile: FileOutputStream, bbox: Array[GeoPoint], floor_number: String): Long = ??? + override def getRadioHeatmapBBox(lat: String, lon: String, buid: String, floor: String, range: Int): util.List[JsonObject] = ??? + override def getRadioHeatmapBBox2(lat: String, lon: String, buid: String, floor: String, range: Int): util.List[JsonObject] = ??? + def convertJson(list: java.util.List[JsonObject]): List[JsValue] = { val jsList = ListBuffer[JsValue]() for (doc <- list) { @@ -2161,5 +2162,29 @@ class CouchbaseDatasource private(hostname: String, override def login(collection: String, username: String, password: String): List[JsValue] = ??? override def register(collection: String, name: String, email: String, username: String, password: String, - external: String, accType: String): Boolean = ??? + external: String, accType: String): JsValue = ??? + + override def isAdmin(col: String): Boolean = ??? + + override def buildingFromKeyAsJson(key: String): JsValue = ??? + + override def poiFromKeyAsJson(collection: String, key: String, value: String): JsValue = ??? + + override def poisByBuildingAsMap(buid: String): util.List[util.HashMap[String, String]] = ??? + + override def floorsByBuildingAsJson(buid: String): util.List[JsValue] = ??? + + override def getAllBuildings(): List[JsValue] = ??? + + /** + * Populates rss-log per buid:floor. + * + * @param outFile rss-log file in frozen dir. It is filled per floor + * @param buid + * @param floor_number + * @return + */ + override def dumpRssLogEntriesByBuildingFloor(outFile: FileOutputStream, buid: String, floor_number: String): Long = ??? + + override def dumpRssLogEntriesByBuildingACCESFloor(outFile: FileOutputStream, buid: String, floor_number: String): Long = ??? } diff --git a/server/app/datasources/DatasourceException.scala b/server/app/datasources/DatasourceException.scala index 10b470bb2..fa6fc51cb 100644 --- a/server/app/datasources/DatasourceException.scala +++ b/server/app/datasources/DatasourceException.scala @@ -39,7 +39,6 @@ import java.io.PrintWriter import java.io.StringWriter class DatasourceException(msg: String) extends Exception(msg) { - def getStacktrace(): String = { val sw = new StringWriter() this.printStackTrace(new PrintWriter(sw)) diff --git a/server/app/datasources/Helpers.scala b/server/app/datasources/Helpers.scala index ae97e2a00..97120d617 100644 --- a/server/app/datasources/Helpers.scala +++ b/server/app/datasources/Helpers.scala @@ -26,7 +26,7 @@ import utils.LPLogger object Helpers { implicit class DocumentObservable[C](val observable: Observable[Document]) extends ImplicitObservable[Document] { - override val converter: (Document) => String = (doc) => doc.toJson + override val converter: (Document) => String = (doc) => doc.toJson() } implicit class GenericObservable[C](val observable: Observable[C]) extends ImplicitObservable[C] { diff --git a/server/app/datasources/IDatasource.scala b/server/app/datasources/IDatasource.scala index befdce0c0..36637afb6 100644 --- a/server/app/datasources/IDatasource.scala +++ b/server/app/datasources/IDatasource.scala @@ -47,11 +47,11 @@ import utils.GeoPoint // TODO: Will use play.json trait IDatasource { def register(collection: String, name: String, email: String, username: String, password: String, - external: String, accType: String): Boolean + external: String, accType: String): JsValue def login(collection: String, username: String, password: String): List[JsValue] - def createTimestampHeatmap(col: String, buid: String, floor: String, level: Int) + def createTimestampHeatmap(col: String, buid: String, floor: String, level: Int): Unit def deleteFingerprint(fingerprint: JsValue): Boolean @@ -77,13 +77,13 @@ trait IDatasource { def deleteFromKey(key: String): Boolean - @deprecated("mdb") - def getFromKey(key: String): AnyRef + //@deprecated("mdb") + //def getFromKey(key: String): AnyRef def getFromKey(collection: String, key: String, value: String): JsValue - @deprecated("mdb") - def getFromKeyAsJson(key: String): JsValue + //@deprecated("mdb") + //def getFromKeyAsJson(key: String): JsValue def getFromKeyAsJson(collection: String, key: String, value: String): JsValue @@ -221,4 +221,6 @@ trait IDatasource { def generateHeatmaps(): Boolean def deleteNotValidDocuments(): Boolean + + def isAdmin(col: String): Boolean } diff --git a/server/app/datasources/InfluxdbDatasource.scala b/server/app/datasources/InfluxdbDatasource.scala index df1d76331..ba064d3f2 100644 --- a/server/app/datasources/InfluxdbDatasource.scala +++ b/server/app/datasources/InfluxdbDatasource.scala @@ -39,9 +39,8 @@ import java.io.IOException import db_models._ import io.razem.influxdbclient._ -import play.Play import utils.{GeoPoint, LPLogger} - +import scala.language.postfixOps import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -50,18 +49,18 @@ object InfluxdbDatasource { private var sInstance: InfluxdbDatasource = _ private var sLockInstance: AnyRef = new AnyRef() - def getStaticInstance: InfluxdbDatasource = { - sLockInstance.synchronized { - if (sInstance == null) { - val hostname = Play.application().configuration().getString("influxdb.hostname", "localhost") - val port = Play.application().configuration().getString("influxdb.port", "8086") - val database = Play.application().configuration().getString("influxdb.database", "anyplace") - val precision = Play.application().configuration().getInt("influxdb.precision", 6) - sInstance = InfluxdbDatasource.createNewInstance(hostname, port, database, precision) - } - sInstance - } - } + //def getStaticInstance: InfluxdbDatasource = { + // sLockInstance.synchronized { + // if (sInstance == null) { + // val hostname = Play.application().configuration().getString("influxdb.hostname", "localhost") + // val port = Play.application().configuration().getString("influxdb.port", "8086") + // val database = Play.application().configuration().getString("influxdb.database", "anyplace") + // val precision = Play.application().configuration().getInt("influxdb.precision", 6) + // sInstance = InfluxdbDatasource.createNewInstance(hostname, port, database, precision) + // } + // sInstance + // } + //} def createNewInstance( hostname_in: String, @@ -153,7 +152,8 @@ class InfluxdbDatasource(host: String, port: Short, database: String, precision: } def recordToDevicePoint(record: Record): DevicePoint = new DevicePoint( - record("deviceID") toString, record("latitude") toString, record("longitude") toString, record(SCHEMA.fTimestamp) toString, record("time") toString + record.apply("deviceID").toString(), record.apply("latitude").toString(), record.apply("longitude").toString(), + record.apply(SCHEMA.fTimestamp).toString(), record.apply("time").toString() ) def flattenResults(list: List[QueryResult]): List[DevicePoint] = { diff --git a/server/app/datasources/MongodbDatasource.scala b/server/app/datasources/MongodbDatasource.scala index 203864df1..aff2099c5 100644 --- a/server/app/datasources/MongodbDatasource.scala +++ b/server/app/datasources/MongodbDatasource.scala @@ -37,34 +37,36 @@ package datasources import java.io.{FileOutputStream, IOException, PrintWriter} +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter import java.util import com.couchbase.client.java.document.json.JsonObject -import datasources.MongodbDatasource.{admins, convertJson, mdb, mongoClient} +import datasources.MongodbDatasource.{admins, generateAccessToken, mdb, mongoClient} import datasources.SCHEMA._ import db_models.RadioMapRaw.unrollFingerprint import db_models.{Connection, Poi, RadioMapRaw} import floor_module.IAlgo +import javax.inject.{Inject, Singleton} import org.mongodb.scala._ -import org.mongodb.scala.bson.BsonDocument +import org.mongodb.scala.bson.{BsonDocument, conversions} import org.mongodb.scala.model.Aggregates import org.mongodb.scala.model.Aggregates.project import org.mongodb.scala.model.Filters._ import org.mongodb.scala.model.Sorts.{ascending, orderBy} -import play.Play +import play.api.Configuration import play.api.libs.json.{JsNumber, JsObject, JsString, JsValue, Json} -import play.twirl.api.TemplateMagic.javaCollectionToScala +import play.twirl.api.TwirlHelperImports.twirlJavaCollectionToScala import utils.JsonUtils.cleanupMongoJson import utils.{GeoJSONPoint, GeoPoint, JsonUtils, LPLogger} -import scala.collection.JavaConversions.mapAsScalaMap import scala.collection.mutable.ListBuffer import scala.concurrent.Await import scala.concurrent.duration.Duration -import scala.text.Document.break +import scala.jdk.CollectionConverters.MapHasAsScala +import scala.util.Random import scala.util.control.Breaks - object MongodbDatasource { val __SCHEMA: Int = 0 private var sInstance: MongodbDatasource = null @@ -72,15 +74,12 @@ object MongodbDatasource { private var admins: List[String] = List[String]() private var mongoClient: MongoClient = null - def getMDB: MongoDatabase = mdb - - def getStaticInstance: MongodbDatasource = { - val conf = Play.application().configuration() - val username = conf.getString("mongodb.app.username") - val password = conf.getString("mongodb.app.password") - val hostname = conf.getString("mongodb.hostname") - val port = conf.getString("mongodb.port") - val database = conf.getString("mongodb.database") + def initialize(conf: Configuration): MongodbDatasource = { + val username = conf.get[String]("mongodb.app.username") + val password = conf.get[String]("mongodb.app.password") + val hostname = conf.get[String]("mongodb.hostname") + val port = conf.get[String]("mongodb.port") + val database = conf.get[String]("mongodb.database") sInstance = createInstance(hostname, database, username, password, port) sInstance } @@ -91,7 +90,7 @@ object MongodbDatasource { // TODO check if database anyplace exists mdb = mongoClient.getDatabase(database) val collections = mdb.listCollectionNames() - val awaited = Await.result(collections.toFuture, Duration.Inf) + val awaited = Await.result(collections.toFuture(), Duration.Inf) val res = awaited.toList LPLogger.info("MongoDB: Connected to: " + hostname + ":" + port) LPLogger.debug("Collections = " + res) @@ -99,6 +98,16 @@ object MongodbDatasource { new MongodbDatasource() } + def generateAccessToken(local: Boolean): String = { + var start = "" + if (local) + start = "apLocal_" + else + start = "apGoogle_" + val end = "ap" + start + Random.alphanumeric.take(500).mkString("") + end + } + /** * Cache admins on MongoDB initialization. * @@ -108,7 +117,7 @@ object MongodbDatasource { val collection = mdb.getCollection(SCHEMA.cUsers) val query = BsonDocument(SCHEMA.fType -> "admin") val adm = collection.find(query) - val awaited = Await.result(adm.toFuture, Duration.Inf) + val awaited = Await.result(adm.toFuture(), Duration.Inf) val res = awaited.toList val ret = new util.ArrayList[String] for (admin <- res) { @@ -117,6 +126,11 @@ object MongodbDatasource { } ret.toList } +} + +@Singleton +class MongodbDatasource @Inject() () extends IDatasource { + def getMDB: MongoDatabase = mdb def convertJson(list: List[Document]): List[JsValue] = { val jsList = ListBuffer[JsValue]() @@ -128,15 +142,13 @@ object MongodbDatasource { } def convertJson(doc: Document) = cleanupMongoJson(Json.parse(doc.toJson())) -} -class MongodbDatasource() extends IDatasource { + def disconnect() = { val res = mongoClient.close() } - var wordsELOT = new java.util.ArrayList[java.util.ArrayList[String]] var allPoisSide = new java.util.HashMap[String, java.util.List[JsValue]]() var allPoisbycuid = new java.util.HashMap[String, java.util.List[JsValue]]() @@ -146,7 +158,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cPOIS) val query = BsonDocument(SCHEMA.fBuid -> buid) val pois = collection.find(query) - val awaited = Await.result(pois.toFuture, Duration.Inf) + val awaited = Await.result(pois.toFuture(), Duration.Inf) val res = awaited.toList val listJson = convertJson(res) val poisArray = new java.util.ArrayList[JsValue]() @@ -270,7 +282,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cCampuses) val query: BsonDocument = BsonDocument(SCHEMA.fCampusCuid -> cuid) val campus = collection.find(query) - val awaited = Await.result(campus.toFuture, Duration.Inf) + val awaited = Await.result(campus.toFuture(), Duration.Inf) val res = awaited.toList convertJson(res) } @@ -556,14 +568,12 @@ class MongodbDatasource() extends IDatasource { String.valueOf(myChars) } - override def init(): Boolean = ??? - def addJsonDocument(key: String, expiry: Int, document: String): Boolean = ??? override def addJsonDocument(col: String, document: String): Boolean = { val collection = mdb.getCollection(col) val addJson = collection.insertOne(Document.apply(document)) - val awaited = Await.result(addJson.toFuture, Duration.Inf) + val awaited = Await.result(addJson.toFuture(), Duration.Inf) val res = awaited if (res.toString() == "The operation completed successfully") true @@ -575,15 +585,15 @@ class MongodbDatasource() extends IDatasource { override def deleteFromKey(key: String): Boolean = ??? - override def getFromKey(key: String) = ??? - - override def getFromKeyAsJson(key: String) = ??? + //override def getFromKey(key: String) = ??? + // + //override def getFromKeyAsJson(key: String) = ??? override def fingerprintExists(col: String, buid: String, floor: String, x: String, y: String, heading: String): Boolean = { val collection = mdb.getCollection(col) val query = BsonDocument(SCHEMA.fBuid -> buid, SCHEMA.fFloor -> floor, SCHEMA.fX -> x, SCHEMA.fY -> y, SCHEMA.fHeading -> heading) val fingerprintLookUp = collection.find(query) - val awaited = Await.result(fingerprintLookUp.toFuture, Duration.Inf) + val awaited = Await.result(fingerprintLookUp.toFuture(), Duration.Inf) val res = awaited.asInstanceOf[List[Document]] if (res.size > 0) return true @@ -611,6 +621,16 @@ class MongodbDatasource() extends IDatasource { (SCHEMA.cPOIS -> Json.toJson(pois.toList)) } + override def isAdmin(col: String): Boolean = { + val collection = mdb.getCollection(col) + val userLookUp = collection.find().first() + val awaited = Await.result(userLookUp.toFuture(), Duration.Inf) + val res = awaited.asInstanceOf[Document] + if (res == null) + return true + return false + } + override def getFromKeyAsJson(collection: String, key: String, value: String): JsValue = { if (key == null || key.trim().isEmpty) { throw new IllegalArgumentException("No null or empty string allowed as key!") @@ -623,7 +643,7 @@ class MongodbDatasource() extends IDatasource { db_res } catch { case e: IOException => { - LPLogger.error("CouchbaseDatasource::getFromKeyAsJson():: Could not convert document from Couchbase into JSON!") + LPLogger.error("Couldn't find the document.") null } } @@ -632,7 +652,7 @@ class MongodbDatasource() extends IDatasource { override def getFromKey(col: String, key: String, value: String): JsValue = { val collection = mdb.getCollection(col) val buildingLookUp = collection.find(equal(key, value)).first() - val awaited = Await.result(buildingLookUp.toFuture, Duration.Inf) + val awaited = Await.result(buildingLookUp.toFuture(), Duration.Inf) val res = awaited.asInstanceOf[Document] if (res != null) convertJson(res) @@ -643,7 +663,7 @@ class MongodbDatasource() extends IDatasource { override def poisByBuildingAsJson(buid: String): java.util.List[JsValue] = { val collection = mdb.getCollection(SCHEMA.cPOIS) val poisLookUp = collection.find(equal(SCHEMA.fBuid, buid)) - val awaited = Await.result(poisLookUp.toFuture, Duration.Inf) + val awaited = Await.result(poisLookUp.toFuture(), Duration.Inf) val res = awaited.toList val listJson = convertJson(res) val pois = new java.util.ArrayList[JsValue]() @@ -656,7 +676,7 @@ class MongodbDatasource() extends IDatasource { override def floorsByBuildingAsJson(buid: String): java.util.List[JsValue] = { val collection = mdb.getCollection(SCHEMA.cFloorplans) val floorLookUp = collection.find(equal(SCHEMA.fBuid, buid)) - val awaited = Await.result(floorLookUp.toFuture, Duration.Inf) + val awaited = Await.result(floorLookUp.toFuture(), Duration.Inf) val res = awaited.toList val listJson = convertJson(res) val floors = new java.util.ArrayList[JsValue]() @@ -687,7 +707,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cPOIS) val query = BsonDocument(SCHEMA.fBuid -> buid, SCHEMA.fFloorNumber -> floor_number) val pois = collection.find(query) - val awaited = Await.result(pois.toFuture, Duration.Inf) + val awaited = Await.result(pois.toFuture(), Duration.Inf) val res = awaited.toList val listJson = convertJson(res) val poisArray = new java.util.ArrayList[JsValue]() @@ -700,7 +720,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cPOIS) val query = BsonDocument(SCHEMA.fBuid -> buid, SCHEMA.fFloorNumber -> floor_number, SCHEMA.fPuid -> puid) val poisLookUp = collection.find(query) - val awaited = Await.result(poisLookUp.toFuture, Duration.Inf) + val awaited = Await.result(poisLookUp.toFuture(), Duration.Inf) val res = awaited.toList if (res.size > 0) return true @@ -733,7 +753,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cEdges) val query = BsonDocument(SCHEMA.fBuid -> buid) val edges = collection.find(query) - val awaited = Await.result(edges.toFuture, Duration.Inf) + val awaited = Await.result(edges.toFuture(), Duration.Inf) val res = awaited.toList convertJson(res) } @@ -742,7 +762,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cEdges) val query = BsonDocument(SCHEMA.fBuid -> buid, SCHEMA.fFloorA -> floor_number, SCHEMA.fFloorB -> floor_number) val edges = collection.find(query) - val awaited = Await.result(edges.toFuture, Duration.Inf) + val awaited = Await.result(edges.toFuture(), Duration.Inf) val res = awaited.toList val listJson = convertJson(res) val edgesArray = new java.util.ArrayList[JsValue]() @@ -755,7 +775,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cEdges) val query = BsonDocument(SCHEMA.fBuid -> buid) val edges = collection.find(query) - val awaited = Await.result(edges.toFuture, Duration.Inf) + val awaited = Await.result(edges.toFuture(), Duration.Inf) val res = awaited.toList val listJson = convertJson(res) val edgesArray = new java.util.ArrayList[JsValue]() @@ -775,8 +795,6 @@ class MongodbDatasource() extends IDatasource { val f = (floor \ SCHEMA.fFloorNumber).as[String] val tempBool = deleteAllByFloor(buid, f) ret = ret && tempBool - val cachedColBool = deleteAffectedHeatmaps(buid, f) - ret = ret && cachedColBool } } @@ -784,7 +802,7 @@ class MongodbDatasource() extends IDatasource { var query = BsonDocument(SCHEMA.fBuid -> buid) var collection = mdb.getCollection(SCHEMA.cSpaces) val objects = collection.deleteOne(query) - val awaited = Await.result(objects.toFuture, Duration.Inf) + val awaited = Await.result(objects.toFuture(), Duration.Inf) val res = awaited val bool = res.wasAcknowledged() @@ -792,7 +810,7 @@ class MongodbDatasource() extends IDatasource { query = BsonDocument(SCHEMA.fBuids -> buid) collection = mdb.getCollection(SCHEMA.cCampuses) val campuses = collection.find(query) - var await = Await.result(campuses.toFuture, Duration.Inf) + var await = Await.result(campuses.toFuture(), Duration.Inf) var re = await.toList val camp = convertJson(re) for (c <- camp) { @@ -811,7 +829,7 @@ class MongodbDatasource() extends IDatasource { query = BsonDocument(SCHEMA.fBuid -> buid) collection = mdb.getCollection(SCHEMA.cFingerprintsWifi) val deleted = collection.deleteMany(query) - val delAwaited = Await.result(deleted.toFuture, Duration.Inf) + val delAwaited = Await.result(deleted.toFuture(), Duration.Inf) val delRes = delAwaited val bool1 = delRes.wasAcknowledged() LPLogger.debug("fingerprints with buid " + buid + " " + delRes.toString) @@ -825,7 +843,7 @@ class MongodbDatasource() extends IDatasource { val query = BsonDocument(key -> value) val update = BsonDocument(document) val replaceJson = collection.replaceOne(query, update) - val awaited = Await.result(replaceJson.toFuture, Duration.Inf) + val awaited = Await.result(replaceJson.toFuture(), Duration.Inf) val res = awaited if (res.getModifiedCount == 0) false @@ -834,15 +852,15 @@ class MongodbDatasource() extends IDatasource { } override def deleteAllByFloor(buid: String, floor_number: String): Boolean = { - LPLogger.debug("deleteAllByFloor::") - LPLogger.debug("Cascade deletion: edges reaching this floor, edges of this floor," + + LPLogger.D3("deleteAllByFloor::") + LPLogger.D3("Cascade deletion: edges reaching this floor, edges of this floor," + " pois of this floor, floorplan(mongoDB), floorplan image(server)") var collection = mdb.getCollection(SCHEMA.cEdges) // queryBuidA deletes edges that start from building buid (containing edges that have buid_b == buid_a) val queryBuidA = BsonDocument(SCHEMA.fBuidA -> buid, SCHEMA.fFloorA -> floor_number) var deleted = collection.deleteMany(queryBuidA) - var awaited = Await.result(deleted.toFuture, Duration.Inf) + var awaited = Await.result(deleted.toFuture(), Duration.Inf) var res = awaited val bool1 = res.wasAcknowledged() LPLogger.debug("edges from buid_a: " + buid + " " + res.toString) @@ -850,7 +868,7 @@ class MongodbDatasource() extends IDatasource { // queryBuidB deletes edges that point to building buid val queryBuidB = BsonDocument(SCHEMA.fBuidB -> buid, SCHEMA.fFloorB -> floor_number) deleted = collection.deleteMany(queryBuidB) - awaited = Await.result(deleted.toFuture, Duration.Inf) + awaited = Await.result(deleted.toFuture(), Duration.Inf) res = awaited val bool2 = res.wasAcknowledged() LPLogger.debug("edges to buid_b: " + buid + " " + res.toString) @@ -859,19 +877,29 @@ class MongodbDatasource() extends IDatasource { val queryFloor = BsonDocument(SCHEMA.fBuid -> buid, SCHEMA.fFloorNumber -> floor_number) collection = mdb.getCollection(SCHEMA.cPOIS) deleted = collection.deleteMany(queryFloor) - awaited = Await.result(deleted.toFuture, Duration.Inf) + awaited = Await.result(deleted.toFuture(), Duration.Inf) res = awaited val bool3 = res.wasAcknowledged() LPLogger.debug("pois in building with buid: " + buid + " " + res.toString) + // delets 7 cached collections + val queryCached = BsonDocument(SCHEMA.fBuid -> buid) + collection = mdb.getCollection(SCHEMA.cFingerprintsWifi) + deleted = collection.deleteMany(queryCached) + awaited = Await.result(deleted.toFuture(), Duration.Inf) + res = awaited + val bool4 = res.wasAcknowledged() + LPLogger.debug("fingerprints with buid " + buid + " " + res.toString) + val bool5 = deleteAffectedHeatmaps(buid, floor_number) + // this query will delete the floor it self collection = mdb.getCollection(SCHEMA.cFloorplans) deleted = collection.deleteMany(queryFloor) - awaited = Await.result(deleted.toFuture, Duration.Inf) + awaited = Await.result(deleted.toFuture(), Duration.Inf) res = awaited - val bool4 = res.wasAcknowledged() + val bool6 = res.wasAcknowledged() LPLogger.debug("floorplan with buid " + buid + " " + res.toString) - bool1 && bool2 && bool3 && bool4 + bool1 && bool2 && bool3 && bool4 && bool5 & bool6 } override def deleteAllByConnection(cuid: String): java.util.List[String] = { @@ -901,7 +929,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(col) val query = BsonDocument(key -> value) val deleted = collection.deleteOne(query) - val awaited = Await.result(deleted.toFuture, Duration.Inf) + val awaited = Await.result(deleted.toFuture(), Duration.Inf) val res = awaited res.wasAcknowledged() } @@ -916,7 +944,7 @@ class MongodbDatasource() extends IDatasource { project( Document(SCHEMA.fLocation -> "$location", "count" -> "$count") ))) - val awaited = Await.result(radioPoints.toFuture, Duration.Inf) + val awaited = Await.result(radioPoints.toFuture(), Duration.Inf) val res = awaited.toList var foundHeatmaps = convertJson(res) if (foundHeatmaps.size == 0) { // cache-collection could be empty @@ -927,9 +955,9 @@ class MongodbDatasource() extends IDatasource { val heatmaps = new util.ArrayList[JsValue]() for (heatmap <- foundHeatmaps) { val count = (heatmap \ "count").as[Int] - heatmaps.add(Json.obj(SCHEMA.fX -> JsString((heatmap \ SCHEMA.fLocation \ SCHEMA.fCoordinates).as[List[Double]].head + ""), - SCHEMA.fY -> JsString((heatmap \ SCHEMA.fLocation \ SCHEMA.fCoordinates).as[List[Double]].tail.head + ""), - "w" -> JsString(count + ""))) + val y = (heatmap \ SCHEMA.fLocation \ SCHEMA.fCoordinates).as[List[Double]].tail.head + val x = (heatmap \ SCHEMA.fLocation \ SCHEMA.fCoordinates).as[List[Double]].head + heatmaps.add(Json.obj(SCHEMA.fX -> JsString(s"$x"), SCHEMA.fY -> JsString(s"$y"), "w" -> JsString(s"$count"))) } return heatmaps.toList } @@ -942,7 +970,7 @@ class MongodbDatasource() extends IDatasource { project( Document(SCHEMA.fLocation -> "$location", "sum" -> "$sum", "count" -> "$count") ))) - val awaited = Await.result(radioPoints.toFuture, Duration.Inf) + val awaited = Await.result(radioPoints.toFuture(), Duration.Inf) val res = awaited.toList var foundHeatmaps = convertJson(res) @@ -973,7 +1001,7 @@ class MongodbDatasource() extends IDatasource { project( Document(SCHEMA.fLocation -> "$location", "sum" -> "$sum", "count" -> "$count", "average" -> "$average") ))) - val awaited = Await.result(radioPoints.toFuture, Duration.Inf) + val awaited = Await.result(radioPoints.toFuture(), Duration.Inf) val res = awaited.toList var foundHeatmaps = convertJson(res) @@ -1003,7 +1031,7 @@ class MongodbDatasource() extends IDatasource { project( Document(SCHEMA.fLocation -> "$location", "sum" -> "$sum", "count" -> "$count", "average" -> "$average") ))) - val awaited = Await.result(radioPoints.toFuture, Duration.Inf) + val awaited = Await.result(radioPoints.toFuture(), Duration.Inf) val res = awaited.toList var foundHeatmaps = convertJson(res) // in case there are 0 heatmaps try to generate them @@ -1033,7 +1061,7 @@ class MongodbDatasource() extends IDatasource { // TODO: Get count from collection and building val radioPoints = collection.find(and(lt(SCHEMA.fTimestamp, timestampY), gt(SCHEMA.fTimestamp, timestampX), equal(SCHEMA.fBuid, buid), equal(SCHEMA.fFloor, floor))) - val awaited = Await.result(radioPoints.toFuture, Duration.Inf) + val awaited = Await.result(radioPoints.toFuture(), Duration.Inf) val res = awaited.toList val heatmaps = new util.ArrayList[JsValue]() for (heatmap <- convertJson(res)) { @@ -1051,7 +1079,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cHeatmapWifiTimestamp1) val radioPoints = collection.find(and(lt(SCHEMA.fTimestamp, timestampY), gt(SCHEMA.fTimestamp, timestampX), equal(SCHEMA.fBuid, buid), equal(SCHEMA.fFloor, floor))) - val awaited = Await.result(radioPoints.toFuture, Duration.Inf) + val awaited = Await.result(radioPoints.toFuture(), Duration.Inf) val res = awaited.toList val heatmaps = new util.ArrayList[JsValue]() for (heatmap <- convertJson(res)) { @@ -1070,7 +1098,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cHeatmapWifiTimestamp2) val radioPoints = collection.find(and(lt(SCHEMA.fTimestamp, timestampY), gt(SCHEMA.fTimestamp, timestampX), equal(SCHEMA.fBuid, buid), equal(SCHEMA.fFloor, floor))) - val awaited = Await.result(radioPoints.toFuture, Duration.Inf) + val awaited = Await.result(radioPoints.toFuture(), Duration.Inf) val res = awaited.toList val heatmaps = new util.ArrayList[JsValue]() for (heatmap <- convertJson(res)) { @@ -1103,7 +1131,7 @@ class MongodbDatasource() extends IDatasource { Aggregates.filter(query), project(Document(SCHEMA.fLocation -> "$location", "sum" -> "$sum", "count" -> "$count", "average" -> "$average") ))) - val awaited = Await.result(radioPoints.toFuture, Duration.Inf) + val awaited = Await.result(radioPoints.toFuture(), Duration.Inf) val res = awaited.toList return convertJson(res) } @@ -1124,7 +1152,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cFingerprintsWifi) val query: BsonDocument = BsonDocument(SCHEMA.fBuid -> buid, SCHEMA.fFloor -> floor) val fingerprintsLookup = collection.find(query) - val awaited = Await.result(fingerprintsLookup.toFuture, Duration.Inf) + val awaited = Await.result(fingerprintsLookup.toFuture(), Duration.Inf) val res = awaited.toList val fingerprints = convertJson(res) if (fingerprints.size == 0) { @@ -1153,7 +1181,7 @@ class MongodbDatasource() extends IDatasource { val storedHeatmap = fetchStoredHeatmap(collectionName, fingerprint, level, hasTimestamp) if (storedHeatmap == null) { val heatmap = createHeatmap(fingerprint, level, hasTimestamp) - ProxyDataSource.getIDatasource().addJsonDocument(collectionName, heatmap.toString()) + addJsonDocument(collectionName, heatmap.toString()) } else { val newSum = confirmNegativity((fingerprint \ "sum").as[Int]) + confirmNegativity((storedHeatmap \ "sum").as[Int]) val newCount = (fingerprint \ "count").as[Int] + (storedHeatmap \ "count").as[Int] @@ -1187,7 +1215,7 @@ class MongodbDatasource() extends IDatasource { "location.coordinates" -> location.toList, SCHEMA.fTimestamp -> (fingerprint \ SCHEMA.fTimestamp).as[String]) } val heatmapLookup = heatmap.find(query).first() - val awaited = Await.result(heatmapLookup.toFuture, Duration.Inf) + val awaited = Await.result(heatmapLookup.toFuture(), Duration.Inf) val res = awaited.asInstanceOf[Document] if (res != null) return convertJson(res) @@ -1208,7 +1236,7 @@ class MongodbDatasource() extends IDatasource { } val update = BsonDocument(newHeatmap.toString()) val heatmapReplace = heatmap.replaceOne(query, update) - val awaited = Await.result(heatmapReplace.toFuture, Duration.Inf) + val awaited = Await.result(heatmapReplace.toFuture(), Duration.Inf) val res = awaited if (res.getModifiedCount == 0) false @@ -1296,7 +1324,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cFingerprintsWifi) val query = BsonDocument(SCHEMA.fBuid -> buid, SCHEMA.fFloor -> floor) val fingerprints = collection.find(query) - val awaited = Await.result(fingerprints.toFuture, Duration.Inf) + val awaited = Await.result(fingerprints.toFuture(), Duration.Inf) val res = awaited.toList val listJson = convertJson(res) val hm = new util.HashMap[JsValue, Array[Double]]() @@ -1323,7 +1351,7 @@ class MongodbDatasource() extends IDatasource { } } val points = new util.ArrayList[JsValue]() - for (h <- hm.toMap.toList) { + for (h <- hm.asScala) { var tempJson: JsValue = h._1 val rss = Json.obj("count" -> JsNumber(h._2(0)), "average" -> JsNumber(h._2(2)), @@ -1339,7 +1367,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cAccessPointsWifi) val query = BsonDocument(SCHEMA.fBuid -> buid, SCHEMA.fFloor -> floor) val accessPointsLookup = collection.find(query) - val awaited = Await.result(accessPointsLookup.toFuture, Duration.Inf) + val awaited = Await.result(accessPointsLookup.toFuture(), Duration.Inf) val res = awaited.toList if (res.size == 0) return null @@ -1355,7 +1383,7 @@ class MongodbDatasource() extends IDatasource { geoWithinBox(SCHEMA.fGeometry, lat1.toDouble, lon1.toDouble, lat2.toDouble, lon2.toDouble), equal(SCHEMA.fBuid, buid), equal(SCHEMA.fFloor, floor))) - val awaited = Await.result(fingerprints.toFuture, Duration.Inf) + val awaited = Await.result(fingerprints.toFuture(), Duration.Inf) val res = awaited.toList val listJson = convertJson(res) val newList = new util.ArrayList[JsValue]() @@ -1372,7 +1400,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cFingerprintsWifi) val fingerprints = collection.find(and(geoWithinBox(SCHEMA.fGeometry, lat1.toDouble, lon1.toDouble, lat2.toDouble, lon2.toDouble), and(gt(SCHEMA.fTimestamp, timestampX), lt(SCHEMA.fTimestamp, timestampY)))) - val awaited = Await.result(fingerprints.toFuture, Duration.Inf) + val awaited = Await.result(fingerprints.toFuture(), Duration.Inf) val res = awaited.toList val listJson = convertJson(res) val newList = new util.ArrayList[JsValue]() @@ -1390,7 +1418,7 @@ class MongodbDatasource() extends IDatasource { and(gt(SCHEMA.fTimestamp, "0"), lt(SCHEMA.fTimestamp, "999999999999999")), and(equal(SCHEMA.fBuid, buid)), equal(SCHEMA.fFloor, floor)) ).sort(orderBy(ascending(SCHEMA.fTimestamp))) - val awaited = Await.result(fingerprints.toFuture, Duration.Inf) + val awaited = Await.result(fingerprints.toFuture(), Duration.Inf) val res = awaited.toList val listJson = convertJson(res) val points = new util.ArrayList[JsValue]() @@ -1411,7 +1439,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cSpaces) val query = BsonDocument(SCHEMA.fIsPublished -> "true") val buildings = collection.find(query) - val awaited = Await.result(buildings.toFuture, Duration.Inf) + val awaited = Await.result(buildings.toFuture(), Duration.Inf) val res = awaited.toList LPLogger.debug(s"Res on complete Length:${res.length}") val listJson = convertJson(res) @@ -1431,7 +1459,7 @@ class MongodbDatasource() extends IDatasource { if (admins.contains(oid)) { buildingLookUp = collection.find() } - val awaited = Await.result(buildingLookUp.toFuture, Duration.Inf) + val awaited = Await.result(buildingLookUp.toFuture(), Duration.Inf) val res = awaited.toList val listJson = convertJson(res) val buildings = new java.util.ArrayList[JsValue]() @@ -1445,7 +1473,7 @@ class MongodbDatasource() extends IDatasource { override def getAllBuildingsByBucode(bucode: String): List[JsValue] = { val collection = mdb.getCollection(SCHEMA.cSpaces) val buildingLookUp = collection.find(equal(SCHEMA.fBuCode, bucode)) - val awaited = Await.result(buildingLookUp.toFuture, Duration.Inf) + val awaited = Await.result(buildingLookUp.toFuture(), Duration.Inf) val res = awaited.toList val listJson = convertJson(res) val buildings = new java.util.ArrayList[JsValue]() @@ -1468,7 +1496,7 @@ class MongodbDatasource() extends IDatasource { bbox(1).dlon), or(equal(SCHEMA.fIsPublished, "true"), and(equal(SCHEMA.fIsPublished, "false"), equal(SCHEMA.fOwnerId, owner_id))))) - val awaited = Await.result(buildingLookUp.toFuture, Duration.Inf) + val awaited = Await.result(buildingLookUp.toFuture(), Duration.Inf) val res = awaited.toList LPLogger.debug("getAllBuildingsNearMe: fetched " + res.size + " building(s) within a range of: " + range) val listJson = convertJson(res) @@ -1492,12 +1520,12 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cFingerprintsWifi) val fingerprints = collection.find(geoWithinBox(SCHEMA.fGeometry, bbox(0).dlat, bbox(0).dlon, bbox(1).dlat, bbox(1).dlon)).limit(queryLimit) - val awaited = Await.result(fingerprints.toFuture, Duration.Inf) + val awaited = Await.result(fingerprints.toFuture(), Duration.Inf) val res = awaited.toList val listJson = convertJson(res) for (rss <- listJson) { - if (floorFetched > floorLimit) - break + //if (floorFetched > floorLimit) + // break totalFetched += 1 if ((rss \ SCHEMA.fFloor).as[String] == floor_number) { floorFetched += 1 @@ -1519,7 +1547,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cFloorplans) val query = BsonDocument(SCHEMA.fFloorNumber -> floor_number) val floorLookUp = collection.find(query) - val awaited = Await.result(floorLookUp.toFuture, Duration.Inf) + val awaited = Await.result(floorLookUp.toFuture(), Duration.Inf) val res = awaited.asInstanceOf[List[Document]] val floorplans = convertJson(res) var unique = 0 @@ -1550,7 +1578,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cFingerprintsWifi) val query = BsonDocument(SCHEMA.fBuid -> buid, SCHEMA.fFloor -> floor_number) val fingerprintLookUp = collection.find(query) - val awaited = Await.result(fingerprintLookUp.toFuture, Duration.Inf) + val awaited = Await.result(fingerprintLookUp.toFuture(), Duration.Inf) val res = awaited.asInstanceOf[List[Document]] val rssLog = convertJson(res) // splitting Measurements[MAC, rss] to buid, floor, .., MAC, rss, ... (old form) @@ -1578,7 +1606,7 @@ class MongodbDatasource() extends IDatasource { override def getAllAccounts(): List[JsValue] = { val collection = mdb.getCollection(SCHEMA.cUsers) val users = collection.find() - val awaited = Await.result(users.toFuture, Duration.Inf) + val awaited = Await.result(users.toFuture(), Duration.Inf) val res = awaited.toList LPLogger.debug(s"Res on complete Length:${res.length}") val usersList = convertJson(res) @@ -1589,7 +1617,47 @@ class MongodbDatasource() extends IDatasource { ret.toList } - override def predictFloor(algo: IAlgo, bbox: Array[GeoPoint], strongestMACs: Array[String]): Boolean = ??? + override def predictFloor(algo: IAlgo, bbox: Array[GeoPoint], strongestMACs: Array[String]): Boolean = { + predictFloorFast(algo, bbox, strongestMACs) + } + + private def predictFloorFast(algo: IAlgo, bbox: Array[GeoPoint], strongestMACs: Array[String]): Boolean = { + val collection = mdb.getCollection(SCHEMA.cFingerprintsWifi) + var totalFetched = 0 + + for (strongestMAC <- strongestMACs) { + val query: conversions.Bson = and(geoWithinBox(SCHEMA.fGeometry, bbox(0).dlat, bbox(0).dlon, bbox(1).dlat, bbox(1).dlon), + equal(SCHEMA.fStrongestWifi, strongestMAC)) + val fingerprintLookup = collection.find(query) + val awaited = Await.result(fingerprintLookup.toFuture(), Duration.Inf) + val res = awaited.toList + val listJson = convertJson(res) + LPLogger.D2("size = " + listJson.size) + if (listJson.size != 0) { + val bucket = new java.util.ArrayList[JsValue](10) + var _floor = "0" + for (json <- listJson) { + val measurements = (json \ SCHEMA.fMeasurements).as[List[List[String]]] + for (measurement <- measurements) { + val fingerprint = unrollFingerprint(json, measurement) + val MAC = (fingerprint \ SCHEMA.fMac).as[String] + if (MAC == strongestMAC) { + algo.proccess(bucket, _floor) + bucket.clear() + _floor = (fingerprint \ SCHEMA.fFloor).as[String] + bucket.add(fingerprint) + totalFetched += 1 + } + } + } + } + } + + if (totalFetched > 10) + true + else + false + } override def deleteRadiosInBox(): Boolean = ??? @@ -1609,7 +1677,7 @@ class MongodbDatasource() extends IDatasource { val collection = mdb.getCollection(SCHEMA.cCampuses) val query: BsonDocument = BsonDocument(SCHEMA.fOwnerId -> owner_id) val campus = collection.find(query) - val awaited = Await.result(campus.toFuture, Duration.Inf) + val awaited = Await.result(campus.toFuture(), Duration.Inf) val res = awaited.toList convertJson(res) } @@ -1621,19 +1689,19 @@ class MongodbDatasource() extends IDatasource { val fiCollection = mdb.getCollection(SCHEMA.cFingerprintsWifi) val tempQuery: BsonDocument = BsonDocument(SCHEMA.fBuid -> "building_e0982a5f-fa50-4200-bab7-99ef2dce7285_1623673422061") val buildingsLookup = bCollection.find(tempQuery) - val awaitedB = Await.result(buildingsLookup.toFuture, Duration.Inf) + val awaitedB = Await.result(buildingsLookup.toFuture(), Duration.Inf) val resB = awaitedB.toList val buildings = convertJson(resB) for (building <- buildings) { val floorsLookup = flCollection.find(equal(SCHEMA.fBuid, (building \ SCHEMA.fBuid).as[String])) - val awaitedFl = Await.result(floorsLookup.toFuture, Duration.Inf) + val awaitedFl = Await.result(floorsLookup.toFuture(), Duration.Inf) val resFl = awaitedFl.toList val floors = convertJson(resFl) for (floor <- floors) { val query: BsonDocument = BsonDocument(SCHEMA.fBuid -> (building \ SCHEMA.fBuid).as[String], SCHEMA.fFloor -> (floor \ SCHEMA.fFloorNumber).as[String]) val fingerprintsLookup = fiCollection.find(query) - val awaitedFi = Await.result(fingerprintsLookup.toFuture, Duration.Inf) + val awaitedFi = Await.result(fingerprintsLookup.toFuture(), Duration.Inf) val resFi = awaitedFi.toList val fingerprints = convertJson(resFi) for (fingerprint <- fingerprints) { @@ -1685,7 +1753,7 @@ class MongodbDatasource() extends IDatasource { for (colName <- collections) { val collection = mdb.getCollection(colName) val deleted = collection.deleteMany(query) - val awaited = Await.result(deleted.toFuture, Duration.Inf) + val awaited = Await.result(deleted.toFuture(), Duration.Inf) val res = awaited.wasAcknowledged() ret = ret && res } @@ -1704,7 +1772,7 @@ class MongodbDatasource() extends IDatasource { SCHEMA.fHeading -> (fingerprint \ SCHEMA.fHeading).as[String], SCHEMA.fTimestamp -> (fingerprint \ fTimestamp).as[String]) val deleted = collection.deleteMany(query) - val awaited = Await.result(deleted.toFuture, Duration.Inf) + val awaited = Await.result(deleted.toFuture(), Duration.Inf) return awaited.wasAcknowledged() } @@ -1716,7 +1784,7 @@ class MongodbDatasource() extends IDatasource { * @param floor * @param level */ - override def createTimestampHeatmap(col: String, buid: String, floor: String, level: Int) { + override def createTimestampHeatmap(col: String, buid: String, floor: String, level: Int) : Unit = { val collection = mdb.getCollection(col) val query = BsonDocument(SCHEMA.fBuid -> buid, SCHEMA.fFloor -> floor) val heatmapLookUp = collection.find(query).first() @@ -1737,16 +1805,25 @@ class MongodbDatasource() extends IDatasource { return convertJson(res) } + + + def createOwnerId(username: String): String = { + username + "_" + LocalDateTime.now.format(DateTimeFormatter.ofPattern("YYYYMMdd_HHmmss")) + } + override def register(col: String, name: String, email: String, username: String, password: String, external: String, - accType: String): Boolean = { - val accessToken = "autoEinaitoAccessToken" - val owner_id = "local_" + "owner_id" + accType: String): JsValue = { + + val accessToken = generateAccessToken(true) + val owner_id = createOwnerId(username) + "_local" val json: JsValue = Json.obj("name" -> JsString(name), SCHEMA.fEmail -> JsString(email), SCHEMA.fUsername -> JsString(username), SCHEMA.fPassword -> JsString(password), SCHEMA.fAccessToken -> JsString(accessToken), SCHEMA.fExternal -> JsString(external), SCHEMA.fType -> JsString(accType), SCHEMA.fOwnerId -> JsString(owner_id)) - return addJsonDocument(SCHEMA.cUsers, json.toString()) + addJsonDocument(SCHEMA.cUsers, json.toString()) + return json.as[JsObject] - SCHEMA.fPassword } + override def init(): Boolean = ??? } diff --git a/server/app/datasources/ProxyDataSource.scala b/server/app/datasources/ProxyDataSource.scala index 271006fad..4fa965e7f 100644 --- a/server/app/datasources/ProxyDataSource.scala +++ b/server/app/datasources/ProxyDataSource.scala @@ -42,24 +42,13 @@ import java.util.HashMap import com.couchbase.client.java.document.json.JsonObject import floor_module.IAlgo +import javax.inject.{Inject, Singleton} +import play.api.Configuration import play.api.libs.json.JsValue import utils.GeoPoint -object ProxyDataSource { - - private var sInstance: ProxyDataSource = _ - - def getInstance(): ProxyDataSource = { - if (sInstance == null) { - sInstance = new ProxyDataSource() - } - sInstance - } - - def getIDatasource(): IDatasource = getInstance() -} - -class ProxyDataSource private() extends IDatasource { +@Singleton +class ProxyDataSource @Inject() (conf: Configuration) extends IDatasource { private var mCouchbase: CouchbaseDatasource = _ private var mongoDB: MongodbDatasource = _ @@ -72,15 +61,26 @@ class ProxyDataSource private() extends IDatasource { initMongodb() //setActiveDatabase(this.mongoDB) // TODO: nneof once all done - private def initCouchbase() { - this.mCouchbase = CouchbaseDatasource.getStaticInstance + private var sInstance: ProxyDataSource = _ + + def getInstance(): ProxyDataSource = { + if (sInstance == null) { + sInstance = new ProxyDataSource(conf) + } + sInstance } - private def initMongodb() { - this.mongoDB = MongodbDatasource.getStaticInstance + def getIDatasource: IDatasource = getInstance() + + private def initCouchbase(): Unit = { + this.mCouchbase = CouchbaseDatasource.initialize(conf) } - private def setActiveDatabase(ds: IDatasource) { + private def initMongodb(): Unit = { + this.mongoDB = MongodbDatasource.initialize(conf) + } + + private def setActiveDatabase(ds: IDatasource): Unit = { this.mActiveDatabase = ds } @@ -121,10 +121,10 @@ class ProxyDataSource private() extends IDatasource { mongoDB.getFromKey(collection, key, value) } - override def getFromKey(key: String): AnyRef = { - _checkActiveDatasource() - mActiveDatabase.getFromKey(key) - } + //override def getFromKey(key: String): AnyRef = { + // _checkActiveDatasource() + // mActiveDatabase.getFromKey(key) + //} override def deleteRadiosInBox(): Boolean = { _checkActiveDatasource() @@ -141,10 +141,10 @@ class ProxyDataSource private() extends IDatasource { mongoDB.fingerprintExists(collection, buid, floor, x, y, heading) } - override def getFromKeyAsJson(key: String): JsValue = { - _checkActiveDatasource() - mActiveDatabase.getFromKeyAsJson(key) - } + //override def getFromKeyAsJson(key: String): JsValue = { + // _checkActiveDatasource() + // mActiveDatabase.getFromKeyAsJson(key) + //} override def buildingFromKeyAsJson(key: String): JsValue = { _checkActiveDatasource() @@ -220,7 +220,7 @@ class ProxyDataSource private() extends IDatasource { override def getRadioHeatmap(): java.util.List[JsonObject] = { _checkActiveDatasource() - mActiveDatabase.getRadioHeatmap + mActiveDatabase.getRadioHeatmap() } override def getRadioHeatmapByBuildingFloor(buid: String, floor: String): List[JsValue] = { @@ -343,7 +343,7 @@ class ProxyDataSource private() extends IDatasource { mongoDB.getAllAccounts() } - def _checkActiveDatasource() { + def _checkActiveDatasource(): Unit = { if (this.mActiveDatabase == null) { throw new DatasourceException("No active Datasource exists!") } @@ -351,7 +351,7 @@ class ProxyDataSource private() extends IDatasource { override def predictFloor(algo: IAlgo, bbox: Array[GeoPoint], strongestMACs: Array[String]): Boolean = { _checkActiveDatasource() - mActiveDatabase.predictFloor(algo, bbox, strongestMACs) + mongoDB.predictFloor(algo, bbox, strongestMACs) } override def magneticPathsByBuildingFloorAsJson(buid: String, floor_number: String): java.util.List[JsonObject] = { @@ -444,7 +444,7 @@ class ProxyDataSource private() extends IDatasource { mongoDB.deleteFingerprint(fingerprint) } - override def createTimestampHeatmap(col: String, buid: String, floor: String, level: Int) { + override def createTimestampHeatmap(col: String, buid: String, floor: String, level: Int) = { _checkActiveDatasource() mongoDB.createTimestampHeatmap(col, buid, floor, level) } @@ -455,8 +455,13 @@ class ProxyDataSource private() extends IDatasource { } override def register(collection: String, name: String, email: String, username: String, password: String, - external: String, accType: String): Boolean = { + external: String, accType: String): JsValue = { _checkActiveDatasource() mongoDB.register(collection, name, email, username, password, external, accType) } + + override def isAdmin(col: String): Boolean = { + _checkActiveDatasource() + mongoDB.isAdmin(col) + } } diff --git a/server/app/db_models/AbstractModel.scala b/server/app/db_models/AbstractModel.scala index 0c158b1d1..048e3f7ae 100644 --- a/server/app/db_models/AbstractModel.scala +++ b/server/app/db_models/AbstractModel.scala @@ -45,9 +45,9 @@ abstract class AbstractModel { def getFields(): HashMap[String, String] = fields - def setFields(f: HashMap[String, String]) { + def setFields(f: HashMap[String, String]): Unit = { this.fields = f - getId + getId() } def getId(): String diff --git a/server/app/db_models/Account.scala b/server/app/db_models/Account.scala index de1b56c0a..abb81f098 100644 --- a/server/app/db_models/Account.scala +++ b/server/app/db_models/Account.scala @@ -40,11 +40,12 @@ import java.io.IOException import com.couchbase.client.java.document.json.JsonObject import datasources.{MongodbDatasource, SCHEMA} +import javax.inject.Singleton import play.api.libs.json._ import utils.JsonUtils.convertToInt import utils.LPLogger -import scala.collection.JavaConverters.mapAsScalaMapConverter +import scala.jdk.CollectionConverters.MapHasAsScala object ExternalType extends Enumeration { @@ -52,23 +53,25 @@ object ExternalType extends Enumeration { val GOOGLE, LOCAL = Value } +@Singleton class Account(hm: java.util.HashMap[String, String]) extends AbstractModel { private var json: JsValue = _ this.fields = hm - def this() { + def this() = { this(new java.util.HashMap[String, String]()) fields.put(SCHEMA.fSchema, MongodbDatasource.__SCHEMA.toString) fields.put(SCHEMA.fOwnerId, "") fields.put(SCHEMA.fName, "") fields.put(SCHEMA.fType, "") + fields.put(SCHEMA.fAccessToken, "") } // TODO make it follow new version of User Json - def this(json: JsValue) { + def this(json: JsValue) = { this() fields.put(SCHEMA.fSchema, MongodbDatasource.__SCHEMA.toString) fields.put(SCHEMA.fOwnerId, (json \ SCHEMA.fOwnerId).as[String]) @@ -76,6 +79,7 @@ class Account(hm: java.util.HashMap[String, String]) extends AbstractModel { fields.put(SCHEMA.fType, (json \ SCHEMA.fType).as[String]) if ((json \ SCHEMA.fExternal).toOption.isDefined) fields.put(SCHEMA.fExternal, (json \ SCHEMA.fExternal).as[String]) + fields.put(SCHEMA.fAccessToken, MongodbDatasource.generateAccessToken(false)) this.json = json } diff --git a/server/app/db_models/BuildingSet.scala b/server/app/db_models/BuildingSet.scala index e1ff86d1e..1e7bd3e82 100644 --- a/server/app/db_models/BuildingSet.scala +++ b/server/app/db_models/BuildingSet.scala @@ -45,7 +45,8 @@ import play.api.libs.json.{JsObject, JsValue, Json} import utils.JsonUtils.convertToInt import utils.LPUtils -import scala.collection.JavaConverters.mapAsScalaMapConverter +import scala.jdk.CollectionConverters.MapHasAsScala + class BuildingSet(hm: HashMap[String, String]) extends AbstractModel { @@ -60,7 +61,7 @@ class BuildingSet(hm: HashMap[String, String]) extends AbstractModel { this.fields = hm - def this() { + def this() = { this(new HashMap[String, String]) fields.put(SCHEMA.fOwnerId, "") fields.put(SCHEMA.fCampusCuid, "") @@ -98,7 +99,7 @@ class BuildingSet(hm: HashMap[String, String]) extends AbstractModel { fields.put(SCHEMA.fOwnerId, owner) } - def isEmptyDeleteElseAdd(json: JsValue, key: String) { + def isEmptyDeleteElseAdd(json: JsValue, key: String) = { val temp = (json \ key).as[String] if (temp != "" && temp != null && temp != "-") { fields.put(key, temp) @@ -110,7 +111,7 @@ class BuildingSet(hm: HashMap[String, String]) extends AbstractModel { def getId(): String = { var cuid: String = fields.get(SCHEMA.fCampusCuid) if (cuid.isEmpty || cuid.==("")) { - val finalId: String = LPUtils.getRandomUUID + "_" + System + val finalId: String = LPUtils.getRandomUUID() + "_" + System .currentTimeMillis() fields.put(SCHEMA.fCampusCuid, "cuid_" + finalId) cuid = fields.get(SCHEMA.fCampusCuid) diff --git a/server/app/db_models/Connection.scala b/server/app/db_models/Connection.scala index 58d29d211..99f69f9dc 100644 --- a/server/app/db_models/Connection.scala +++ b/server/app/db_models/Connection.scala @@ -43,7 +43,8 @@ import datasources.SCHEMA import play.api.libs.json.{JsObject, JsString, JsValue, Json} import utils.JsonUtils.convertToInt -import scala.collection.JavaConverters.mapAsScalaMapConverter +import scala.jdk.CollectionConverters.MapHasAsScala + object Connection { @@ -62,7 +63,7 @@ class Connection(hm: HashMap[String, String]) extends AbstractModel { this.fields = hm - def this() { + def this() = { this(new HashMap[String, String]) fields.put(SCHEMA.fIsPublished, "") fields.put(SCHEMA.fEdgeType, "") @@ -77,7 +78,7 @@ class Connection(hm: HashMap[String, String]) extends AbstractModel { fields.put(SCHEMA.fConCuid, "") } - def this(json: JsValue) { + def this(json: JsValue) = { this() if ((json \ SCHEMA.fIsPublished).toOption.isDefined) fields.put(SCHEMA.fIsPublished, (json \ SCHEMA.fIsPublished).as[String]) diff --git a/server/app/db_models/Floor.scala b/server/app/db_models/Floor.scala index 3f97d696e..f17671f5f 100644 --- a/server/app/db_models/Floor.scala +++ b/server/app/db_models/Floor.scala @@ -43,7 +43,8 @@ import datasources.SCHEMA import play.api.libs.json.{JsObject, JsString, JsValue, Json} import utils.JsonUtils.convertToInt -import scala.collection.JavaConverters.mapAsScalaMapConverter +import scala.jdk.CollectionConverters.MapHasAsScala + object Floor { @@ -62,7 +63,7 @@ class Floor(hm: HashMap[String, String]) extends AbstractModel { this.fields = hm - def this() { + def this() = { this(new HashMap[String, String]) fields.put(SCHEMA.fBuid, "") fields.put(SCHEMA.fIsPublished, "") @@ -71,7 +72,7 @@ class Floor(hm: HashMap[String, String]) extends AbstractModel { fields.put(SCHEMA.fDescription, "") } - def this(json: JsValue) { + def this(json: JsValue) = { this() if ((json \ SCHEMA.fFuid).toOption.isDefined) fields.put(SCHEMA.fFuid, (json \ SCHEMA.fFuid).as[String]) diff --git a/server/app/db_models/MagneticMilestone.scala b/server/app/db_models/MagneticMilestone.scala index ffa117cfd..42a12eef6 100644 --- a/server/app/db_models/MagneticMilestone.scala +++ b/server/app/db_models/MagneticMilestone.scala @@ -46,7 +46,7 @@ class MagneticMilestone(hm: HashMap[String, String]) extends AbstractModel { this.fields = hm - def this() { + def this() = { this(new HashMap[String, String]) fields.put("buid", "") fields.put("floor_num", "") @@ -64,7 +64,7 @@ class MagneticMilestone(hm: HashMap[String, String]) extends AbstractModel { fields.put("doctype", "magnetic_milestone") } - def this(json: JsonObject) { + def this(json: JsonObject) = { this() fields.put("buid", json.getString("buid")) fields.put("floor_num", json.getString("floor_num")) @@ -86,7 +86,7 @@ class MagneticMilestone(hm: HashMap[String, String]) extends AbstractModel { def this(json: JsonObject, buid: String, floor_num: String, - mpuid: String) { + mpuid: String) = { this() fields.put("buid", buid) fields.put("floor_num", floor_num) @@ -107,7 +107,7 @@ class MagneticMilestone(hm: HashMap[String, String]) extends AbstractModel { def getId(): String = { var id: String = fields.get("mmuid") if (id.isEmpty || id== "") { - id = "mmilestone_" + LPUtils.getRandomUUID + "_" + System.currentTimeMillis() + id = "mmilestone_" + LPUtils.getRandomUUID() + "_" + System.currentTimeMillis() } id } diff --git a/server/app/db_models/MagneticPath.scala b/server/app/db_models/MagneticPath.scala index 15631ea42..5aeda37c1 100644 --- a/server/app/db_models/MagneticPath.scala +++ b/server/app/db_models/MagneticPath.scala @@ -46,7 +46,7 @@ class MagneticPath(hm: HashMap[String, String]) extends AbstractModel { this.fields = hm - def this() { + def this() = { this(new HashMap[String, String]) fields.put("lat_a", "") fields.put("lng_a", "") @@ -58,7 +58,7 @@ class MagneticPath(hm: HashMap[String, String]) extends AbstractModel { fields.put("doctype", "magnetic_path") } - def this(json: JsonObject) { + def this(json: JsonObject) = { this() fields.put("lat_a", json.getString("lat_a")) fields.put("lng_a", json.getString("lng_a")) @@ -74,14 +74,14 @@ class MagneticPath(hm: HashMap[String, String]) extends AbstractModel { def getId(): String = { var id: String = fields.get("mpuid") if (id.isEmpty || id == "") { - id = "mpath_" + LPUtils.getRandomUUID + "_" + System.currentTimeMillis() + id = "mpath_" + LPUtils.getRandomUUID() + "_" + System.currentTimeMillis() } id } def toValidJson(): JsonObject = { // initialize id if not initialized - getId + getId() JsonObject.from(this.getFields()) } diff --git a/server/app/db_models/Poi.scala b/server/app/db_models/Poi.scala index 85f9d9ed7..18a0df0fe 100644 --- a/server/app/db_models/Poi.scala +++ b/server/app/db_models/Poi.scala @@ -45,7 +45,8 @@ import play.api.libs.json.{JsObject, JsString, JsValue, Json} import utils.JsonUtils.convertToInt import utils.{GeoJSONPoint, LPUtils} -import scala.collection.JavaConverters.mapAsScalaMapConverter +import scala.jdk.CollectionConverters.MapHasAsScala + object Poi { @@ -59,7 +60,7 @@ object Poi { buid: String, floor_number: String, coordinates_lat: String, - coordinates_lon: String): String = "poi_" + LPUtils.getRandomUUID + coordinates_lon: String): String = "poi_" + LPUtils.getRandomUUID() } class Poi(hm: HashMap[String, String]) extends AbstractModel { @@ -72,7 +73,7 @@ class Poi(hm: HashMap[String, String]) extends AbstractModel { this.fields = hm - def this() { + def this() = { this(new HashMap[String, String]) fields.put(SCHEMA.fPuid, "") fields.put(SCHEMA.fBuid, "") @@ -89,7 +90,7 @@ class Poi(hm: HashMap[String, String]) extends AbstractModel { fields.put(SCHEMA.fCoordinatesLon, "") } - def this(json: JsValue) { + def this(json: JsValue) = { this() if ((json \ SCHEMA.fPuid).toOption.isDefined) fields.put(SCHEMA.fPuid, (json \ SCHEMA.fPuid).as[String]) @@ -157,12 +158,12 @@ class Poi(hm: HashMap[String, String]) extends AbstractModel { def toValidJson(): JsonObject = { // initialize id if not initialized - getId + getId() JsonObject.from(this.getFields()) } def toValidMongoJson(): JsValue = { - getId + getId() toJson() } diff --git a/server/app/db_models/RadioMapRaw.scala b/server/app/db_models/RadioMapRaw.scala index b2c57c58b..1fdd1f91c 100644 --- a/server/app/db_models/RadioMapRaw.scala +++ b/server/app/db_models/RadioMapRaw.scala @@ -37,24 +37,17 @@ package db_models -import java.io.{File, FileNotFoundException, FileOutputStream, IOException} +import java.io.IOException import java.util.HashMap import com.couchbase.client.java.document.json.JsonObject -import controllers.AnyplacePosition.BBOX_MAX -import datasources.{ProxyDataSource, SCHEMA} -import json.VALIDATE.{Coordinate, StringNumber} -import play.Play +import datasources.SCHEMA import play.api.libs.json._ -import play.api.mvc.Result -import radiomapserver.RadioMap.{RBF_ENABLED, RadioMap} -import utils.AnyplaceServerAPI._ -import utils.FileUtils.getDirFrozenFloor import utils.JsonUtils.convertToInt -import utils.LPUtils.MD5 import utils._ -import scala.collection.JavaConverters.mapAsScalaMapConverter +import scala.jdk.CollectionConverters.MapHasAsScala + object RadioMapRaw { @@ -94,105 +87,6 @@ object RadioMapRaw { sb.toString } - /** - * Every time it creates a new radiomap file - * We have only coordinates and floor. We dont have a building so we download from a bounding box - * - * @param json - * @param range - * @return - */ - def findRadioBbox(json: JsValue, range: Int): Result = { - if (Coordinate(json, SCHEMA.fCoordinatesLat) == null) - return AnyResponseHelper.bad_request("coordinates_lat field must be String containing a float!") - val lat = (json \ SCHEMA.fCoordinatesLat).as[String] - if (Coordinate(json, SCHEMA.fCoordinatesLon) == null) - return AnyResponseHelper.bad_request("coordinates_lon field must be String containing a float!") - val lon = (json \ SCHEMA.fCoordinatesLon).as[String] - if (StringNumber(json, SCHEMA.fFloorNumber) == null) - return AnyResponseHelper.bad_request("floor_number field must be String, containing a number!") - val floorNumber = (json \ SCHEMA.fFloorNumber).as[String] - if (!Floor.checkFloorNumberFormat(floorNumber)) { - return AnyResponseHelper.bad_request("Floor number cannot contain whitespace!") - } else { - val bbox = GeoPoint.getGeoBoundingBox(java.lang.Double.parseDouble(lat), java.lang.Double.parseDouble(lon), - range) - LPLogger.D4("LowerLeft: " + bbox(0) + " UpperRight: " + bbox(1)) - - // create unique name for cached file based on coordinates, floor_number, range - val pathName = "radiomaps" - val hashKey = lat + lon + floorNumber - val bboxRadioDir = MD5(hashKey) + "-" + range.toString - LPLogger.debug("hashkey = " + hashKey) - LPLogger.debug("bbox_token = " + bboxRadioDir) - // store in radioMapRawDir/tmp/buid/floor/bbox_token - val fullPath = Play.application().configuration().getString("radioMapRawDir") + "/bbox/" + bboxRadioDir - val dir = new File(fullPath) - val radiomap_filename = new File(fullPath + URL_SEP + "indoor-radiomap.txt") - .getAbsolutePath - var msg = "" - if (!dir.exists()) { - // if the range is maximum then we are looking for the entire floor - if (range == BBOX_MAX) { - val buid = ProxyDataSource.getIDatasource.dumpRssLogEntriesWithCoordinates(floorNumber, lat.toDouble, lon.toDouble) - if (buid != null) { // building found. return path to file - val radiomap_mean_filename = SERVER_API_ROOT - val path = radiomap_mean_filename.dropRight(1) + getDirFrozenFloor(buid, floorNumber) + "/indoor-radiomap-mean.txt" - val res = Json.obj("map_url_mean" -> path) - return AnyResponseHelper.ok(res, "Successfully retrieved radiomap: full-floor (according to lat lon)") - } - } - msg = "created bbox: " + fullPath - if (!dir.mkdirs()) { - return AnyResponseHelper.internal_server_error("Failed to create bbox dir: " + fullPath) - } - val rssLog = new File(dir.getAbsolutePath + URL_SEP + "rss-log") - var fout: FileOutputStream = null - var floorFetched: Long = 0l - try { - fout = new FileOutputStream(rssLog) - LPLogger.D5("RSS path: " + rssLog.toPath().getFileName.toString) - floorFetched = ProxyDataSource.getIDatasource.dumpRssLogEntriesSpatial(fout, bbox, floorNumber) - fout.close() - if (floorFetched == 0) { - return AnyResponseHelper.bad_request("Area not supported yet!") - } - val rm = new RadioMap(new File(fullPath), radiomap_filename, "", -110) - val resCreate = rm.createRadioMap() - if (resCreate != null) { - return AnyResponseHelper.internal_server_error("findRadioBbox: radiomap on-the-fly: " + resCreate) - } - } catch { - case fnfe: FileNotFoundException => return AnyResponseHelper.internal_server_error("findRadioBbox: " + - "rssLog: " + rssLog, fnfe) - case e: Exception => return AnyResponseHelper.internal_server_error("findRadioBbox" , e) - } - } else { - msg = "cached-bbox: " + fullPath - LPLogger.debug("findRadioBbox: " + msg) - } - var radiomap_mean_filename = radiomap_filename.replace(".txt", "-mean.txt") - var radiomap_rbf_weights_filename = radiomap_filename.replace(".txt", "-weights.txt") - var radiomap_parameters_filename = radiomap_filename.replace(".txt", "-parameters.txt") - val api = AnyplaceServerAPI.SERVER_API_ROOT - var pos = radiomap_mean_filename.indexOf(pathName) - radiomap_mean_filename = api + radiomap_mean_filename.substring(pos) - var res: JsValue = null - if (RBF_ENABLED) { - pos = radiomap_rbf_weights_filename.indexOf(pathName) - radiomap_rbf_weights_filename = api + radiomap_rbf_weights_filename.substring(pos) - pos = radiomap_parameters_filename.indexOf(pathName) - radiomap_parameters_filename = api + radiomap_parameters_filename.substring(pos) - res = Json.obj("map_url_mean" -> radiomap_mean_filename, - "map_url_weights" -> radiomap_rbf_weights_filename, "map_url_parameters" -> radiomap_parameters_filename) - } else { - res = Json.obj("map_url_mean" -> radiomap_mean_filename) - } - - AnyResponseHelper.ok(res, "Successfully retrieved radiomap: " + msg) - } - } - def unrollFingerprint(rss: JsValue, measurement: List[String]): JsValue = { var json = Json.obj(SCHEMA.fBuid -> (rss \ SCHEMA.fBuid).as[String], SCHEMA.fFloor -> (rss \ SCHEMA.fFloor).as[String], SCHEMA.fX -> (rss \ SCHEMA.fX).as[String], SCHEMA.fY -> (rss \ SCHEMA.fY).as[String], SCHEMA.fHeading -> (rss \ SCHEMA.fHeading).as[String], @@ -213,7 +107,7 @@ class RadioMapRaw(h: HashMap[String, String]) extends AbstractModel { x: String, y: String, heading: String - ) { + ) = { this(new HashMap[String, String]) fields.put(SCHEMA.fTimestamp, timestamp) fields.put(SCHEMA.fX, x) @@ -227,7 +121,7 @@ class RadioMapRaw(h: HashMap[String, String]) extends AbstractModel { y: String, heading: String, - floor: String) { + floor: String) = { this(new HashMap[String, String]) fields.put(SCHEMA.fTimestamp, timestamp) fields.put(SCHEMA.fX, x) @@ -241,7 +135,7 @@ class RadioMapRaw(h: HashMap[String, String]) extends AbstractModel { y: String, heading: String, floor: String, - strongestWifi: String) { + strongestWifi: String) = { this(new HashMap[String, String]) fields.put(SCHEMA.fTimestamp, timestamp) fields.put(SCHEMA.fX, x) @@ -257,7 +151,7 @@ class RadioMapRaw(h: HashMap[String, String]) extends AbstractModel { heading: String, floor: String, strongestWifi: String, - buid: String) { + buid: String) = { this(new HashMap[String, String]) fields.put(SCHEMA.fTimestamp, timestamp) fields.put(SCHEMA.fX, x) @@ -289,7 +183,7 @@ class RadioMapRaw(h: HashMap[String, String]) extends AbstractModel { val timestampToSec = (json \ SCHEMA.fTimestamp).as[String].toLong / 1000 // milliseconds to seconds val roundTimestamp = (timestampToSec - (timestampToSec % 86400)) * 1000 // rounds down to day json = json.as[JsObject] + (SCHEMA.fMeasurements -> Json.toJson(measurements)) + - (SCHEMA.fTimestamp -> JsString(roundTimestamp + "")) + (SCHEMA.fTimestamp -> JsString(s"$roundTimestamp")) json = json.as[JsObject] + (SCHEMA.fGeometry -> Json.toJson( new GeoJSONPoint(java.lang.Double.parseDouble(fields.get(SCHEMA.fX)), java.lang.Double.parseDouble(fields.get(SCHEMA.fY))).toGeoJSON())) diff --git a/server/app/db_models/Space.scala b/server/app/db_models/Space.scala index 73b6d1cb0..26d771797 100644 --- a/server/app/db_models/Space.scala +++ b/server/app/db_models/Space.scala @@ -47,11 +47,10 @@ import java.util.HashMap import com.couchbase.client.java.document.json.JsonObject import datasources.SCHEMA import play.api.libs.json._ -import play.twirl.api.TemplateMagic.javaCollectionToScala import utils.JsonUtils.convertToInt import utils.{GeoJSONPoint, LPUtils} -import scala.collection.JavaConverters.mapAsScalaMapConverter +import scala.jdk.CollectionConverters.{CollectionHasAsScala, MapHasAsScala} class Space(hm: HashMap[String, String]) extends AbstractModel { private var json: JsValue = _ @@ -60,7 +59,7 @@ class Space(hm: HashMap[String, String]) extends AbstractModel { private var co_owners = JsArray() this.fields = hm - def this() { + def this() = { this(new HashMap[String, String]) fields.put(SCHEMA.fBuid, "") fields.put(SCHEMA.fIsPublished, "") @@ -74,7 +73,7 @@ class Space(hm: HashMap[String, String]) extends AbstractModel { fields.put(SCHEMA.fSpaceType, "") } - def this(json: JsValue) { + def this(json: JsValue) = { this() fields.put(SCHEMA.fOwnerId, (json \ SCHEMA.fOwnerId).as[String]) if ((json \ SCHEMA.fBuid).toOption.isDefined) @@ -99,7 +98,7 @@ class Space(hm: HashMap[String, String]) extends AbstractModel { this.lng = java.lang.Double.parseDouble((json \ SCHEMA.fCoordinatesLon).as[String]) } - def this(json: JsValue, owner: String) { + def this(json: JsValue, owner: String) = { this(json) fields.put(SCHEMA.fOwnerId, owner) } @@ -107,7 +106,7 @@ class Space(hm: HashMap[String, String]) extends AbstractModel { def getId(): String = { var buid: String = fields.get(SCHEMA.fBuid) if (buid == null || buid.isEmpty || buid == "") { - val finalId = LPUtils.getRandomUUID + "_" + System.currentTimeMillis() + val finalId = LPUtils.getRandomUUID() + "_" + System.currentTimeMillis() fields.put(SCHEMA.fBuid, "building_" + finalId) buid = fields.get(SCHEMA.fBuid) this.json.as[JsObject] + (SCHEMA.fBuid -> Json.toJson(buid)) @@ -115,12 +114,12 @@ class Space(hm: HashMap[String, String]) extends AbstractModel { buid } - def hasAccess(ownerId: String): Boolean = { - if (fields.get(SCHEMA.fOwnerId) == ownerId) return true - co_owners.value.foreach(coOwner => if (coOwner == ownerId) return true) - - false - } + //def hasAccess(ownerId: String): Boolean = { + // if (fields.get(SCHEMA.fOwnerId) == ownerId) return true + // co_owners.value.foreach(coOwner => if (coOwner == ownerId) return true) + // + // false + //} def toGeoJSON(): String = { val sb = new StringBuilder() @@ -165,7 +164,7 @@ class Space(hm: HashMap[String, String]) extends AbstractModel { val co_owners = (jsonReq \ SCHEMA.fCoOwners).as[String] ja.add(co_owners) } - val arr = Json.toJson(ja.toList) + val arr = Json.toJson(ja.asScala) json = Json.toJson(json.as[JsObject] + (SCHEMA.fCoOwners -> arr)) json = json.as[JsObject] + (SCHEMA.fGeometry -> Json.toJson(new GeoJSONPoint(java.lang.Double.parseDouble(fields.get(SCHEMA.fCoordinatesLat)), java.lang.Double.parseDouble(fields.get(SCHEMA.fCoordinatesLon))).toGeoJSON())) @@ -199,7 +198,7 @@ class Space(hm: HashMap[String, String]) extends AbstractModel { json = json.as[JsObject] + (SCHEMA.fGeometry -> Json.toJson(new GeoJSONPoint(java.lang.Double.parseDouble(fields.get(SCHEMA.fCoordinatesLat)), java.lang.Double.parseDouble(fields.get(SCHEMA.fCoordinatesLon))).toGeoJSON())) json = Json.toJson(json.as[JsObject] + (SCHEMA.fOwnerId -> JsString(newOwnerId))) - json = Json.toJson(json.as[JsObject] + (SCHEMA.fCoOwners -> Json.toJson(newCoOwners.toList))) + json = Json.toJson(json.as[JsObject] + (SCHEMA.fCoOwners -> Json.toJson(newCoOwners.asScala))) } catch { case e: IOException => e.printStackTrace() } @@ -227,7 +226,7 @@ class Space(hm: HashMap[String, String]) extends AbstractModel { ret } - def cleanupFieldKey(json: JsValue, key: String) { + def cleanupFieldKey(json: JsValue, key: String): Unit = { if ((json \ key).toOption.isDefined && (json \ key) != JsDefined(JsNull)) { val temp = (json \ key).as[String] if (!temp.equals("")) { diff --git a/server/app/floor_module/Algo1.scala b/server/app/floor_module/Algo1.scala index 3435028e8..0adc090fe 100644 --- a/server/app/floor_module/Algo1.scala +++ b/server/app/floor_module/Algo1.scala @@ -39,9 +39,10 @@ import java.util.{ArrayList, HashMap} import datasources.SCHEMA import play.api.libs.json.{JsValue, Json} -import utils.LPLogger + +import scala.jdk.CollectionConverters.CollectionHasAsScala //remove if not needed -import scala.collection.JavaConversions._ +// import scala.collection.JavaConversions._ class Algo1(json: JsValue) extends IAlgo { @@ -51,6 +52,8 @@ class Algo1(json: JsValue) extends IAlgo { var input: HashMap[String, Wifi] = new HashMap[String, Wifi]() var mostSimilar: ArrayList[Score] = new ArrayList[Score](10) val listenList = (json\"wifi").as[List[String]] + //val listenList = json.getArray("wifi") + if (listenList == null) { throw new Exception("Wifi parameter is not array") @@ -60,7 +63,11 @@ class Algo1(json: JsValue) extends IAlgo { val obj = Json.parse(listenObject) val mac = (obj\SCHEMA.fMac).as[String] val rss = (obj\SCHEMA.fRSS).as[String].toInt - if (mac == null || rss == null) { + //for (listenObject <- listenList.iterator()) { + // val obj=listenObject.asInstanceOf[JsonObject] + // val mac = obj.getString("MAC") + // val rss = obj.getInt("rss") + if (mac == null) { throw new Exception("Invalid array wifi:: require mac,rss") } @@ -71,11 +78,12 @@ class Algo1(json: JsValue) extends IAlgo { var score = 0 var nNCM = 0 var nCM = 0 - for (wifiDatabase <- bucket) { + for (wifiDatabase <- bucket.asScala) { + //val mac = wifiDatabase.getString("MAC") val mac = (wifiDatabase\SCHEMA.fMac).as[String] if (input.containsKey(mac)) { - val diff = java.lang.Integer.parseInt((wifiDatabase\SCHEMA.fRSS).as[String]) - - input.get(mac).rss + //val diff = java.lang.Integer.parseInt(wifiDatabase.getString("rss")) - input.get(mac).rss + val diff = java.lang.Integer.parseInt((wifiDatabase\SCHEMA.fRSS).as[String]) - input.get(mac).rss score += diff * diff nCM += 1 } else { @@ -85,7 +93,7 @@ class Algo1(json: JsValue) extends IAlgo { Math.sqrt(score) - a * nCM + b * nNCM } - private def checkScore(similarity: Double, floor: String) { + private def checkScore(similarity: Double, floor: String): Unit ={ if (mostSimilar.size == 0) { mostSimilar.add(new Score(similarity, floor)) return @@ -102,14 +110,14 @@ class Algo1(json: JsValue) extends IAlgo { } } - def proccess(bucket: ArrayList[JsValue], floor: String) { + def proccess(bucket: ArrayList[JsValue], floor: String) : Unit = { val similarity = compare(bucket) checkScore(similarity, floor) } def getFloor(): String = { val sum_floor_score = new HashMap[String, Integer]() - for (s <- mostSimilar) { + for (s <- mostSimilar.asScala) { var score = 1 if (sum_floor_score.containsKey(s.floor)) { score = sum_floor_score.get(s.floor) + 1 @@ -118,7 +126,7 @@ class Algo1(json: JsValue) extends IAlgo { } var max_floor = "0" var max_score = 0 - for (floor <- sum_floor_score.keySet) { + for (floor <- sum_floor_score.keySet.asScala) { val score = sum_floor_score.get(floor) if (max_score < score) { max_score = score diff --git a/server/app/json/VALIDATE.scala b/server/app/json/VALIDATE.scala index 51ece843f..ae4ae2677 100644 --- a/server/app/json/VALIDATE.scala +++ b/server/app/json/VALIDATE.scala @@ -40,11 +40,11 @@ import java.util import com.google.common.collect.Lists import datasources.SCHEMA._ -import play.api.libs.json.{JsResultException, JsValue} +import play.api.libs.json.{JsLookupResult, JsResultException, JsValue} import play.api.mvc.Result -import utils.AnyResponseHelper +import utils.{AnyResponseHelper, JsonUtils} -import scala.collection.JavaConversions.asScalaBuffer +import scala.jdk.CollectionConverters.CollectionHasAsScala object VALIDATE { @@ -109,18 +109,19 @@ object VALIDATE { json } - def buid(json: JsValue): String = { - if (String(json, fBuid) == null) return "buid field must be String." + def buid(json: JsValue, key: String): String = { + if (String(json, key) == null) return key + " field must be String." null } - def credentials(json: JsValue, key: String): String = { + def userFields(json: JsValue, key: String, value: JsLookupResult): String = { if (String(json, key) == null) return "Credentials must be String." + if (value.as[String].length == 0) return key + " can not be empty." null } - def floor(json: JsValue): String = { - if (StringNumber(json, fFloor) == null) return "floor field must be String, containing a number." + def floor(json: JsValue, key: String): String = { + if (StringNumber(json, key) == null) return "floor field must be String, containing a number." null } @@ -130,17 +131,22 @@ object VALIDATE { } def timestamp(json: JsValue, key: String): String = { - if (StringNumber(json, key) == null) return "timestamp field must be String, containing a number." + if (StringNumber(json, key) == null) return key + " field must be String, containing a number." null } def xyz(json: JsValue, key: String): String = { - if (Int(json, key) == null) return "timestamp field must be String, containing a number." + if (Int(json, key) == null) return key + " field must be an integer." null } def coordinates(json: JsValue, key: String): String = { - if (Coordinate(json, key) == null) return "timestamp field must be String, containing a number." + if (Coordinate(json, key) == null) return key + " field must be String, containing a coordinate." + null + } + + def stringField(json: JsValue, key: String): String = { + if (String(json, key) == null) return key + " field must be String." null } @@ -150,11 +156,11 @@ object VALIDATE { val errors = new util.ArrayList[String]() for (k <- keys) { val value = json \ k - if (k == fBuid) { - val r = buid(json) + if (k == fBuid || k == fBuidA || k == fBuidB) { + val r = buid(json, k) if (r != null) errors.add(r) - } else if (k == fFloor) { - val r = floor(json) + } else if (k == fFloor || k == fFloorA || k == fFloorB) { + val r = floor(json, k) if (r != null) errors.add(r) } else if (k == fTimestampY || k == fTimestampX || k == fTimestampY) { val r = timestamp(json, k) @@ -168,21 +174,35 @@ object VALIDATE { } else if (k == "new_owner") { val r = newOwner(json) if (r != null) errors.add(r) - } else if (k == fUsername || k == fPassword) { - val r = credentials(json, k) + } else if (k == fUsername || k == fPassword || k == fEmail || k == fName) { + val r = userFields(json, k, value) + if (r != null) errors.add(r) + } else if (k == fPoisA || k == fPoisB || k == "pois_from" || k == "pois_to" || k == fCampusCuid) { + val r = stringField(json, k) if (r != null) errors.add(r) } } new Validation(errors) } + def checkRequirements(json: JsValue, keys: String*): Result = { + for (key <- keys) { + val requiredMissing = JsonUtils.hasProperties(json, key) + if (!requiredMissing.isEmpty) return AnyResponseHelper.requiredFieldsMissing(requiredMissing) + val validation = VALIDATE.fields(json, key) + if (validation.failed()) return validation.response() + } + null + } + + class Validation(private val errors: java.util.List[String]) { def failed():Boolean = !errors.isEmpty def response(): Result = { var str = "" - for (error:String <- errors) str += error + "\n" + for (error:String <- errors.asScala) str += error + "\n" AnyResponseHelper.bad_request("ERROR: Validation:\n" + str) } diff --git a/server/app/oauth/provider/v2/controllers/AnyplaceOAuth.scala b/server/app/oauth/provider/v2/controllers/AnyplaceOAuth.scala index 9501d66ac..e127b29ce 100644 --- a/server/app/oauth/provider/v2/controllers/AnyplaceOAuth.scala +++ b/server/app/oauth/provider/v2/controllers/AnyplaceOAuth.scala @@ -35,148 +35,140 @@ */ package oauth.provider.v2.controllers -import oauth.provider.v2.utils.OAuth2Responses -import oauth.provider.v2.granttype.GrantHandlerFactory -import oauth.provider.v2.granttype.IGrantHandler -import oauth.provider.v2.models.AccountModel -import oauth.provider.v2.models.ClientCredentials +import javax.inject.{Inject, Singleton} import oauth.provider.v2.models.OAuth2Request -import accounts.IAccountService -import accounts.ProxyAccountService -import oauth.provider.v2.OAuth2Constant -import org.apache.commons.lang3.StringUtils -import play.api.mvc.Action -import play.mvc.Controller +import play.api.mvc.{AbstractController, ControllerComponents} import utils.{AnyResponseHelper, LPLogger} -object AnyplaceOAuth extends Controller{ +@Singleton +class AnyplaceOAuth @Inject()(cc: ControllerComponents) extends AbstractController(cc) { /** - * This endpoint interacts with the resource owner in order to obtain - * authorization grant. The authorization server first authenticates - * the resource owner, using credentials (HTML Form) or session cookies. - * - * TLS/SSL connection is REQUIRED. - * - * REQUIRED: GET, [POST] - * - * This endpoint is used by grant types: - * a) Authorization Code - * b) Implicit grant - * and the field 'response_type' is required with values 'code' or 'token' - * respectively. - * - * @return - */ - def authorize()=Action { + * This endpoint interacts with the resource owner in order to obtain + * authorization grant. The authorization server first authenticates + * the resource owner, using credentials (HTML Form) or session cookies. + * + * TLS/SSL connection is REQUIRED. + * + * REQUIRED: GET, [POST] + * + * This endpoint is used by grant types: + * a) Authorization Code + * b) Implicit grant + * and the field 'response_type' is required with values 'code' or 'token' + * respectively. + * + * @return + */ + def authorize() = Action { implicit request => - // create the Request and check it - val anyReq: OAuth2Request = new OAuth2Request(request) - if (!anyReq.assertJsonBody()) { - AnyResponseHelper.bad_request( - AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) - } - val json = anyReq.getJsonBody - LPLogger.info("AnyplaceOAuth::authorize():: " + json.toString) - AnyResponseHelper.not_found( - "OAuth grant types using authenticate are not supported!") + // create the Request and check it + val anyReq: OAuth2Request = new OAuth2Request(request) + if (!anyReq.assertJsonBody()) { + AnyResponseHelper.bad_request( + AnyResponseHelper.CANNOT_PARSE_BODY_AS_JSON) + } + val json = anyReq.getJsonBody() + LPLogger.info("AnyplaceOAuth::authorize():: " + json.toString) + AnyResponseHelper.not_found( + "OAuth grant types using authenticate are not supported!") } - /** - * This endpoint is used by all the grant types flows except 'implicit grant' - * since the token is issued directly. - * - * TLS/SSL connection is REQUIRED. - * REQUIRED: POST - * Required parameters with no value are treated as omitted and unknowns are ignored. - * - * ////// REQUEST A TOKEN ////////////// - * Access Token Request (application/x-www-form-urlencoded): RFC 4.3.2 - * grant_type: 'password' - * username: The resource owner username - * password: The resource owner password - * scope: The scope of the access request (optional) - * client_id: The client id issued by the registration service (optional) - * client_secret: The client secret issued by the registration service (optional) - * - * After successful request the response is like below: - * - * HTTP/1.1 200 OK - * Content-Type: application/json;charset=utf-8 - * Cache-Control: no-store - * Pragma: no-cache - * - * { - * "access_token": "access token here", - * "token_type": "Bearer", - * "expires_in": lifetime in seconds, - * "refresh_token": "refresh token here" - * } - * - * ////// REFRESH A TOKEN ////////////// - * Access Token Refresh (application/x-www-form-urlencoded): RFC 4.3.2 - * grant_type: 'refresh_token' - * refresh_token: 'the refresh token issued in the token request' - * scope: The scope of the access request (optional) - * client_id: The client id issued by the registration service (optional) - * client_secret: The client secret issued by the registration service (optional) - * - * After successful request the response is like below: - * - * HTTP/1.1 200 OK - * Content-Type: application/json;charset=utf-8 - * Cache-Control: no-store - * Pragma: no-cache - * - * { - * "access_token": "access token here", - * "token_type": "Bearer", - * "expires_in": lifetime in seconds, - * "refresh_token": "refresh token here" - * } - * - * @return - */ - @deprecated("") - def token()=Action { - implicit request => - - LPLogger.info("AnyplaceOAuth::token():: " + request.body.toString) - // wrap the Request into our own OAuth2Request - val anyReq: OAuth2Request = new OAuth2Request(request) - // ensure that a grant_type exists - val grantType: String = anyReq.getParameter(OAuth2Constant.GRANT_TYPE) - if (StringUtils.isBlank(grantType)) { - OAuth2Responses.InvalidRequest("'grant_type' not found") - } - // make sure that we can handle the specified grant_type - val grantHandler: IGrantHandler = - GrantHandlerFactory.fromGrantType(grantType) - if (grantHandler == null) { - OAuth2Responses.UnsupportedGrantType( - "'grant_type' requested is not supported") - } - // ensure that client credentials have been submitted and are valid - val clientCredentials: ClientCredentials = anyReq.getCredentials - if (StringUtils.isBlank(clientCredentials.client_id)) { - OAuth2Responses.InvalidRequest("'client_id' not found") - } - if (StringUtils.isBlank(clientCredentials.client_secret)) { - OAuth2Responses.InvalidRequest("'client_secret' not found") - } - val accountService: IAccountService = ProxyAccountService.getInstance - val account: AccountModel = accountService.validateClient( - clientCredentials.client_id, - clientCredentials.client_secret, - grantType) - if (account == null) { - OAuth2Responses.InvalidClient( - "Specified client credentials are not valid") - } - // and return the appropriate response either the token or the error json -// grantHandler.handleRequest(anyReq, accountService, account) - null - } + ///** + // * This endpoint is used by all the grant types flows except 'implicit grant' + // * since the token is issued directly. + // * + // * TLS/SSL connection is REQUIRED. + // * REQUIRED: POST + // * Required parameters with no value are treated as omitted and unknowns are ignored. + // * + // * ////// REQUEST A TOKEN ////////////// + // * Access Token Request (application/x-www-form-urlencoded): RFC 4.3.2 + // * grant_type: 'password' + // * username: The resource owner username + // * password: The resource owner password + // * scope: The scope of the access request (optional) + // * client_id: The client id issued by the registration service (optional) + // * client_secret: The client secret issued by the registration service (optional) + // * + // * After successful request the response is like below: + // * + // * HTTP/1.1 200 OK + // * Content-Type: application/json;charset=utf-8 + // * Cache-Control: no-store + // * Pragma: no-cache + // * + // * { + // * "access_token": "access token here", + // * "token_type": "Bearer", + // * "expires_in": lifetime in seconds, + // * "refresh_token": "refresh token here" + // * } + // * + // * ////// REFRESH A TOKEN ////////////// + // * Access Token Refresh (application/x-www-form-urlencoded): RFC 4.3.2 + // * grant_type: 'refresh_token' + // * refresh_token: 'the refresh token issued in the token request' + // * scope: The scope of the access request (optional) + // * client_id: The client id issued by the registration service (optional) + // * client_secret: The client secret issued by the registration service (optional) + // * + // * After successful request the response is like below: + // * + // * HTTP/1.1 200 OK + // * Content-Type: application/json;charset=utf-8 + // * Cache-Control: no-store + // * Pragma: no-cache + // * + // * { + // * "access_token": "access token here", + // * "token_type": "Bearer", + // * "expires_in": lifetime in seconds, + // * "refresh_token": "refresh token here" + // * } + // * + // * @return + // */ + //@deprecated("") + //def token() = Action { + // implicit request => + // + // LPLogger.info("AnyplaceOAuth::token():: " + request.body.toString) + // // wrap the Request into our own OAuth2Request + // val anyReq: OAuth2Request = new OAuth2Request(request) + // // ensure that a grant_type exists + // val grantType: String = anyReq.getParameter(OAuth2Constant.GRANT_TYPE) + // if (StringUtils.isBlank(grantType)) { + // OAuth2Responses.InvalidRequest("'grant_type' not found") + // } + // // make sure that we can handle the specified grant_type + // val grantHandler: IGrantHandler = + // GrantHandlerFactory.fromGrantType(grantType) + // if (grantHandler == null) { + // OAuth2Responses.UnsupportedGrantType( + // "'grant_type' requested is not supported") + // } + // // ensure that client credentials have been submitted and are valid + // val clientCredentials: ClientCredentials = anyReq.getCredentials + // if (StringUtils.isBlank(clientCredentials.client_id)) { + // OAuth2Responses.InvalidRequest("'client_id' not found") + // } + // if (StringUtils.isBlank(clientCredentials.client_secret)) { + // OAuth2Responses.InvalidRequest("'client_secret' not found") + // } + // val accountService: IAccountService = ProxyAccountService.getInstance + // val account: AccountModel = accountService.validateClient( + // clientCredentials.client_id, + // clientCredentials.client_secret, + // grantType) + // if (account == null) { + // OAuth2Responses.InvalidClient( + // "Specified client credentials are not valid") + // } + // // and return the appropriate response either the token or the error json + // // grantHandler.handleRequest(anyReq, accountService, account) + // null + //} // depending on the grant_type the handler will take over the procedure now // depending on the grant_type the handler will take over the procedure now diff --git a/server/app/oauth/provider/v2/granttype/GrantHandlerFactory.scala b/server/app/oauth/provider/v2/granttype/GrantHandlerFactory.scala index 02639c801..acdb11ea4 100644 --- a/server/app/oauth/provider/v2/granttype/GrantHandlerFactory.scala +++ b/server/app/oauth/provider/v2/granttype/GrantHandlerFactory.scala @@ -37,8 +37,6 @@ package oauth.provider.v2.granttype import java.util -import oauth.provider.v2.OAuth2Constant - /** * This factory is responsible to return the appropriate handler * to process the token request specified by the grant_type. @@ -64,5 +62,5 @@ object GrantHandlerFactory { def isGrantTypeSupported(`type`: String): Boolean = fromGrantType(`type`) != null sGrantHandlers = new util.HashMap[String, IGrantHandler] - sGrantHandlers.put(OAuth2Constant.GRANT_TYPE_PASSWORD, new PasswordHandler) + //sGrantHandlers.put(OAuth2Constant.GRANT_TYPE_PASSWORD, new PasswordHandler) } \ No newline at end of file diff --git a/server/app/oauth/provider/v2/granttype/PasswordHandler.scala b/server/app/oauth/provider/v2/granttype/PasswordHandler.scala index 0f51a767f..b9c1c16d1 100644 --- a/server/app/oauth/provider/v2/granttype/PasswordHandler.scala +++ b/server/app/oauth/provider/v2/granttype/PasswordHandler.scala @@ -33,74 +33,67 @@ * DEALINGS IN THE SOFTWARE. * */ -package oauth.provider.v2.granttype +//package oauth.provider.v2.granttype +// +//import oauth.provider.v2.OAuth2Constant +//import oauth.provider.v2.utils.OAuth2Responses +//import oauth.provider.v2.models._ +//import accounts.IAccountService +//import play.mvc.Result +//import utils.AnyResponseHelper +// +////remove if not needed +//// import scala.collection.JavaConversions._ +// +///** +// * This class is the handler that is responsible to handle the requests +// * with grant_type specified as 'password'. +// */ +//class PasswordHandler extends AbstractGrantHandler { +// +// override def handleRequest(request: OAuth2Request, +// accountService: IAccountService, +// account: AccountModel): Result = { +// val clientCredentials: ClientCredentials = request.getCredentials -import oauth.provider.v2.OAuth2Constant + //val username: String = request.getParameter(OAuth2Constant.USERNAME) + //if (StringUtils.isBlank(username)) { + // OAuth2Responses.InvalidRequest("'username' not provided") + //} + //val password: String = request.getParameter(OAuth2Constant.PASSWORD) + //if (StringUtils.isBlank(password)) { + // OAuth2Responses.InvalidRequest("'password' not provided") + //} + // + //if (!accountService.validateAccount(account, username, password)) { + // OAuth2Responses.InvalidGrant( + // "username:password credentials are not valid") + //} + // + //val scope: String = request.getParameter(OAuth2Constant.SCOPE) + //if (StringUtils.isBlank(scope)) { + // OAuth2Responses.InvalidRequest("'scope' not provided") + //} -import oauth.provider.v2.utils.OAuth2Responses - -import oauth.provider.v2.models._ - -import accounts.IAccountService - -import org.apache.commons.lang3.StringUtils - -import play.mvc.Result - -import utils.AnyResponseHelper - -//remove if not needed -import scala.collection.JavaConversions._ - -/** - * This class is the handler that is responsible to handle the requests - * with grant_type specified as 'password'. - */ -class PasswordHandler extends AbstractGrantHandler { - - override def handleRequest(request: OAuth2Request, - accountService: IAccountService, - account: AccountModel): Result = { - val clientCredentials: ClientCredentials = request.getCredentials -// ensure that username and password exists - val username: String = request.getParameter(OAuth2Constant.USERNAME) - if (StringUtils.isBlank(username)) { - OAuth2Responses.InvalidRequest("'username' not provided") - } - val password: String = request.getParameter(OAuth2Constant.PASSWORD) - if (StringUtils.isBlank(password)) { - OAuth2Responses.InvalidRequest("'password' not provided") - } -// ensure that the provided username/password relates to an account - if (!accountService.validateAccount(account, username, password)) { - OAuth2Responses.InvalidGrant( - "username:password credentials are not valid") - } -// and the specific client currently being used - val scope: String = request.getParameter(OAuth2Constant.SCOPE) - if (StringUtils.isBlank(scope)) { - OAuth2Responses.InvalidRequest("'scope' not provided") - } -// try to issue the new access token - val authInfo: AuthInfo = accountService.createOrUpdateAuthInfo( - account, - clientCredentials.client_id, - scope) - if (authInfo == null) { - OAuth2Responses.InvalidGrant("Could not authorize you for this scope") - } -//LPLogger.info("before issuing token"); - val accessTokenModel: AccessTokenModel = - issueAccessToken(accountService, authInfo) - if (accessTokenModel == null) { - AnyResponseHelper.internal_server_error("Could not create access token") - } -//LPLogger.info("new token: [" + accessTokenModel.getAccessToken() + "]"); - OAuth2Responses.ValidToken(accessTokenModel) - } + //val authInfo: AuthInfo = accountService.createOrUpdateAuthInfo( + // account, + // clientCredentials.client_id, + // scope) +// if (authInfo == null) { +// OAuth2Responses.InvalidGrant("Could not authorize you for this scope") +// } +////LPLogger.info("before issuing token"); +// val accessTokenModel: AccessTokenModel = +// issueAccessToken(accountService, authInfo) +// if (accessTokenModel == null) { +// AnyResponseHelper.internal_server_error("Could not create access token") +// } +////LPLogger.info("new token: [" + accessTokenModel.getAccessToken() + "]"); +// OAuth2Responses.ValidToken(accessTokenModel) +// } // now we have to make sure that the scope requested is valid // and that is included in the scope granted for the specific account // now we have to make sure that the scope requested is valid // and that is included in the scope granted for the specific account -} +//} diff --git a/server/app/oauth/provider/v2/models/AccessTokenModel.scala b/server/app/oauth/provider/v2/models/AccessTokenModel.scala index 95adaccf0..a8b8cf11a 100644 --- a/server/app/oauth/provider/v2/models/AccessTokenModel.scala +++ b/server/app/oauth/provider/v2/models/AccessTokenModel.scala @@ -69,19 +69,19 @@ class AccessTokenModel(private var access_token: String, def getClientId(): String = client_id - override def toString(): String = this.getTuid + override def toString(): String = this.getTuid() def toJson(): JsonObject = { val json: JsonObject= JsonObject.empty() - json.put("token_type", this.getTokenType) - json.put("access_token", this.getAccessToken) - json.put("expires_in", this.getExpiresIn) - json.put("refresh_token", this.getRefreshToken) - json.put("tuid", this.getTuid) - json.put("scope", this.getScope) - json.put("client_id", this.getClientId) - json.put("auid", this.getAuid) - json.put("created_at", this.getCreatedAt) + json.put("token_type", this.getTokenType()) + json.put("access_token", this.getAccessToken()) + json.put("expires_in", this.getExpiresIn()) + json.put("refresh_token", this.getRefreshToken()) + json.put("tuid", this.getTuid()) + json.put("scope", this.getScope()) + json.put("client_id", this.getClientId()) + json.put("auid", this.getAuid()) + json.put("created_at", this.getCreatedAt()) json } diff --git a/server/app/oauth/provider/v2/models/AccountModel.scala b/server/app/oauth/provider/v2/models/AccountModel.scala index 15814b0cf..413375600 100644 --- a/server/app/oauth/provider/v2/models/AccountModel.scala +++ b/server/app/oauth/provider/v2/models/AccountModel.scala @@ -39,12 +39,13 @@ import java.util._ import com.couchbase.client.java.document.json.{JsonArray, JsonObject} import oauth.provider.v2.models.AccountModel._ -import utils.{LPUtils, PasswordService} +import play.twirl.api.TwirlHelperImports.twirlJavaCollectionToScala +import utils.{LPUtils} import scala.beans.BeanProperty //remove if not needed -import scala.collection.JavaConversions._ +// import scala.collection.JavaConversions._ object AccountModel { @@ -105,12 +106,12 @@ object AccountModel { "account_" + LPUtils.hashStringHex( LPUtils.generateRandomToken() + System.currentTimeMillis() + - LPUtils.getRandomUUID) + LPUtils.getRandomUUID()) private def generateNewClientId(auid: String): String = "client_" + LPUtils.hashStringHex( - LPUtils.getRandomUUID + auid + System.currentTimeMillis()) + LPUtils.getRandomUUID() + auid + System.currentTimeMillis()) private def generateNewClientSecret(auid: String, client_id: String): String = @@ -182,7 +183,7 @@ class AccountModel(json: JsonObject) { false } val scopes: Array[String] = scope.split(" ") - val accountScopes: Array[String] = this.getScope.split(" ") + val accountScopes: Array[String] = this.getScope().split(" ") // if more scopes requested reject if (scopes.length > accountScopes.length) { false @@ -216,7 +217,7 @@ class AccountModel(json: JsonObject) { def addNewClient(grant_type: String, scope: String, redirect_uri: String): Unit = { - val client_id: String = generateNewClientId(this.getAuid) + val client_id: String = generateNewClientId(this.getAuid()) val client_secret: String = generateNewClientSecret(auid, client_id) this.clients.add( new ClientModel(client_id, @@ -227,14 +228,14 @@ class AccountModel(json: JsonObject) { } override def toString(): String = - String.format("AccountModel: uaid[%s]", this.getAuid) + String.format("AccountModel: uaid[%s]", this.getAuid()) def toJson(): JsonObject = { val json: JsonObject = JsonObject.empty() json.put("doctype", "account") json.put("auid", this.auid) json.put("username", this.username) - json.put("password", PasswordService.createHash(this.password)) + //json.put("password", PasswordService.createHash(this.password)) json.put("scope", this.scope) json.put("nickname", this.nickname) json.put("email", this.email) diff --git a/server/app/oauth/provider/v2/models/AuthInfo.scala b/server/app/oauth/provider/v2/models/AuthInfo.scala index 425351d0c..17099a3f2 100644 --- a/server/app/oauth/provider/v2/models/AuthInfo.scala +++ b/server/app/oauth/provider/v2/models/AuthInfo.scala @@ -50,7 +50,7 @@ class AuthInfo { private var code : String = _ private var redirect_uri : String = _ - def this(sauid: String, sclient_id: String, sscope: String) { + def this(sauid: String, sclient_id: String, sscope: String) = { this() this.auid = sauid this.client_id = sclient_id diff --git a/server/app/oauth/provider/v2/models/OAuth2Request.scala b/server/app/oauth/provider/v2/models/OAuth2Request.scala index d6a09033c..7b0c2668f 100644 --- a/server/app/oauth/provider/v2/models/OAuth2Request.scala +++ b/server/app/oauth/provider/v2/models/OAuth2Request.scala @@ -54,7 +54,7 @@ class OAuth2Request(request: Request[AnyContent], enableCORS: Boolean) { assertFormUrlEncodedBody() } - def this(request: Request[AnyContent]) { + def this(request: Request[AnyContent]) = { this(request, true) } @@ -107,6 +107,7 @@ class OAuth2Request(request: Request[AnyContent], enableCORS: Boolean) { } null } + /////////////////////////////////////////////////////////////////////////////////// // OAUTH RELATED METHODS @@ -132,3 +133,5 @@ class OAuth2Request(request: Request[AnyContent], enableCORS: Boolean) { new ClientCredentials(client_id, client_secret) } } + + diff --git a/server/app/oauth/provider/v2/token/TokenService.scala b/server/app/oauth/provider/v2/token/TokenService.scala index e2db772bc..a103001dc 100644 --- a/server/app/oauth/provider/v2/token/TokenService.scala +++ b/server/app/oauth/provider/v2/token/TokenService.scala @@ -67,7 +67,7 @@ object TokenService { // Used by the secure encryption/decryption algorithms val timeNow = new Date().getTime val plainText = authInfo.getAuid + "]" + authInfo.getScope + "]" + authInfo.getClientId + "]" + String.valueOf(timeNow) LPLogger.info("plaintext : >" + plainText + "<") - val randomString = LPUtils.generateRandomToken + val randomString = LPUtils.generateRandomToken() LPLogger.info("randomstr PH1: >" + randomString + "<") val encrypted_token = LPUtils.secureEncrypt(SECURE_PASSWORD_PHASE1, randomString + "." + plainText) LPLogger.info("encrypted PH2: >" + encrypted_token + "<") @@ -96,7 +96,7 @@ object TokenService { // Used by the secure encryption/decryption algorithms LPLogger.info("plaintext : >" + plainText + "<") val signature = LPUtils.secureEncrypt(SECURE_PASSWORD_PHASE1, plainText) LPLogger.info("signature PH1: >" + signature + "<") - val randomString = LPUtils.generateRandomToken + val randomString = LPUtils.generateRandomToken() LPLogger.info("randomstr PH1: >" + randomString + "<") val encrypted_token = LPUtils.secureEncrypt(SECURE_PASSWORD_PHASE2, randomString + "." + signature) LPLogger.info("encrypted PH2: >" + encrypted_token + "<") @@ -106,5 +106,5 @@ object TokenService { // Used by the secure encryption/decryption algorithms /** * Return a new Client Id */ - def createUserId: String = LPUtils.getRandomUUID + def createUserId: String = LPUtils.getRandomUUID() } \ No newline at end of file diff --git a/server/app/oauth/provider/v2/utils/OAuth2Responses.scala b/server/app/oauth/provider/v2/utils/OAuth2Responses.scala index 4317158b4..c7582bc53 100644 --- a/server/app/oauth/provider/v2/utils/OAuth2Responses.scala +++ b/server/app/oauth/provider/v2/utils/OAuth2Responses.scala @@ -36,10 +36,9 @@ package oauth.provider.v2.utils import com.couchbase.client.java.document.json.JsonObject +import oauth.provider.v2.OAuth2Constant import oauth.provider.v2.models.AccessTokenModel -import oauth.provider.v2.{OAuth2Constant, utils} -import play.mvc.Result -import play.mvc.Results +import play.mvc.{Result, Results} object OAuth2Responses { @@ -124,10 +123,10 @@ object OAuth2Responses { def ValidToken(tokenModel: AccessTokenModel): Result = { val json = JsonObject.empty() - json.put(OAuth2Constant.ACCESS_TOKEN, tokenModel.getAccessToken) - json.put(OAuth2Constant.TOKEN_TYPE, tokenModel.getTokenType) - json.put(OAuth2Constant.EXPIRES_IN, tokenModel.getExpiresIn) - json.put(OAuth2Constant.REFRESH_TOKEN, tokenModel.getRefreshToken) + json.put(OAuth2Constant.ACCESS_TOKEN, tokenModel.getAccessToken()) + json.put(OAuth2Constant.TOKEN_TYPE, tokenModel.getTokenType()) + json.put(OAuth2Constant.EXPIRES_IN, tokenModel.getExpiresIn()) + json.put(OAuth2Constant.REFRESH_TOKEN, tokenModel.getRefreshToken()) Results.ok(json.toString) } diff --git a/server/app/radiomapserver/RadioMap.scala b/server/app/radiomapserver/RadioMap.scala index 3ead8a579..d5dd7a491 100644 --- a/server/app/radiomapserver/RadioMap.scala +++ b/server/app/radiomapserver/RadioMap.scala @@ -44,8 +44,10 @@ import java.util.{ArrayList, HashMap, LinkedList} import Jama.Matrix import utils.LPLogger +import scala.jdk.CollectionConverters.{CollectionHasAsScala, MapHasAsScala} + //remove if not needed -import scala.collection.JavaConversions._ +// import scala.collection.JavaConversions._ object RadioMap { @@ -160,7 +162,7 @@ object RadioMap { null } - private def createRadioMapFromPath(inFile: File) { + private def createRadioMapFromPath(inFile: File): Unit = { if (inFile.exists()) { // how is this if working... ?? if (inFile.canExecute() && inFile.isDirectory) { @@ -176,7 +178,7 @@ object RadioMap { } } - def parseLogFileToRadioMap(inFile: File) { + def parseLogFileToRadioMap(inFile: File): Unit = { var MACAddressMap: HashMap[String, ArrayList[Integer]] = null var RSS_Values: ArrayList[Integer] = null val MAG_Values: ArrayList[ArrayList[Float]] = null @@ -215,7 +217,7 @@ object RadioMap { num_orientations).toInt orientationLists = NewRadioMap.get(key) if (orientationLists == null) { - orientationLists = new HashMap[Integer, ArrayList[Any]](Math.round(num_orientations)) + orientationLists = new HashMap[Integer, ArrayList[Any]](Math.round(num_orientations.toFloat)) orientationList = new ArrayList[Any](2) orientationLists.put(group, orientationList) MACAddressMap = new HashMap[String, ArrayList[Integer]]() @@ -407,7 +409,7 @@ object RadioMap { true } - private def set_MIN_MAX_RSS(RSS_Value: Int) { + private def set_MIN_MAX_RSS(RSS_Value: Int) : Unit = { if (MIN_RSS > RSS_Value && RSS_Value != this.defaultNaNValue) { MIN_RSS = RSS_Value } @@ -425,7 +427,7 @@ object RadioMap { // must have size >= 2 for (i <- 0 until RM.getOrderList().size; j <- i + 1 until RM.getOrderList().size) { val RadioMapFile = RM.getLocationRSS_HashMap(group) - if (RadioMapFile != null && RadioMapFile.get(RM.getOrderList.get(i)) != null && + if (RadioMapFile != null && RadioMapFile.get(RM.getOrderList().get(i)) != null && RadioMapFile.get(RM.getOrderList().get(j)) != null) { result = calculateEuclideanDistance(RadioMapFile.get(RM.getOrderList().get(i)), RadioMapFile.get(RM.getOrderList().get(j))) if (result == java.lang.Float.NEGATIVE_INFINITY) { @@ -434,8 +436,8 @@ object RadioMap { allDistances.add(result) } } - maximumDistance = allDistances.max - java.lang.Float.valueOf((maximumDistance / Math.sqrt(2 * RM.getOrderList.size)).toFloat) + maximumDistance = allDistances.asScala.max + java.lang.Float.valueOf((maximumDistance / Math.sqrt(2 * RM.getOrderList().size())).toFloat) } private def calculateEuclideanDistance(real: String, estimate: String): Double @@ -551,11 +553,11 @@ object RadioMap { var heading = 0 var x_y = "" var group = 0 - for ((key, value) <- NewRadioMap) { + for ((key, value) <- NewRadioMap.asScala) { val degrees = 360 - for ((key, value) <- value) { + for ((key, value) <- value.asScala) { MACAddressMap = value.get(0).asInstanceOf[HashMap[String, ArrayList[Integer]]] - for ((key, value) <- MACAddressMap) { + for ((key, value) <- MACAddressMap.asScala) { val MACAddress = key if (!MACKeys.contains(MACAddress.toLowerCase())) { if (AP.size == 0 || AP.contains(MACAddress.toLowerCase())) { @@ -573,15 +575,15 @@ object RadioMap { } } } - for ((key, value) <- NewRadioMap) { + for ((key, value) <- NewRadioMap.asScala) { val degrees = 360 group = degrees / orientations x_y = key - for ((key, value) <- value) { + for ((key, value) <- value.asScala) { max_values = 0 heading = key * group MACAddressMap = value.get(0).asInstanceOf[HashMap[String, ArrayList[Integer]]] - for ((key, value) <- MACAddressMap) { + for ((key, value) <- MACAddressMap.asScala) { val wifi_rss_values = value if (wifi_rss_values.size > max_values) { max_values = wifi_rss_values.size @@ -675,7 +677,7 @@ object RadioMap { try { if (x == 0) fos.write("# Heading wx, wy\n".getBytes) for (i <- 0 until w.getRowDimension) { - fos.write((group + ", ").getBytes) + fos.write((s"$group").getBytes) for (j <- 0 until w.getColumnDimension) { fos.write(dec.format(w.get(i, j)).getBytes) if (j != w.getColumnDimension - 1) { @@ -978,10 +980,10 @@ object RadioMap { Math.sqrt(finalResult).toFloat } - private def printMatrix(m: Matrix) { + private def printMatrix(m: Matrix): Unit = { for (i <- 0 until m.getRowDimension) { - for (j <- 0 until m.getColumnDimension) { - System.out.print(m.get(i, j) + " ") + for (j <- 0 until m.getColumnDimension()) { + System.out.print(s"$m.get(i, j)") } println() } diff --git a/server/app/radiomapserver/RadioMapMean.scala b/server/app/radiomapserver/RadioMapMean.scala index 96849eb1e..e3157f9ea 100644 --- a/server/app/radiomapserver/RadioMapMean.scala +++ b/server/app/radiomapserver/RadioMapMean.scala @@ -41,8 +41,9 @@ import java.util.{ArrayList, HashMap} import utils.LPLogger import scala.beans.BeanProperty +import scala.jdk.CollectionConverters.CollectionHasAsScala //remove if not needed -import scala.collection.JavaConversions._ +// import scala.collection.JavaConversions._ import scala.util.control.Breaks._ class RadioMapMean(private val isIndoor: Boolean, @BeanProperty val defaultNaNValue: Int) { @@ -89,14 +90,14 @@ class RadioMapMean(private val isIndoor: Boolean, @BeanProperty val defaultNaNVa c += 1 if (line.trim() == "") { //continue (break from breakable inside loop) - break + break() } line = line.replace(", ", " ") temp = line.split(" ") if (temp(0).trim() == "#") { if (temp(1).trim() == "NaN") { //continue (break from breakable inside loop) - break + break() } if (temp.length < 5) { return false @@ -111,7 +112,7 @@ class RadioMapMean(private val isIndoor: Boolean, @BeanProperty val defaultNaNVa this.MacAdressList.add(temp(i)) } //continue (break from breakable inside loop) - break + break() } key = temp(0) + " " + temp(1) group = java.lang.Integer.parseInt(temp(2)) @@ -132,7 +133,7 @@ class RadioMapMean(private val isIndoor: Boolean, @BeanProperty val defaultNaNVa this.LocationRSS_HashMap.put(key, RSS_Values) this.GroupLocationRSS_HashMap.put(group, LocationRSS_HashMap) //continue (break from breakable inside loop) - break + break() } this.LocationRSS_HashMap.put(key, RSS_Values) } @@ -159,7 +160,7 @@ class RadioMapMean(private val isIndoor: Boolean, @BeanProperty val defaultNaNVa str += MacAdressList.get(i) + " " } str += "\nLocations\n" - for (location <- LocationRSS_HashMap.keySet) { + for (location <- LocationRSS_HashMap.keySet.asScala) { str += location + " " temp = LocationRSS_HashMap.get(location) for (i <- 0 until temp.size) { diff --git a/server/app/utils/AndroidAPKFile.scala b/server/app/utils/AndroidAPKFile.scala index 12209246e..74dc881b1 100644 --- a/server/app/utils/AndroidAPKFile.scala +++ b/server/app/utils/AndroidAPKFile.scala @@ -50,8 +50,8 @@ object AndroidAPKFile { override def compare(thiss: AndroidAPKFile, that: AndroidAPKFile): Int = try { - val vThis: String = thiss.getVersion.substring(1) - val vThat: String = that.getVersion.substring(1) + val vThis: String = thiss.getVersion().substring(1) + val vThat: String = that.getVersion().substring(1) val segsThis: Array[String] = vThis.split("[.]") val segsThat: Array[String] = vThat.split("[.]") for (i <- 0 until segsThis.length) { @@ -63,7 +63,7 @@ object AndroidAPKFile { 1 } } - if (thiss.isRelease) -1 else 1 + if (thiss.isRelease()) -1 else 1 } catch { case e: NumberFormatException => -1 diff --git a/server/app/utils/AnyPlaceTilerHelper.scala b/server/app/utils/AnyPlaceTilerHelper.scala index 0ca120409..8f1a79e72 100644 --- a/server/app/utils/AnyPlaceTilerHelper.scala +++ b/server/app/utils/AnyPlaceTilerHelper.scala @@ -3,11 +3,15 @@ package utils import java.io._ import java.nio.file.Files -import play.Logger -//remove if not needed -import play.Play +import javax.inject.{Inject, Singleton} +import play.api.Configuration +import play.api.mvc.{AbstractController, ControllerComponents} -object AnyPlaceTilerHelper { +@Singleton +class AnyPlaceTilerHelper @Inject()(cc: ControllerComponents, + conf: Configuration, + api: AnyplaceServerAPI) + extends AbstractController(cc) { private val ANYPLACE_TILER_SCRIPT_START = "start-anyplace-tiler.sh" private val FLOOR_PLANS_ROOT_DIR = "floor_plans" + File.separatorChar @@ -16,15 +20,15 @@ object AnyPlaceTilerHelper { val FLOOR_TILES_ZIP_NAME = "tiles_archive.zip" def getTilerScriptStart(): String = { - Play.application().configuration().getString("tilerRootDir") + File.separatorChar + ANYPLACE_TILER_SCRIPT_START + conf.get[String]("tilerRootDir") + File.separatorChar + ANYPLACE_TILER_SCRIPT_START } def getRootFloorPlansDir(): String = { - Play.application().configuration().getString("floorPlansRootDir") + File.separatorChar + conf.get[String]("floorPlansRootDir") + File.separatorChar } def getRootFloorPlansDirFor(buid: String): String = { - getRootFloorPlansDir + buid + File.separatorChar + getRootFloorPlansDir() + buid + File.separatorChar } def getRootFloorPlansDirFor(buid: String, floor: String): String = { @@ -60,7 +64,7 @@ object AnyPlaceTilerHelper { if (buid.trim().isEmpty || floor.trim().isEmpty) { return null } - AnyplaceServerAPI.SERVER_FULL_URL + File.separatorChar + + api.SERVER_FULL_URL + File.separatorChar + "anyplace/floortiles/" + buid + File.separatorChar + @@ -77,7 +81,7 @@ object AnyPlaceTilerHelper { * @return */ def storeFloorPlanToServer(buid: String, floor_number: String, file: File): File = { - val dirS = AnyPlaceTilerHelper.getRootFloorPlansDirFor(buid, floor_number) + val dirS = getRootFloorPlansDirFor(buid, floor_number) val dir = new File(dirS) dir.mkdirs() if (!dir.isDirectory || !dir.canWrite() || !dir.canExecute()) { @@ -102,7 +106,7 @@ object AnyPlaceTilerHelper { imageFile.toString + "]") } - val pb = new ProcessBuilder(getTilerScriptStart, imageFile.getAbsolutePath.toString, lat, + val pb = new ProcessBuilder(getTilerScriptStart(), imageFile.getAbsolutePath().toString(), lat, lng, "-DISLOG") val log = new File(imageDir, "anyplace_tiler_" + imageFile.getName + ".log") pb.redirectErrorStream(true) @@ -121,7 +125,7 @@ object AnyPlaceTilerHelper { val err = "Tiling for image[" + imageFile.toString + "] failed with exit code[" + p.exitValue() + "]!" - Logger.error(err) + LPLogger.error(err) throw new AnyPlaceException(err) } } catch { @@ -129,14 +133,14 @@ object AnyPlaceTilerHelper { val err = "Tiling for image[" + imageFile.toString + "] failed with IOException[" + e.getMessage + "]!" - Logger.error(err) + LPLogger.error(err) throw new AnyPlaceException(err) } case e: InterruptedException => { val err = "Tiling for image[" + imageFile.toString + "] failed with InterruptedException[" + e.getMessage + "]!" - Logger.error(err) + LPLogger.error(err) throw new AnyPlaceException(err) } } @@ -153,7 +157,7 @@ object AnyPlaceTilerHelper { imageFile.toString + "]") } - val pb = new ProcessBuilder(getTilerScriptStart, imageFile.getAbsolutePath.toString, lat, + val pb = new ProcessBuilder(getTilerScriptStart(), imageFile.getAbsolutePath().toString(), lat, lng,"-DISLOG",zoom) val log = new File(imageDir, "anyplace_tiler_" + imageFile.getName + ".log") pb.redirectErrorStream(true) @@ -172,7 +176,7 @@ object AnyPlaceTilerHelper { val err = "Tiling for image[" + imageFile.toString + "] failed with exit code[" + p.exitValue() + "]!" - Logger.error(err) + LPLogger.error(err) throw new AnyPlaceException(err) } } catch { @@ -180,14 +184,14 @@ object AnyPlaceTilerHelper { val err = "Tiling for image[" + imageFile.toString + "] failed with IOException[" + e.getMessage + "]!" - Logger.error(err) + LPLogger.error(err) throw new AnyPlaceException(err) } case e: InterruptedException => { val err = "Tiling for image[" + imageFile.toString + "] failed with InterruptedException[" + e.getMessage + "]!" - Logger.error(err) + LPLogger.error(err) throw new AnyPlaceException(err) } } diff --git a/server/app/utils/AnyResponseHelper.scala b/server/app/utils/AnyResponseHelper.scala index f06c6a509..2984d36f9 100644 --- a/server/app/utils/AnyResponseHelper.scala +++ b/server/app/utils/AnyResponseHelper.scala @@ -39,11 +39,11 @@ import java.util.List import com.couchbase.client.java.document.json.{JsonArray, JsonObject} import play.api.libs.json.{JsNumber, JsObject, JsString, JsValue} -//import play.api.mvc.{Result, Results} import play.api.mvc._ import utils.AnyResponseHelper.Response.Response -//remove if not needed -import scala.collection.JavaConversions._ + +import scala.jdk.CollectionConverters.CollectionHasAsScala +import scala.language.implicitConversions object AnyResponseHelper { @@ -51,17 +51,11 @@ object AnyResponseHelper { val WRONG_API_USAGE = "Wrong API usage!" object Response extends Enumeration { - val BAD_REQUEST = new Response() - val OK = new Response() - val FORBIDDEN = new Response() - val UNAUTHORIZED_ACCESS = new Response() - val INTERNAL_SERVER_ERROR = new Response() - val NOT_FOUND = new Response() class Response extends Val @@ -69,8 +63,8 @@ object AnyResponseHelper { implicit def convertValue(v: Value): Response = v.asInstanceOf[Response] } - def ok(json: JsValue, msg: String) = CreateResultResponse(Response.OK, json, msg) - def bad_request(json: JsValue, msg: String) = CreateResultResponse(Response.BAD_REQUEST, json, msg) + def ok(json: JsValue, msg: String): Result = CreateResultResponse(Response.OK, json, msg) + def bad_request(json: JsValue, msg: String): Result = CreateResultResponse(Response.BAD_REQUEST, json, msg) private def CreateResultResponse(r: Response, json_in: JsValue, message: String): Result = { @@ -130,9 +124,9 @@ object AnyResponseHelper { } // ##################################################### - // TODO: DEPRECATE (couchbase) + // TODO:PM DEPRECATE (couchbase) - def ok(json: JsonObject, msg: String): Result = { + def ok(json: JsonObject, msg: String=""): Result = { createResultResponse(Response.OK, json, msg) } @@ -201,7 +195,7 @@ object AnyResponseHelper { val error_messages = JsonArray.empty() val json = JsonObject.empty() - for (s <- missing) { + for (s <- missing.asScala) { error_messages.add(String.format("Missing or Invalid parameter:: [%s]", s)) } json.put("error_messages",error_messages) diff --git a/server/app/utils/AnyplaceServerAPI.scala b/server/app/utils/AnyplaceServerAPI.scala index 02d990452..9d348fd50 100644 --- a/server/app/utils/AnyplaceServerAPI.scala +++ b/server/app/utils/AnyplaceServerAPI.scala @@ -35,19 +35,15 @@ */ package utils +import play.api.{Configuration} +import javax.inject.{Inject, Singleton} -import play.Play - -object AnyplaceServerAPI { +@Singleton +class AnyplaceServerAPI @Inject() (conf: Configuration) { val URL_SEP = '/' - - val SERVER_ADDRESS = Play.application().configuration().getString("server.address") - - val SERVER_PORT = Play.application().configuration().getString("server.port") - - val SERVER_FULL_URL = SERVER_ADDRESS + ":" + SERVER_PORT - - val SERVER_API_ROOT = SERVER_FULL_URL + URL_SEP + "anyplace" + URL_SEP - - val ANDROID_API_ROOT = SERVER_FULL_URL + URL_SEP + "android" + URL_SEP + val SERVER_ADDRESS: String = conf.get[String]("server.address") + val SERVER_PORT: String = conf.get[String]("server.port") + val SERVER_FULL_URL: String = SERVER_ADDRESS + ":" + SERVER_PORT + val SERVER_API_ROOT: String = SERVER_FULL_URL + URL_SEP + "anyplace" + URL_SEP + val ANDROID_API_ROOT: String = SERVER_FULL_URL + URL_SEP + "android" + URL_SEP } diff --git a/server/app/utils/Dijkstra.scala b/server/app/utils/Dijkstra.scala index 5ae867956..976f31430 100644 --- a/server/app/utils/Dijkstra.scala +++ b/server/app/utils/Dijkstra.scala @@ -35,14 +35,13 @@ */ package utils -import play.Logger -import java.text.NumberFormat -import java.text.ParseException +import java.text.{NumberFormat, ParseException} import java.util._ import datasources.SCHEMA -//remove if not needed -import scala.collection.JavaConversions._ + +import scala.jdk.CollectionConverters.CollectionHasAsScala + object Dijkstra { @@ -52,33 +51,33 @@ object Dijkstra { var hmp: HashMap[String, DVertex] = new HashMap[String, DVertex]() - def addPois(pois: List[HashMap[String, String]]) { - for (p <- pois) { + def addPois(pois: List[HashMap[String, String]]): Unit = { + for (p <- pois.asScala) { val dv = new DVertex(p) this.vertices.add(dv) hmp.put(p.get(SCHEMA.fPuid), dv) } } - def addPoi(p: HashMap[String, String]) { + def addPoi(p: HashMap[String, String]): Unit ={ val dv = new DVertex(p) this.vertices.add(dv) hmp.put(p.get(SCHEMA.fPuid), dv) } - def addEdges(conns: List[HashMap[String, String]]) { + def addEdges(conns: List[HashMap[String, String]]) : Unit ={ val nf = NumberFormat.getInstance(Locale.ENGLISH) var w = 0.0 - for (e <- conns) { + for (e <- conns.asScala) { try { - val weight = e.getOrElse(SCHEMA.fWeight,null) + val weight = e.getOrDefault(SCHEMA.fWeight,null) if (weight != null) w = nf.parse(weight).doubleValue() } catch { case e1: ParseException => } - val a = hmp.getOrElse(e.get(SCHEMA.fPoisA), null) - val b = hmp.getOrElse(e.get(SCHEMA.fPoisB), null) + val a = hmp.getOrDefault(e.get(SCHEMA.fPoisA), null) + val b = hmp.getOrDefault(e.get(SCHEMA.fPoisB), null) if (!(a == null || b == null)) { a.adjacencies.add(new DEdge(w, b)) b.adjacencies.add(new DEdge(w, a)) @@ -86,7 +85,7 @@ object Dijkstra { } } - def addEdge(conn: HashMap[String, String]) { + def addEdge(conn: HashMap[String, String]): Unit = { val nf = NumberFormat.getInstance(Locale.ENGLISH) var w = 0.0 try { @@ -94,8 +93,8 @@ object Dijkstra { } catch { case e1: ParseException => } - val a = hmp.getOrElse(conn.get(SCHEMA.fPoisA), null) - val b = hmp.getOrElse(conn.get(SCHEMA.fPoisB), null) + val a = hmp.getOrDefault(conn.get(SCHEMA.fPoisA), null) + val b = hmp.getOrDefault(conn.get(SCHEMA.fPoisB), null) if (a == null || b == null) { return } @@ -147,10 +146,10 @@ object Dijkstra { return Collections.emptyList() } if (dv.puid.equalsIgnoreCase(puid_to)) { - Logger.info("Path found!") + //Logger.info("Path found!") return path(dv) } - for (e <- dv.adjacencies) { + for (e <- dv.adjacencies.asScala) { tar = e.target val dist_no_tar = dv.minDistance + e.weight if (dist_no_tar < tar.minDistance) { @@ -176,8 +175,8 @@ object Dijkstra { } def getShortestPath(graph: Graph, puid_from: String, puid_to: String): List[HashMap[String, String]] = { - Logger.info("Dijkstra from[" + puid_from + "]") - Logger.info("Dijkstra to[" + puid_to + "]") + //Logger.info("Dijkstra from[" + puid_from + "]") + //Logger.info("Dijkstra to[" + puid_to + "]") computePath(graph, puid_from, puid_to) } } diff --git a/server/app/utils/FileUtils.scala b/server/app/utils/FileUtils.scala index e4bcba72b..cb5f39b95 100644 --- a/server/app/utils/FileUtils.scala +++ b/server/app/utils/FileUtils.scala @@ -2,26 +2,32 @@ package utils import java.io.File -import play.Play +import javax.inject.{Inject, Singleton} +import play.api.Configuration +import play.api.mvc.{AbstractController, ControllerComponents} -object FileUtils { - val RADIO_MAPS_FROZEN_DIR = Play.application().configuration().getString("radioMapFrozenDir") +@Singleton +class FileUtils @Inject()(cc: ControllerComponents, + conf: Configuration, + api: AnyplaceServerAPI) + extends AbstractController(cc) { + val RADIO_MAPS_FROZEN_DIR = conf.get[String]("radioMapFrozenDir") def getDirFrozenFloor(buid: String, floor_number: String): File = { - return new File(RADIO_MAPS_FROZEN_DIR + AnyplaceServerAPI.URL_SEP + buid + AnyplaceServerAPI.URL_SEP + floor_number) + return new File(RADIO_MAPS_FROZEN_DIR + api.URL_SEP + buid + api.URL_SEP + floor_number) } def getRadiomapFile(buid: String, floor_number: String): File = { - return new File(RADIO_MAPS_FROZEN_DIR + AnyplaceServerAPI.URL_SEP + buid + AnyplaceServerAPI.URL_SEP + - floor_number + AnyplaceServerAPI.URL_SEP + "indoor-radiomap.txt") + return new File(RADIO_MAPS_FROZEN_DIR + api.URL_SEP + buid + api.URL_SEP + + floor_number + api.URL_SEP + "indoor-radiomap.txt") } def getMeanFile(buid: String, floor_number: String): File = { - return new File(RADIO_MAPS_FROZEN_DIR + AnyplaceServerAPI.URL_SEP + buid + AnyplaceServerAPI.URL_SEP + - floor_number + AnyplaceServerAPI.URL_SEP + "indoor-radiomap-mean.txt") + return new File(RADIO_MAPS_FROZEN_DIR + api.URL_SEP + buid + api.URL_SEP + + floor_number + api.URL_SEP + "indoor-radiomap-mean.txt") } def getRadioMapFileName(buid: String, floor_number: String): File = { - return new File(getDirFrozenFloor(buid, floor_number).toString + AnyplaceServerAPI.URL_SEP + "indoor-radiomap.txt") + return new File(getDirFrozenFloor(buid, floor_number).toString + api.URL_SEP + "indoor-radiomap.txt") } def getFilePos(fileName: String): Int = { diff --git a/server/app/utils/GeoJSONMultiPoint.scala b/server/app/utils/GeoJSONMultiPoint.scala index 071319fa0..0862c3fd2 100644 --- a/server/app/utils/GeoJSONMultiPoint.scala +++ b/server/app/utils/GeoJSONMultiPoint.scala @@ -35,13 +35,13 @@ */ package utils -import org.codehaus.jettison.json.JSONArray -import org.codehaus.jettison.json.JSONException -import org.codehaus.jettison.json.JSONObject -import java.util.ArrayList -import java.util.List +import java.util.{ArrayList, List} + +import org.codehaus.jettison.json.{JSONArray, JSONObject} + +import scala.jdk.CollectionConverters.CollectionHasAsScala //remove if not needed -import scala.collection.JavaConversions._ +// import scala.collection.JavaConversions._ class GeoJSONMultiPoint(points_in: GeoPoint*) { @@ -55,7 +55,7 @@ class GeoJSONMultiPoint(points_in: GeoPoint*) { var ja: JSONArray = null var jall = new JSONArray() - for (p <- this.points) { + for (p <- this.points.asScala) { ja = new JSONArray() ja.put(p.dlat) ja.put(p.dlon) diff --git a/server/app/utils/GeoJSONPoint.scala b/server/app/utils/GeoJSONPoint.scala index 118561bd3..f57506482 100644 --- a/server/app/utils/GeoJSONPoint.scala +++ b/server/app/utils/GeoJSONPoint.scala @@ -38,7 +38,8 @@ package utils import java.util import play.api.libs.json.{JsObject, JsString, JsValue, Json} -import play.twirl.api.TemplateMagic.javaCollectionToScala + +import scala.jdk.CollectionConverters.CollectionHasAsScala class GeoJSONPoint(var lat: Double, var lon: Double) { @@ -46,7 +47,7 @@ class GeoJSONPoint(var lat: Double, var lon: Double) { val ja = new util.ArrayList[Double] ja.add(this.lat) ja.add(this.lon) - var jo = Json.obj("coordinates" -> Json.toJson(ja.toList)) + var jo = Json.obj("coordinates" -> Json.toJson(ja.asScala)) jo = jo.as[JsObject] + ("type" -> JsString("Point")) jo } diff --git a/server/app/utils/GeoPoint.scala b/server/app/utils/GeoPoint.scala index 882d5e1a1..7f6b9b466 100644 --- a/server/app/utils/GeoPoint.scala +++ b/server/app/utils/GeoPoint.scala @@ -172,7 +172,7 @@ class GeoPoint { var dlat: Double = 0.0 var dlon: Double = 0.0 - def this(lat: Double, lon: Double) { + def this(lat: Double, lon: Double) = { this() this.lat = java.lang.Double.toString(lat) this.lon = java.lang.Double.toString(lon) @@ -180,7 +180,7 @@ class GeoPoint { this.dlon = lon } - def this(lat: String, lon: String) { + def this(lat: String, lon: String) = { this() try { this.dlat = java.lang.Double.parseDouble(lat) diff --git a/server/app/utils/HelperMethods.scala b/server/app/utils/HelperMethods.scala index 1616a0a72..81f2cbe90 100644 --- a/server/app/utils/HelperMethods.scala +++ b/server/app/utils/HelperMethods.scala @@ -35,14 +35,12 @@ */ package utils -import java.io.{File, FileOutputStream, IOException} +import java.io.File import java.nio.file.Files import java.util.HashMap import com.couchbase.client.java.document.json.JsonObject import org.apache.commons.codec.binary.Base64 -import play.Play -import utils.LPUtils.generateRandomRssLogFileName //remove if not needed object HelperMethods { @@ -79,41 +77,12 @@ object HelperMethods { def base64ToString(base64_in: String): String = new String(decodeBase64(base64_in)) - def storeRadioMapRawToServer(file: File): Boolean = { - /* - * FeatureAdd : Configuring location for server generated files - */ - //val radio_dir = "radio_maps_raw/" - val radio_dir = Play.application().configuration().getString("radioMapRawDir") - val dir = new File(radio_dir) - dir.mkdirs() - if (!dir.isDirectory || !dir.canWrite() || !dir.canExecute()) { - return false - } - val name = generateRandomRssLogFileName() - //FeatureAdd : Configuring location for server generated files - val dest_f = new File(radio_dir + AnyplaceServerAPI.URL_SEP + name) - var fout: FileOutputStream = null - try { - fout = new FileOutputStream(dest_f) - Files.copy(file.toPath(), fout) - fout.close() - LPLogger.D1("storeRadioMapToServer: Stored raw rss-log: " + name) - } catch { - case e: IOException => { - e.printStackTrace() - return false - } - } - true - } - /* * DELETE FLOOR : BuxFix * Fixing function as parent level floor plan files and directory * was not getting removed during floor delete */ - def recDeleteDirFile(f: File, root: Boolean =true) { + def recDeleteDirFile(f: File, root: Boolean =true): Unit ={ if (f.isFile) { Files.delete(f.toPath()) } else if (f.isDirectory) { diff --git a/server/app/utils/LPLogger.scala b/server/app/utils/LPLogger.scala index cdf1d8005..ee36a6a8d 100644 --- a/server/app/utils/LPLogger.scala +++ b/server/app/utils/LPLogger.scala @@ -35,53 +35,61 @@ */ package utils -import play.Logger +import play.api.Logger + // TODO rename to LOG object LPLogger { -private val LEVEL:Int = 2 + val logger: Logger = Logger(this.getClass()) + private val LEVEL: Int = 2 + + def error(tag: String, message: String, e: Exception): Unit = { + // Logger.error(String.format("%s: %s [%s]", tag, message, e.getMessage), e) + error(tag + ": " + message, e) + } + + def error(tag: String, e: Exception): Unit = { + val msg = String.format("%s: %s: %s\n%s", tag, e.getClass, e.getMessage, e.getStackTrace.toString) + logger.error(msg, e) + } + + def error(message: String): Unit = { + logger.error(String.format("%s", message)) + } + + def info(tag: String, message: String, e: Exception): Unit = { + logger.info(String.format("%s: %s [%s]", tag, message, e.getMessage), e) + } + + def info(message: String): Unit = { + logger.info(String.format("%s", message)) + } + + def debug(tag: String, message: String, e: Exception): Unit = { + logger.debug(String.format("%s: %s [%s]", tag, message, e.getMessage), e) + } - def error(tag: String, message: String, e: Exception) { - // Logger.error(String.format("%s: %s [%s]", tag, message, e.getMessage), e) - error(tag+": " + message, e) - } + def debug(message: String): Unit = { + logger.debug(String.format("%s", message)) + } - def error(tag: String, e: Exception) { - val msg = String.format("%s: %s: %s\n%s", tag, e.getClass, e.getMessage, e.getStackTrace.toString) - Logger.error(msg, e) - } + def D1(): Boolean = LEVEL >= 1 - def error(message: String) { - Logger.error(String.format("%s", message)) - } + def D2(): Boolean = LEVEL >= 2 - def info(tag: String, message: String, e: Exception) { - Logger.info(String.format("%s: %s [%s]", tag, message, e.getMessage), e) - } + def D3(): Boolean = LEVEL >= 3 - def info(message: String) { - Logger.info(String.format("%s", message)) - } + def D4(): Boolean = LEVEL >= 4 - def debug(tag: String, message: String, e: Exception) { - Logger.debug(String.format("%s: %s [%s]", tag, message, e.getMessage), e) - } + def D5(): Boolean = LEVEL >= 5 - def debug(message: String) { - Logger.debug(String.format("%s", message)) - } + def D1(message: String): Unit = if (D1()) logger.warn(String.format("%s", message)) - def D1():Boolean = LEVEL >= 1 - def D2():Boolean = LEVEL >= 2 - def D3():Boolean = LEVEL >= 3 - def D4():Boolean = LEVEL >= 4 - def D5():Boolean = LEVEL >= 5 + def D2(message: String): Unit = if (D2()) logger.debug(String.format("%s", message)) - def D1(message: String): Unit = if (D1()) Logger.debug(String.format("%s", message)) - def D2(message: String): Unit = if (D2()) Logger.debug(String.format("%s", message)) - def D3(message: String): Unit = if (D3()) Logger.debug(String.format("%s", message)) - def D4(message: String): Unit = if (D4()) Logger.debug(String.format("%s", message)) - def D5(message: String): Unit = if (D5()) Logger.debug(String.format("%s", message)) + def D3(message: String): Unit = if (D3()) logger.debug(String.format("%s", message)) + def D4(message: String): Unit = if (D4()) logger.debug(String.format("%s", message)) + def D5(message: String): Unit = if (D5()) logger.debug(String.format("%s", message)) } diff --git a/server/app/utils/LPUtils.scala b/server/app/utils/LPUtils.scala index 57b42b261..2dc878f8a 100644 --- a/server/app/utils/LPUtils.scala +++ b/server/app/utils/LPUtils.scala @@ -69,7 +69,7 @@ object LPUtils { secureRandom = SecureRandom.getInstance("SHA1PRNG") secureRandom.setSeed(secureRandom.generateSeed(PRNG_SEED)) val digest = MessageDigest.getInstance("SHA-1") - val dig = digest.digest((secureRandom.nextLong() + "").getBytes) + val dig = digest.digest((s"$secureRandom.nextLong()").getBytes) binaryToHex(dig) } catch { case e: NoSuchAlgorithmException => { @@ -245,4 +245,14 @@ object LPUtils { } null } + + + def appendGoogleIdIfNeeded(id: String) = { + if (id.contains("_local")) + id + else if (id.contains("_google")) + id + else + id + "_google" + } } diff --git a/server/app/utils/PasswordService.scala b/server/app/utils/PasswordService.scala index 0dfac96b1..82a43a3f9 100644 --- a/server/app/utils/PasswordService.scala +++ b/server/app/utils/PasswordService.scala @@ -1,217 +1,217 @@ -/* - * AnyPlace: A free and open Indoor Navigation Service with superb accuracy! - * - * Anyplace is a first-of-a-kind indoor information service offering GPS-less - * localization, navigation and search inside buildings using ordinary smartphones. - * - * Author(s): Constantinos Costa, Kyriakos Georgiou, Lambros Petrou - * - * Supervisor: Demetrios Zeinalipour-Yazti - * - * URL: https://anyplace.cs.ucy.ac.cy - * Contact: anyplace@cs.ucy.ac.cy - * - * Copyright (c) 2016, Data Management Systems Lab (DMSL), University of Cyprus. - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the “Software”), to deal in the - * Software without restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ -package utils - -import javax.crypto.SecretKeyFactory - -import javax.crypto.spec.PBEKeySpec - -import java.math.BigInteger - -import java.security.NoSuchAlgorithmException - -import java.security.SecureRandom - -import java.security.spec.InvalidKeySpecException - -object PasswordService { - - /** ****************************************************************************** - * USED FOR SECURE PASSWORD STORAGE - similar to secureEncrypt and secureDecrypt - * in LPUtils but only up to the hashing step. No encryption is applied since - * we only need one-direction hashing of the password and not decryption. - * ******************************************************************************* - */ - - val PBKDF2_ALGORITHM: String = "PBKDF2WithHmacSHA1" - - // The following constants may be changed without breaking existing hashes. - val SALT_BYTE_SIZE: Int = 24 - - val HASH_BYTE_SIZE: Int = 24 - - val PBKDF2_ITERATIONS: Int = 1000 - - val ITERATION_INDEX: Int = 0 - - val SALT_INDEX: Int = 1 - - val PBKDF2_INDEX: Int = 2 - - /** - * Returns a salted PBKDF2 hash of the password. - * - * @param password the password to hash - * @return a salted PBKDF2 hash of the password - */ - def createHash(password: String): String = createHash(password.toCharArray()) - - /** - * Returns a salted PBKDF2 hash of the password. - * - * @param password the password to hash - * @return a salted PBKDF2 hash of the password - */ - def createHash(password: Array[Char]): String = { - // Generate a random salt - val random: SecureRandom = new SecureRandom() - val salt: Array[Byte] = Array.ofDim[Byte](SALT_BYTE_SIZE) - random.nextBytes(salt) - // Hash the password - var hash: Array[Byte] = Array.ofDim[Byte](0) - try hash = pbkdf2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE) - catch { - case e: NoSuchAlgorithmException => e.printStackTrace() - - case e: InvalidKeySpecException => e.printStackTrace() - - } - // format iterations:salt:hash - PBKDF2_ITERATIONS + ":" + toHex(salt) + ":" + toHex(hash) - } - - /** - * Validates a password using a hash. - * - * @param password the password to check - * @param correctHash the hash of the valid password - * @return true if the password is correct, false if not - */ - def validatePassword(password: String, correctHash: String): Boolean = - validatePassword(password.toCharArray(), correctHash) - - /** - * Validates a password using a hash. - * - * @param password the password to check - * @param correctHash the hash of the valid password - * @return true if the password is correct, false if not - */ - def validatePassword(password: Array[Char], correctHash: String): Boolean = { - // Decode the hash into its parameters - val params: Array[String] = correctHash.split(":") - val iterations: Int = java.lang.Integer.parseInt(params(ITERATION_INDEX)) - val salt: Array[Byte] = fromHex(params(SALT_INDEX)) - val hash: Array[Byte] = fromHex(params(PBKDF2_INDEX)) - // iteration count, and hash length - var testHash: Array[Byte] = Array.ofDim[Byte](0) - try testHash = pbkdf2(password, salt, iterations, hash.length) - catch { - case e: NoSuchAlgorithmException => e.printStackTrace() - - case e: InvalidKeySpecException => e.printStackTrace() - - } - // both hashes match. - slowEquals(hash, testHash) - } - - // Compute the hash of the provided password, using the same salt, - // Compare the hashes in constant time. The password is correct if - // Compute the hash of the provided password, using the same salt, - // Compare the hashes in constant time. The password is correct if - - /** - * Compares two byte arrays in length-constant time. This comparison method - * is used so that password hashes cannot be extracted from an on-line - * system using a timing attack and then attacked off-line. - * - * @param a the first byte array - * @param b the second byte array - * @return true if both byte arrays are the same, false if not - */ - def slowEquals(a: Array[Byte], b: Array[Byte]): Boolean = { - var diff: Int = a.length ^ b.length - var i: Int = 0 - while (i < a.length && i < b.length) { - diff |= a(i) ^ b(i) - i += 1 - } - diff == 0 - } - - /** - * Computes the PBKDF2 hash of a password. - * - * @param password the password to hash. - * @param salt the salt - * @param iterations the iteration count (slowness factor) - * @param bytes the length of the hash to compute in bytes - * @return the PBDKF2 hash of the password - */ - def pbkdf2(password: Array[Char], - salt: Array[Byte], - iterations: Int, - bytes: Int): Array[Byte] = { - val spec: PBEKeySpec = - new PBEKeySpec(password, salt, iterations, bytes * 8) - val skf: SecretKeyFactory = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM) - skf.generateSecret(spec).getEncoded - } - - /** - * Converts a string of hexadecimal characters into a byte array. - * - * @param hex the hex string - * @return the hex string decoded into a byte array - */ - def fromHex(hex: String): Array[Byte] = { - val binary: Array[Byte] = Array.ofDim[Byte](hex.length / 2) - for (i <- 0 until binary.length) { - binary(i) = - java.lang.Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16).toByte - } - binary - } - - /** - * Converts a byte array into a hexadecimal string. - * - * @param array the byte array to convert - * @return a length*2 character string encoding the byte array - */ - def toHex(array: Array[Byte]): String = { - val bi: BigInteger = new BigInteger(1, array) - val hex: String = bi.toString(16) - val paddingLength: Int = (array.length * 2) - hex.length - if (paddingLength > 0) { - val padding="%0" + paddingLength + "d" - String.format(padding, new Integer(0)) + hex - }else - hex - } - -} \ No newline at end of file +///* +// * AnyPlace: A free and open Indoor Navigation Service with superb accuracy! +// * +// * Anyplace is a first-of-a-kind indoor information service offering GPS-less +// * localization, navigation and search inside buildings using ordinary smartphones. +// * +// * Author(s): Constantinos Costa, Kyriakos Georgiou, Lambros Petrou +// * +// * Supervisor: Demetrios Zeinalipour-Yazti +// * +// * URL: https://anyplace.cs.ucy.ac.cy +// * Contact: anyplace@cs.ucy.ac.cy +// * +// * Copyright (c) 2016, Data Management Systems Lab (DMSL), University of Cyprus. +// * All rights reserved. +// * +// * Permission is hereby granted, free of charge, to any person obtaining a copy of +// * this software and associated documentation files (the “Software”), to deal in the +// * Software without restriction, including without limitation the rights to use, copy, +// * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +// * and to permit persons to whom the Software is furnished to do so, subject to the +// * following conditions: +// * +// * The above copyright notice and this permission notice shall be included in all +// * copies or substantial portions of the Software. +// * +// * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +// * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// * DEALINGS IN THE SOFTWARE. +// * +// */ +//package utils +// +//import javax.crypto.SecretKeyFactory +// +//import javax.crypto.spec.PBEKeySpec +// +//import java.math.BigInteger +// +//import java.security.NoSuchAlgorithmException +// +//import java.security.SecureRandom +// +//import java.security.spec.InvalidKeySpecException +// +//object PasswordService { +// +// /** ****************************************************************************** +// * USED FOR SECURE PASSWORD STORAGE - similar to secureEncrypt and secureDecrypt +// * in LPUtils but only up to the hashing step. No encryption is applied since +// * we only need one-direction hashing of the password and not decryption. +// * ******************************************************************************* +// */ +// +// val PBKDF2_ALGORITHM: String = "PBKDF2WithHmacSHA1" +// +// // The following constants may be changed without breaking existing hashes. +// val SALT_BYTE_SIZE: Int = 24 +// +// val HASH_BYTE_SIZE: Int = 24 +// +// val PBKDF2_ITERATIONS: Int = 1000 +// +// val ITERATION_INDEX: Int = 0 +// +// val SALT_INDEX: Int = 1 +// +// val PBKDF2_INDEX: Int = 2 +// +// /** +// * Returns a salted PBKDF2 hash of the password. +// * +// * @param password the password to hash +// * @return a salted PBKDF2 hash of the password +// */ +// def createHash(password: String): String = createHash(password.toCharArray()) +// +// /** +// * Returns a salted PBKDF2 hash of the password. +// * +// * @param password the password to hash +// * @return a salted PBKDF2 hash of the password +// */ +// def createHash(password: Array[Char]): String = { +// // Generate a random salt +// val random: SecureRandom = new SecureRandom() +// val salt: Array[Byte] = Array.ofDim[Byte](SALT_BYTE_SIZE) +// random.nextBytes(salt) +// // Hash the password +// var hash: Array[Byte] = Array.ofDim[Byte](0) +// try hash = pbkdf2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE) +// catch { +// case e: NoSuchAlgorithmException => e.printStackTrace() +// +// case e: InvalidKeySpecException => e.printStackTrace() +// +// } +// // format iterations:salt:hash +// PBKDF2_ITERATIONS + ":" + toHex(salt) + ":" + toHex(hash) +// } +// +// /** +// * Validates a password using a hash. +// * +// * @param password the password to check +// * @param correctHash the hash of the valid password +// * @return true if the password is correct, false if not +// */ +// def validatePassword(password: String, correctHash: String): Boolean = +// validatePassword(password.toCharArray(), correctHash) +// +// /** +// * Validates a password using a hash. +// * +// * @param password the password to check +// * @param correctHash the hash of the valid password +// * @return true if the password is correct, false if not +// */ +// def validatePassword(password: Array[Char], correctHash: String): Boolean = { +// // Decode the hash into its parameters +// val params: Array[String] = correctHash.split(":") +// val iterations: Int = java.lang.Integer.parseInt(params(ITERATION_INDEX)) +// val salt: Array[Byte] = fromHex(params(SALT_INDEX)) +// val hash: Array[Byte] = fromHex(params(PBKDF2_INDEX)) +// // iteration count, and hash length +// var testHash: Array[Byte] = Array.ofDim[Byte](0) +// try testHash = pbkdf2(password, salt, iterations, hash.length) +// catch { +// case e: NoSuchAlgorithmException => e.printStackTrace() +// +// case e: InvalidKeySpecException => e.printStackTrace() +// +// } +// // both hashes match. +// slowEquals(hash, testHash) +// } +// +// // Compute the hash of the provided password, using the same salt, +// // Compare the hashes in constant time. The password is correct if +// // Compute the hash of the provided password, using the same salt, +// // Compare the hashes in constant time. The password is correct if +// +// /** +// * Compares two byte arrays in length-constant time. This comparison method +// * is used so that password hashes cannot be extracted from an on-line +// * system using a timing attack and then attacked off-line. +// * +// * @param a the first byte array +// * @param b the second byte array +// * @return true if both byte arrays are the same, false if not +// */ +// def slowEquals(a: Array[Byte], b: Array[Byte]): Boolean = { +// var diff: Int = a.length ^ b.length +// var i: Int = 0 +// while (i < a.length && i < b.length) { +// diff |= a(i) ^ b(i) +// i += 1 +// } +// diff == 0 +// } +// +// /** +// * Computes the PBKDF2 hash of a password. +// * +// * @param password the password to hash. +// * @param salt the salt +// * @param iterations the iteration count (slowness factor) +// * @param bytes the length of the hash to compute in bytes +// * @return the PBDKF2 hash of the password +// */ +// def pbkdf2(password: Array[Char], +// salt: Array[Byte], +// iterations: Int, +// bytes: Int): Array[Byte] = { +// val spec: PBEKeySpec = +// new PBEKeySpec(password, salt, iterations, bytes * 8) +// val skf: SecretKeyFactory = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM) +// skf.generateSecret(spec).getEncoded +// } +// +// /** +// * Converts a string of hexadecimal characters into a byte array. +// * +// * @param hex the hex string +// * @return the hex string decoded into a byte array +// */ +// def fromHex(hex: String): Array[Byte] = { +// val binary: Array[Byte] = Array.ofDim[Byte](hex.length / 2) +// for (i <- 0 until binary.length) { +// binary(i) = +// java.lang.Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16).toByte +// } +// binary +// } +// +// /** +// * Converts a byte array into a hexadecimal string. +// * +// * @param array the byte array to convert +// * @return a length*2 character string encoding the byte array +// */ +// def toHex(array: Array[Byte]): String = { +// val bi: BigInteger = new BigInteger(1, array) +// val hex: String = bi.toString(16) +// val paddingLength: Int = (array.length * 2) - hex.length +// if (paddingLength > 0) { +// val padding="%0" + paddingLength + "d" +// String.format(padding, new Integer(0)) + hex +// }else +// hex +// } +// +//} \ No newline at end of file diff --git a/server/app/views/anyplace_android.scala.html b/server/app/views/anyplace_android.scala.html deleted file mode 100644 index 04f54f180..000000000 --- a/server/app/views/anyplace_android.scala.html +++ /dev/null @@ -1,35 +0,0 @@ -@(apks: java.util.List[utils.AndroidAPKFile]) - - - - - - - - -
- -

AnyPlace for Android Client(Logout)

- -

- -
- -
- -
-

Available Versions: [ @apks.size() ]

-
    - @for(apk <- apks) { -
  • Download@apk.getVersion() ( @apk.getDate().toString() ) — @if( apk.isRelease()){ Release }else{ Dev }
  • - } -
-
- - -
Maintained by Lambros Petrou
-
- - - - \ No newline at end of file diff --git a/server/app/views/anyplace_login.scala.html b/server/app/views/anyplace_login.scala.html deleted file mode 100644 index 6a3621897..000000000 --- a/server/app/views/anyplace_login.scala.html +++ /dev/null @@ -1,49 +0,0 @@ -@(form: Form[ApplicationAnyplace.Login]) -// Where is this view used for? - - - AnyPlace Admin - - - - - -
- @helper.form(routes.ApplicationAnyplace.authenticate) { -

AnyPlace Admin

- - @if(form.hasGlobalErrors) { -

- @form.globalError.get.message -

- } - @if(!form.hasGlobalErrors) { -

- Success -

- } - -

- -

-

- -

- -

- -

- -

- -

- } -
- - - \ No newline at end of file diff --git a/server/build.sbt b/server/build.sbt index c038c88a5..6f6b2a23d 100644 --- a/server/build.sbt +++ b/server/build.sbt @@ -1,69 +1,107 @@ -import com.typesafe.sbt.packager.MappingsHelper._ +// TODO:PM +//import com.typesafe.config._ +//val conf = ConfigFactory.parseFile(new File("conf/reference.conf")).resolve() +//name := conf.get[String]("application.name") +//version := conf.get[String]("application.version") + +lazy val root = (project in file(".")) + .enablePlugins(PlayScala) + .settings( + name := """Anyplace""", + version := "4.2.1", + scalaVersion := "2.13.6", + libraryDependencies ++= Seq( + guice, + "org.mongodb.scala" %% "mongo-scala-driver" % "2.9.0", + "com.typesafe.play" %% "play-json" % "2.10.0-RC2", + "com.typesafe.play" %% "play" % "2.8.7", + "io.razem" %% "scala-influxdb-client" % "0.6.2", + "com.couchbase.client" % "java-client" % "2.7.18" + //"org.scalatestplus.play" %% "scalatestplus-play" % "5.0.0" % Test + ), + scalacOptions ++= Seq( + "-feature", + "-deprecation", + "-Xfatal-warnings" + ) + ) + + + + +// CLR:PM OLD CONFIGURATION +//import com.typesafe.sbt.packager.MappingsHelper._ +//mappings in Universal ++= directory(baseDirectory.value / "floor_plans") + +//name := "anyplace" +//version := "4.2" +//scalaVersion := "2.13.2" +//val playVersion = "2.8.7" // see also plugins.sbt -mappings in Universal ++= directory(baseDirectory.value / "floor_plans") - -name := "anyplace" - -version := "4.0" - -scalaVersion := "2.11.7" - -val playVersion = "2.4.2" // see also plugins.sbt - -libraryDependencies ++= Seq( jdbc, cache , ws, specs2 % Test ) -//scalaVersion := "2.12.11" -//scalaVersion := "2.13.2" // Cant be updated due to ACCES //libraryDependencies ++= Seq(jdbc, cacheApi, ws, specs2 % Test ) // Needed by StartModule to @Inject EagerSingletons for mounting // callbacks on startup and termination of the app -// libraryDependencies += "com.google.inject" % "guice" % "3.0" +//libraryDependencies += "com.google.inject" % "guice" % "3.0" +//libraryDependencies += "net.codingwell" %% "scala-guice" % "5.0.1" // TODO ACCES: all these should be updated to 1.0 version, once bayes-scala-gp is replaced. -libraryDependencies ++= Seq( - // Add here the specific dependencies for this module: - filters, - // TODO ACCESS: with % (single percentage) and by appending _VERSION to lib-name, - // we force it to use an earlier version - // The should instead become: - // "package" %% "lib-name" % "1.0", e.g.: - // (adding another % between package and lib-name concatenation, and removing _VERSOIN suffix from libname) - // "org.scalanlp" %% "breeze" % "1.0", - "org.scalanlp" % "breeze_2.11" % "0.12", - "org.scalanlp" % "breeze-natives_2.11" % "0.12", - "org.scalanlp" % "breeze-viz_2.11" % "0.12", - "org.mongodb.scala" %% "mongo-scala-driver" % "2.9.0" -) +//libraryDependencies ++= Seq( +// Add here the specific dependencies for this module: +//filters, +//guice, +// TODO ACCESS: with % (single percentage) and by appending _VERSION to lib-name, +// we force it to use an earlier version +// The should instead become: +// "package" %% "lib-name" % "1.0", e.g.: +// (adding another % between package and lib-name concatenation, and removing _VERSOIN suffix from libname) + + +//"org.scalanlp" %% "breeze" % "1.0", CHECK:PM +//"org.scalanlp" % "breeze_2.11" % "0.12", +//"org.scalanlp" % "breeze-natives_2.11" % "0.12", +//"org.scalanlp" % "breeze-viz_2.11" % "0.12", +//"org.mongodb.scala" %% "mongo-scala-driver" % "2.9.0", +//"javax.inject" % "javax.inject" % "1" +//) // Play json -libraryDependencies += "com.typesafe.play" %% "play-json" % playVersion - -// TODO ACCES: DEPRECATE this library -libraryDependencies += "com.github.danielkorzekwa" % "bayes-scala-gp_2.11" % "0.1-SNAPSHOT" - -// INFO: updated version to work with couchbase 6.5 version -// Due to wiping/reinstalling Couchbase to v6.5 -libraryDependencies += "com.couchbase.client" % "java-client" % "2.7.18" -// This version works with couchbase 6.0 -//libraryDependencies += "com.couchbase.client" % "java-client" % "2.4.5" - -resolvers += "scalaz-bintray" at "https://dl.bintray.com/scalaz/releases" - -resolvers += Resolver.sonatypeRepo("snapshots") - -// unmanagedResourceDirectories in Test += baseDirectory ( _ /"target/web/public/test" ) - -javaOptions += "-Dfile.encoding=UTF-8" +//libraryDependencies += "com.typesafe.play" %% "play-json" % playVersion +// find version: https://mvnrepository.com/artifact/com.typesafe.play/play-json +//libraryDependencies += "com.typesafe.play" %% "play-json" % "2.10.0-RC2" + +//// TODO:NN TODO:PM Deprecate +//// INFO: updated version to work with couchbase 6.5 version +//// Due to wiping/reinstalling Couchbase to v6.5 +//libraryDependencies += "com.couchbase.client" % "java-client" % "2.7.18" +//// This version works with couchbase 6.0 +////libraryDependencies += "com.couchbase.client" % "java-client" % "2.4.5" +// +////resolvers += "scalaz-bintray" at "https://dl.bintray.com/scalaz/releases" +//resolvers += Resolver.sonatypeRepo("snapshots") +//// unmanagedResourceDirectories in Test += baseDirectory ( _ /"target/web/public/test" ) + +// CHECK:PM +//javaOptions += "-Dfile.encoding=UTF-8" //Required for InfluxDB -libraryDependencies += "io.razem" %% "scala-influxdb-client" % "0.6.2" +//libraryDependencies += "io.razem" %% "scala-influxdb-client" % "0.6.2" // libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3" - -resolvers ++= Seq( - // other resolvers here - // if you want to use snapshot builds (currently 0.12-SNAPSHOT), use this. - "Sonatype Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/", - "Sonatype Releases" at "https://oss.sonatype.org/content/repositories/releases/" -) - -lazy val `anyplace` = (project in file(".")).enablePlugins(PlayScala) +// +//resolvers ++= Seq( +// // other resolvers here +// // if you want to use snapshot builds (currently 0.12-SNAPSHOT), use this. +// "Sonatype Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/", +// "Sonatype Releases" at "https://oss.sonatype.org/content/repositories/releases/" +//) +// +////resolvers ++= Seq( +//// Resolver.sonatypeRepo("snapshots"), +//// Resolver.sonatypeRepo("releases"), +//// Resolver.typesafeRepo("snapshots"), +//// Resolver.typesafeRepo("releases") +////) +// +////libraryDependencies += "com.typesafe.play" %% "play-json" % playVersion +// +//lazy val `anyplace` = (project in file(".")).enablePlugins(PlayScala) diff --git a/server/conf/api.routes b/server/conf/api.routes new file mode 100644 index 000000000..65dbc0332 --- /dev/null +++ b/server/conf/api.routes @@ -0,0 +1,5 @@ +########### +### MISC: +########### +# TODO:NN update usages of /anyplace/version (architect) +GET /version controllers.ApplicationAnyplace.Version \ No newline at end of file diff --git a/server/conf/reference.conf b/server/conf/reference.conf index 8a24b4465..c674a68e2 100644 --- a/server/conf/reference.conf +++ b/server/conf/reference.conf @@ -4,9 +4,7 @@ ## that should not change unless one know what is doing. application.name="anyplace" -application.version="4.0.1a" - - +application.version="4.2.1" # Languages: application.langs="en" @@ -31,7 +29,6 @@ logger.play=INFO # application: logger.application=DEBUG - # Router # ~~~~~ # Define the Router object to use for this application. diff --git a/server/conf/routes b/server/conf/routes index 5737fc826..63522cf6b 100644 --- a/server/conf/routes +++ b/server/conf/routes @@ -1,41 +1,64 @@ -##################################################################################################### -# This file defines all application routes (Higher priority routes first) -###################################### -######## VERIFIED MONGODB ######## -###################################### -# TODO: Sort at the end (by category) # /login/google/anyplace_token generate and return anyplaceToken (in order to replace old token) -POST /anyplace/mapping/accounts/sign controllers.AnyplaceMapping.addAccount() +-> /api api.Routes + +################ +# Accounts +################ +# TODO:NN for each endpoint: add in swagger-js +# TODO:NN add usages... renamed stuff.. etc.. +# TODO: other API.... local.. +# /user/login/google (move from AnyplaceMapping to: AnyplaceAccounts (AnypalceAccounts->Accounts) +POST /anyplace/mapping/accounts/sign controllers.AnyplaceMapping.addAccount() + +POST /user/register controllers.UserController.register() +POST /user/login controllers.UserController.login() +#POST /user/logout controllers.UserController.logout() +# ADMIN +POST /user/admin/accounts_all controllers.Admin.fetchAllAccounts() +POST /user/admin/migration/run controllers.Admin.migrateToMongoDB() + +#POST /accounts/oauth2/token oauth.provider.v2.controllers.AnyplaceOAuth.token() +#GET /login controllers.ApplicationAnyplace.login() +#GET /logout controllers.ApplicationAnyplace.logout() +#POST /authenticate controllers.ApplicationAnyplace.authenticate() +#POST /anyplace/mapping/maintenance controllers.AnyplaceMapping.maintenance() + +################ +# Spaces +################ POST /anyplace/mapping/space/add controllers.AnyplaceMapping.spaceAdd() POST /anyplace/mapping/space/update controllers.AnyplaceMapping.spaceUpdate() -# verified all except fingerprints +# TODO:NN verified all except fingerprints: must also delete radiomaps_frozen POST /anyplace/mapping/space/delete controllers.AnyplaceMapping.spaceDelete() POST /anyplace/mapping/space/all controllers.AnyplaceMapping.spaceAll() POST /anyplace/mapping/space/all_owner controllers.AnyplaceMapping.spaceAllByOwner() -# CHANGES: removed owner_id, added optional range POST /anyplace/mapping/space/coordinates controllers.AnyplaceMapping.spaceCoordinates() POST /anyplace/mapping/space/get controllers.AnyplaceMapping.spaceGetOne() - +# POIs POST /anyplace/mapping/pois/add controllers.AnyplaceMapping.poisAdd() POST /anyplace/mapping/pois/delete controllers.AnyplaceMapping.poisDelete() POST /anyplace/mapping/pois/update controllers.AnyplaceMapping.poisUpdate() POST /anyplace/mapping/pois/all_floor controllers.AnyplaceMapping.poisByFloor() POST /anyplace/mapping/pois/all_building controllers.AnyplaceMapping.poisByBuid() +# RENAMED: all_pois -> search +POST /anyplace/mapping/pois/search controllers.AnyplaceMapping.searchPois() - +# Connections POST /anyplace/mapping/connection/add controllers.AnyplaceMapping.connectionAdd() POST /anyplace/mapping/connection/delete controllers.AnyplaceMapping.connectionDelete() POST /anyplace/mapping/connection/all_floor controllers.AnyplaceMapping.connectionsByFloor() POST /anyplace/mapping/connection/all_floors controllers.AnyplaceMapping.connectionsByallFloors() +# Floors POST /anyplace/mapping/floor/add controllers.AnyplaceMapping.floorAdd() POST /anyplace/mapping/floor/delete controllers.AnyplaceMapping.floorDelete() # CHECK:PM ASK:DZ is setting floorplan description obsolete? POST /anyplace/mapping/floor/uploadWithZoom controllers.AnyplaceMapping.floorPlanUploadWithZoom() POST /anyplace/mapping/floor/all controllers.AnyplaceMapping.floorAll() +# Campus POST /anyplace/mapping/campus/add controllers.AnyplaceMapping.buildingSetAdd() # CHECK:NN CHECK:PM on frontend(js) buildings and greeklish are not set in the form POST /anyplace/mapping/campus/update controllers.AnyplaceMapping.campusUpdate() @@ -44,103 +67,151 @@ POST /anyplace/mapping/campus/delete POST /anyplace/mapping/campus/all_cucode controllers.AnyplaceMapping.buildingSetAll() POST /anyplace/mapping/campus/all_owner controllers.AnyplaceMapping.buildingsetAllByOwner() -############################### -### VERIFIED:MDB UNUSED ### -############################### -POST /anyplace/mapping/building/coowners controllers.AnyplaceMapping.spaceUpdateCoOwners() -# Fetches all buildings that matches bucode. -POST /anyplace/mapping/building/all_bucode controllers.AnyplaceMapping.spaceByBucode() -POST /anyplace/mapping/building/newowner controllers.AnyplaceMapping.spaceUpdateOwner() -# Not in use by anyplace API. Used by Rayzit -POST /anyplace/mapping/pois/all_pois_nconnectors controllers.AnyplaceMapping.poisByBuidincConnectors() -# Not in use. (Replaced JsonObject with JsValue, didnt test) -POST /anyplace/mapping/floor/upload controllers.AnyplaceMapping.floorPlanUpload() -# ASK:DZ : called by updateConnection(js) which is never called. -POST /anyplace/mapping/connection/update controllers.AnyplaceMapping.connectionUpdate() -# ASK:DZ : called by updateFloor(js) which is never called. -POST /anyplace/mapping/floor/update controllers.AnyplaceMapping.floorUpdate() - - - -##################################################################################################### -############### -### MAPPING ### -############### - - -# RENAMED: all_pois -> search -POST /anyplace/mapping/pois/search controllers.AnyplaceMapping.searchPois() - - -##################################################################################################### -################## -### NAVIGATION ### -################## +################ +### NAVIGATION +################ POST /anyplace/navigation/route_xy controllers.AnyplaceNavigation.getNavigationRouteXY() POST /anyplace/navigation/route controllers.AnyplaceNavigation.getNavigationRoute() +# SPACE POST /anyplace/navigation/building/id controllers.AnyplaceNavigation.getBuildingById() POST /anyplace/navigation/pois/id controllers.AnyplaceNavigation.getPoisById() -##################################################################################################### ################ -### POSITION ### +### POSITION +################ +# TODO algo1 +# used by android +POST /anyplace/position/predictFloorAlgo1 controllers.AnyplacePosition.predictFloorAlgo1() +# TODO:NN estimate_position (implement this as well..) +POST /anyplace/position/estimate_position controllers.AnyplaceMapping.findPosition() + +################ +### RADIOMAPS +################ +# /radiomap/delete +# /radiomap/upload +POST /anyplace/position/radio/delete controllers.AnyplaceMapping.FingerPrintsDelete() +POST /anyplace/position/radio_by_building_floor_all controllers.AnyplacePosition.radioDownloadByBuildingFloorall() +POST /anyplace/position/radio_by_floor_bbox controllers.AnyplacePosition.radioDownloadFloorBbox() +# TODO TEST:NN TEST:PM test on mobile app +POST /anyplace/position/radio_upload controllers.AnyplacePosition.radioUpload() +# TODO TEST:NN TEST:PM test on mobile app +POST /anyplace/position/radio_download_floor controllers.AnyplacePosition.radioDownloadFloor() +POST /anyplace/position/radio_by_building_floor controllers.AnyplacePosition.radioDownloadByBuildingFloor() + +################ +### ACCESS POINTS +################ +# bug mdb: fails to identify access points location +# TODO:NN fix bug NEXT MEETING +# where is it called (we want to rename) +# TODO:NN access_points/APs.. +POST /anyplace/position/radio/APs_building_floor controllers.AnyplaceMapping.getAPsByBuildingFloor() +POST /anyplace/position/radio/aps_ids controllers.AnyplaceMapping.getAPsIds() + ################ +### HEATMAP DATA +################ +# RENAMED: +# NEW FILE: +# /anyplace/position/radio/heatmap_building_floor_average_1 -> /heatmap/floor/average/1 /2 /3 /3/tiles .. TODO:NN POST /anyplace/position/radio/heatmap_building_floor_average_1 controllers.AnyplaceMapping.getHeatmapByFloorAVG1() POST /anyplace/position/radio/heatmap_building_floor_average_2 controllers.AnyplaceMapping.getHeatmapByFloorAVG2() POST /anyplace/position/radio/heatmap_building_floor_average_3 controllers.AnyplaceMapping.getHeatmapByFloorAVG3() POST /anyplace/position/radio/heatmap_building_floor_average_3_tiles controllers.AnyplaceMapping.getHeatmapByFloorAVG3Tiles() +# Time-based data POST /anyplace/position/radio/time controllers.AnyplaceMapping.FingerprintsByTime() -# CHECK:PM CHECK:DZ the old code does not group the heatmaps on higher levels +POST /anyplace/position/radio/delete/time controllers.AnyplaceMapping.FingerPrintsTimestampDelete() +# CHECK:PM CHECK:DZ the old code does not group the heatmaps on higher levels BUGFIX +# TODO:NN REMOVE building_... and tell PM where is it used?! POST /anyplace/position/radio/heatmap_building_floor_timestamp_average_1 controllers.AnyplaceMapping.heatmapByFloorTimestampAVG1() POST /anyplace/position/radio/heatmap_building_floor_timestamp_average_2 controllers.AnyplaceMapping.heatmapByFloorTimestampAVG2() POST /anyplace/position/radio/heatmap_building_floor_timestamp_average_3 controllers.AnyplaceMapping.heatmapByFloorTimestampAVG3() POST /anyplace/position/radio/heatmap_building_floor_timestamp_tiles controllers.AnyplaceMapping.heatmapByFloorTimestampTiles() -POST /anyplace/position/radio/delete controllers.AnyplaceMapping.FingerPrintsDelete() -# OPTIMIZED: caching same lat+lon+floor+range radiomaps (instead of re-saving) -POST /anyplace/position/radio_by_floor_bbox controllers.AnyplacePosition.radioDownloadFloorBbox() -POST /anyplace/position/radio/aps_ids controllers.AnyplaceMapping.getAPsIds() -# BuildingController.js -> DownloadBackup() -POST /anyplace/position/radio_by_building_floor_all controllers.AnyplacePosition.radioDownloadByBuildingFloorall() +########### +### RESOURCES: +########### +## WEB APPS: +# DEVELOPERS: +GET /developers/*file controllers.Assets.at(path="/public/developers", file) +GET /developers/ controllers.WebAppController.serveDevelopers(file="index.html") +GET /developers controllers.WebAppController.AddTrailingSlash() + +# ARCHITECT: +GET /architect/*file controllers.Assets.at(path="/public/anyplace_architect", file) +GET /architect/ controllers.WebAppController.serveArchitect(file="index.html") +GET /architect controllers.WebAppController.AddTrailingSlash() +# VIEWER: +GET /viewer/index.html controllers.WebAppController.serveViewer(file="index.html") +GET /viewer/*file controllers.AnyplaceAssets.at(path="/public", file) +GET /viewer/ controllers.WebAppController.serveViewer(file="index.html") +GET /viewer controllers.WebAppController.AddTrailingSlash() -##################################################################################################### -################## -### BLUEPRINTS ### OK -################## +# NEW ANGULAR WEB APP (Login, register) : +#GET /new2/*file controllers.Assets.at(path="/public/new2", file) +#GET /new2/ controllers.WebAppController.serveArchitect2(file="index.html") +#GET /new2 controllers.WebAppController.AddTrailingSlash() + +## BLUEPRINTS POST /anyplace/floortiles/:buid/:floor_number controllers.AnyplaceMapping.serveFloorPlanTilesZipLink( buid: String, floor_number: String ) GET /anyplace/floortiles/:buid/:floor_number/*file controllers.AnyplaceMapping.serveFloorPlanTilesStatic( buid: String, floor_number: String, file: String ) -# used by the Android Navigator +# USED BY: Android Navigator: POST /anyplace/floortiles/zip/:buid/:floor_number controllers.AnyplaceMapping.serveFloorPlanTilesZip( buid: String, floor_number: String ) -# used by the websites +# USED BY: Web apps POST /anyplace/floorplans64/:buid/:floor_number controllers.AnyplaceMapping.serveFloorPlanBase64( buid: String, floor_number: String ) POST /anyplace/floorplans64all/:buid/:floor_number controllers.AnyplaceMapping.serveFloorPlanBase64all( buid: String, floor_number: String ) -#POST /anyplace/floorplans/:buid/:floor_number controllers.AnyplaceMapping.serveFloorPlanBinary( buid: String, floor_number: String ) - POST /anyplace/radiomaps_frozen/:building/:floor/:filename controllers.AnyplacePosition.serveFrozenRadioMap(building: String, floor: String, filename: String) POST /anyplace/radiomaps/:radio_folder/:filename controllers.AnyplacePosition.serveRadioMap( radio_folder: String, filename: String ) -##################################################################################################### -############# -### ADMIN ### -############# -POST /admin/accounts_all controllers.Admin.fetchAllAccounts() -POST /admin/migration/run controllers.Admin.migrateToMongoDB() +## OTHER: +GET /favicon.ico controllers.Assets.at(path="/public/images", file="favicon.png") +# must match application.conf +GET /floortiles/zip/*file controllers.ExternalAssets.at(path="/floor_plans", file) +# maps from /public to /assets +GET /assets/*file controllers.Assets.at(path="/public", file) +# root +GET / controllers.ApplicationAnyplace.index() +# REDIRECT REMAINING TO INDEX +GET /*any controllers.ApplicationAnyplace.indexAny(any) -##################################################################################################### -############# -### DEBUG ### -############# +##################### +### CHECK:NN IF USED ### +##################### +# ADMIN WEBSITE CHECK:NN /admin ... else: delete and report to PM +#GET /admin/*file controllers.WebAppController.serveAdmin(file: String) +#GET /admin controllers.WebAppController.AddTrailingSlash() ##################################################################################################### -##################################### -### UNUSED AND UNCONVERTED TO MDB ### -##################################### -# CHECK:NN search last part +# ACCES MAP +# TODO:PM: clear crlb mentions.. +# TODO:NN na epistrefi deprecated kai bad request "will be removed" +#POST /anyplace/position/radio/acces controllers.AnyplaceMapping.getAccesHeatmapByBuildingFloor() +#POST /anyplace/position/radio/heatmap_building_floor_delete controllers.AnyplaceMapping.deleteAccesSpaceData() + + +################### +# Unused Endpoints +################### +POST /anyplace/mapping/building/coowners controllers.AnyplaceMapping.spaceUpdateCoOwners() +# Fetches all buildings that matches bucode. +POST /anyplace/mapping/building/all_bucode controllers.AnyplaceMapping.spaceByBucode() +POST /anyplace/mapping/building/newowner controllers.AnyplaceMapping.spaceUpdateOwner() +# Not in use by anyplace API. Used by Rayzit +POST /anyplace/mapping/pois/all_pois_nconnectors controllers.AnyplaceMapping.poisByBuidincConnectors() +# Not in use. (Replaced JsonObject with JsValue, didnt test) +#POST /anyplace/mapping/floor/upload controllers.AnyplaceMapping.floorPlanUpload() +## ASK:DZ : called by updateConnection(js) which is never called. +#POST /anyplace/mapping/connection/update controllers.AnyplaceMapping.connectionUpdate() +## ASK:DZ : called by updateFloor(js) which is never called. +#POST /anyplace/mapping/floor/update controllers.AnyplaceMapping.floorUpdate() + +# CHECK:DZ POST /anyplace/position/path_add controllers.AnyplacePosition.magneticPathAdd() POST /anyplace/position/path_delete controllers.AnyplacePosition.magneticPathDelete() POST /anyplace/position/paths_by_floor controllers.AnyplacePosition.magneticPathByFloor() @@ -148,133 +219,14 @@ POST /anyplace/position/paths_by_buid POST /anyplace/position/milestones_add controllers.AnyplacePosition.magneticMilestoneUpload() POST /anyplace/position/milestones_by_floor controllers.AnyplacePosition.magneticMilestoneByFloor() -# CHECK:NN -POST /anyplace/position/estimate_position controllers.AnyplaceMapping.findPosition() POST /anyplace/mapping/radio/radio_buid_floor controllers.AnyplaceMapping.getRadioHeatmapBbox() -POST /accounts/oauth2/token oauth.provider.v2.controllers.AnyplaceOAuth.token() -GET /login controllers.ApplicationAnyplace.login() -GET /logout controllers.ApplicationAnyplace.logout() -POST /authenticate controllers.ApplicationAnyplace.authenticate() - -POST /anyplace/mapping/maintenance controllers.AnyplaceMapping.maintenance() +### INFLUXDB +# CHECK:DZ Make it obsolete? +#POST /anyplace/geolocation/insert controllers.AnyplaceInfluxdb.insertInfluxdb() +#POST /anyplace/geolocation/range_lookup controllers.AnyplaceInfluxdb.locationLookup() +#POST /anyplace/geolocation/distance_lookup controllers.AnyplaceInfluxdb.locationLookup() -##################################################################################################### -############### -### DELETED ### -############### +### DELETED CHECK:DZ #POST /anyplace/mapping/pois/types controllers.AnyplaceMapping.poisTypes() #POST /anyplace/mapping/pois/add_category controllers.AnyplaceMapping.categoryAdd() - -##################################################################################################### -################ -### DISABLED ### -################ -#POST /anyplace/mapping/radio/addbuids controllers.AnyplaceMapping.addBuidInRssLogs() -#POST /anyplace/mapping/pois/temp_url controllers.AnyplaceMapping.tempAllPoisWithoutUrl() -#POST /anyplace/mapping/radio/heatmap controllers.AnyplaceMapping.getRadioHeatmap() - -##################################################################################################### -# ACCES MAP -# TODO:NN na epistrefi deprecated kai bad request "will be removed" -POST /anyplace/position/radio/acces controllers.AnyplaceMapping.getAccesHeatmapByBuildingFloor() -POST /anyplace/position/radio/heatmap_building_floor_delete controllers.AnyplaceMapping.deleteAccesSpaceData() - -##################################################################################################### -##### NEED EXTRA TEST - -# TESTED: TEST:NN TEST:PM test on mobile app -POST /anyplace/position/radio_upload controllers.AnyplacePosition.radioUpload() - -# TESTED: TEST:NN TEST:PM test on mobile app -POST /anyplace/position/radio_download_floor controllers.AnyplacePosition.radioDownloadFloor() - -POST /anyplace/position/radio_by_building_floor controllers.AnyplacePosition.radioDownloadByBuildingFloor() - - -# Anyplace API - Position - -# bug mdb: fails to identify access points location -# TODO:NN fix bug NEXT MEETING -# where is it called (we want to rename) -POST /anyplace/position/radio/APs_building_floor controllers.AnyplaceMapping.getAPsByBuildingFloor() - -# DEVELOPING -# used by android -## very complicated -POST /anyplace/position/predictFloorAlgo1 controllers.AnyplacePosition.predictFloorAlgo1() - -######################## -# TIME BASED ENDPOINTS # -######################## - -# CHECK:PM CHECK:DZ remove "building" from endpoints -# INFO: Timestamp endpoints did not work (at all) in couchbase/old code - -POST /anyplace/position/radio/delete/time controllers.AnyplaceMapping.FingerPrintsTimestampDelete() - - -##################################################################################################### -##################### -### CHECK IF USED ### -##################### -# ADMIN WEBSITE -GET /admin/*file controllers.AnyplaceWebApps.serveAdmin(file: String) -GET /admin controllers.AnyplaceWebApps.AddTrailingSlash() - -# Android -POST /android controllers.AnyplaceAndroid.getApks() -GET /android/apk/:file controllers.AnyplaceAndroid.downloadApk(file: String) - -##################################################################################################### -#################### -### INFLUXDB ### -#################### -# CHECK: Make it obsolete? -POST /anyplace/geolocation/insert controllers.AnyplaceInfluxdb.insertInfluxdb() -POST /anyplace/geolocation/range_lookup controllers.AnyplaceInfluxdb.locationLookup() -POST /anyplace/geolocation/distance_lookup controllers.AnyplaceInfluxdb.locationLookup() - -##################################################################################################### -########### -### GET ### -########### - -POST /anyplace/version controllers.ApplicationAnyplace.Version - -### WEB APPS: -##### DEVELOPERS: -GET /developers/*file controllers.Assets.at(path="/public/anyplace_developers", file) -GET /developers/ controllers.AnyplaceWebApps.serveDevelopers(file="index.html") -GET /developers controllers.AnyplaceWebApps.AddTrailingSlash() -##### ARCHITECT: -GET /architect/*file controllers.Assets.at(path="/public/anyplace_architect", file) -GET /architect/ controllers.AnyplaceWebApps.serveArchitect2(file="index.html") -GET /architect controllers.AnyplaceWebApps.AddTrailingSlash() -##### VIEWER: -GET /viewer/index.html controllers.AnyplaceWebApps.serveViewer(file="index.html") -GET /viewer/*file controllers.AnyplaceAssets.at(path="/public", file) -GET /viewer/ controllers.AnyplaceWebApps.serveViewer(file="index.html") -GET /viewer controllers.AnyplaceWebApps.AddTrailingSlash() -##### NEW ANGULAR WEB APP (Login, register) : -GET /new2/*file controllers.Assets.at(path="/public/new2", file) -GET /new2/ controllers.AnyplaceWebApps.serveArchitect2(file="index.html") -GET /new2 controllers.AnyplaceWebApps.AddTrailingSlash() - -### RESOURCES: -GET /favicon.ico controllers.Assets.at(path="/public/images", file="favicon.png") -# must match application.conf -GET /floortiles/zip/*file controllers.ExternalAssets.at(path="/floor_plans", file) -# maps from /public to /assets -GET /assets/*file controllers.Assets.at(path="/public", file) -# root -GET / controllers.ApplicationAnyplace.index() -# REDIRECT REMAINING TO INDEX -GET /*any controllers.ApplicationAnyplace.indexAny(any) - -####################### -### AnyplaceNEW ### -####################### -POST /user/register controllers.AnyplaceAccounts.register() -POST /user/login controllers.AnyplaceAccounts.login() -#POST /user/logout controllers.AnyplaceAccounts.logout() diff --git a/server/database/.idea/codeStyles/Project.xml b/server/database/.idea/codeStyles/Project.xml deleted file mode 100644 index 80eafa973..000000000 --- a/server/database/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/server/database/.idea/codeStyles/codeStyleConfig.xml b/server/database/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index a55e7a179..000000000 --- a/server/database/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/server/database/.idea/database.iml b/server/database/.idea/database.iml deleted file mode 100644 index d6ebd4805..000000000 --- a/server/database/.idea/database.iml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/server/database/.idea/modules.xml b/server/database/.idea/modules.xml deleted file mode 100644 index 2a103ea5c..000000000 --- a/server/database/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/server/database/.idea/vcs.xml b/server/database/.idea/vcs.xml deleted file mode 100644 index b2bdec2d7..000000000 --- a/server/database/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/server/database/helpers/fixSchema.py b/server/database/helpers/fixSchema.py index 4fcf6cde3..a3d6f90d8 100644 --- a/server/database/helpers/fixSchema.py +++ b/server/database/helpers/fixSchema.py @@ -10,7 +10,7 @@ def fixBUILDING(obj, outrangedCoordsFile): fixCoordinateTypo(fixed, obj) markOutrangedCoordinates(fixed, outrangedCoordsFile) fixDashesOrNulls(fixed) - fixed['type'] = "building" + fixed['type'] = "Building" return fixed diff --git a/server/deploy/config.sh b/server/deploy/config.sh old mode 100755 new mode 100644 index 58e5df15f..a523f099c --- a/server/deploy/config.sh +++ b/server/deploy/config.sh @@ -1,23 +1,23 @@ -#!/bin/bash - -# ONCE UPDATED IGNORE THIS FILE USING: -# git update-index --assume-unchanged config.sh -USER= -DOMAIN= -REMOTE=$USER@$DOMAIN - -# L: Local -# R: Remote -LFOLDER=.. - -RFOLDER='~/alpha-deploy/' -RPORT=9001 - -# optionally send to a second folder -RFOLDER2='' -RPORT2= - -## COMPILATION NOTIFICATIONS: -# macOS: terminal-notifier -# Ubuntu/Windows: ? -NOTIFIER= +#!/bin/bash + +# ONCE UPDATED IGNORE THIS FILE USING: +# git update-index --assume-unchanged config.sh +USER= +DOMAIN= +REMOTE=$USER@$DOMAIN + +# L: Local +# R: Remote +LFOLDER=.. + +RFOLDER='~/alpha-deploy/' +RPORT=9001 + +# optionally send to a second folder +RFOLDER2='' +RPORT2= + +## COMPILATION NOTIFICATIONS: +# macOS: terminal-notifier +# Ubuntu/Windows: ? +NOTIFIER= diff --git a/server/deploy/watchdog.sh b/server/deploy/watchdog.sh index 4fca6daef..746451d6d 100755 --- a/server/deploy/watchdog.sh +++ b/server/deploy/watchdog.sh @@ -5,7 +5,7 @@ PORT= ./sync.sh watchmedo shell-command \ - --patterns="*.scala;*.js;*.css;*.vue;*.html;*.htm" \ + --patterns="*.scala;*.js;*.css;*.vue;*.html;*.htm;*.json" \ --recursive \ --command="./sync.sh" \ .. diff --git a/server/project/build.properties b/server/project/build.properties index f3af5708d..33951c5ee 100644 --- a/server/project/build.properties +++ b/server/project/build.properties @@ -1,7 +1,10 @@ +sbt.version=1.3.13 + + +// CLR: PM # stuck to pre 1.0 versions due to ACCES implementation # Last pre 1.0 release is: -sbt.version=0.13.18 - +#sbt.version=0.13.18 # CLR:PM # TODO: upgrade to > 1.0 #sbt.version=1.2.8 #sbt.version=1.3.10 diff --git a/server/project/plugins.sbt b/server/project/plugins.sbt index 764eb9703..16102eb17 100644 --- a/server/project/plugins.sbt +++ b/server/project/plugins.sbt @@ -1,9 +1,14 @@ -logLevel := Level.Warn +addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.8") + + +// CLR: PM +//logLevel := Level.Warn +// +//resolvers += "Typesafe repository" at "https://repo.typesafe.com/typesafe/releases/" +// +////playVersion := "2.4.2" +// +//addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.7") -resolvers += "Typesafe repository" at "https://repo.typesafe.com/typesafe/releases/" -//playVersion := "2.4.2" - addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.4.2") -//addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.2") // CANT do this -//addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.5") diff --git a/server/public/README.md b/server/public/README.md index 886f07410..2dacf6d9b 100644 --- a/server/public/README.md +++ b/server/public/README.md @@ -1,24 +1,90 @@ -# Web applications -Architect, Viewer, Viewer Campus, and Developers are separate -web application front-ends, that share some common images, JS, and CSS files. +# WEB APPLICATIONS: +Separate web application frontends written in Angular-JS. +They utilize Google Maps JS. In future work we aim to migrate to Leaflet/Angular. +They share some common resources: +- images +- js/css -## anyplace_architect (web-app) -Architect web application sources. +#### 1. [architect](./anyplace_architect) +#### 2. [viewer](./anyplace_viewer) +#### 3. [viewer_campus](./anyplace_viewer_campus) -## anyplace_developers (web-app/Documentation) -API Documentation sources. +## Compilation: +To compile the +[architect](./anyplace_architect), [viewer](./anyplace_viewer), or [viewer_campus](./anyplace_viewer_campus) +please follow the below instructions: -## anyplace_viewer (web-app) -Viewer web application sources. +
+ +Show Compilation Instructions + +1. `cd` to the relevant web app directory -## anyplace_viewer_campus (web-app) -Viewer Campus web application sources. +2. Install [Bower](http://bower.io/) dependencies: +``` +bower install +``` -## images -Common images shared between above web applications. +3. Install [Grunt](http://gruntjs.com/) tasks (requires [npm](https://www.npmjs.com/)): -## js -Common JavaScript shared between above web applications. +``` +# For Unix: +npm install +# For Windows: +npm install -g grunt-cli +``` +4. Build the web app: -## stylesheets -Common CSS shared between above web applications. +4.1 Development Version: +``` +# grunt will keep 'watching' for resource updates (js/css/images) +grunt +``` +4.1 Deployment version: +``` +grunt deploy +``` +For windows: use `grunt.cmd` + + +### The built files will be in the *build* folder with the following structure: +``` + + ├── build + │ ├── css + │ │ └── anyplace.min.css # Concatenated and minified CSS + │ ├── images + │ │ └── ... # Optimized images + │ └── js + │ └── anyplace.min.js # Concatenated and minified JS files + ├── bower_components + │ └── ... # Bower dependencies + └── index.html +``` + +#### Older notes on deploying the HTML: +Once the *build* folder is ready, we need to access the index.html file through the http protocol. +An easy way to do that is to start a Python [SimpleHTTPServer](https://docs.python.org/2/library/simplehttpserver.html) in the directory were the index.html is located. + +``` +python -m SimpleHTTPServer 9000 +``` + +Then hit *http://localhost:9000/* in your browser to launch AnyplaceArchitect. + +(The index.html file cannot be simply opened through the file system because the browser will throw security errors.) + +**The port number is important**. +For security purposes, AnyplaceServer accepts Cross-Origin requests from *localhost* only on ports 3030, 8080 and 9000. + +
+ +--- + +# DOCUMENTATION: +- [developers](./developers): Uses `Swagger-UI` + +# Common resources: +- [images](./images): Common images shared between above web applications. +- [js](./js): Common JavaScript shared between above web applications. +- [style](./style): Common CSS shared between above web applications. diff --git a/server/public/anyplace_architect/Gruntfile.js b/server/public/anyplace_architect/Gruntfile.js index 76d636c4f..9afaf58df 100644 --- a/server/public/anyplace_architect/Gruntfile.js +++ b/server/public/anyplace_architect/Gruntfile.js @@ -7,9 +7,9 @@ module.exports = function (grunt) { concat: { js: { src: [ - 'app.js', - '../js/shared.js', - '../js/anyplace-core-js/*.js', // Anyplace JS lib + '../shared/js/*.js', // FIRST + 'app.js', // SECOND + '../shared/js/anyplace-core-js/*.js', 'scripts/*.js', 'controllers/*.js' ], @@ -17,8 +17,8 @@ module.exports = function (grunt) { }, css: { src: [ + '../shared/css/*.css', 'style/*.css', - '../style/*.css', ], dest: 'build/css/anyplace.css' } @@ -51,34 +51,37 @@ module.exports = function (grunt) { src: ['**/*.{png,jpg,gif,svg}'], dest: 'build/images/' }, - // shared images folder - { + { // shared images folder expand: true, - cwd: '../images/', + cwd: '../shared/images/', src: ['**/*.{png,jpg,gif,svg}'], dest: 'build/images/' } ] } }, - watch: { js: { - files: ['app.js', '../js/shared.js', 'scripts/*.js', 'controllers/*.js'], + files: [ + 'app.js', + '../shared/js/*.js', + '../shared/js/anyplace-core-js/*.js', + 'scripts/*.js', + 'controllers/*.js'], tasks: ['concat:js', 'uglify'], options: { spawn: false } }, css: { - files: ['style/*.css', '../style/*.css'], + files: ['style/*.css', '../shared/css/*.css'], tasks: ['concat:css', 'cssmin'], options: { spawn: false } }, images: { - files: ['../images/*'], + files: ['../shared/images/*'], tasks: ['imagemin'], options: { spawn: false diff --git a/server/public/anyplace_architect/README.md b/server/public/anyplace_architect/README.md index 7f9b09a03..d12060b14 100644 --- a/server/public/anyplace_architect/README.md +++ b/server/public/anyplace_architect/README.md @@ -1,60 +1,3 @@ -## Anyplace Architect +# Architect -### Installing dependencies - -Install [Bower](http://bower.io/) dependencies: -``` -bower install -``` - -Install [Grunt](http://gruntjs.com/) tasks (requires [npm](https://www.npmjs.com/)): - -``` -npm install -``` -Or (for Windows) - -``` -npm install -g grunt-cli -``` - -### Building the app - -#### Development: -``` -grunt -``` - -#### Deployment: -``` -grunt deploy -``` - -NOTE: On windows use `grunt.cmd` - -#### The built files will be in the *build* folder with the following structure: - - . - ├── build - │ ├── css - │ │ └── anyplace.min.css # Concatenated and minified CSS - │ ├── images - │ │ └── ... # Optimized images - │ └── js - │ └── anyplace.min.js # Concatenated and minified JS files - ├── bower_components - │ └── ... # Bower dependencies - └── index.html - - -Once the *build* folder is ready, we need to access the index.html file through the http protocol. An easy way to do that is to start a Python [SimpleHTTPServer](https://docs.python.org/2/library/simplehttpserver.html) in the directory were the index.html is located. - -``` -python -m SimpleHTTPServer 9000 -``` - -Then hit *http://localhost:9000/* in your browser to launch AnyplaceArchitect. - -(The index.html file cannot be simply opened through the file system because the browser will throw security errors.) - -**The port number is important**. For security purposes, AnyplaceServer accepts Cross-Origin requests from *localhost* only on ports 3030, 8080 and 9000. +See [here](../README.md) for build instructions. \ No newline at end of file diff --git a/server/public/anyplace_architect/app.js b/server/public/anyplace_architect/app.js index afd7891d0..94d25da5f 100644 --- a/server/public/anyplace_architect/app.js +++ b/server/public/anyplace_architect/app.js @@ -138,15 +138,13 @@ app.service('GMapService', function () { return tile; }; - var mapTypeId = "roadmap"; + var mapTypeId = DEFAULT_MAP_TILES; if (typeof(Storage) !== "undefined" && localStorage) { - if (localStorage.getItem('mapTypeId')) - mapTypeId = localStorage.getItem('mapTypeId'); - else - localStorage.setItem("mapTypeId", "roadmap"); + localStorage.setItem("mapTypeId", DEFAULT_MAP_TILES);// FORCE OSM + // if (localStorage.getItem('mapTypeId')) mapTypeId = localStorage.getItem('mapTypeId'); + // else localStorage.setItem("mapTypeId", DEFAULT_MAP_TILES); } - self.gmap = new google.maps.Map(element, { center: new google.maps.LatLng(57, 21), zoomControl: true, @@ -161,6 +159,7 @@ app.service('GMapService', function () { zoom: 3, mapTypeId: mapTypeId, mapTypeControlOptions: { + // TODO:NN if cartodark exists un-comment mapTypeIds: ['OSM', /* 'CartoDark',*/ 'CartoLight', /* 'coordinate',*/ 'roadmap', 'satellite'], style: google.maps.MapTypeControlStyle.DROPDOWN_MENU, position: google.maps.ControlPosition.LEFT_CENTER diff --git a/server/public/anyplace_architect/bower.json b/server/public/anyplace_architect/bower.json index fbae4032c..cf4bfbb22 100644 --- a/server/public/anyplace_architect/bower.json +++ b/server/public/anyplace_architect/bower.json @@ -1,6 +1,6 @@ { "name": "AnyplaceArchitect", - "version": "3.2.0", + "version": "4.2.0", "homepage": "http://anyplace.cs.ucy.ac.cy/architect/", "authors": [ "Costantinos Costa","Kyriakos Georgiou" diff --git a/server/public/anyplace_architect/controllers/BuildingController.js b/server/public/anyplace_architect/controllers/BuildingController.js index c5f6b482d..1cc1ffaf2 100644 --- a/server/public/anyplace_architect/controllers/BuildingController.js +++ b/server/public/anyplace_architect/controllers/BuildingController.js @@ -69,57 +69,26 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa promise.then( function (resp) { // on success var data = resp.data; - // console.log("VERSION:: " + data); + var prettyVersion=getPrettyVersion(data); + console.log("VERSION:: " + prettyVersion); var element = document.getElementById("anyplace-version"); - element.textContent = "v"+data; + element.textContent = "v"+prettyVersion; }, function (resp) { console.log("Failed to get version: " + resp.data); } ); }; $scope.fetchVersion(); - -// // Replace this with your URL. -// var BUILDING_TILE_URL = AnyplaceAPI.FULL_SERVER + '/floortiles/{building}/{floor}/{z}/z{z}x{x}y{y}.png'; -// -// // Name the layer anything you like. -// var layerID = 'building_layer'; -// -// // Create a new ImageMapType layer. static_tiles/19/z19x310801y207411.png -// var maptiler = new google.maps.ImageMapType({ -// name: layerID, -// getTileUrl: function (coord, zoom) { -// var buid = $scope.anyService.getBuildingId(); -// -// var floor = $scope.anyService.getFloorNumber(); -// var url = BUILDING_TILE_URL -// .replace('{building}', buid) -// .replace('{floor}', floor) -// .replace('{z}', zoom) -// .replace('{x}', coord.x) -// .replace('{y}', coord.y) -// .replace('{z}', zoom); -// return url; -// }, -// tileSize: new google.maps.Size(256, 256), -// isPng: true -// }); -// -// // Register the new layer, then activate it. -// $scope.gmapService.gmap.overlayMapTypes.insertAt(0, maptiler); - $scope.setCrudTabSelected = function (n) { $scope.crudTabSelected = n; if (!$scope.anyService.getBuilding()) { _err($scope, "No building selected."); return; } - var b = $scope.myBuildingsHashT[$scope.anyService.getBuildingId()]; if (!b) { return; } - var m = b.marker; if (!m) { return; @@ -130,7 +99,6 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa } else { m.setDraggable(false); } - }; $scope.isCrudTabSelected = function (n) { return $scope.crudTabSelected === n; @@ -297,69 +265,47 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa $scope.fetchAllBuildings = function () { var jsonReq = {}; - jsonReq.username = $scope.creds.username; - jsonReq.password = $scope.creds.password; - jsonReq.owner_id = $scope.owner_id; - - if (!jsonReq.owner_id) { - _err($scope, ERR_USER_AUTH); - return; - } - + // jsonReq.owner_id = $scope.owner_id; + jsonReq.access_token = $scope.user.access_token; var promise = $scope.anyAPI.allOwnerBuildings(jsonReq); promise.then( - function (resp) { - // on success + function (resp) { // on success var data = resp.data; - //var bs = JSON.parse( data.buildings ); $scope.myBuildings = data.spaces; - var infowindow = new google.maps.InfoWindow({ content: '-', maxWidth: 500 }); - var localStoredBuildingIndex = -1; var localStoredBuildingId = undefined; if (typeof(Storage) !== "undefined" && localStorage && localStorage.getItem('lastBuilding')) { localStoredBuildingId = localStorage.getItem('lastBuilding'); } - for (var i = 0; i < $scope.myBuildings.length; i++) { - var b = $scope.myBuildings[i]; - $scope.example9data[i] = {id: b.buid, label: b.name}; $scope.example9dataedit[i] = {id: b.buid, label: b.name}; - if (localStoredBuildingId && localStoredBuildingId === b.buid) { localStoredBuildingIndex = i; } - if (b.is_published === 'true' || b.is_published == true) { b.is_published = true; } else { b.is_published = false; } - var marker = getMapsIconBuildingArchitect(GMapService.gmap, _latLngFromBuilding(b)) - - var htmlContent = '
' + '
Building:
' + '' + b.name + '' + '
Description:
' + '' + '
'; - marker.infoContent = htmlContent; marker.building = b; - $scope.myBuildingsHashT[b.buid] = { marker: marker, model: b }; - google.maps.event.addListener(marker, 'click', function () { infowindow.setContent(this.infoContent); infowindow.open(GMapService.gmap, this); @@ -389,11 +335,6 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa $scope.addNewBuilding = function (id) { if ($scope.myMarkers[id] && $scope.myMarkers[id].marker) { var building = $scope.myMarkers[id].model; - building.owner_id = $scope.owner_id; // set owner id - if (!building.owner_id) { - _err($scope, ERR_USER_AUTH); - return; - } building.coordinates_lat = String($scope.myMarkers[id].marker.position.lat()); building.coordinates_lon = String($scope.myMarkers[id].marker.position.lng()); if (building.coordinates_lat === undefined || building.coordinates_lat === null) { @@ -412,7 +353,7 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa if (!building.description) { building.description = "-"; } - if (building.owner_id && building.name && building.description && building.is_published && building.url && building.address && building.space_type) { + if (building.name && building.description && building.is_published && building.url && building.address && building.space_type) { var promise = $scope.anyAPI.addBuilding(building); promise.then( function (resp) { @@ -458,37 +399,17 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa }; $scope.deleteBuilding = function () { - var b = $scope.anyService.getBuilding(); - var reqObj = $scope.creds; - - if (!$scope.owner_id) { - _err($scope, "Could not identify user. Please refresh and sign in again."); - return; - } - - reqObj.owner_id = $scope.owner_id; - - if (!b || !b.buid) { - _err($scope, "No building selected for deletion."); - return; - } - reqObj.buid = b.buid; - var promise = $scope.anyAPI.deleteBuilding(reqObj); promise.then( - function (resp) { - // on success + function (resp) { // on success var data = resp.data; - console.log("building deleted: ", b); - // delete the building from the loadedBuildings $scope.myBuildingsHashT[b.buid].marker.setMap(null); delete $scope.myBuildingsHashT[b.buid]; - var bs = $scope.myBuildings; var sz = bs.length; for (var i = 0; i < sz; i++) { @@ -497,14 +418,11 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa break; } } - // update the selected building if ($scope.myBuildings && $scope.myBuildings.length > 0) { $scope.anyService.selectedBuilding = $scope.myBuildings[0]; } - $scope.setCrudTabSelected(1); - _suc($scope, "Successfully deleted indoor space."); }, function (resp) { @@ -539,46 +457,29 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa $scope.updateBuilding = function () { var b = $scope.anyService.getBuilding(); - if (LPUtils.isNullOrUndefined(b) || LPUtils.isNullOrUndefined(b.buid)) { _err($scope, "No selected building found."); return; } - var reqObj = {}; - - // from controlBarController - reqObj = $scope.creds; - if (!$scope.owner_id) { - _err($scope, ERR_USER_AUTH); - return; - } - - reqObj.owner_id = $scope.owner_id; - reqObj.buid = b.buid; - reqObj.description = b.description; if (isNullOrEmpty(b.description)) { reqObj.description = ""; } - if (b.name) { reqObj.name = b.name; } - if (b.is_published === true || b.is_published == "true") { reqObj.is_published = "true"; } else { reqObj.is_published = "false"; } - - reqObj.bucode = b.bucode; if (isNullOrEmpty(b.bucode)) { reqObj.bucode = ""; } - + LOG.D2(b); var marker = $scope.myBuildingsHashT[b.buid].marker; if (marker) { var latLng = marker.position; @@ -590,16 +491,13 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa var promise = $scope.anyAPI.updateBuilding(reqObj); promise.then( - function (resp) { - // on success + function (resp) { // on success var data = resp.data; - if (b.is_published === 'true' || b.is_published == true) { b.is_published = true; } else { b.is_published = false; } - _suc($scope, "Successfully updated building.") }, function (resp) { @@ -611,28 +509,17 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa $scope.fetchAllCampus = function () { var jsonReq = {}; - jsonReq.username = $scope.creds.username; - jsonReq.password = $scope.creds.password; - jsonReq.owner_id = $scope.owner_id; $scope.myCampus = []; - if (!jsonReq.owner_id) { - _err($scope, ERR_USER_AUTH); - return; - } - var promise = $scope.anyAPI.allCampus(jsonReq); promise.then( - function (resp) { - // on success + function (resp) { // on success var data = resp.data; - //var bs = JSON.parse( data.buildings ); $scope.myCampus = data.buildingsets; var localStoredCampusIndex = -1; var localStoredCampusId = undefined; if (typeof(Storage) !== "undefined" && localStorage && localStorage.getItem('lastCampus')) { localStoredCampusId = localStorage.getItem('lastCampus'); } - for (var i = 0; i < $scope.myCampus.length; i++) { var b = $scope.myCampus[i]; @@ -641,7 +528,6 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa localStoredCampusIndex = i; } } - // using the latest building set form localStorage if (localStoredCampusIndex >= 0) { $scope.anyService.selectedCampus = $scope.myCampus[localStoredCampusIndex]; @@ -657,41 +543,25 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa $scope.updateCampus = function () { var b = $scope.anyService.getCampus(); - if (LPUtils.isNullOrUndefined(b) || LPUtils.isNullOrUndefined(b.cuid)) { _err($scope, "No selected campus found."); return; } - var reqObj = {}; - // from controlBarController - reqObj = $scope.creds; - if (!$scope.owner_id) { - _err($scope, ERR_USER_AUTH); - return; - } - - reqObj.owner_id = $scope.owner_id; - reqObj.cuid = b.cuid; - reqObj.description = b.description; if (isNullOrEmpty(b.description)) { reqObj.description = ""; } - reqObj.name = b.name; if (isNullOrEmpty(b.name)) { reqObj.name = ""; } - if (b.newcuid) { reqObj.newcuid = b.newcuid; } - var sz = $scope.example9modeledit.length; - if (sz == 0) { _err($scope, "No buildings selected."); return; @@ -701,12 +571,8 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa buids = buids + "\"" + $scope.example9modeledit[i].id + "\","; } buids = buids + "\"" + $scope.example9modeledit[0].id + "\"]"; - reqObj.greeklish = document.getElementById("Greeklish-OnOffedit").checked; - reqObj.buids = buids; - - var promise = $scope.anyAPI.updateCampus(reqObj); promise.then( function (resp) { @@ -723,34 +589,17 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa }; $scope.deleteCampus = function () { - var b = $scope.anyService.getCampus(); - - var reqObj = $scope.creds; - - if (!$scope.owner_id) { - _err($scope, ERR_USER_AUTH); - return; - } - - reqObj.owner_id = $scope.owner_id; - if (!b || !b.cuid) { _err($scope, "No Campus selected for deletion."); return; } - + var reqObj = {}; reqObj.cuid = b.cuid; - var promise = $scope.anyAPI.deleteCampus(reqObj); promise.then( - function (resp) { - // on success + function (resp) { // on success var data = resp.data; - - console.log("campus deleted: ", b); - - var bs = $scope.myCampus; var sz = bs.length; for (var i = 0; i < sz; i++) { @@ -759,7 +608,6 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa break; } } - // update the selected building if ($scope.myCampus && $scope.myCampus.length > 0) { $scope.anyService.selectedCampus = $scope.myCampus[0]; @@ -767,9 +615,7 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa else if ($scope.myCampus.length == 0) { $scope.anyService.selectedCampus = undefined; } - $scope.setCrudTabSelected(1); - _suc($scope, "Successfully deleted campus."); }, function (resp) { @@ -778,28 +624,21 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa "the campus is deleted but please refresh to make sure or try again.", true) } ); - }; $scope.addCampus = function () { - var name_element = document.getElementById("CampusName"); var name = "\"name\":\"" + name_element.value + "\""; - if (document.getElementById("CampusDescription").value.localeCompare("") == 0) { document.getElementById("CampusDescription").value = "-"; } - var des = document.getElementById("CampusDescription"); var des = "\"description\":\"" + des.value + "\""; - var mycuid = document.getElementById("CampusID"); var mycuid = "\"cuid\":\"" + mycuid.value + "\""; - var greeklish = document.getElementById("Greeklish-OnOff").checked; greeklish = "\"greeklish\":\"" + greeklish + "\""; var sz = $scope.example9model.length; - if (sz == 0) { _err($scope, "No buildings selected."); return; @@ -809,7 +648,6 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa buids = buids + "\"" + $scope.example9model[i].id + "\","; } buids = buids + "\"" + $scope.example9model[0].id + "\"]"; - var jreq = "{" + greeklish + "," + buids + "," + mycuid + "," + des + "," + name + ",\"owner_id\":\"" + $scope.owner_id + "\",\"access_token\":\"" + $scope.gAuth.access_token + "\"}"; //alert(document.getElementById("Greeklish-OnOff").checked); var promise = $scope.anyAPI.addBuildingSet(jreq); @@ -1309,16 +1147,9 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa pois: [] }; $scope.updatePoifromExcel = function (id, lat, lng, building_entrance, nm, des, ptype, ovwrite, bid, buildingname) { - var obj = {}; - - obj.username = $scope.creds.username; - obj.password = $scope.creds.password; - obj.owner_id = $scope.owner_id; - obj.coordinates_lat = lat; obj.coordinates_lon = lng; - obj.is_building_entrance = building_entrance; obj.name = nm; obj.puid = id; @@ -1332,7 +1163,6 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa function (resp) { var data = resp.data; if ($scope.anyService.progress == 100) { - if ($scope.anyService.downloadlogfile) { $scope.anyService.downloadlogfile = false; _suc($scope, "Successfully updated POIs.A log file will be downloaded"); @@ -1377,16 +1207,9 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa $scope.updatePoifromFile = function (id, lat, lng, nm, des, ptype, ovwrite, bid, i, j, count, countok, buildingname) { - var obj = {}; - - obj.username = $scope.creds.username; - obj.password = $scope.creds.password; - obj.owner_id = $scope.owner_id; - obj.coordinates_lat = lat; obj.coordinates_lon = lng; - obj.name = nm; obj.puid = id; obj.description = des; @@ -1755,15 +1578,32 @@ app.controller('BuildingController', ['$cookieStore', '$scope', '$compile', 'GMa $scope.signLocalAccount = function () { var jsonReq = {}; - jsonReq.username = $scope.creds.username; - jsonReq.password = $scope.creds.password; + jsonReq.username = $scope.user.username; + jsonReq.password = $scope.user.password; var promise = $scope.anyAPI.signLocalAccount(jsonReq); promise.then( - function (resp) { - // on success + function (resp) { // on success + var data = resp.data; - $scope.$broadcast('loggedIn', []); + $scope.user.username = data.user.username; + $scope.user.name = data.user.name; + $scope.user.email = data.user.email; + // $scope.user.owner_id = data.user.owner_id; + // $scope.user.access_token = data.user.access_token; + + $scope.gAuth.access_token = data.user.access_token; + app.access_token = data.user.access_token; + $scope.setAuthenticated(true); + + // $scope.person = resp.getBasicProfile(); // BUG + // $scope.person.image = $scope.person.getImageUrl(); // BUG + // $scope.person.id = $scope.person.getId(); // BUG + // $scope.person.displayName = $scope.person.getName(); + // $scope.displayName = $scope.person.displayName; + + $scope.fetchAllBuildings(); + $scope.fetchAllCampus(); _suc($scope, "Successfully logged in."); }, function (resp) { diff --git a/server/public/anyplace_architect/controllers/ControlBarController.js b/server/public/anyplace_architect/controllers/ControlBarController.js index 3076fc291..5eca5c3e9 100644 --- a/server/public/anyplace_architect/controllers/ControlBarController.js +++ b/server/public/anyplace_architect/controllers/ControlBarController.js @@ -24,25 +24,24 @@ app.controller('ControlBarController', ['$scope', '$rootScope', 'AnyplaceService $scope.anyService = AnyplaceService; $scope.gmapService = GMapService; - $scope.isAuthenticated = false; - $scope.signInType = "google"; - $scope.gAuth = {}; $scope.person = undefined; - $scope.creds = { + $scope.creds = { //TODO:NN delete eventually.. fullName: undefined, username: undefined, password: undefined }; - $scope.user = { + $scope.user = { // TODO:NN make it compatible with google account... name: undefined, email: undefined, username: undefined, - password: undefined + password: undefined, + owner_id: undefined, + access_token: undefined } $scope.owner_id = undefined; @@ -51,7 +50,6 @@ app.controller('ControlBarController', ['$scope', '$rootScope', 'AnyplaceService var self = this; //to be able to reference to it in a callback, you could use $scope instead - $scope.setAuthenticated = function (bool) { $scope.isAuthenticated = bool; }; @@ -88,21 +86,14 @@ app.controller('ControlBarController', ['$scope', '$rootScope', 'AnyplaceService }; $scope.onSignIn = function (googleUser) { - if ($scope.getCookie("username") === "") { $scope.setCookie("username", "true", 365); location.reload(); } - //location.reload(); $scope.setAuthenticated(true); - $scope.gAuth = gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse(); - - $scope.gAuth.access_token = $scope.gAuth.id_token; - app.access_token = $scope.gAuth.id_token; - $scope.personLookUp(googleUser); }; @@ -124,10 +115,6 @@ app.controller('ControlBarController', ['$scope', '$rootScope', 'AnyplaceService $scope.owner_id = $scope.person.id + '_' + $scope.signInType; $scope.displayName = $scope.person.displayName; - if ($scope.person && $scope.person.id) { - $scope.$broadcast('loggedIn', []); - } - var promise = AnyplaceAPIService.signGoogleAccount({ name: $scope.person.displayName, external: "google" @@ -137,6 +124,11 @@ app.controller('ControlBarController', ['$scope', '$rootScope', 'AnyplaceService function (resp) { // console.log(resp) $scope.userType = resp.data.type; + $scope.gAuth.access_token = resp.data.access_token; + app.access_token = resp.data.access_token; + if ($scope.person && $scope.person.id) { + $scope.$broadcast('loggedIn', []); + } }, function (resp) { console.log("error: personLookUp") diff --git a/server/public/anyplace_architect/controllers/FloorController.js b/server/public/anyplace_architect/controllers/FloorController.js index 1034f610c..b752c4888 100644 --- a/server/public/anyplace_architect/controllers/FloorController.js +++ b/server/public/anyplace_architect/controllers/FloorController.js @@ -361,29 +361,15 @@ app.controller('FloorController', ['$scope', 'AnyplaceService', 'GMapService', ' $scope.addFloorObject = function (flJson, selectedBuilding, flData) { var obj = _checkFloorFormat(flJson); - - obj.owner_id = $scope.owner_id; - - if (!obj.owner_id) { - _err($scope, ERR_USER_AUTH); - return; - } - - // make the request at AnyplaceAPI - var promise = $scope.anyAPI.addFloor(obj); + var promise = $scope.anyAPI.addFloor(obj); // make the request at AnyplaceAPI promise.then( - function (resp) { - // on success + function (resp) { // on success var data = resp.data; // insert the newly created building inside the loadedBuildings $scope.xFloors.push(obj); - $scope.anyService.selectedFloor = $scope.xFloors[$scope.xFloors.length - 1]; - _suc($scope, "Successfully added new floor"); - $scope.uploadWithZoom(selectedBuilding, obj, flData); - }, function (resp) { ShowError($scope, resp, @@ -415,49 +401,34 @@ app.controller('FloorController', ['$scope', 'AnyplaceService', 'GMapService', ' }; $scope.deleteFloor = function () { - var bobj = $scope.anyService.getFloor(); - if (LPUtils.isNullOrUndefined(bobj) || LPUtils.isStringBlankNullUndefined(bobj.floor_number) || LPUtils.isStringBlankNullUndefined(bobj.buid)) { _err($scope, "No floor seems to be selected."); return; } - - bobj.username = $scope.creds.username; - bobj.password = $scope.creds.password; - bobj.owner_id = $scope.owner_id; - - console.log(bobj); - - // make the request at AnyplaceAPI - var promise = $scope.anyAPI.deleteFloor(bobj); + var promise = $scope.anyAPI.deleteFloor(bobj); // make the request at AnyplaceAPI promise.then( function (resp) { // on success var data = resp.data; - // delete the building from the loadedBuildings var lf = $scope.xFloors; var sz = lf.length; - for (var i = 0; i < sz; i++) { if (lf[i].floor_number == bobj.floor_number) { lf.splice(i, 1); break; } } - if ($scope.data.floor_plan_groundOverlay != null) { $scope.data.floor_plan_groundOverlay.setMap(null); $scope.data.floor_plan_groundOverlay = null; } - if ($scope.xFloors && $scope.xFloors.length > 0) { $scope.anyService.selectedFloor = $scope.xFloors[0]; } else { $scope.anyService.selectedFloor = undefined; } - _suc($scope, "Successfully deleted floor."); }, function (resp) { diff --git a/server/public/anyplace_architect/controllers/PoiController.js b/server/public/anyplace_architect/controllers/PoiController.js index 02302d4d9..24200aacf 100644 --- a/server/public/anyplace_architect/controllers/PoiController.js +++ b/server/public/anyplace_architect/controllers/PoiController.js @@ -543,20 +543,14 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS marker.tpl2 = tpl; marker.model = p; - marker.infowindow = infowindow; - $scope.myPoisHashT[p.puid].marker = marker; $scope.anyService.setAllPois($scope.myPoisHashT); - google.maps.event.addListener(marker, 'click', function () { - if ($scope.edgeMode) { if ($scope.connectPois.prev) { - if ($scope.connectPois.prev == this) { $scope.connectPois.prev = undefined; - if (this.model.pois_type === "None") { this.setIcon(_getConnectorIconNormal()); } else { @@ -564,14 +558,12 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS } return; } - // No longer the beginning of an edge, make smaller. if ($scope.connectPois.prev.model.pois_type === "None") { $scope.connectPois.prev.setIcon(_getConnectorIconNormal()); } else { $scope.connectPois.prev.setIcon(_getNormalPoiIconNormal()); } - var flightPath = new google.maps.Polyline({ path: [this.position, $scope.connectPois.prev.position], geodesic: true, @@ -579,64 +571,45 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS strokeOpacity: 0.5, strokeWeight: 4 }); - flightPath.setMap(GMapService.gmap); - // Construct the request var poiA = $scope.connectPois.prev.model; var poiB = this.model; - if (!poiA || !poiB || !poiA.puid || !poiB.puid || !poiA.buid || !poiB.buid || LPUtils.isNullOrUndefined(poiA.floor_number) || LPUtils.isNullOrUndefined(poiB.floor_number)) { _err($scope, "One or both of the POIs attempted to be connected seem to be be malformed. Please refresh."); return; } - var jsonReq = { - - username: $scope.creds.username, - password: $scope.creds.password, owner_id: $scope.owner_id, - pois_a: poiA.puid, floor_a: poiA.floor_number, buid_a: poiA.buid, - // insert the connection buid ( needed by the Dijkstra algorithm at the moment ) buid: poiA.buid, - pois_b: poiB.puid, floor_b: poiB.floor_number, buid_b: poiB.buid, - is_published: 'true', edge_type: 'hallway' }; - flightPath.model = jsonReq; - - // make the request at AnyplaceAPI - - var promise = $scope.anyAPI.addConnection(jsonReq); + var promise = $scope.anyAPI.addConnection(jsonReq); // make the request at AnyplaceAPI promise.then( function (resp) { var data = resp.data; var cuid = data.cuid; - flightPath.model.cuid = cuid; var cloneModel = flightPath.model; cloneModel.polyLine = flightPath; $scope.myConnectionsHashT[cuid] = cloneModel; $scope.anyService.setAllConnection($scope.myConnectionsHashT); - flightPath.setOptions({ strokeColor: '#0000FF', strokeOpacity: 0.5 }); - google.maps.event.addListener(flightPath, 'click', function () { $scope.$apply(_deleteConnection(this)); }); - }, function (resp) { ShowError($scope, resp, @@ -645,13 +618,9 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS flightPath.setMap(null); } ); - $scope.connectPois.prev = undefined; - } else { - $scope.connectPois.prev = this; - // Increase the size of markers to indicate as the start of an edge if (this.model.pois_type === "None") { this.setIcon(_getConnectorIconBigger()); @@ -659,7 +628,6 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS this.setIcon(_getNormalPoiIconBigger()); } } - } else { infowindow.setContent(this.tpl2[0]); infowindow.open(GMapService.gmap, this); @@ -821,8 +789,6 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS }; $scope.fetchAllPoisForFloor = function (fl) { - - //TODO: validation var jsonReq = AnyplaceService.jsonReq; jsonReq.buid = AnyplaceService.getBuildingId(); jsonReq.floor_number = AnyplaceService.getFloorNumber(); @@ -831,33 +797,25 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS promise.then( function (resp) { var data = resp.data; - $scope.clearPoisOnMap(); - $scope.myPois = data.pois; - var sz = $scope.myPois.length; for (var i = sz - 1; i >= 0; i--) { // insert the pois inside the hashtable // TODO clone (?) var puid = $scope.myPois[i].puid; - if ($scope.myPois[i].is_building_entrance == 'true') { $scope.myPois[i].is_building_entrance = true; } else { $scope.myPois[i].is_building_entrance = false; } - $scope.myPois[i].pois_type2=$scope.myPois[i].pois_type; - $scope.myPoisHashT[puid] = {}; $scope.myPoisHashT[puid].model = $scope.myPois[i]; $scope.anyService.setAllPois($scope.myPoisHashT); } - // draw the markers $scope.drawPoisOnMap(); - //_suc($scope, "Successfully fetched all POIs."); }, function (resp) { @@ -873,98 +831,71 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS $scope.addPoi = function (id) { if ($scope.myMarkers[id] && $scope.myMarkers[id].marker) { - if ($scope.myMarkers[id].model.pois_type2.localeCompare("")!=0){ $scope.myMarkers[id].model.pois_type=$scope.myMarkers[id].model.pois_type2; } - var poi = $scope.myMarkers[id].model; - - // set owner id - poi.owner_id = $scope.owner_id; - poi.coordinates_lat = String($scope.myMarkers[id].marker.position.lat()); poi.coordinates_lon = String($scope.myMarkers[id].marker.position.lng()); - poi.is_building_entrance = String(poi.is_building_entrance); - if (poi.coordinates_lat === undefined || poi.coordinates_lat === null) { _err($scope, "POI has invalid latitude format"); return; } - if (poi.coordinates_lon === undefined || poi.coordinates_lon === null) { _err($scope, "POI has invalid longitude format"); return; } - - if (poi.owner_id && poi.name && poi.buid && poi.pois_type + if (poi.name && poi.buid && poi.pois_type && !LPUtils.isNullOrUndefined(poi.is_building_entrance) && !LPUtils.isNullOrUndefined(poi.is_published) && !LPUtils.isNullOrUndefined(poi.is_door) && !LPUtils.isNullOrUndefined(poi.floor_name) && !LPUtils.isNullOrUndefined(poi.floor_number)) { - if (poi.is_building_entrance == 'true') { poi.is_building_entrance = 'true'; } else { poi.is_building_entrance = 'false'; } - var json_req = poi; - // make the request at AnyplaceAPI var promise = $scope.anyAPI.addPois(json_req); promise.then( function (resp) { var data = resp.data; - poi.puid = data.puid; - if (poi.is_building_entrance == 'true') { poi.is_building_entrance = true; } else { poi.is_building_entrance = false; } - // insert the newly created building inside the loadedBuildings $scope.myPois.push(poi); $scope.anyService.selectedPoi = $scope.myPois[$scope.myPois.length - 1]; - // update the hashtable - $scope.myPoisHashT[poi.puid] = { model: poi, marker: $scope.myMarkers[id].marker }; $scope.anyService.setAllPois($scope.myPoisHashT); - $scope.myMarkers[id].model = poi; - if ($scope.myMarkers[id].infowindow) { $scope.myMarkers[id].infowindow.close(); $scope.myMarkers[id].infowindow.setContent($scope.myMarkers[id].marker.tpl2[0]); } - $scope.myMarkers[id].marker.model = poi; - if ($scope.myMarkers[id].marker.model.pois_type == "None") { $scope.myMarkers[id].marker.setIcon(_getConnectorIconNormal()); } else { $scope.myMarkers[id].marker.setIcon(_getNormalPoiIconNormal()); } - google.maps.event.clearListeners($scope.myMarkers[id].marker, 'click'); - var infowindow = $scope.myMarkers[id].infowindow; - google.maps.event.addListener($scope.myMarkers[id].marker, 'click', function () { if ($scope.edgeMode) { if ($scope.connectPois.prev) { - if ($scope.connectPois.prev == this) { $scope.connectPois.prev = undefined; - if (this.model.pois_type === "None") { this.setIcon(_getConnectorIconNormal()); } else { @@ -972,14 +903,12 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS } return; } - // No longer the beginning of an edge, make smaller. if ($scope.connectPois.prev.model.pois_type === "None") { $scope.connectPois.prev.setIcon(_getConnectorIconNormal()); } else { $scope.connectPois.prev.setIcon(_getNormalPoiIconNormal()); } - var flightPath = new google.maps.Polyline({ path: [this.position, $scope.connectPois.prev.position], geodesic: true, @@ -987,64 +916,45 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS strokeOpacity: 0.5, strokeWeight: 4 }); - flightPath.setMap(GMapService.gmap); - // Construct the request var poiA = $scope.connectPois.prev.model; var poiB = this.model; - if (!poiA || !poiB || !poiA.puid || !poiB.puid || !poiA.buid || !poiB.buid || LPUtils.isNullOrUndefined(poiA.floor_number) || LPUtils.isNullOrUndefined(poiB.floor_number)) { _err($scope, "One or both of the POIs attempted to be connected seem to be be malformed. Please refresh."); return; } - var jsonReq = { - - username: $scope.creds.username, - password: $scope.creds.password, - owner_id: $scope.owner_id, - pois_a: poiA.puid, floor_a: poiA.floor_number, buid_a: poiA.buid, - // insert the connection buid ( needed by the Dijkstra algorithm at the moment ) buid: poiA.buid, - pois_b: poiB.puid, floor_b: poiB.floor_number, buid_b: poiB.buid, - is_published: 'true', edge_type: 'hallway' }; - flightPath.model = jsonReq; - // make the request at AnyplaceAPI - var promise = $scope.anyAPI.addConnection(jsonReq); promise.then( function (resp) { var data = resp.data; var cuid = data.cuid; - flightPath.model.cuid = cuid; var cloneModel = flightPath.model; cloneModel.polyLine = flightPath; $scope.myConnectionsHashT[cuid] = cloneModel; $scope.anyService.setAllConnection($scope.myConnectionsHashT); - flightPath.setOptions({ strokeColor: '#0000FF', strokeOpacity: 0.5 }); - google.maps.event.addListener(flightPath, 'click', function () { $scope.$apply(_deleteConnection(this)); }); - }, function (resp) { ShowError($scope, resp, @@ -1052,11 +962,9 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS flightPath.setMap(null); } ); - $scope.connectPois.prev = undefined; } else { $scope.connectPois.prev = this; - // Increase the size of markers to indicate as the start of an edge if (this.model.pois_type === "None") { this.setIcon(_getConnectorIconBigger()); @@ -1075,16 +983,13 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS }) } }); - google.maps.event.addListener($scope.myMarkers[id].marker, "dragend", function (event) { if (this.model && this.model.puid) { $scope.updatePoiPosition(this); } }); - // Too spammy. //_suc($scope, "Successfully added new POI."); - }, function (resp) { ShowError($scope, resp, "Something went wrong while adding the new POI.", true); @@ -1201,32 +1106,22 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS $scope.updatePoi = function (id) { var bobj = $scope.myPoisHashT[id]; - if (!bobj || !bobj.model || !bobj.model.puid) { if ($scope.myPoisHashT && $scope.myMarkers && $scope.myMarkers[id] && $scope.myMarkers[id].model && $scope.myPoisHashT[$scope.myMarkers[id].model.puid]) { - bobj = $scope.myPoisHashT[$scope.myMarkers[id].model.puid]; - if (!bobj || !bobj.model || !bobj.model.puid) { _err($scope, "No valid POI selected to be updated."); return; } - } else { _err($scope, "No valid POI selected to be updated."); return; } } - if (bobj.model.pois_type2.localeCompare("")!=0){ bobj.model.pois_type = bobj.model.pois_type2; } - var obj = bobj.model; - obj.username = $scope.creds.username; - obj.password = $scope.creds.password; - obj.owner_id = $scope.owner_id; - var marker = bobj.marker; if (marker) { var latLng = marker.position; @@ -1235,43 +1130,35 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS obj.coordinates_lon = String(latLng.lng()); } } - if (obj.is_building_entrance) { obj.is_building_entrance = 'true'; } else { obj.is_building_entrance = 'false'; } - // make the request at AnyplaceAPI var promise = $scope.anyAPI.updatePois(obj); promise.then( function (resp) { // success var data = resp.data; - if (marker) { marker.infowindow.setMap(null); } - if (obj.is_building_entrance == 'true') { obj.is_building_entrance = true; } else { obj.is_building_entrance = false; } - for (var c in $scope.myConnectionsHashT) { if ($scope.myConnectionsHashT.hasOwnProperty(c)) { if ($scope.myConnectionsHashT[c].pois_a == obj.puid || $scope.myConnectionsHashT[c].pois_b == obj.puid) { - var pa = $scope.myConnectionsHashT[c].pois_a; var pb = $scope.myConnectionsHashT[c].pois_b; - var flightPlanCoordinates = [ new google.maps.LatLng($scope.myPoisHashT[pa].model.coordinates_lat, $scope.myPoisHashT[pa].model.coordinates_lon), new google.maps.LatLng($scope.myPoisHashT[pb].model.coordinates_lat, $scope.myPoisHashT[pb].model.coordinates_lon) ]; - $scope.myConnectionsHashT[c].polyLine.setPath(flightPlanCoordinates); $scope.anyService.setAllConnection($scope.myConnectionsHashT); $scope.anyService.setAllPois($scope.myPoisHashT); @@ -1289,62 +1176,47 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS }; $scope.updatePoiPosition = function (marker) { - var obj; - if (marker && marker.model) { obj = marker.model; } - - obj.username = $scope.creds.username; - obj.password = $scope.creds.password; - obj.owner_id = $scope.owner_id; - var latLng = marker.position; if (latLng && latLng.lat() && latLng.lng()) { obj.coordinates_lat = String(latLng.lat()); obj.coordinates_lon = String(latLng.lng()); } - if (obj.is_building_entrance) { obj.is_building_entrance = 'true'; } else { obj.is_building_entrance = 'false'; } - // make the request at AnyplaceAPI var promise = $scope.anyAPI.updatePois(obj); promise.then( function (resp) { // success var data = resp.data; - if (obj.is_building_entrance == 'true' || obj.is_building_entrance === true) { obj.is_building_entrance = true; } else { obj.is_building_entrance = false; } - for (var c in $scope.myConnectionsHashT) { if ($scope.myConnectionsHashT.hasOwnProperty(c)) { if ($scope.myConnectionsHashT[c].pois_a == marker.model.puid || $scope.myConnectionsHashT[c].pois_b == marker.model.puid) { - var pa = $scope.myConnectionsHashT[c].pois_a; var pb = $scope.myConnectionsHashT[c].pois_b; - var flightPlanCoordinates = [ new google.maps.LatLng($scope.myPoisHashT[pa].model.coordinates_lat, $scope.myPoisHashT[pa].model.coordinates_lon), new google.maps.LatLng($scope.myPoisHashT[pb].model.coordinates_lat, $scope.myPoisHashT[pb].model.coordinates_lon) ]; - $scope.myConnectionsHashT[c].polyLine.setPath(flightPlanCoordinates); $scope.anyService.setAllConnection($scope.myConnectionsHashT); $scope.anyService.setAllPois($scope.myPoisHashT); } } } - }, function (resp) { ShowError($scope, resp, "Something went wrong while moving POI.", true); @@ -1421,12 +1293,14 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS + '' + '' + '' + + '
' + '
Or enter your one type name:' + '' + '
' + '
' + ' is building entrance?' + '
' + + '
' + '
' + '
' + '
' + + '
' + '
Or enter your one type name:' + '' + '
' + '
' + ' is building entrance?' + '
' + + '
' + '
' + '
' + '
- - + + - + @@ -194,16 +193,16 @@
- + - + - + - + @@ -259,7 +258,7 @@
diff --git a/server/public/anyplace_architect/package-lock.json b/server/public/anyplace_architect/package-lock.json index c270fa039..9684e9b6d 100644 --- a/server/public/anyplace_architect/package-lock.json +++ b/server/public/anyplace_architect/package-lock.json @@ -2630,17 +2630,6 @@ "which": "~1.3.0" } }, - "grunt-notify": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/grunt-notify/-/grunt-notify-0.4.5.tgz", - "integrity": "sha1-BSk5kGFhENtrwK0V5sBZL/4YrDE=", - "dev": true, - "requires": { - "semver": "^5.1.0", - "stack-parser": "^0.0.1", - "which": "^1.2.4" - } - }, "gulp-uglify-es": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/gulp-uglify-es/-/gulp-uglify-es-2.0.0.tgz", @@ -4984,12 +4973,6 @@ "dev": true, "optional": true }, - "stack-parser": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/stack-parser/-/stack-parser-0.0.1.tgz", - "integrity": "sha1-fTtjoXiH6eLCv1Xb0zGP40o50ec=", - "dev": true - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", diff --git a/server/public/anyplace_developers/.gitignore b/server/public/anyplace_developers/.gitignore deleted file mode 100644 index b31610996..000000000 --- a/server/public/anyplace_developers/.gitignore +++ /dev/null @@ -1 +0,0 @@ -anyplace.json diff --git a/server/public/anyplace_developers/README.md b/server/public/anyplace_developers/README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/server/public/anyplace_developers/anyplace.json b/server/public/anyplace_developers/anyplace.json deleted file mode 100644 index d9b4544b8..000000000 --- a/server/public/anyplace_developers/anyplace.json +++ /dev/null @@ -1,1557 +0,0 @@ -{ - "globals": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "get_token_from_architect", - "description": "You can find your API key (access_token) by signing in Anyplace Architect, in the \"More\" section." - } - ], - "baseurl": "https://ap.cs.ucy.ac.cy/anyplace", - "endpoints": [ - { - "name": "Navigation", - "description": "Get navigation information between Points of Interest using AnyPlace services.", - "methods": [ - { - "method_name": "POI Details", - "method_description": "Get Point of Interest details", - "http_method": "POST", - "uri": "/navigation/pois/id", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "pois", - "required": "Y", - "type": "text", - "default": "", - "description": "POI id (puid)" - } - ] - }, - { - "method_name": "Navigation Route Coordinates-to-Poi", - "method_description": "Get Navigation instructions from a given location to a POI", - "http_method": "POST", - "uri": "/navigation/route_xy", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "pois_to", - "required": "Y", - "type": "text", - "default": "", - "description": "Destination POI id (puid)" - }, - { - "name": "buid", - "required": "N", - "type": "text", - "default": "", - "description": "Source location building id" - }, - { - "name": "floor_number", - "required": "Y", - "type": "text", - "default": "", - "description": "Source location floor number" - }, - { - "name": "coordinates_lat", - "required": "Y", - "type": "text", - "default": "", - "description": "Source location latitude" - }, - { - "name": "coordinates_lon", - "required": "Y", - "type": "text", - "default": "", - "description": "Source location lonigitude" - } - ] - }, - { - "method_name": "Navigation Route Poi-to-Poi", - "method_description": "Get Navigation instructions between 2 POIs", - "http_method": "POST", - "uri": "/navigation/route", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "pois_from", - "required": "Y", - "type": "text", - "default": "", - "description": "Source POI id (puid)" - }, - { - "name": "pois_to", - "required": "Y", - "type": "text", - "default": "", - "description": "Destination POI id (puid)" - } - ] - } - ] - }, - { - "name": "Mapping (Public)", - "description": "Getters | Mapping information and API calls to add building / floor / POI / connection.", - "methods": [ - { - "method_name": "World Buildings", - "method_description": "Get all annotated buildings", - "http_method": "POST", - "uri": "/mapping/building/all", - "parameters": [ - ] - }, - - { - "method_name": "Buildings By Campus Code", - "method_description": "Get all buildings for a campus", - "http_method": "POST", - "uri": "/mapping/campus/all_cucode", - "parameters": [ - { - "name": "cuid", - "required": "Y", - "type": "text", - "default": "", - "description": "Your Campus ID" - } - ] - }, - { - "method_name": "Buildings By Building Code", - "method_description": "Get all buildings with the same code", - "http_method": "POST", - "uri": "/mapping/building/all_bucode", - "parameters": [ - ] - }, - { - "method_name": "NearBy Buildings", - "method_description": "Get annotated buildings near you (50 meters radius)", - "http_method": "POST", - "uri": "/mapping/building/coordinates", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "coordinates_lat", - "required": "Y", - "type": "text", - "default": "", - "description": "Your Location latitude" - }, - { - "name": "coordinates_lon", - "required": "Y", - "type": "text", - "default": "", - "description": "Your location longitude" - } - ] - }, - { - "method_name": "All building floors", - "method_description": "Get all floors of a building", - "http_method": "POST", - "uri": "/mapping/floor/all", - "parameters": [ - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - } - ] - }, - { - "method_name": "POIs by building", - "method_description": "Get all POIs inside a building", - "http_method": "POST", - "uri": "/mapping/pois/all_building", - "parameters": [ - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - } - ] - }, - { - "method_name": "POIs by floor", - "method_description": "Get all POIs inside a floor", - "http_method": "POST", - "uri": "/mapping/pois/all_floor", - "parameters": [ - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor_number", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - } - ] - }, - { - "method_name": "Connections by floor", - "method_description": "Get all POI connecitons inside a floor", - "http_method": "POST", - "uri": "/mapping/connection/all_floor", - "parameters": [ - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor_number", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - } - ] - }, - { - "method_name": "Radio Heat-Map by floor", - "method_description": "Get all points (latitude, longitude) along with their number of Wi-Fi radio measurements recorded to draw a heat-map on the client side.", - "http_method": "POST", - "uri": "/mapping/radio/heatmap_building_floor ", - "parameters": [ - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - } - ] - }, - { - "method_name": "Radio Heat-Map in Box", - "method_description": "Get all heat-map points.", - "http_method": "POST", - "uri": "/mapping/radio/radio_heatmap_bbox ", - "parameters": [ - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - }, - { - "name": "coordinates_lat", - "required": "Y", - "type": "text" - }, - { - "name": "coordinates_lon", - "required": "Y", - "type": "text" - }, - { - "name": "range", - "required": "Y", - "type": "text" - }, - { - "name": "weight", - "required": "Y", - "type": "text", - "default": "", - "description": "Choices : 1.true,2.false,3.no spatial" - } - ] - } - ] - }, - { - "name": "Blueprints", - "description": "Download the blueprints of a building floor", - "methods": [ - { - "method_name": "Download Base64", - "method_description": "Downloads the floor plan in a base64 png format (w/o prefix)", - "http_method": "POST", - "uri": "/floorplans64/:buid/:floor_number ", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor_number", - "required": "Y", - "type": "text", - "default": "", - "description": "Building floor number" - } - ] - }, - { - "method_name": "Download Tiles", - "method_description": "Fetches the floor plan tiles zip link", - "http_method": "POST", - "uri": "/floortiles/:buid/:floor_number ", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor_number", - "required": "Y", - "type": "text", - "default": "", - "description": "Building floor number" - } - ] - } - ] - }, - { - "name": "Mapping (Authorization required)", - "description": "Modifiers | Add building / floor / POI / connection.", - "methods": [ - { - "method_name": "Add building", - "method_description": "Add a new building", - "http_method": "POST", - "uri": "/mapping/building/add", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "is_published", - "required": "Y", - "type": "boolean" - }, - { - "name": "name", - "required": "Y", - "type": "text" - }, - { - "name": "description", - "required": "Y", - "type": "text" - }, - { - "name": "url", - "required": "Y", - "type": "text", - "default": "-" - }, - { - "name": "address", - "required": "Y", - "type": "text", - "default": "-" - }, - { - "name": "coordinates_lat", - "required": "Y", - "type": "text" - }, - { - "name": "coordinates_lon", - "required": "Y", - "type": "text" - } - ] - }, - { - "method_name": "Add campus", - "method_description": "Add a new campus", - "http_method": "POST", - "uri": "/mapping/campus/add", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "name", - "required": "Y", - "type": "text" - }, - { - "name": "description", - "required": "Y", - "type": "text" - }, - { - "name": "buids", - "required": "Y", - "type": "text" - } - ] - }, - { - "method_name": "Update building", - "method_description": "Update an existing building", - "http_method": "POST", - "uri": "/mapping/building/update", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text" - }, - { - "name": "is_published", - "required": "N", - "type": "boolean" - }, - { - "name": "name", - "required": "N", - "type": "text" - }, - { - "name": "description", - "required": "N", - "type": "text" - }, - { - "name": "url", - "required": "N", - "type": "text", - "default": "-" - }, - { - "name": "address", - "required": "N", - "type": "text", - "default": "-" - }, - { - "name": "coordinates_lat", - "required": "N", - "type": "text" - }, - { - "name": "coordinates_lon", - "required": "N", - "type": "text" - } - ] - }, - { - "method_name": "Update campus", - "method_description": "Update an existing campus", - "http_method": "POST", - "uri": "/mapping/campus/update", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "cuid", - "required": "Y", - "type": "text" - }, - { - "name": "name", - "required": "N", - "type": "text" - }, - { - "name": "description", - "required": "N", - "type": "text" - } - ] - }, - { - "method_name": "Delete building", - "method_description": "Delete an existing building", - "http_method": "POST", - "uri": "/mapping/building/delete", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text" - } - ] - }, - { - "method_name": "Delete campus", - "method_description": "Delete an existing campus", - "http_method": "POST", - "uri": "/mapping/campus/delete", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "cuid", - "required": "Y", - "type": "text" - } - ] - }, - { - "method_name": "Add floor", - "method_description": "Add a new floor", - "http_method": "POST", - "uri": "/mapping/floor/add", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text" - }, - { - "name": "is_published", - "required": "Y", - "type": "boolean", - "default": true - }, - { - "name": "description", - "required": "Y", - "type": "text", - "default": true - }, - { - "name": "floor_name", - "required": "Y", - "type": "text", - "default": true - }, - { - "name": "floor_number", - "required": "Y", - "type": "text" - } - ] - }, - { - "method_name": "Update floor", - "method_description": "Update an existing floor", - "http_method": "POST", - "uri": "/mapping/floor/update", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text" - }, - { - "name": "description", - "required": "N", - "type": "text", - "default": true - }, - { - "name": "floor_name", - "required": "N", - "type": "text", - "default": true - }, - { - "name": "floor_number", - "required": "Y", - "type": "text" - } - ] - }, - { - "method_name": "Delete floor", - "method_description": "Delete an existing floor", - "http_method": "POST", - "uri": "/mapping/floor/delete", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text" - }, - { - "name": "floor_number", - "required": "Y", - "type": "text" - } - ] - }, - { - "method_name": "Add poi", - "method_description": "Add a new poi", - "http_method": "POST", - "uri": "/mapping/pois/add", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text" - }, - { - "name": "floor_name", - "required": "Y", - "type": "text" - }, - { - "name": "floor_number", - "required": "Y", - "type": "text" - }, - { - "name": "name", - "required": "Y", - "type": "text" - }, - { - "name": "description", - "required": "N", - "type": "text", - "default": "-" - }, - { - "name": "is_door", - "required": "Y", - "type": "boolean", - "default": false - }, - { - "name": "is_building_entrance", - "required": "Y", - "type": "boolean", - "default": false - }, - { - "name": "coordinates_lat", - "required": "Y", - "type": "text" - }, - { - "name": "coordinates_lon", - "required": "Y", - "type": "text" - }, - { - "name": "is_published", - "required": "Y", - "type": "boolean", - "default": true - } - ] - }, - { - "method_name": "Update poi", - "method_description": "Update an existing point of interest", - "http_method": "POST", - "uri": "/mapping/pois/update", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "puid", - "required": "Y", - "type": "text" - }, - { - "name": "buid", - "required": "Y", - "type": "text" - }, - { - "name": "floor_name", - "required": "N", - "type": "text" - }, - { - "name": "floor_number", - "required": "N", - "type": "text" - }, - { - "name": "name", - "required": "N", - "type": "text" - }, - { - "name": "description", - "required": "N", - "type": "text", - "default": "-" - }, - { - "name": "is_door", - "required": "N", - "type": "boolean", - "default": false - }, - { - "name": "is_building_entrance", - "required": "N", - "type": "boolean", - "default": false - }, - { - "name": "coordinates_lat", - "required": "N", - "type": "text" - }, - { - "name": "coordinates_lon", - "required": "N", - "type": "text" - } - ] - }, - { - "method_name": "Delete poi", - "method_description": "Delete an existing point of interest", - "http_method": "POST", - "uri": "/mapping/pois/delete", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "puid", - "required": "Y", - "type": "text" - }, - { - "name": "buid", - "required": "Y", - "type": "text" - } - ] - }, - { - "method_name": "Add connection", - "method_description": "Add a new connection between 2 poi", - "http_method": "POST", - "uri": "/mapping/connection/add", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "pois_a", - "required": "Y", - "type": "text" - }, - { - "name": "floor_a", - "required": "Y", - "type": "text" - }, - { - "name": "pois_b", - "required": "Y", - "type": "text" - }, - { - "name": "floor_b", - "required": "Y", - "type": "text" - }, - { - "name": "buid_a", - "required": "Y", - "type": "text" - }, - { - "name": "buid_b", - "required": "Y", - "type": "text" - }, - { - "name": "buid", - "required": "Y", - "type": "text" - }, - { - "name": "edge_type", - "required": "Y", - "type": "text", - "default": "indoors" - }, - { - "name": "is_published", - "required": "Y", - "type": "boolean", - "default": true - } - ] - }, - { - "method_name": "Update connection", - "method_description": "Update an existing connection", - "http_method": "POST", - "uri": "/mapping/connection/update", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "pois_a", - "required": "Y", - "type": "text" - }, - { - "name": "pois_b", - "required": "Y", - "type": "text" - }, - { - "name": "buid_a", - "required": "Y", - "type": "text" - }, - { - "name": "buid_b", - "required": "Y", - "type": "text" - }, - { - "name": "edge_type", - "required": "N", - "type": "text" - } - ] - }, - { - "method_name": "Delete connection", - "method_description": "Delete an existing connection", - "http_method": "POST", - "uri": "/mapping/connection/delete", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "pois_a", - "required": "Y", - "type": "text" - }, - { - "name": "pois_b", - "required": "Y", - "type": "text" - }, - { - "name": "buid_a", - "required": "Y", - "type": "text" - }, - { - "name": "buid_b", - "required": "Y", - "type": "text" - } - ] - } - ] - }, - { - "name": "Position", - "description": "Radio Map related API calls", - "methods": [ - { - "method_name": "Upload RSS Log", - "method_description": "Upload the rss log with measurements", - "http_method": "POST", - "uri": "/position/radio_upload", - "form_json_name": "json", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "radiomap", - "required": "Y", - "type": "file", - "default": "", - "description": "The rss-log file with measurements" - } - ] - }, - { - "method_name": "Radiomap by coordinates and floor", - "method_description": "Radiomap using all the entries near the coordinate parameters", - "http_method": "POST", - "uri": "/position/radio_download_floor", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "coordinates_lat", - "required": "Y", - "type": "text", - "default": "", - "description": "Your location latitude" - }, - { - "name": "coordinates_lon", - "required": "Y", - "type": "text", - "default": "", - "description": "Your location lonigtude" - }, - { - "name": "floor_number", - "required": "Y", - "type": "text", - "default": "", - "description": "Your location floor number" - } - ] - }, - { - "method_name": "Radiomap by building and floor", - "method_description": "Radiomap using all the entries of an entire floor of a building", - "http_method": "POST", - "uri": "/position/radio_by_building_floor", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Your location floor number" - } - ] - }, - { - "method_name": "Radiomap by building and floor in a range", - "method_description": "Radiomap using all the entries of an entire floor of a building", - "http_method": "POST", - "uri": "/position/radio_by_building_floor_bbox", - "parameters": [ - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - }, - { - "name": "coordinates_lat", - "required": "Y", - "type": "text" - }, - { - "name": "coordinates_lon", - "required": "Y", - "type": "text" - }, - { - "name": "range", - "required": "Y", - "type": "text" - } - ] - }, - { - "method_name": "Estimate the user's position using APs", - "method_description": "Estimate the location of the user. ", - "http_method": "POST", - "uri": "/position/estimate_position", - "parameters": [ - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - }, - { - "name": "APs", - "required": "Y", - "type": "List[JsValue]", - "description": "APs as for example [{\"bssid\":,\"rss\": -40},..]" - }, - { - "name": "algorithm_choice", - "required": "Y", - "type": "integer", - "description": "choices: KNN_WKNN_Algorithm (1 for non weighted, 2 for weighted), MAP_MMSE_Algorithm (3 for non weighted, 4 for weighted) " - } - ] - }, - { - "method_name": "Radio Heat-Map by floor High-level Clustering", - "method_description": "Get all heat-map points for High-level Clustering.", - "http_method": "POST", - "uri": "/position/radio/heatmap_building_floor_average_1 ", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - } - ] - }, - { - "method_name": "Radio Heat-Map by floor Medium-level Clustering", - "method_description": "Get all heat-map points for Medium-level Clustering.", - "http_method": "POST", - "uri": "/position/radio/heatmap_building_floor_average_2 ", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - } - ] - }, - { - "method_name": "Radio Heat-Map by floor Low-level Clustering", - "method_description": "Get all heat-map points for Low-level Clustering.", - "http_method": "POST", - "uri": "/position/radio/heatmap_building_floor_average_3 ", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - } - ] - }, - { - "method_name": "Timestamps of Wi-Fi radio measurements by floor ", - "method_description": "Get the number of Wi-Fi radio measurements based on their timestamp.", - "http_method": "POST", - "uri": "/position/radio/time ", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - } - ] - }, - { - "method_name": "Radio Heat-Map by timestamp range High-level Clustering", - "method_description": "Get all heat-map points based on timestamps for High-level Clustering.", - "http_method": "POST", - "uri": "/position/radio/heatmap_building_floor_timestamp_average_1 ", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - }, - { - "name": "timestampX", - "required": "Y", - "type": "text", - "default": "", - "description": "Start timestamp (non-whitespace)" - }, - { - "name": "timestampY", - "required": "Y", - "type": "text", - "default": "", - "description": "End timestamp (non-whitespace)" - } - ] - }, - { - "method_name": "Radio Heat-Map by timestamp range Medium-level Clustering", - "method_description": "Get all heat-map points based on timestamps for Medium-level Clustering.", - "http_method": "POST", - "uri": "/position/radio/heatmap_building_floor_timestamp_average_2 ", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - }, - { - "name": "timestampX", - "required": "Y", - "type": "text", - "default": "", - "description": "Start timestamp (non-whitespace)" - }, - { - "name": "timestampY", - "required": "Y", - "type": "text", - "default": "", - "description": "End timestamp (non-whitespace)" - } - ] - }, - { - "method_name": "Radio Heat-Map by timestamp range Low-level Clustering", - "method_description": "Get all heat-map points based on timestamps for Low-level Clustering.", - "http_method": "POST", - "uri": "/position/radio/heatmap_building_floor_timestamp_average_3 ", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - }, - { - "name": "timestampX", - "required": "Y", - "type": "text", - "default": "", - "description": "Start timestamp (non-whitespace)" - }, - { - "name": "timestampY", - "required": "Y", - "type": "text", - "default": "", - "description": "End timestamp (non-whitespace)" - } - ] - }, - { - "method_name": "Access Points by floor", - "method_description": "Get all estimated Access Point positions.", - "http_method": "POST", - "uri": "/position/radio/APs_building_floor ", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - } - ] - }, - { - "method_name": "Access Points Manufacturer by floor", - "method_description": "Get the manufacturers of the requested APs.", - "http_method": "POST", - "uri": "/position/radio/aps_ids ", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "ids", - "required": "Y", - "type": "", - "description": "MAC addresses of required Access Points" - } - ] - }, - { - "method_name": "Delete Wi-Fi radio measurements by range ", - "method_description": "Delete required points of Wi-Fi radio measurements.", - "http_method": "POST", - "uri": "/position/radio/delete ", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - }, - { - "name": "lat1", - "required": "Y", - "type": "text", - "default": "", - "description": "Start Latitude (y1) " - }, - { - "name": "lon1", - "required": "Y", - "type": "text", - "default": "", - "description": "Start Longitude (x1)" - }, - { - "name": "lat2", - "required": "Y", - "type": "text", - "default": "", - "description": "End Latitude (y2) " - }, - { - "name": "lon2", - "required": "Y", - "type": "text", - "default": "", - "description": "End Longitude (x2)" - } - ] - }, - { - "method_name": "Acces Heat-Map by floor", - "method_description": "Get the accuracy of all estimated positions.", - "http_method": "POST", - "uri": "/position/radio/acces ", - "parameters": [ - { - "name": "access_token", - "required": "Y", - "type": "text", - "default": "api_tester", - "description": "OAuth2 Access Token" - }, - { - "name": "buid", - "required": "Y", - "type": "text", - "default": "", - "description": "Building ID (buid)" - }, - { - "name": "floor", - "required": "Y", - "type": "text", - "default": "", - "description": "Floor number (non-whitespace)" - } - ] - } - ] - } - ] -} diff --git a/server/public/anyplace_developers/images/00.png b/server/public/anyplace_developers/images/00.png deleted file mode 100644 index f689f5d3e..000000000 Binary files a/server/public/anyplace_developers/images/00.png and /dev/null differ diff --git a/server/public/anyplace_developers/images/anyplace_logo_text3_2.png b/server/public/anyplace_developers/images/anyplace_logo_text3_2.png deleted file mode 100644 index 431a8e9de..000000000 Binary files a/server/public/anyplace_developers/images/anyplace_logo_text3_2.png and /dev/null differ diff --git a/server/public/anyplace_developers/images/anyplace_logo_text3_3.png b/server/public/anyplace_developers/images/anyplace_logo_text3_3.png deleted file mode 100644 index e1f5f842c..000000000 Binary files a/server/public/anyplace_developers/images/anyplace_logo_text3_3.png and /dev/null differ diff --git a/server/public/anyplace_developers/images/anyplace_logo_text3_4.png b/server/public/anyplace_developers/images/anyplace_logo_text3_4.png deleted file mode 100644 index b58d8ebd4..000000000 Binary files a/server/public/anyplace_developers/images/anyplace_logo_text3_4.png and /dev/null differ diff --git a/server/public/anyplace_developers/images/anyplace_logo_text_white.png b/server/public/anyplace_developers/images/anyplace_logo_text_white.png deleted file mode 100644 index fb5cdb1a6..000000000 Binary files a/server/public/anyplace_developers/images/anyplace_logo_text_white.png and /dev/null differ diff --git a/server/public/anyplace_developers/images/anyplace_logo_text_white3_2.png b/server/public/anyplace_developers/images/anyplace_logo_text_white3_2.png deleted file mode 100644 index ea53a6071..000000000 Binary files a/server/public/anyplace_developers/images/anyplace_logo_text_white3_2.png and /dev/null differ diff --git a/server/public/anyplace_developers/images/anyplace_logo_text_white3_3.png b/server/public/anyplace_developers/images/anyplace_logo_text_white3_3.png deleted file mode 100644 index 5812292f8..000000000 Binary files a/server/public/anyplace_developers/images/anyplace_logo_text_white3_3.png and /dev/null differ diff --git a/server/public/anyplace_developers/images/anyplace_logo_text_white_.png b/server/public/anyplace_developers/images/anyplace_logo_text_white_.png deleted file mode 100644 index 8ad1a5467..000000000 Binary files a/server/public/anyplace_developers/images/anyplace_logo_text_white_.png and /dev/null differ diff --git a/server/public/anyplace_developers/index.html b/server/public/anyplace_developers/index.html deleted file mode 100644 index 7f2a1ac39..000000000 --- a/server/public/anyplace_developers/index.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - AnyPlace Developers - - - - - - - - - -
-
- -
-

Global Parameters

— These parameters will globally override method parameters if changed. -
- -
-
    -
-
- -
-
- - - - - - - diff --git a/server/public/anyplace_developers/main.dart.js b/server/public/anyplace_developers/main.dart.js deleted file mode 100644 index 3accc0fe0..000000000 --- a/server/public/anyplace_developers/main.dart.js +++ /dev/null @@ -1,4234 +0,0 @@ -// Generated by dart2js, the Dart to JavaScript compiler. -(function($){var A={} -delete A.x -var B={} -delete B.x -var C={} -delete C.x -var D={} -delete D.x -var E={} -delete E.x -var F={} -delete F.x -var G={} -delete G.x -var H={} -delete H.x -var J={} -delete J.x -var K={} -delete K.x -var L={} -delete L.x -var M={} -delete M.x -var N={} -delete N.x -var O={} -delete O.x -var P={} -delete P.x -var Q={} -delete Q.x -var R={} -delete R.x -var S={} -delete S.x -var T={} -delete T.x -var U={} -delete U.x -var V={} -delete V.x -var W={} -delete W.x -var X={} -delete X.x -var Y={} -delete Y.x -var Z={} -delete Z.x -function I(){} -init() -$=I.p -var $$={} -$$.YP=[H,{"":"v;wc,nn,lv,Pp", -call$0:function(){return this.nn.call(this.wc,this.lv)}}] -$$.Pm=[H,{"":"v;wc,nn,lv,Pp", -call$1:function(a){return this.nn.call(this.wc,a)}, -$is_aB:true}] -$$.CQ=[P,{"":"v;wc,nn,lv,Pp", -call$2:function(a,b){return this.nn.call(this.wc,a,b)}, -call$1:function(a){return this.call$2(a,null)}, -$is_bh:true, -$is_aB:true}] -$$.EV=[P,{"":"v;wc,nn,lv,Pp", -call$0:function(){return this.nn.call(this.wc)}}] -$$.C7=[W,{"":"v;wc,nn,lv,Pp", -call$1:function(a){return this.nn.call(this.wc,this.lv,a)}, -$is_aB:true}] -$$.Wv=[H,{"":"Tp;call$2,$name",$is_bh:true}] -$$.yh=[H,{"":"Tp;call$0,$name"}] -$$.Pz=[H,{"":"Tp;call$7,$name"}] -$$.vE=[T,{"":"Tp;call$1,$name",$is_aB:true}] -$$.zy=[P,{"":"Tp;call$2,$name", -call$1:function(a){return this.call$2(a,null)}, -$is_bh:true, -$is_aB:true}] -$$.kq=[W,{"":"Tp;call$4,$name"}] -;(function (reflectionData) { - function map(x){x={x:x};delete x.x;return x} - if (!init.libraries) init.libraries = []; - if (!init.mangledNames) init.mangledNames = map(); - if (!init.mangledGlobalNames) init.mangledGlobalNames = map(); - if (!init.statics) init.statics = map(); - if (!init.typeInformation) init.typeInformation = map(); - if (!init.globalFunctions) init.globalFunctions = map(); - var libraries = init.libraries; - var mangledNames = init.mangledNames; - var mangledGlobalNames = init.mangledGlobalNames; - var hasOwnProperty = Object.prototype.hasOwnProperty; - var length = reflectionData.length; - for (var i = 0; i < length; i++) { - var data = reflectionData[i]; - var name = data[0]; - var uri = data[1]; - var metadata = data[2]; - var globalObject = data[3]; - var descriptor = data[4]; - var isRoot = !!data[5]; - var fields = descriptor && descriptor[""]; - var classes = []; - var functions = []; - function processStatics(descriptor) { - for (var property in descriptor) { - if (!hasOwnProperty.call(descriptor, property)) continue; - if (property === "") continue; - var element = descriptor[property]; - var firstChar = property.substring(0, 1); - var previousProperty; - if (firstChar === "+") { - mangledGlobalNames[previousProperty] = property.substring(1); - if (descriptor[property] == 1) descriptor[previousProperty].$reflectable = 1; - if (element && element.length) init.typeInformation[previousProperty] = element; - } else if (firstChar === "@") { - property = property.substring(1); - $[property]["@"] = element; - } else if (firstChar === "*") { - globalObject[previousProperty].$defaultValues = element; - var optionalMethods = descriptor.$methodsWithOptionalArguments; - if (!optionalMethods) { - descriptor.$methodsWithOptionalArguments = optionalMethods = {} - } - optionalMethods[property] = previousProperty; - } else if (typeof element === "function") { - globalObject[previousProperty = property] = element; - functions.push(property); - init.globalFunctions[property] = element; - } else { - previousProperty = property; - var newDesc = {}; - var previousProp; - for (var prop in element) { - if (!hasOwnProperty.call(element, prop)) continue; - firstChar = prop.substring(0, 1); - if (prop === "static") { - processStatics(init.statics[property] = element[prop]); - } else if (firstChar === "+") { - mangledNames[previousProp] = prop.substring(1); - if (element[prop] == 1) element[previousProp].$reflectable = 1; - } else if (firstChar === "@" && prop !== "@") { - newDesc[prop.substring(1)]["@"] = element[prop]; - } else if (firstChar === "*") { - newDesc[previousProp].$defaultValues = element[prop]; - var optionalMethods = newDesc.$methodsWithOptionalArguments; - if (!optionalMethods) { - newDesc.$methodsWithOptionalArguments = optionalMethods={} - } - optionalMethods[prop] = previousProp; - } else { - newDesc[previousProp = prop] = element[prop]; - } - } - $$[property] = [globalObject, newDesc]; - classes.push(property); - } - } - } - processStatics(descriptor); - libraries.push([name, uri, classes, functions, metadata, fields, isRoot, - globalObject]); - } -})([["_foreign_helper","dart:_foreign_helper",,H,{FK:{"":"a;tT"}}],["_interceptors","dart:_interceptors",,J,{x:function(a){return void 0},Qu:function(a,b,c,d){return{i: a, p: b, e: c, x: d}},ks:function(a){var z,y,x,w -z=a[init.dispatchPropertyName] -if(z==null)if($.Bv==null){H.XD() -z=a[init.dispatchPropertyName]}if(z!=null){y=z.p -if(!1===y)return z.i -if(!0===y)return a -x=Object.getPrototypeOf(a) -if(y===x)return z.i -if(z.e===x)throw H.b(P.SY("Return interceptor for "+H.d(y(a,z))))}w=H.w3(a) -if(w==null)return C.vB -return w},Gv:{"":"a;", -n:function(a,b){return a===b}, -giO:function(a){return H.eQ(a)}, -bu:function(a){return H.a5(a)}, -"%":"DOMError|DOMImplementation|FileError|FormData|MediaError|MediaKeyError|Navigator|NavigatorUserMediaError|PositionError|SQLError|SVGAnimatedNumberList|SVGAnimatedString"},kn:{"":"bool/Gv;", -bu:function(a){return String(a)}, -giO:function(a){return a?519018:218159}, -$isbool:true},PE:{"":"Gv;", -n:function(a,b){return null==b}, -bu:function(a){return"null"}, -giO:function(a){return 0}},Ue:{"":"Gv;", -giO:function(a){return 0}},iC:{"":"Ue;"},is:{"":"Ue;"},Q:{"":"List/Gv;", -h:function(a,b){if(!!a.fixed$length)H.vh(P.f("add")) -a.push(b)}, -FV:function(a,b){var z -for(z=new H.a7(b,b.length,0,null);z.G();)this.h(a,z.mD)}, -aN:function(a,b){return H.bQ(a,b)}, -Zv:function(a,b){if(b<0||b>=a.length)throw H.e(a,b) -return a[b]}, -XU:function(a,b,c){return H.Ub(a,b,c,a.length)}, -u8:function(a,b){return this.XU(a,b,0)}, -tg:function(a,b){var z -for(z=0;z=a.length||b<0)throw H.b(P.N(b)) -return a[b]}, -u:function(a,b,c){if(!!a.immutable$list)H.vh(P.f("indexed set")) -if(typeof b!=="number"||Math.floor(b)!==b)throw H.b(new P.AT(b)) -if(b>=a.length||b<0)throw H.b(P.N(b)) -a[b]=c}, -$isList:true, -$aszM:null, -$isList:true, -$isqC:true},nM:{"":"Q;",$isnM:true, -$asQ:function(){return[null]}, -$aszM:function(){return[null]}},tN:{"":"nM;"},Jt:{"":"nM;",$isJt:true},P:{"":"num/Gv;", -JV:function(a,b){return a%b}, -Vy:function(a){return Math.abs(a)}, -yu:function(a){var z -if(a>=-2147483648&&a<=2147483647)return a|0 -if(isFinite(a)){z=a<0?Math.ceil(a):Math.floor(a) -return z+0}throw H.b(P.f(''+a))}, -bu:function(a){if(a===0&&1/a<0)return"-0.0" -else return""+a}, -giO:function(a){return a&0x1FFFFFFF}, -g:function(a,b){if(typeof b!=="number")throw H.b(new P.AT(b)) -return a+b}, -Z:function(a,b){if((a|0)===a&&(b|0)===b&&0!==b&&-1!==b)return a/b|0 -else return this.ZP(a,b)}, -ZP:function(a,b){return this.yu(a/b)}, -m:function(a,b){if(b<0)throw H.b(P.u(b)) -if(a>0){if(b>31)return 0 -return a>>>b}if(b>31)b=31 -return a>>b>>>0}, -C:function(a,b){if(typeof b!=="number")throw H.b(P.u(b)) -return ab}, -F:function(a,b){if(typeof b!=="number")throw H.b(P.u(b)) -return a>=b}, -$isnum:true, -static:{"":"SA,nr",}},im:{"":"int/P;",$isnum:true,$isint:true},VA:{"":"double/P;",$isnum:true},O:{"":"String/Gv;", -j:function(a,b){if(typeof b!=="number"||Math.floor(b)!==b)throw H.b(P.u(b)) -if(b<0)throw H.b(P.N(b)) -if(b>=a.length)throw H.b(P.N(b)) -return a.charCodeAt(b)}, -dd:function(a,b){return H.ZT(a,b)}, -g:function(a,b){if(typeof b!=="string")throw H.b(new P.AT(b)) -return a+b}, -h8:function(a,b,c){return H.ys(a,b,c)}, -Qi:function(a,b,c){var z -if(c<0||c>a.length)throw H.b(P.TE(c,0,a.length)) -z=c+b.length -if(z>a.length)return!1 -return b===a.substring(c,z)}, -nC:function(a,b){return this.Qi(a,b,0)}, -Nj:function(a,b,c){if(typeof b!=="number"||Math.floor(b)!==b)H.vh(P.u(b)) -if(c==null)c=a.length -if(typeof c!=="number"||Math.floor(c)!==c)H.vh(P.u(c)) -if(b<0)throw H.b(P.N(b)) -if(typeof c!=="number")throw H.s(c) -if(b>c)throw H.b(P.N(b)) -if(c>a.length)throw H.b(P.N(c)) -return a.substring(b,c)}, -yn:function(a,b){return this.Nj(a,b,null)}, -hc:function(a){return a.toLowerCase()}, -bS:function(a){var z,y,x,w,v -for(z=a.length,y=0;y=z)H.vh(P.N(y)) -x=a.charCodeAt(y) -if(x===32||x===13||J.Ga(x))++y -else break}if(y===z)return"" -for(w=z;!0;w=v){v=w-1 -if(v<0)H.vh(P.N(v)) -if(v>=z)H.vh(P.N(v)) -x=a.charCodeAt(v) -if(x===32||x===13||J.Ga(x));else break}if(y===0&&w===z)return a -return a.substring(y,w)}, -XU:function(a,b,c){if(typeof c!=="number"||Math.floor(c)!==c)throw H.b(new P.AT(c)) -if(c<0||c>a.length)throw H.b(P.TE(c,0,a.length)) -return a.indexOf(b,c)}, -u8:function(a,b){return this.XU(a,b,0)}, -Is:function(a,b,c){if(c<0||c>a.length)throw H.b(P.TE(c,0,a.length)) -return H.m2(a,b,c)}, -tg:function(a,b){return this.Is(a,b,0)}, -gl0:function(a){return a.length===0}, -bu:function(a){return a}, -giO:function(a){var z,y,x -for(z=a.length,y=0,x=0;x>>0) -y^=y>>6}y=536870911&y+((67108863&y)<<3>>>0) -y^=y>>11 -return 536870911&y+((16383&y)<<15>>>0)}, -gB:function(a){return a.length}, -t:function(a,b){if(typeof b!=="number"||Math.floor(b)!==b)throw H.b(new P.AT(b)) -if(b>=a.length||b<0)throw H.b(P.N(b)) -return a[b]}, -$isString:true, -static:{Ga:function(a){if(a<256)switch(a){case 9:case 10:case 11:case 12:case 13:case 32:case 133:case 160:return!0 -default:return!1}switch(a){case 5760:case 6158:case 8192:case 8193:case 8194:case 8195:case 8196:case 8197:case 8198:case 8199:case 8200:case 8201:case 8202:case 8232:case 8233:case 8239:case 8287:case 12288:case 65279:return!0 -default:return!1}}}}}],["_isolate_helper","dart:_isolate_helper",,H,{zd:function(a,b){var z=a.vV(b) -$globalState.Xz.bL() -return z},Rq:function(a){var z -$globalState=H.Zh(a) -if($globalState.EF===!0)return -z=H.TJ() -$globalState.yc=z -$globalState.N0=z -if(!!a.$is_aB)z.vV(new H.PK(a)) -else if(!!a.$is_bh)z.vV(new H.JO(a)) -else z.vV(a) -$globalState.Xz.bL()},Td:function(){var z=init.currentScript -if(z!=null)return String(z.src) -if(typeof version=="function"&&typeof os=="object"&&"system" in os)return H.ZV() -if(typeof version=="function"&&typeof system=="function")return thisFilename() -return},ZV:function(){var z,y -z=new Error().stack -if(z==null){z=(function() {try { throw new Error() } catch(e) { return e.stack }})() -if(z==null)throw H.b(P.f("No stack trace"))}y=z.match(new RegExp("^ *at [^(]*\\((.*):[0-9]*:[0-9]*\\)$","m")) -if(y!=null)return y[1] -y=z.match(new RegExp("^[^@]*@(.*):[0-9]*$","m")) -if(y!=null)return y[1] -throw H.b(P.f("Cannot extract URI from \""+z+"\""))},Mg:function(a,b){var z,y,x,w,v,u,t,s,r,q -z=H.Hh(b.data) -y=J.U6(z) -switch(y.t(z,"command")){case"start":$globalState.oL=y.t(z,"id") -x=y.t(z,"functionName") -w=x==null?$globalState.w2:init.globalFunctions[x] -v=y.t(z,"args") -u=H.Hh(y.t(z,"msg")) -t=y.t(z,"isSpawnUri") -s=H.Hh(y.t(z,"replyTo")) -r=H.TJ() -$globalState.Xz.Rk.NZ(new H.IY(r,new H.jl(w,v,u,t,s),"worker-start")) -$globalState.N0=r -$globalState.Xz.bL() -break -case"spawn-worker":H.oT(y.t(z,"functionName"),y.t(z,"uri"),y.t(z,"args"),y.t(z,"msg"),y.t(z,"isSpawnUri"),y.t(z,"replyPort")) -break -case"message":if(y.t(z,"port")!=null)J.jV(y.t(z,"port"),y.t(z,"msg")) -$globalState.Xz.bL() -break -case"close":y=$globalState.XC -q=$.p6() -y.Rz(y,q.t(q,a)) -a.terminate() -$globalState.Xz.bL() -break -case"log":H.VL(y.t(z,"msg")) -break -case"print":if($globalState.EF===!0){y=$globalState.vd -q=H.t0(H.B7(["command","print","msg",z],P.L5(null,null,null,null,null))) -y.toString -self.postMessage(q)}else P.JS(y.t(z,"msg")) -break -case"error":throw H.b(y.t(z,"msg")) -default:}},VL:function(a){var z,y,x,w -if($globalState.EF===!0){y=$globalState.vd -x=H.t0(H.B7(["command","log","msg",a],P.L5(null,null,null,null,null))) -y.toString -self.postMessage(x)}else try{$.jk().console.log(a)}catch(w){H.Ru(w) -z=new H.XO(w,null) -throw H.b(P.FM(z))}},Z7:function(a,b,c,d,e){var z -H.Ku($globalState.N0.jO) -$.Dz=H.Ty() -z=$.Dz -z.toString -J.jV(e,["spawned",new H.JM(z,$globalState.N0.jO)]) -if(d!==!0)a.call$1(c) -else{z=J.x(a) -if(!!z.$is_bh)a.call$2(b,c) -else if(!!z.$is_aB)a.call$1(b) -else a.call$0()}},oT:function(a,b,c,d,e,f){var z,y,x -if(b==null)b=$.Rs() -z=new Worker(b) -z.onmessage=function(e) { H.NB.call$2(z, e); } -y=$globalState -x=y.Y7 -y.Y7=x+1 -y=$.p6() -y.u(y,z,x) -y=$globalState.XC -y.u(y,x,z) -z.postMessage(H.t0(H.B7(["command","start","id",x,"replyTo",H.t0(f),"args",c,"msg",H.t0(d),"isSpawnUri",e,"functionName",a],P.L5(null,null,null,null,null))))},ff:function(a,b){var z=H.ZF() -z.h7(a) -P.pH(z.Gx).ml(new H.yc(b))},t0:function(a){var z -if($globalState.ji===!0){z=new H.Bj(0,new H.X1()) -z.iq=new H.fP(null) -return z.h7(a)}else{z=new H.NO(new H.X1()) -z.iq=new H.fP(null) -return z.h7(a)}},Hh:function(a){if($globalState.ji===!0)return new H.II(null).QS(a) -else return a},vM:function(a){return a==null||typeof a==="string"||typeof a==="number"||typeof a==="boolean"},uu:function(a){return a==null||typeof a==="string"||typeof a==="number"||typeof a==="boolean"},PK:{"":"Tp;a", -call$0:function(){this.a.call$1([])}},JO:{"":"Tp;b", -call$0:function(){this.b.call$2([],null)}},O2:{"":"a;Hg,oL,Y7,N0,yc,Xz,Ai,EF,ji,i2,vd,XC,w2", -N1:function(){var z,y -z=$.C5()==null -y=$.Nl() -this.EF=z&&$.Iz()===!0 -if(this.EF!==!0)y=y!=null&&$.Rs()!=null -else y=!0 -this.ji=y -this.Ai=z&&this.EF!==!0}, -hn:function(){var z=function (e) { H.NB.call$2(this.vd, e); } -$.jk().onmessage=z -$.jk().dartPrint = function (object) {}}, -i6:function(a){this.N1() -this.Xz=new H.cC(P.NZ(null,H.IY),0) -this.i2=P.L5(null,null,null,J.im,H.aX) -this.XC=P.L5(null,null,null,J.im,null) -if(this.EF===!0){this.vd=new H.JH() -this.hn()}}, -static:{Zh:function(a){var z=new H.O2(0,0,1,null,null,null,null,null,null,null,null,null,a) -z.i6(a) -return z}}},aX:{"":"a;jO,Gx,En<", -vV:function(a){var z,y -z=$globalState.N0 -$globalState.N0=this -$=this.En -y=null -try{y=a.call$0()}finally{$globalState.N0=z -if(z!=null)$=z.gEn()}return y}, -Zt:function(a){var z=this.Gx -return z.t(z,a)}, -mg:function(a,b,c){var z -if(this.Gx.x4(b))throw H.b(P.FM("Registry: ports must be registered only once.")) -z=this.Gx -z.u(z,b,c) -z=$globalState.i2 -z.u(z,this.jO,this)}, -IJ:function(a){var z=this.Gx -z.Rz(z,a) -if(this.Gx.X5===0){z=$globalState.i2 -z.Rz(z,this.jO)}}, -iZ:function(){var z,y -z=$globalState -y=z.Hg -z.Hg=y+1 -this.jO=y -this.Gx=P.L5(null,null,null,J.im,P.rR) -this.En=new I()}, -static:{TJ:function(){var z=new H.aX(null,null,null) -z.iZ() -return z}}},cC:{"":"a;Rk,bZ", -mj:function(){var z=this.Rk -if(z.av===z.HV)return -return z.Ux()}, -LM:function(){if($globalState.yc!=null&&$globalState.i2.x4($globalState.yc.jO)&&$globalState.Ai===!0&&$globalState.yc.Gx.X5===0)throw H.b(P.FM("Program exited with open ReceivePorts."))}, -xB:function(){var z,y,x -z=this.mj() -if(z==null){this.LM() -y=$globalState -if(y.EF===!0&&y.i2.X5===0&&y.Xz.bZ===0){y=y.vd -x=H.t0(H.B7(["command","close"],P.L5(null,null,null,null,null))) -y.toString -self.postMessage(x)}return!1}z.VU() -return!0}, -Wu:function(){if($.C5()!=null)new H.RA(this).call$0() -else for(;this.xB(););}, -bL:function(){var z,y,x,w,v -if($globalState.EF!==!0)this.Wu() -else try{this.Wu()}catch(x){w=H.Ru(x) -z=w -y=new H.XO(x,null) -w=$globalState.vd -v=H.t0(H.B7(["command","error","msg",H.d(z)+"\n"+H.d(y)],P.L5(null,null,null,null,null))) -w.toString -self.postMessage(v)}}},RA:{"":"Tp;a", -call$0:function(){if(!this.a.xB())return -P.rT(C.RT,this)}},IY:{"":"a;od,i3,G1", -VU:function(){this.od.vV(this.i3)}},JH:{"":"a;"},jl:{"":"Tp;a,b,c,d,e", -call$0:function(){H.Z7(this.a,this.b,this.c,this.d,this.e)}},Iy:{"":"a;",$isbC:true},JM:{"":"Iy;JE,tv", -wR:function(a,b){H.ff(b,new H.Ua(this,b))}, -n:function(a,b){var z -if(b==null)return!1 -z=J.x(b) -return typeof b==="object"&&b!==null&&!!z.$isJM&&J.xC(this.JE,b.JE)}, -giO:function(a){return this.JE.gx6()}, -$isJM:true, -$isbC:true},Ua:{"":"Tp;b,c", -call$0:function(){var z,y,x,w,v,u,t -z={} -y=$globalState.i2 -x=this.b -w=x.tv -v=y.t(y,w) -if(v==null)return -if((x.JE.gda().Gv&4)!==0)return -u=$globalState.N0!=null&&$globalState.N0.jO!==w -t=this.c -z.a=t -if(u)z.a=H.t0(z.a) -y=$globalState.Xz -w="receive "+H.d(t) -y.Rk.NZ(new H.IY(v,new H.JG(z,x,u),w))}},JG:{"":"Tp;a,d,e", -call$0:function(){var z,y -z=this.d.JE -if((z.gda().Gv&4)===0){if(this.e){y=this.a -y.a=H.Hh(y.a)}z=z.da -y=this.a.a -if(z.Gv>=4)H.vh(z.nG()) -z.Rg(y)}}},ns:{"":"Iy;Ws,bv,tv", -wR:function(a,b){H.ff(b,new H.wd(this,b))}, -n:function(a,b){var z -if(b==null)return!1 -z=J.x(b) -return typeof b==="object"&&b!==null&&!!z.$isns&&J.xC(this.Ws,b.Ws)&&J.xC(this.tv,b.tv)&&J.xC(this.bv,b.bv)}, -giO:function(a){var z,y,x -z=this.Ws -if(typeof z!=="number")throw z.O() -y=this.tv -if(typeof y!=="number")throw y.O() -x=this.bv -if(typeof x!=="number")throw H.s(x) -return(z<<16^y<<8^x)>>>0}, -$isns:true, -$isbC:true},wd:{"":"Tp;a,b", -call$0:function(){var z,y,x,w -z=this.a -y=H.t0(H.B7(["command","message","port",z,"msg",this.b],P.L5(null,null,null,null,null))) -if($globalState.EF===!0){$globalState.vd.toString -self.postMessage(y)}else{x=$globalState.XC -w=x.t(x,z.Ws) -if(w!=null)w.postMessage(y)}}},fc:{"":"qh;x6<,da<", -KR:function(a,b,c,d){var z=this.da -z.toString -z=new P.O9(z) -H.VM(z,[null]) -return z.KR(a,b,c,d)}, -xO:function(a){var z=this.da -if((z.Gv&4)!==0)return -z.xO(z) -$globalState.N0.IJ(this.x6)}, -gJK:function(a){return new H.YP(this,H.fc.prototype.xO,a,"xO")}, -zH:function(){this.da=P.x2(this.gJK(this),null,null,null,!0,null) -var z=$globalState.N0 -z.mg(z,this.x6,this)}, -static:{"":"b9",Ty:function(){var z=$.b9 -$.b9=z+1 -z=new H.fc(z,null) -z.zH() -return z}}},yc:{"":"Tp;a", -call$1:function(a){return this.a.call$0()}, -$is_aB:true},I9:{"":"HU;Gx,iq", -Pq:function(a){}, -wb:function(a){var z=this.iq -if(z.t(z,a)!=null)return -z=this.iq -z.u(z,a,!0) -J.kH(a,this.gRQ())}, -w5:function(a){var z=this.iq -if(z.t(z,a)!=null)return -z=this.iq -z.u(z,a,!0) -J.kH(a.gUQ(a),this.gRQ())}, -aC:function(a){}, -IW:function(){this.iq=new H.fP(null)}, -static:{ZF:function(){var z=new H.I9([],new H.X1()) -z.IW() -return z}}},Bj:{"":"Tf;CN,iq", -aC:function(a){if(!!a.$isJM)return["sendport",$globalState.oL,a.tv,a.JE.gx6()] -if(!!a.$isns)return["sendport",a.Ws,a.tv,a.bv] -throw H.b("Illegal underlying port "+H.d(a))}},NO:{"":"oo;iq", -aC:function(a){if(!!a.$isJM)return new H.JM(a.JE,a.tv) -if(!!a.$isns)return new H.ns(a.Ws,a.bv,a.tv) -throw H.b("Illegal underlying port "+H.d(a))}},II:{"":"iY;RZ", -Vf:function(a){var z,y,x,w,v,u -z=J.U6(a) -y=z.t(a,1) -x=z.t(a,2) -w=z.t(a,3) -if(J.xC(y,$globalState.oL)){z=$globalState.i2 -v=z.t(z,x) -if(v==null)return -u=v.Zt(w) -if(u==null)return -return new H.JM(u,x)}else return new H.ns(y,w,x)}},fP:{"":"a;kw", -t:function(a,b){return b.__MessageTraverser__attached_info__}, -u:function(a,b,c){this.kw.push(b) -b.__MessageTraverser__attached_info__=c}, -CH:function(a){this.kw=P.A(null,null)}, -F4:function(){var z,y,x -for(z=this.kw.length,y=0;y=x.length)throw H.e(x,y) -x[y].__MessageTraverser__attached_info__=null}this.kw=null}},X1:{"":"a;", -t:function(a,b){return}, -u:function(a,b,c){}, -CH:function(a){}, -F4:function(){}},HU:{"":"a;", -h7:function(a){var z,y -if(H.vM(a))return this.Pq(a) -y=this.iq -y.CH(y) -z=null -try{z=this.I8(a)}finally{this.iq.F4()}return z}, -I8:function(a){var z -if(a==null||typeof a==="string"||typeof a==="number"||typeof a==="boolean")return this.Pq(a) -z=J.x(a) -if(typeof a==="object"&&a!==null&&(a.constructor===Array||!!z.$isList))return this.wb(a) -if(typeof a==="object"&&a!==null&&!!z.$isZ0)return this.w5(a) -if(typeof a==="object"&&a!==null&&!!z.$isbC)return this.aC(a) -return this.YZ(a)}, -gRQ:function(){return new H.Pm(this,H.HU.prototype.I8,null,"I8")}, -YZ:function(a){throw H.b("Message serialization: Illegal value "+H.d(a)+" passed")}},oo:{"":"HU;", -Pq:function(a){return a}, -wb:function(a){var z,y,x,w,v -z=this.iq -y=z.t(z,a) -if(y!=null)return y -z=J.U6(a) -x=z.gB(a) -y=P.A(x,null) -w=this.iq -w.u(w,a,y) -for(v=0;v=x)throw H.e(y,v) -y[v]=w}return y}, -w5:function(a){var z,y -z={} -y=this.iq -z.a=y.t(y,a) -y=z.a -if(y!=null)return y -z.a=P.L5(null,null,null,null,null) -y=this.iq -y.u(y,a,z.a) -a.aN(a,new H.OW(z,this)) -return z.a}},OW:{"":"Tp;a,b", -call$2:function(a,b){var z=this.b -J.kW(this.a.a,z.I8(a),z.I8(b))}, -$is_bh:true},Tf:{"":"HU;", -Pq:function(a){return a}, -wb:function(a){var z,y,x -z=this.iq -y=z.t(z,a) -if(y!=null)return["ref",y] -x=this.CN -this.CN=x+1 -z=this.iq -z.u(z,a,x) -return["list",x,this.mE(a)]}, -w5:function(a){var z,y,x -z=this.iq -y=z.t(z,a) -if(y!=null)return["ref",y] -x=this.CN -this.CN=x+1 -z=this.iq -z.u(z,a,x) -return["map",x,this.mE(J.qA(a.gvc())),this.mE(J.qA(a.gUQ(a)))]}, -mE:function(a){var z,y,x,w,v -z=J.U6(a) -y=z.gB(a) -x=P.A(y,null) -for(w=0;w=y)throw H.e(x,w) -x[w]=v}return x}},iY:{"":"a;", -QS:function(a){if(H.uu(a))return a -this.RZ=P.Py(null,null,null,null,null) -return this.XE(a)}, -XE:function(a){var z,y -if(a==null||typeof a==="string"||typeof a==="number"||typeof a==="boolean")return a -z=J.U6(a) -switch(z.t(a,0)){case"ref":y=z.t(a,1) -z=this.RZ -return z.t(z,y) -case"list":return this.Dj(a) -case"map":return this.GD(a) -case"sendport":return this.Vf(a) -default:return this.PR(a)}}, -Dj:function(a){var z,y,x,w,v -z=J.U6(a) -y=z.t(a,1) -x=z.t(a,2) -z=this.RZ -z.u(z,y,x) -z=J.U6(x) -w=z.gB(x) -if(typeof w!=="number")throw H.s(w) -v=0 -for(;v65535)return H.Cq(a)}return H.VK(a)},o2:function(a){if(a.date===void 0)a.date=new Date(a.rq) -return a.date},tJ:function(a){return a.aL?H.o2(a).getUTCFullYear()+0:H.o2(a).getFullYear()+0},NS:function(a){return a.aL?H.o2(a).getUTCMonth()+1:H.o2(a).getMonth()+1},jA:function(a){return a.aL?H.o2(a).getUTCDate()+0:H.o2(a).getDate()+0},KL:function(a){return a.aL?H.o2(a).getUTCHours()+0:H.o2(a).getHours()+0},ch:function(a){return a.aL?H.o2(a).getUTCMinutes()+0:H.o2(a).getMinutes()+0},Jd:function(a){return a.aL?H.o2(a).getUTCSeconds()+0:H.o2(a).getSeconds()+0},o1:function(a){return a.aL?H.o2(a).getUTCMilliseconds()+0:H.o2(a).getMilliseconds()+0},of:function(a,b){if(a==null||typeof a==="boolean"||typeof a==="number"||typeof a==="string")throw H.b(new P.AT(a)) -return a[b]},aw:function(a,b,c){if(a==null||typeof a==="boolean"||typeof a==="number"||typeof a==="string")throw H.b(new P.AT(a)) -a[b]=c},s:function(a){throw H.b(P.u(a))},e:function(a,b){if(a==null)J.q8(a) -if(typeof b!=="number"||Math.floor(b)!==b)H.s(b) -throw H.b(P.N(b))},b:function(a){var z -if(a==null)a=new P.LK() -z=new Error() -z.dartException=a -if("defineProperty" in Object){Object.defineProperty(z, "message", { get: H.Eu.call$0 }) -z.name=""}else z.toString=H.Eu.call$0 -return z},Ju:function(){return J.AG(this.dartException)},vh:function(a){throw H.b(a)},Ru:function(a){var z,y,x,w,v,u,t,s,r,q,p,o,n,m -z=new H.Am(a) -if(a==null)return -if(typeof a!=="object")return a -if("dartException" in a)return z.call$1(a.dartException) -else if(!("message" in a))return a -y=a.message -if("number" in a&&typeof a.number=="number"){x=a.number -w=x&65535 -if((C.jn.m(x,16)&8191)===10)switch(w){case 438:return z.call$1(H.T3(H.d(y)+" (Error "+w+")",null)) -case 445:case 5007:v=H.d(y)+" (Error "+w+")" -return z.call$1(new H.W0(v,null)) -default:}}if(a instanceof TypeError){v=$.WD() -u=$.OI() -t=$.PH() -s=$.D1() -r=$.rx() -q=$.Kr() -p=$.zO() -$.Bi() -o=$.eA() -n=$.ko() -m=v.qS(y) -if(m!=null)return z.call$1(H.T3(y,m)) -else{m=u.qS(y) -if(m!=null){m.method="call" -return z.call$1(H.T3(y,m))}else{m=t.qS(y) -if(m==null){m=s.qS(y) -if(m==null){m=r.qS(y) -if(m==null){m=q.qS(y) -if(m==null){m=p.qS(y) -if(m==null){m=s.qS(y) -if(m==null){m=o.qS(y) -if(m==null){m=n.qS(y) -v=m!=null}else v=!0}else v=!0}else v=!0}else v=!0}else v=!0}else v=!0}else v=!0 -if(v){v=m==null?null:m.method -return z.call$1(new H.W0(y,v))}}}v=typeof y==="string"?y:"" -return z.call$1(new H.vV(v))}if(a instanceof RangeError){if(typeof y==="string"&&y.indexOf("call stack")!==-1)return new P.VS() -return z.call$1(new P.AT(null))}if(typeof InternalError=="function"&&a instanceof InternalError)if(typeof y==="string"&&y==="too much recursion")return new P.VS() -return a},CU:function(a){if(a==null||typeof a!='object')return J.v1(a) -else return H.eQ(a)},B7:function(a,b){var z,y,x,w -z=a.length -for(y=0;y"},Y9:function(a,b){if(typeof a==="object"&&a!==null&&a.constructor===Array)b=a -else if(typeof a=="function"){a=H.ml(a,null,b) -if(typeof a==="object"&&a!==null&&a.constructor===Array)b=a -else if(typeof a=="function")b=H.ml(a,null,b)}return b},IG:function(a,b,c){return H.ml(a,b,H.IM(b,c))},ml:function(a,b,c){return a.apply(b,c)},F3:function(a){var z=$.NF -return"Instance of "+(z==null?"":z.call$1(a))},wz:function(a){return H.eQ(a)},iw:function(a,b,c){Object.defineProperty(a, b, {value: c, enumerable: false, writable: true, configurable: true})},w3:function(a){var z,y,x,w,v,u -z=$.NF.call$1(a) -y=$.nw[z] -if(y!=null){Object.defineProperty(a, init.dispatchPropertyName, {value: y, enumerable: false, writable: true, configurable: true}) -return y.i}x=$.vv[z] -if(x!=null)return x -w=init.interceptorsByTag[z] -if(w==null){z=$.TX.call$2(a,z) -if(z!=null){y=$.nw[z] -if(y!=null){Object.defineProperty(a, init.dispatchPropertyName, {value: y, enumerable: false, writable: true, configurable: true}) -return y.i}x=$.vv[z] -if(x!=null)return x -w=init.interceptorsByTag[z]}}if(w==null)return -x=w.prototype -v=z[0] -if(v==="!"){y=H.Va(x) -$.nw[z]=y -Object.defineProperty(a, init.dispatchPropertyName, {value: y, enumerable: false, writable: true, configurable: true}) -return y.i}if(v==="~"){$.vv[z]=x -return x}if(v==="-"){u=H.Va(x) -Object.defineProperty(Object.getPrototypeOf(a), init.dispatchPropertyName, {value: u, enumerable: false, writable: true, configurable: true}) -return u.i}if(v==="+")return H.Lc(a,x) -if(v==="*")throw H.b(P.SY(z)) -if(init.leafTags[z]===true){u=H.Va(x) -Object.defineProperty(Object.getPrototypeOf(a), init.dispatchPropertyName, {value: u, enumerable: false, writable: true, configurable: true}) -return u.i}else return H.Lc(a,x)},Lc:function(a,b){var z,y -z=Object.getPrototypeOf(a) -y=J.Qu(b,z,null,null) -Object.defineProperty(z, init.dispatchPropertyName, {value: y, enumerable: false, writable: true, configurable: true}) -return b},Va:function(a){return J.Qu(a,!1,null,!!a.$isXj)},VF:function(a,b,c){var z=b.prototype -if(init.leafTags[a]===true)return J.Qu(z,!1,null,!!z.$isXj) -else return J.Qu(z,c,null,null)},XD:function(){if(!0===$.Bv)return -$.Bv=!0 -H.Z1()},Z1:function(){var z,y,x,w,v,u,t -$.nw=Object.create(null) -$.vv=Object.create(null) -H.kO() -z=init.interceptorsByTag -y=Object.getOwnPropertyNames(z) -if(typeof window!="undefined"){window -for(x=0;x>>0}, -$isv:true},Pe:{"":"Ge;G1", -bu:function(a){return this.G1}, -$isGe:true, -static:{aq:function(a,b){return new H.Pe("CastError: Casting value of type "+a+" to incompatible type "+H.d(b))}}},dC:{"":"Tp;a", -call$1:function(a){return this.a(a)}, -$is_aB:true},wN:{"":"Tp;b", -call$2:function(a,b){return this.b(a,b)}, -$is_bh:true},VX:{"":"Tp;c", -call$1:function(a){return this.c(a)}, -$is_aB:true},VR:{"":"a;SQ,h2,fX", -goX:function(){var z=this.h2 -if(z!=null)return z -z=this.SQ -z=H.v4(z.source,z.multiline,!z.ignoreCase,!0) -this.h2=z -return z}, -dd:function(a,b){if(typeof b!=="string")H.vh(new P.AT(b)) -return new H.KW(this,b)}, -oG:function(a,b){var z,y -z=this.goX() -z.lastIndex=b -y=z.exec(a) -if(y==null)return -return H.pO(this,y)}, -$isVR:true, -static:{v4:function(a,b,c,d){var z,y,x,w,v -if(typeof a!=="string")H.vh(new P.AT(a)) -z=b?"m":"" -y=c?"":"i" -x=d?"g":"" -w=(function() {try {return new RegExp(a, z + y + x);} catch (e) {return e;}})() -if(w instanceof RegExp)return w -v=String(w) -throw H.b(P.cD("Illegal RegExp pattern: "+H.d(a)+", "+v))}}},EK:{"":"a;zO,oH", -t:function(a,b){var z=this.oH -if(b>>>0!==b||b>=z.length)throw H.e(z,b) -return z[b]}, -kx:function(a,b){}, -static:{pO:function(a,b){var z=new H.EK(a,b) -z.kx(a,b) -return z}}},KW:{"":"mW;td,BZ", -gA:function(a){return new H.Pb(this.td,this.BZ,null)}},Pb:{"":"a;EW,BZ,Jz", -gl:function(){return this.Jz}, -G:function(){var z,y,x -if(this.BZ==null)return!1 -z=this.Jz -if(z!=null){z=z.oH -y=z.index -if(0>=z.length)throw H.e(z,0) -z=J.q8(z[0]) -if(typeof z!=="number")throw H.s(z) -x=y+z -if(this.Jz.oH.index===x)++x}else x=0 -this.Jz=this.EW.oG(this.BZ,x) -if(this.Jz==null){this.BZ=null -return!1}return!0}},tQ:{"":"a;M,J9,zO", -t:function(a,b){if(b!==0)H.vh(P.N(b)) -return this.zO}}}],["anyplace_developers","file:///home/lambros/Development/github/repos/anyplace/anyplace_developers/AnyPlaceDevelopers/web/main.dart",,T,{E2:function(){T.t9()},t9:function(){var z=W.Kn("anyplace.json",null,null) -z.ml(T.bn) -z.OA(T.TM)},Fa:function(a){P.JS(J.AG(a))},qP:function(a){var z,y -z=C.Ct.kV(a) -y=new T.fl(document.querySelector("#globals"),document.querySelector("#endpoints-list"),z,null,null,null) -y.SE=P.L5(null,null,null,null,null) -y.kW=P.A(null,null) -y.NY() -$.XS=y},fl:{"":"a;vZ,pf,dP,SE,S3,kW", -NY:function(){var z,y -z=this.dP -y=J.U6(z) -this.S3=y.t(z,"baseurl") -this.DS(y.t(z,"globals")) -this.Rq(y.t(z,"endpoints")) -this.MD()}, -DS:function(a){var z,y,x,w,v,u -z=this.vZ -z.appendChild($.Mv().cloneNode(!0)) -for(y=J.GP(a);y.G();){x=T.SW(y.gl()) -w=this.SE -w.u(w,J.UQ(x.Vu,"name"),x) -z.appendChild(x.p8) -w=x.p8.querySelector(".param-column-value input") -w.toString -w=new W.eu(w,C.mt.Ph,!1) -w.$builtinTypeInfo=[null] -v=H.Y9(w.$asRO,H.oX(w)) -u=v==null?null:v[0] -w=new W.Ov(0,w.uv,w.Ph,W.aF(new T.UG(this,x)),w.Sg) -w.$builtinTypeInfo=[u] -u=w.u7 -if(u!=null&&w.VP<=0)J.qV(w.uv,w.Ph,u,w.Sg)}}, -Rq:function(a){var z,y,x -for(z=J.GP(a),y=this.pf;z.G();){x=T.Cb(z.gl(),this.S3,this.SE) -this.kW.push(x) -y.appendChild(x.KQ)}}, -LC:function(a){var z -for(z=this.kW,z=new H.a7(z,z.length,0,null);z.G();)z.mD.zy(a)}, -MD:function(){var z,y,x -for(z=this.SE,z.toString,y=new P.i5(z),H.VM(y,[H.W8(z,"YB",0)]),y=y.Fb,y=new P.N6(y,y.zN,null,null),y.zq=y.Fb.H9;y.G();){x=y.fD -z=this.SE -this.LC(z.t(z,x))}}},UG:{"":"Tp;a,b", -call$1:function(a){this.a.LC(this.b)}, -$is_aB:true},Jc:{"":"a;Vu,p8", -gox:function(){return J.UQ(this.Vu,"name")}, -gqk:function(){return this.p8}, -CD:function(){var z,y -z=this.Vu -y=J.U6(z) -if(J.xC(y.t(z,"type"),"file")){z=H.Go(this.p8.querySelector(".param-column-value input"),"$isMi").files -if(0>=z.length)throw H.e(z,0) -return z[0]}if(J.xC(y.t(z,"type"),"bool"))return J.AG(H.Go(this.p8.querySelector(".param-column-value input"),"$isMi").checked) -return H.Go(this.p8.querySelector(".param-column-value input"),"$isMi").value}, -gCB:function(){return J.xC(J.UQ(this.Vu,"type"),"file")}, -M2:function(a){var z,y,x,w,v,u,t,s,r -z=document.createElement("div",null) -y=J.pP(z) -y.h(y,"param") -this.p8=z -x=document.createElement("span",null) -z=this.Vu -y=J.U6(z) -x.textContent=y.t(z,"name") -w=J.pP(x) -w.h(w,"param-column-name") -this.p8.appendChild(x) -if(J.xC(y.t(z,"type"),"text"))v="text" -else if(J.xC(y.t(z,"type"),"bool"))v="checkbox" -else v=J.xC(y.t(z,"type"),"file")?"file":null -u=document.createElement("span",null) -w=J.pP(u) -w.h(w,"param-column-value") -t=W.dy(v) -w=J.RE(t) -w.soc(t,y.t(z,"name")) -w.sP(t,y.t(z,"default")) -w.sSY(t,J.xC(y.t(z,"required"),"Y")&&!0) -w.sbO(t,J.xC(y.t(z,"required"),"Y")?"Required":"") -u.appendChild(t) -this.p8.appendChild(u) -s=document.createElement("span",null) -w=J.pP(s) -w.h(w,"param-column-type") -s.textContent=y.t(z,"type") -this.p8.appendChild(s) -r=document.createElement("span",null) -w=J.pP(r) -w.h(w,"param-column-description") -r.textContent=y.t(z,"description") -this.p8.appendChild(r)}, -static:{"":"Me",SW:function(a){var z=new T.Jc(a,null) -z.M2(a) -return z}}},Im:{"":"a;dP,tH,fq,R6,qs,pN,PG,Z3,iN,SE,KQ", -Y5:function(a){var z,y,x,w,v,u,t,s,r,q,p,o -z=document.createElement("div",null) -y=J.pP(z) -y.h(y,"endpoint-method") -this.KQ=z -x=document.createElement("div",null) -z=J.pP(x) -z.h(z,"endpoint-method-header") -w=document.createElement("span",null) -w.textContent=this.R6 -z=J.RE(w) -y=z.gDD(w) -y.h(y,"endpoint-method-header-method") -z=z.gDD(w) -z.h(z,J.xC(this.R6,"POST")?"endpoint-method-header-post":"endpoint-method-header-get") -x.appendChild(w) -v=document.createElement("span",null) -v.textContent=this.tH -z=J.pP(v) -z.h(z,"endpoint-method-header-name") -x.appendChild(v) -u=document.createElement("span",null) -u.textContent=this.qs -z=J.pP(u) -z.h(z,"endpoint-method-header-uri") -x.appendChild(u) -t=document.createElement("span",null) -t.textContent=this.fq -z=J.pP(t) -z.h(z,"endpoint-method-header-description") -x.appendChild(t) -this.KQ.appendChild(x) -s=document.createElement("div",null) -z=J.pP(s) -z.h(z,"method-details") -s.appendChild($.Mv().cloneNode(!0)) -r=document.createElement("ul",null) -z=J.pP(r) -z.h(z,"endpoint-method-params-list") -for(z=this.PG,z=new H.a7(z,z.length,0,null);z.G();){q=z.mD -p=document.createElement("li",null) -y=J.pP(p) -y.h(y,"endpoint-method-params-item") -p.appendChild(q.gqk()) -r.appendChild(p)}s.appendChild(r) -z=document.createElement("button",null) -y=J.pP(z) -y.FV(y,["endpoint-method-submit"]) -z.textContent="Try Endpoint" -s.appendChild(z) -o=document.createElement("div",null) -z=J.RE(o) -y=z.gDD(o) -y.h(y,"endpoint-method-results") -o.appendChild(this.XW("Request","URL")) -o.appendChild(this.XW("Response","Headers")) -o.appendChild(this.XW("Response","Body")) -o.appendChild(this.XW("Repsonse","Time")) -z=z.gDD(o) -z.h(z,"hidden") -s.appendChild(o) -this.KQ.appendChild(s) -this.AD()}, -XW:function(a,b){var z,y,x -z=document.createElement("div",null) -y=J.pP(z) -y.FV(y,["method-resp-result","method-resp-"+b.toLowerCase()]) -y=document.createElement("span",null) -y.textContent=a+" "+b -x=J.pP(y) -x.h(x,"method-resp-result-title") -z.appendChild(y) -y=document.createElement("div",null) -x=J.pP(y) -x.h(x,"method-resp-result-value") -z.appendChild(y) -return z}, -AD:function(){var z,y,x,w -z=this.KQ.querySelector(".endpoint-method-header") -z.toString -y=C.T1.Ph -z=new W.eu(z,y,!1) -H.VM(z,[null]) -x=new W.Ov(0,z.uv,z.Ph,W.aF(new T.qz(this)),z.Sg) -H.VM(x,[H.W8(z,"RO",0)]) -x.Zz() -w=this.KQ.querySelector(".endpoint-method-submit") -w.toString -y=new W.eu(w,y,!1) -H.VM(y,[null]) -x=new W.Ov(0,y.uv,y.Ph,W.aF(new T.Cy(this)),y.Sg) -H.VM(x,[H.W8(y,"RO",0)]) -x.Zz()}, -mq:function(){var z,y,x -z=P.L5(null,null,null,null,null) -for(y=this.PG,y=new H.a7(y,y.length,0,null);y.G();){x=y.mD -if(!x.gCB())z.u(z,J.UQ(x.Vu,"name"),x.CD())}return z}, -V8:function(a){var z,y,x,w,v -z=this.qs -for(y=this.Z3,x=new P.i5(y),H.VM(x,[H.W8(y,"YB",0)]),x=x.Fb,x=new P.N6(x,x.zN,null,null),x.zq=x.Fb.H9;x.G();){w=x.fD -v=a.t(a,y.t(y,w)) -z=J.JA(z,new H.VR(H.v4(w,!1,!0,!1),null,null),"/"+H.d(v))}return z}, -ph:function(a,b,c){var z,y,x -y=J.DA(a) -if(y==null?4==null:y===4){J.Qy(b.querySelector(".method-resp-headers").querySelector(".method-resp-result-value"),"
"+this.b1(J.Vu(a),"")+"
") -z="" -try{z=C.Ct.kV(J.CA(a))}catch(x){H.Ru(x) -z=J.CA(a)}J.Qy(b.querySelector(".method-resp-body").querySelector(".method-resp-result-value"),"
"+this.b1(z,"")+"
") -J.Qy(b.querySelector(".method-resp-time").querySelector(".method-resp-result-value"),"

Total Time: "+H.d(c)+" milliseconds

")}}, -b1:function(a,b){var z,y,x,w,v,u,t,s,r -y=new P.Rn("") -y.vM="" -z=!1 -try{a=C.Ct.kV(a) -z=!0}catch(x){H.Ru(x)}w=a -v=J.x(w) -if(typeof w==="object"&&w!==null&&!!v.$isZ0){w=b+" {" -y.vM=y.vM+w -y.vM=y.vM+"\n" -b+=" " -u=J.q8(a) -for(w=J.GP(a.gvc()),t=0;w.G();){s=w.gl();++t -v=J.UQ(a,s) -r=J.x(v) -if(typeof v!=="object"||v===null||!r.$isZ0){v=J.UQ(a,s) -r=J.x(v) -r=typeof v==="object"&&v!==null&&(v.constructor===Array||!!r.$isList) -v=r}else v=!0 -if(v){v=b+" \""+H.d(J.AG(s))+"\": " -y.vM=y.vM+v -y.vM=y.vM+"\n" -v=this.b1(J.UQ(a,s),b+" ") -y.vM=y.vM+v}else{v=J.UQ(a,s) -r=J.x(s) -if(typeof v==="number"&&Math.floor(v)===v){v=b+" \""+H.d(r.bu(s))+"\": "+H.d(J.AG(J.UQ(a,s))) -y.vM=y.vM+v}else{v=b+" \""+H.d(r.bu(s))+"\": \""+H.d(J.AG(J.UQ(a,s)))+"\"" -y.vM=y.vM+v}}if(typeof u!=="number")throw H.s(u) -v=t=v.length)throw H.e(v,0) -v=v[0] -y.u(y,v,J.ZZ(v,2))}}this.Y5(this)}, -static:{nX:function(a,b,c){var z=new T.Im(a,null,null,null,null,null,null,P.L5(null,null,null,null,null),b,c,null) -z.mS(a,b,c) -return z}}},qz:{"":"Tp;a", -call$1:function(a){this.a.uw()}, -$is_aB:true},Cy:{"":"Tp;b", -call$1:function(a){var z,y,x,w,v,u,t,s,r,q,p,o -z=this.b -y=z.mq() -x=z.V8(y) -w=z.iN -v=J.Qc(w) -J.Qy(z.KQ.querySelector(".method-resp-url").querySelector(".method-resp-result-value"),"

"+H.d(v.g(w,x))+"

") -u=J.pP(z.KQ.querySelector(".endpoint-method-results")) -u.Rz(u,"hidden") -u.h(u,"visible-block") -for(u=z.PG,u=new H.a7(u,u.length,0,null);t=!1,u.G();)if(u.mD.gCB()){t=!0 -break}u=C.tF.Ph -if(t){s=P.Gi() -r=new XMLHttpRequest() -C.W3.EP(r,z.R6,v.g(w,x)) -u=new W.RO(r,u,!1) -H.VM(u,[null]) -s=new W.Ov(0,u.uv,u.Ph,W.aF(new T.bY(z,s.rq)),u.Sg) -H.VM(s,[H.W8(u,"RO",0)]) -s.Zz() -q=W.Yb(null) -q.append("json",C.Ct.KP(y)) -for(z=z.PG,z=new H.a7(z,z.length,0,null);z.G();){p=z.mD -if(p.gCB()){o=p.CD() -q.append(J.UQ(p.Vu,"name"),o)}}r.send(q)}else{s=P.Gi() -r=new XMLHttpRequest() -C.W3.EP(r,z.R6,v.g(w,x)) -r.setRequestHeader("Content-type","application/json") -u=new W.RO(r,u,!1) -H.VM(u,[null]) -s=new W.Ov(0,u.uv,u.Ph,W.aF(new T.DQ(z,s.rq)),u.Sg) -H.VM(s,[H.W8(u,"RO",0)]) -s.Zz() -r.send(C.Ct.KP(y))}}, -$is_aB:true},bY:{"":"Tp;c,d", -call$1:function(a){var z,y -z=P.Gi() -y=this.c -y.ph(J.l2(a),y.KQ,z.rq-this.d)}, -$is_aB:true},DQ:{"":"Tp;e,f", -call$1:function(a){var z,y -z=P.Gi() -y=this.e -y.ph(J.l2(a),y.KQ,z.rq-this.f)}, -$is_aB:true},IB:{"":"a;dP,tH,fq,Lu,iN,SE,KQ,og", -Ev:function(){var z,y,x,w,v,u -z=document.createElement("div",null) -y=J.pP(z) -y.h(y,"endpoint") -this.KQ=z -z=this.KQ -y=document.createElement("div",null) -x=J.pP(y) -x.h(x,"endpoint-title") -y.textContent=this.tH -z.appendChild(y) -y=this.KQ -z=document.createElement("div",null) -x=J.pP(z) -x.h(x,"endpoint-description") -z.textContent=this.fq -y.appendChild(z) -z=this.KQ -y=document.createElement("div",null) -x=J.pP(y) -x.FV(x,["endpoint-toggleall"]) -x=document.createElement("button",null) -x.textContent="Show All" -y.appendChild(x) -z.appendChild(y) -w=document.createElement("ul",null) -y=J.pP(w) -y.h(y,"endpoint-methods-list") -for(z=this.Lu,z=new H.a7(z,z.length,0,null);z.G();){v=z.mD -u=document.createElement("li",null) -y=J.pP(u) -y.h(y,"endpoint-methods-item") -u.appendChild(v.gqk()) -w.appendChild(u)}this.KQ.appendChild(w) -this.AD()}, -AD:function(){var z,y -z=this.KQ.querySelector(".endpoint-toggleall button") -z.toString -z=new W.eu(z,C.T1.Ph,!1) -H.VM(z,[null]) -y=new W.Ov(0,z.uv,z.Ph,W.aF(new T.ZG(this)),z.Sg) -H.VM(y,[H.W8(z,"RO",0)]) -y.Zz()}, -zy:function(a){var z -for(z=this.Lu,z=new H.a7(z,z.length,0,null);z.G();)z.mD.zy(a)}, -gqk:function(){return this.KQ}, -ne:function(a,b,c){var z,y,x -z=this.dP -y=J.U6(z) -this.tH=y.t(z,"name") -this.fq=y.t(z,"description") -this.Lu=P.A(null,null) -for(z=J.GP(y.t(z,"methods")),y=this.iN;z.G();){x=z.gl() -this.Lu.push(T.nX(x,y,this.SE))}this.Ev()}, -static:{Cb:function(a,b,c){var z=new T.IB(a,null,null,null,b,c,null,!0) -z.ne(a,b,c) -return z}}},ZG:{"":"Tp;a", -call$1:function(a){var z,y -z=this.a -if(z.og){for(y=z.Lu,y=new H.a7(y,y.length,0,null);y.G();)y.mD.Dn() -H.Go(J.BC(a),"$isIF").textContent="Hide All"}else{for(y=z.Lu,y=new H.a7(y,y.length,0,null);y.G();)y.mD.Pn() -H.Go(J.BC(a),"$isIF").textContent="Show All"}z.og=!z.og}, -$is_aB:true}},1],["dart._collection.dev","dart:_collection-dev",,H,{Zi:function(a,b,c,d,e){var z,y,x -if(b=b;--z,--y){if(z<0||z>=a.length)throw H.e(a,z) -C.Nm.u(c,y,a[z])}else for(x=b+e,y=d,z=b;z=a.length)throw H.e(a,z) -C.Nm.u(c,y,a[z])}},Ub:function(a,b,c,d){var z -if(c>=a.length)return-1 -if(c<0)c=0 -for(z=c;z=a.length)throw H.e(a,z) -if(J.xC(a[z],b))return z}return-1},bQ:function(a,b){var z -for(z=new H.a7(a,a.length,0,null);z.G();)b.call$1(z.mD)},Ck:function(a,b){var z -for(z=new H.a7(a,a.length,0,null);z.G();)if(b.call$1(z.mD)===!0)return!0 -return!1},mx:function(a,b,c){var z,y,x -for(y=0;y<$.RM().length;++y){x=$.RM() -if(y>=x.length)throw H.e(x,y) -if(x[y]===a)return H.d(b)+"..."+H.d(c)}z=P.p9("") -try{$.RM().push(a) -z.KF(b) -z.We(a,", ") -z.KF(c)}finally{x=$.RM() -if(0>=x.length)throw H.e(x,0) -x.pop()}return z.gvM()},S6:function(a,b,c){if(b<0||b>a.length)throw H.b(P.TE(b,0,a.length)) -if(ca.length)throw H.b(P.TE(c,b,a.length))},qG:function(a,b,c,d,e){var z -H.S6(a,b,c) -z=c-b -if(z===0)return -if(e<0)throw H.b(new P.AT(e)) -if(e+z>d.length)throw H.b(P.w("Not enough elements")) -H.Zi(d,e,a,b,z)},LJ:function(a){if(typeof dartPrint=="function"){dartPrint(a) -return}if(typeof console=="object"&&typeof console.log=="function"){console.log(a) -return}if(typeof window=="object")return -if(typeof print=="function"){print(a) -return}throw "Unable to print message: " + String(a)},Fv:function(a){return a.ghr()},aL:{"":"mW;", -gA:function(a){return new H.a7(this,this.gB(this),0,null)}, -aN:function(a,b){var z,y -z=this.gB(this) -for(y=0;y=x){this.mD=null -return!1}this.mD=y.Zv(z,w) -this.j2=this.j2+1 -return!0}},i1:{"":"mW;Kw,ew", -gA:function(a){var z=this.Kw -z=z.gA(z) -z=new H.MH(null,z,this.ew) -H.VM(z,[H.W8(this,"i1",0),H.W8(this,"i1",1)]) -return z}, -gB:function(a){var z=this.Kw -return z.gB(z)}, -gl0:function(a){var z=this.Kw -return z.gl0(z)}, -$asmW:function(a,b){return[b]}, -static:{K1:function(a,b,c,d){var z -if(!!a.$isqC){z=new H.xy(a,b) -H.VM(z,[c,d]) -return z}z=new H.i1(a,b) -H.VM(z,[c,d]) -return z}}},xy:{"":"i1;Kw,ew",$asi1:null,$isqC:true},MH:{"":"An;mD,RX,ew", -ei:function(a){return this.ew.call$1(a)}, -G:function(){var z=this.RX -if(z.G()){this.mD=this.ei(z.gl()) -return!0}this.mD=null -return!1}, -gl:function(){return this.mD}, -$asAn:function(a,b){return[b]}},A8:{"":"aL;qb,ew", -ei:function(a){return this.ew.call$1(a)}, -gB:function(a){return J.q8(this.qb)}, -Zv:function(a,b){return this.ei(J.i4(this.qb,b))}, -$asaL:function(a,b){return[b]}, -$isqC:true},U5:{"":"mW;Kw,ew", -gA:function(a){var z=J.GP(this.Kw) -z=new H.SO(z,this.ew) -H.VM(z,[H.W8(this,"U5",0)]) -return z}, -$asmW:null},SO:{"":"An;RX,ew", -ei:function(a){return this.ew.call$1(a)}, -G:function(){for(var z=this.RX;z.G();)if(this.ei(z.gl())===!0)return!0 -return!1}, -gl:function(){return this.RX.gl()}, -$asAn:null},SU:{"":"a;", -sB:function(a,b){throw H.b(P.f("Cannot change the length of a fixed-length list"))}, -h:function(a,b){throw H.b(P.f("Cannot add to a fixed-length list"))}, -FV:function(a,b){throw H.b(P.f("Cannot add to a fixed-length list"))}}}],["dart.async","dart:async",,P,{K2:function(a,b,c){var z=J.x(a) -if(!!z.$is_bh)return a.call$2(b,c) -else return a.call$1(b)},VH:function(a,b){var z=J.x(a) -b.toString -if(!!z.$is_bh)return a -else return a},pH:function(a){var z,y,x,w,v,u,t,s,r -z={} -z.a=null -z.b=null -y=new P.VN(z) -z.c=0 -for(x=new H.a7(a,a.length,0,null);x.G();){w=x.mD -v=z.c -z.c=v+1 -u=w.OA(y) -t=$.X3 -t.toString -s=new P.vs(0,t,null,null,new P.iK(z,v),null,P.VH(null,t),null) -s.$builtinTypeInfo=[null] -u.au(s)}y=z.c -if(y===0)return P.Ab(C.xD,null) -z.b=P.A(y,null) -y=J.Q -r=new P.Zf(P.Dt(y)) -H.VM(r,[y]) -z.a=r -return z.a.MM},BG:function(){var z,y,x,w -for(;y=$.P8(),y.av!==y.HV;){z=$.P8().Ux() -try{z.call$0()}catch(x){H.Ru(x) -w=C.CD.Z(C.RT.Fq,1000) -H.cy(w<0?0:w,P.qZ) -throw x}}$.TH=!1},IA:function(a){$.P8().NZ(a) -if(!$.TH){P.jL(C.RT,P.qZ) -$.TH=!0}},rb:function(a){var z=$.X3 -if(z===C.NU){z.toString -P.IA(a) -return}P.IA(z.xi(a,!0))},x2:function(a,b,c,d,e,f){var z -if(e){z=new P.ly(b,c,d,a,null,0,null) -H.VM(z,[f])}else{z=new P.q1(b,c,d,a,null,0,null) -H.VM(z,[f])}return z},ot:function(a){var z,y,x,w,v,u -if(a==null)return -try{z=a.call$0() -w=z -v=J.x(w) -if(typeof w==="object"&&w!==null&&!!v.$isb8)return z -return}catch(u){w=H.Ru(u) -y=w -x=new H.XO(u,null) -w=$.X3 -w.toString -P.L2(w,null,w,y,x)}},QE:function(a){},SZ:function(a,b){var z=$.X3 -z.toString -P.L2(z,null,z,a,b)},dL:function(){},FE:function(a,b,c){var z,y,x,w -try{b.call$1(a.call$0())}catch(x){w=H.Ru(x) -z=w -y=new H.XO(x,null) -c.call$2(z,y)}},NX:function(a,b,c,d){var z,y -z=a.ed() -y=J.x(z) -if(typeof z==="object"&&z!==null&&!!y.$isb8)z.wM(new P.dR(b,c,d)) -else b.K5(c,d)},TB:function(a,b){return new P.uR(a,b)},Bb:function(a,b,c){var z,y -z=a.ed() -y=J.x(z) -if(typeof z==="object"&&z!==null&&!!y.$isb8)z.wM(new P.QX(b,c)) -else b.rX(c)},rT:function(a,b){var z=$.X3 -if(z===C.NU){z.toString -return P.jL(a,b)}return P.jL(a,z.xi(b,!0))},jL:function(a,b){var z=C.CD.Z(a.Fq,1000) -return H.cy(z<0?0:z,b)},L2:function(a,b,c,d,e){P.T8(a,null,a,new P.pK(d,e))},T8:function(a,b,c,d){var z,y,x -y=$.X3 -x=c -if(y==null?x==null:y===x)return d.call$0() -z=y -try{$.X3=c -y=d.call$0() -return y}finally{$.X3=z}},V7:function(a,b,c,d,e){var z,y,x -y=$.X3 -x=c -if(y==null?x==null:y===x)return d.call$1(e) -z=y -try{$.X3=c -y=d.call$1(e) -return y}finally{$.X3=z}},Ca:{"":"a;kc>,I4<",$isGe:true},b8:{"":"a;",$isb8:true},VN:{"":"Tp;a", -call$1:function(a){var z=this.a -if(z.b!=null){z.b=null -z.a.pm(a)}return}, -$is_aB:true},iK:{"":"Tp;a,b", -call$1:function(a){var z,y,x -z=this.a -y=z.b -if(y==null)return -x=this.b -if(x<0||x>=y.length)throw H.e(y,x) -y[x]=a -z.c=z.c-1 -if(z.c===0){y=z.a -z=z.b -y=y.MM -if(y.Gv!==0)H.vh(P.w("Future already completed")) -y.OH(z)}}, -$is_aB:true},Pf:{"":"a;"},Zf:{"":"Pf;MM", -w0:function(a,b){var z -if(a==null)throw H.b(new P.AT("Error must not be null")) -z=this.MM -if(z.Gv!==0)throw H.b(P.w("Future already completed")) -z.CG(a,b)}, -pm:function(a){return this.w0(a,null)}, -gYJ:function(){return new P.CQ(this,P.Zf.prototype.w0,null,"w0")}, -$asPf:null},vs:{"":"a;Gv,Lj<,jk,BQ<,OY,As,qV,o4", -gcg:function(){return this.Gv>=4}, -gNm:function(){return this.Gv===8}, -swG:function(a){if(a)this.Gv=2 -else this.Gv=0}, -gO1:function(){return this.Gv===2?null:this.OY}, -GP:function(a){return this.gO1().call$1(a)}, -gIa:function(){return this.Gv===2?null:this.o4}, -xY:function(){return this.gIa().call$0()}, -Rx:function(a,b){var z=P.Y8(a,b,null) -this.au(z) -return z}, -ml:function(a){return this.Rx(a,null)}, -co:function(a,b){var z=P.RP(a,b,null) -this.au(z) -return z}, -OA:function(a){return this.co(a,null)}, -wM:function(a){var z=P.X4(a,H.W8(this,"vs",0)) -this.au(z) -return z}, -gDL:function(){return this.jk}, -gcG:function(){return this.jk}, -Am:function(a){this.Gv=4 -this.jk=a}, -E6:function(a,b){this.Gv=8 -this.jk=new P.Ca(a,b)}, -au:function(a){if(this.Gv>=4){this.Lj.toString -P.IA(new P.da(this,a))}else{a.BQ=this.jk -this.jk=a}}, -L3:function(){var z,y,x -z=this.jk -this.jk=null -for(y=null;z!=null;y=z,z=x){x=z.gBQ() -z.BQ=y}return y}, -rX:function(a){var z,y -z=J.x(a) -if(typeof a==="object"&&a!==null&&!!z.$isb8){P.GZ(a,this) -return}y=this.L3() -this.Am(a) -P.HZ(this,y)}, -K5:function(a,b){var z=this.L3() -this.E6(a,b) -P.HZ(this,z)}, -gbY:function(){return new P.CQ(this,P.vs.prototype.K5,null,"K5")}, -OH:function(a){if(this.Gv!==0)H.vh(P.w("Future already completed")) -this.Gv=1 -this.Lj.toString -P.IA(new P.rH(this,a))}, -CG:function(a,b){if(this.Gv!==0)H.vh(P.w("Future already completed")) -this.Gv=1 -this.Lj.toString -P.IA(new P.ZL(this,a,b))}, -L7:function(a,b){this.OH(a)}, -$isvs:true, -$isb8:true, -static:{"":"Gn,Ry,C3,oN,NK",Dt:function(a){var z=new P.vs(0,$.X3,null,null,null,null,null,null) -H.VM(z,[a]) -return z},Ab:function(a,b){var z=new P.vs(0,$.X3,null,null,null,null,null,null) -H.VM(z,[b]) -z.L7(a,b) -return z},Y8:function(a,b,c){var z=$.X3 -z.toString -z=new P.vs(0,z,null,null,a,null,P.VH(b,z),null) -H.VM(z,[c]) -return z},RP:function(a,b,c){var z,y -z=$.X3 -y=P.VH(a,z) -z.toString -y=new P.vs(0,z,null,null,null,b,y,null) -H.VM(y,[c]) -return y},X4:function(a,b){var z=$.X3 -z.toString -z=new P.vs(0,z,null,null,null,null,null,a) -H.VM(z,[b]) -return z},GZ:function(a,b){var z -b.Gv=2 -z=J.x(a) -if(typeof a==="object"&&a!==null&&!!z.$isvs)if(a.Gv>=4)P.HZ(a,b) -else a.au(b) -else a.Rx(new P.xw(b),new P.dm(b))},yE:function(a,b){var z -do{z=b.gBQ() -b.BQ=null -P.HZ(a,b) -if(z!=null){b=z -continue}else break}while(!0)},HZ:function(a,b){var z,y,x,w,v,u,t,s,r -z={} -z.e=a -for(;!0;){y={} -if(!z.e.gcg())return -x=z.e.gNm() -if(x&&b==null){y=z.e -w=y.gcG() -y=y.Lj -v=J.w8(w) -u=w.gI4() -y.toString -P.L2(y,null,y,v,u) -return}if(b==null)return -if(b.BQ!=null){P.yE(z.e,b) -return}if(x){v=z.e.gLj() -u=b.Lj -v.toString -u.toString -v=u==null?v!=null:u!==v}else v=!1 -if(v){y=z.e -w=y.gcG() -y=y.Lj -v=J.w8(w) -u=w.gI4() -y.toString -P.L2(y,null,y,v,u) -return}v=$.X3 -u=b.Lj -if(v==null?u!=null:v!==u){u.toString -P.T8(u,null,u,new P.mi(z,b)) -return}y.b=null -y.c=null -y.d=!1 -u.toString -P.T8(u,null,u,new P.jb(z,y,x,b)) -if(y.d)return -v=y.b===!0 -if(v){u=y.c -t=J.x(u) -t=typeof u==="object"&&u!==null&&!!t.$isb8 -u=t}else u=!1 -if(u){s=y.c -y=J.x(s) -if(typeof s==="object"&&s!==null&&!!y.$isvs&&s.Gv>=4){b.Gv=2 -z.e=s -continue}P.GZ(s,b) -return}if(v){r=b.L3() -y=y.c -b.Gv=4 -b.jk=y}else{r=b.L3() -w=y.c -y=J.w8(w) -v=w.gI4() -b.Gv=8 -b.jk=new P.Ca(y,v)}z.e=b -b=r}}}},da:{"":"Tp;a,b", -call$0:function(){P.HZ(this.a,this.b)}},xw:{"":"Tp;a", -call$1:function(a){this.a.rX(a)}, -$is_aB:true},dm:{"":"Tp;b", -call$2:function(a,b){this.b.K5(a,b)}, -call$1:function(a){return this.call$2(a,null)}, -$is_bh:true, -$is_aB:true},rH:{"":"Tp;a,b", -call$0:function(){this.a.rX(this.b)}},ZL:{"":"Tp;a,b,c", -call$0:function(){this.a.K5(this.b,this.c)}},mi:{"":"Tp;c,d", -call$0:function(){P.HZ(this.c.e,this.d)}},jb:{"":"Tp;c,b,e,f", -call$0:function(){var z,y,x,w,v,u,t,s,r,q,p,o -z={} -try{r=this.c -if(!this.e){y=r.e.gDL() -r=this.f -q=r.Gv===2?null:r.OY -p=this.b -if(q!=null){p.c=r.GP(y) -p.b=!0}else{p.c=y -p.b=!0}}else{x=r.e.gcG() -r=this.f -w=r.Gv===2?null:r.As -v=!0 -if(w!=null)v=w.call$1(J.w8(x)) -if(v===!0)q=(r.Gv===2?null:r.qV)!=null -else q=!1 -if(q){u=r.Gv===2?null:r.qV -r=this.b -r.c=P.K2(u,J.w8(x),x.gI4()) -r.b=!0}else{r=this.b -r.c=x -r.b=!1}}r=this.f -if((r.Gv===2?null:r.o4)!=null){z.a=r.xY() -q=z.a -p=J.x(q) -if(typeof q==="object"&&q!==null&&!!p.$isb8){r.swG(!0) -z.a.Rx(new P.wB(this.c,r),new P.Pu(z,r)) -this.b.d=!0}}}catch(o){z=H.Ru(o) -t=z -s=new H.XO(o,null) -if(this.e){z=J.w8(this.c.e.gcG()) -r=t -r=z==null?r==null:z===r -z=r}else z=!1 -r=this.b -if(z)r.c=this.c.e.gcG() -else r.c=new P.Ca(t,s) -this.b.b=!1}}},wB:{"":"Tp;c,g", -call$1:function(a){P.HZ(this.c.e,this.g)}, -$is_aB:true},Pu:{"":"Tp;a,h", -call$2:function(a,b){var z,y,x -z=this.a -y=z.a -x=J.x(y) -if(typeof y!=="object"||y===null||!x.$isvs){z.a=P.Dt(null) -z.a.E6(a,b)}P.HZ(z.a,this.h)}, -call$1:function(a){return this.call$2(a,null)}, -$is_bh:true, -$is_aB:true},qh:{"":"a;", -tg:function(a,b){var z,y -z={} -y=P.Dt(J.kn) -z.a=null -z.a=this.KR(new P.Sd(z,this,b,y),!0,new P.YJ(y),y.gbY()) -return y}, -aN:function(a,b){var z,y -z={} -y=P.Dt(null) -z.a=null -z.a=this.KR(new P.lz(z,this,b,y),!0,new P.M4(y),y.gbY()) -return y}, -gB:function(a){var z,y -z={} -y=P.Dt(J.im) -z.a=0 -this.KR(new P.B5(z),!0,new P.PI(z,y),y.gbY()) -return y}, -gl0:function(a){var z,y -z={} -y=P.Dt(J.kn) -z.a=null -z.a=this.KR(new P.j4(z,y),!0,new P.i9(y),y.gbY()) -return y}},Sd:{"":"Tp;a,b,c,d", -call$1:function(a){var z,y -z=this.a -y=this.d -P.FE(new P.jv(this.c,a),new P.bi(z,y),P.TB(z.a,y))}, -$is_aB:true},jv:{"":"Tp;e,f", -call$0:function(){return J.xC(this.f,this.e)}},bi:{"":"Tp;a,g", -call$1:function(a){if(a===!0)P.Bb(this.a.a,this.g,!0)}, -$is_aB:true},YJ:{"":"Tp;h", -call$0:function(){this.h.rX(!1)}},lz:{"":"Tp;a,b,c,d", -call$1:function(a){P.FE(new P.Rl(this.c,a),new P.Jb(),P.TB(this.a.a,this.d))}, -$is_aB:true},Rl:{"":"Tp;e,f", -call$0:function(){return this.e.call$1(this.f)}},Jb:{"":"Tp;", -call$1:function(a){}, -$is_aB:true},M4:{"":"Tp;g", -call$0:function(){this.g.rX(null)}},B5:{"":"Tp;a", -call$1:function(a){var z=this.a -z.a=z.a+1}, -$is_aB:true},PI:{"":"Tp;a,b", -call$0:function(){this.b.rX(this.a.a)}},j4:{"":"Tp;a,b", -call$1:function(a){P.Bb(this.a.a,this.b,!1)}, -$is_aB:true},i9:{"":"Tp;c", -call$0:function(){this.c.rX(!0)}},MO:{"":"a;"},Kd:{"":"a;", -gh6:function(){if((this.Gv&8)===0)return this.iP -return this.iP.gJg()}, -Mp:function(){if((this.Gv&8)===0){if(this.iP==null)this.iP=new P.Qk(null,null,0) -return this.iP}var z=this.iP.gJg() -return z}, -ghG:function(){if((this.Gv&8)!==0)return this.iP.gJg() -return this.iP}, -nG:function(){if((this.Gv&4)!==0)return new P.lj("Cannot add event after closing") -return new P.lj("Cannot add event while adding a stream")}, -SL:function(){if(this.yx==null){this.yx=P.Dt(null) -if((this.Gv&2)!==0)this.yx.rX(null)}return this.yx}, -h:function(a,b){if(this.Gv>=4)throw H.b(this.nG()) -this.Rg(b)}, -xO:function(a){var z=this.Gv -if((z&4)!==0)return this.yx -if(z>=4)throw H.b(this.nG()) -this.Gv=(z|4)>>>0 -this.SL() -z=this.Gv -if((z&1)!==0)this.Du() -else if((z&3)===0){z=this.Mp() -z.h(z,C.Wj)}return this.yx}, -Rg:function(a){var z=this.Gv -if((z&1)!==0)this.Iv(a) -else if((z&3)===0){z=this.Mp() -z.h(z,new P.LV(a,null))}}, -ET:function(a){var z,y,x,w,v -if((this.Gv&3)!==0)throw H.b(P.w("Stream has already been listened to.")) -z=$.X3 -y=a?1:0 -x=new P.yU(this,null,null,null,z,y,null,null) -H.VM(x,[null]) -w=this.gh6() -this.Gv=(this.Gv|1)>>>0 -if((this.Gv&8)!==0){v=this.iP -v.sJg(x) -v.QE()}else this.iP=x -x.WN(w) -x.J7(new P.UO(this)) -return x}, -j0:function(a){var z,y -if((this.Gv&8)!==0)this.iP.ed() -this.iP=null -this.Gv=(this.Gv&4294967286|2)>>>0 -z=new P.Bc(this) -y=P.ot(this.gQC()) -if(y!=null)y=y.wM(z) -else z.call$0() -return y}},UO:{"":"Tp;a", -call$0:function(){P.ot(this.a.gnL())}},Bc:{"":"Tp;a", -call$0:function(){var z=this.a.yx -if(z!=null&&z.Gv===0)z.OH(null)}},VT:{"":"a;", -Iv:function(a){this.ghG().Rg(a)}, -Du:function(){this.ghG().Qj()}},Fj:{"":"a;", -Iv:function(a){this.ghG().w6(new P.LV(a,null))}, -Du:function(){this.ghG().w6(C.Wj)}},q1:{"":"Zz;nL<,p4<,Z9<,QC<,iP,Gv,yx"},Zz:{"":"Kd+Fj;"},ly:{"":"MF;nL<,p4<,Z9<,QC<,iP,Gv,yx"},MF:{"":"Kd+VT;"},O9:{"":"ez;Y8", -w4:function(a){return this.Y8.ET(a)}, -giO:function(a){return(H.eQ(this.Y8)^892482866)>>>0}, -n:function(a,b){var z -if(b==null)return!1 -if(this===b)return!0 -z=J.x(b) -if(typeof b!=="object"||b===null||!z.$isO9)return!1 -return b.Y8===this.Y8}, -$isO9:true, -$asez:null},yU:{"":"KA;Y8,dB,o7,Bd,Lj,Gv,lz,Ri", -tA:function(){return this.Y8.j0(this)}, -uO:function(){var z,y -z=this.Y8 -if((z.Gv&8)!==0){y=z.iP -y.yy(y)}P.ot(z.gp4())}, -gp4:function(){return new P.EV(this,P.yU.prototype.uO,null,"uO")}, -LP:function(){var z=this.Y8 -if((z.Gv&8)!==0)z.iP.QE() -P.ot(z.gZ9())}, -gZ9:function(){return new P.EV(this,P.yU.prototype.LP,null,"LP")}, -$asKA:null},nP:{"":"a;"},KA:{"":"a;dB,o7,Bd,Lj<,Gv,lz,Ri", -WN:function(a){if(a==null)return -this.Ri=a -if(!a.gl0(a)){this.Gv=(this.Gv|64)>>>0 -this.Ri.t2(this)}}, -fe:function(a){$.X3.toString -this.dB=a}, -fm:function(a,b){this.o7=P.VH(b,$.X3)}, -y5:function(a){$.X3.toString -this.Bd=a}, -nB:function(a,b){var z=this.Gv -if((z&8)!==0)return -this.Gv=(z+128|4)>>>0 -if(z<128&&this.Ri!=null)this.Ri.FK() -if((z&4)===0&&(this.Gv&32)===0)this.J7(this.gp4())}, -yy:function(a){return this.nB(a,null)}, -QE:function(){var z,y -z=this.Gv -if((z&8)!==0)return -if(z>=128){this.Gv=z-128 -z=this.Gv -if(z<128){if((z&64)!==0){y=this.Ri -y=!y.gl0(y)}else y=!1 -if(y)this.Ri.t2(this) -else{this.Gv=(z&4294967291)>>>0 -if((this.Gv&32)===0)this.J7(this.gZ9())}}}}, -ed:function(){this.Gv=(this.Gv&4294967279)>>>0 -if((this.Gv&8)!==0)return this.lz -this.Ek() -return this.lz}, -gzG:function(){if(this.Gv<128){var z=this.Ri -z=z==null||z.gl0(z)}else z=!1 -return z}, -Ek:function(){this.Gv=(this.Gv|8)>>>0 -if((this.Gv&64)!==0)this.Ri.FK() -if((this.Gv&32)===0)this.Ri=null -this.lz=this.tA()}, -Rg:function(a){var z=this.Gv -if((z&8)!==0)return -if(z<32)this.Iv(a) -else this.w6(new P.LV(a,null))}, -Qj:function(){var z=this.Gv -if((z&8)!==0)return -this.Gv=(z|2)>>>0 -if(this.Gv<32)this.Du() -else this.w6(C.Wj)}, -uO:function(){}, -gp4:function(){return new P.EV(this,P.KA.prototype.uO,null,"uO")}, -LP:function(){}, -gZ9:function(){return new P.EV(this,P.KA.prototype.LP,null,"LP")}, -tA:function(){}, -w6:function(a){var z,y -z=this.Ri -if(z==null){z=new P.Qk(null,null,0) -this.Ri=z}z.h(z,a) -y=this.Gv -if((y&64)===0){this.Gv=(y|64)>>>0 -if(this.Gv<128)this.Ri.t2(this)}}, -Iv:function(a){var z=this.Gv -this.Gv=(z|32)>>>0 -this.Lj.m1(this.dB,a) -this.Gv=(this.Gv&4294967263)>>>0 -this.Kl((z&4)!==0)}, -Du:function(){var z,y,x -z=new P.qB(this) -this.Ek() -this.Gv=(this.Gv|16)>>>0 -y=this.lz -x=J.x(y) -if(typeof y==="object"&&y!==null&&!!x.$isb8)y.wM(z) -else z.call$0()}, -J7:function(a){var z=this.Gv -this.Gv=(z|32)>>>0 -a.call$0() -this.Gv=(this.Gv&4294967263)>>>0 -this.Kl((z&4)!==0)}, -Kl:function(a){var z,y,x -z=this.Gv -if((z&64)!==0){y=this.Ri -y=y.gl0(y)}else y=!1 -if(y){this.Gv=(z&4294967231)>>>0 -if((this.Gv&4)!==0&&this.gzG())this.Gv=(this.Gv&4294967291)>>>0}for(;!0;a=x){z=this.Gv -if((z&8)!==0){this.Ri=null -return}x=(z&4)!==0 -if(a===x)break -this.Gv=(z^32)>>>0 -if(x)this.uO() -else this.LP() -this.Gv=(this.Gv&4294967263)>>>0}z=this.Gv -if((z&64)!==0&&z<128)this.Ri.t2(this)}, -static:{"":"ry,bG,Q9,Ir,na,lk,mN,N3,bs",}},qB:{"":"Tp;a", -call$0:function(){var z,y -z=this.a -y=z.Gv -if((y&16)===0)return -z.Gv=(y|42)>>>0 -z.Lj.bH(z.Bd) -z.Gv=(z.Gv&4294967263)>>>0}},ez:{"":"qh;", -KR:function(a,b,c,d){var z=this.w4(!0===b) -z.fe(a) -z.fm(z,d) -z.y5(c) -return z}, -w4:function(a){var z,y -z=$.X3 -y=a?1:0 -return new P.KA(null,null,null,z,y,null,null)}, -$asqh:null},fI:{"":"a;LD@"},LV:{"":"fI;P,LD", -Fx:function(a){a.Iv(this.P)}},dp:{"":"a;", -Fx:function(a){a.Du()}, -gLD:function(){return}, -sLD:function(a){throw H.b(P.w("No events after a done."))}},B3:{"":"a;", -t2:function(a){var z=this.Gv -if(z===1)return -if(z>=1){this.Gv=1 -return}P.rb(new P.CR(this,a)) -this.Gv=1}, -FK:function(){if(this.Gv===1)this.Gv=3}},CR:{"":"Tp;a,b", -call$0:function(){var z,y -z=this.a -y=z.Gv -z.Gv=0 -if(y===3)return -z.TO(this.b)}},Qk:{"":"B3;zR,N6,Gv", -gl0:function(a){return this.N6==null}, -h:function(a,b){var z=this.N6 -if(z==null){this.N6=b -this.zR=b}else{z.sLD(b) -this.N6=b}}, -TO:function(a){var z=this.zR -this.zR=z.gLD() -if(this.zR==null)this.N6=null -z.Fx(a)}},dR:{"":"Tp;a,b,c", -call$0:function(){return this.a.K5(this.b,this.c)}},uR:{"":"Tp;a,b", -call$2:function(a,b){return P.NX(this.a,this.b,a,b)}, -$is_bh:true},QX:{"":"Tp;a,b", -call$0:function(){return this.a.rX(this.b)}},fZ:{"":"a;", -bH:function(a){var z,y,x,w -try{x=this.Gr(a) -return x}catch(w){x=H.Ru(w) -z=x -y=new H.XO(w,null) -return this.hk(z,y)}}, -m1:function(a,b){var z,y,x,w -try{x=this.FI(a,b) -return x}catch(w){x=H.Ru(w) -z=x -y=new H.XO(w,null) -return this.hk(z,y)}}, -xi:function(a,b){var z=this.Al(a) -if(b)return new P.TF(this,z) -else return new P.K5(this,z)}, -oj:function(a,b){var z=this.cR(a) -if(b)return new P.Cg(this,z) -else return new P.Hs(this,z)}},TF:{"":"Tp;a,b", -call$0:function(){return this.a.bH(this.b)}},K5:{"":"Tp;c,d", -call$0:function(){return this.c.Gr(this.d)}},Cg:{"":"Tp;a,b", -call$1:function(a){return this.a.m1(this.b,a)}, -$is_aB:true},Hs:{"":"Tp;c,d", -call$1:function(a){return this.c.FI(this.d,a)}, -$is_aB:true},pK:{"":"Tp;a,b", -call$0:function(){P.IA(new P.eM(this.a,this.b))}},eM:{"":"Tp;c,d", -call$0:function(){var z,y,x -z=this.c -P.JS("Uncaught Error: "+H.d(z)) -y=this.d -if(y==null){x=J.x(z) -x=typeof z==="object"&&z!==null&&!!x.$isGe}else x=!1 -if(x)y=z.gI4() -if(y!=null)P.JS("Stack Trace: \n"+H.d(y)+"\n") -throw H.b(z)}},R8:{"":"fZ;", -t:function(a,b){return}, -hk:function(a,b){return P.L2(this,null,this,a,b)}, -Gr:function(a){return P.T8(this,null,this,a)}, -FI:function(a,b){return P.V7(this,null,this,a,b)}, -Al:function(a){return a}, -cR:function(a){return a}}}],["dart.collection","dart:collection",,P,{Ou:function(a,b){return J.xC(a,b)},T9:function(a){return J.v1(a)},Py:function(a,b,c,d,e){var z=new P.k6(0,null,null,null,null) -H.VM(z,[d,e]) -return z},yv:function(a){var z=new P.YO(0,null,null,null,null) -H.VM(z,[a]) -return z},FO:function(a){var z,y -y=$.xb() -if(y.tg(y,a))return"(...)" -y=$.xb() -y.h(y,a) -z=[] -try{P.Vr(a,z)}finally{y=$.xb() -y.Rz(y,a)}y=P.p9("(") -y.We(z,", ") -y.KF(")") -return y.vM},Vr:function(a,b){var z,y,x,w,v,u,t,s,r,q -z=a.gA(a) -y=0 -x=0 -while(!0){if(!(y<80||x<3))break -if(!z.G())return -w=H.d(z.gl()) -b.push(w) -y+=w.length+2;++x}if(!z.G()){if(x<=5)return -if(0>=b.length)throw H.e(b,0) -v=b.pop() -if(0>=b.length)throw H.e(b,0) -u=b.pop()}else{t=z.gl();++x -if(!z.G()){if(x<=4){b.push(H.d(t)) -return}v=H.d(t) -if(0>=b.length)throw H.e(b,0) -u=b.pop() -y+=v.length+2}else{s=z.gl();++x -for(;z.G();t=s,s=r){r=z.gl();++x -if(x>100){while(!0){if(!(y>75&&x>3))break -if(0>=b.length)throw H.e(b,0) -y-=b.pop().length+2;--x}b.push("...") -return}}u=H.d(t) -v=H.d(s) -y+=v.length+u.length+4}}if(x>b.length+2){y+=5 -q="..."}else q=null -while(!0){if(!(y>80&&b.length>3))break -if(0>=b.length)throw H.e(b,0) -y-=b.pop().length+2 -if(q==null){y+=5 -q="..."}}if(q!=null)b.push(q) -b.push(u) -b.push(v)},L5:function(a,b,c,d,e){var z=new P.YB(0,null,null,null,null,null,0) -H.VM(z,[d,e]) -return z},Ls:function(a,b,c,d){var z=new P.b6(0,null,null,null,null,null,0) -H.VM(z,[d]) -return z},vW:function(a){var z,y,x,w -z={} -for(x=0;x<$.tw().length;++x){w=$.tw() -if(x>=w.length)throw H.e(w,x) -if(w[x]===a)return"{...}"}y=P.p9("") -try{$.tw().push(a) -y.KF("{") -z.a=!0 -J.kH(a,new P.ZQ(z,y)) -y.KF("}")}finally{z=$.tw() -if(0>=z.length)throw H.e(z,0) -z.pop()}return y.gvM()},k6:{"":"a;X5,vv,OX,OB,aw", -gB:function(a){return this.X5}, -gl0:function(a){return this.X5===0}, -gvc:function(){var z=new P.fG(this) -H.VM(z,[H.W8(this,"k6",0)]) -return z}, -gUQ:function(a){var z=new P.fG(this) -H.VM(z,[H.W8(this,"k6",0)]) -return H.K1(z,new P.oi(this),H.W8(z,"mW",0),null)}, -x4:function(a){var z=this.OB -if(z==null)return!1 -return this.aH(z[this.nm(a)],a)>=0}, -FV:function(a,b){H.bQ(b,new P.DJ(this))}, -t:function(a,b){var z,y,x,w,v,u,t -if(typeof b==="string"&&b!=="__proto__"){z=this.vv -if(z==null)y=null -else{x=z[b] -y=x===z?null:x}return y}else if(typeof b==="number"&&(b&0x3ffffff)===b){w=this.OX -if(w==null)y=null -else{x=w[b] -y=x===w?null:x}return y}else{v=this.OB -if(v==null)return -u=v[this.nm(b)] -t=this.aH(u,b) -return t<0?null:u[t+1]}}, -u:function(a,b,c){var z,y,x,w,v,u -if(typeof b==="string"&&b!=="__proto__"){z=this.vv -if(z==null){z=P.a0() -this.vv=z}this.dg(z,b,c)}else if(typeof b==="number"&&(b&0x3ffffff)===b){y=this.OX -if(y==null){y=P.a0() -this.OX=y}this.dg(y,b,c)}else{x=this.OB -if(x==null){x=P.a0() -this.OB=x}w=this.nm(b) -v=x[w] -if(v==null){P.a8(x,w,[b,c]) -this.X5=this.X5+1 -this.aw=null}else{u=this.aH(v,b) -if(u>=0)v[u+1]=c -else{v.push(b,c) -this.X5=this.X5+1 -this.aw=null}}}}, -aN:function(a,b){var z,y,x,w -z=this.Ig() -for(y=z.length,x=0;x",z) -delete z[""] -return z}}},oi:{"":"Tp;a", -call$1:function(a){var z=this.a -return z.t(z,a)}, -$is_aB:true},DJ:{"":"Tp;a", -call$2:function(a,b){var z=this.a -z.u(z,a,b)}, -$is_bh:true},fG:{"":"mW;Fb", -gB:function(a){return this.Fb.X5}, -gl0:function(a){return this.Fb.X5===0}, -gA:function(a){var z=this.Fb -return new P.EQ(z,z.Ig(),0,null)}, -tg:function(a,b){return this.Fb.x4(b)}, -aN:function(a,b){var z,y,x,w -z=this.Fb -y=z.Ig() -for(x=y.length,w=0;w=z.length){this.fD=null -return!1}else{this.fD=z[y] -this.zi=y+1 -return!0}}},YB:{"":"a;X5,vv,OX,OB,H9,lX,zN", -gB:function(a){return this.X5}, -gl0:function(a){return this.X5===0}, -gvc:function(){var z=new P.i5(this) -H.VM(z,[H.W8(this,"YB",0)]) -return z}, -gUQ:function(a){var z=new P.i5(this) -H.VM(z,[H.W8(this,"YB",0)]) -return H.K1(z,new P.a1(this),H.W8(z,"mW",0),null)}, -x4:function(a){var z,y,x -if(typeof a==="string"&&a!=="__proto__"){z=this.vv -if(z==null)return!1 -return z[a]!=null}else if(typeof a==="number"&&(a&0x3ffffff)===a){y=this.OX -if(y==null)return!1 -return y[a]!=null}else{x=this.OB -if(x==null)return!1 -return this.aH(x[this.nm(a)],a)>=0}}, -FV:function(a,b){H.bQ(b,new P.S9(this))}, -t:function(a,b){var z,y,x,w,v,u -if(typeof b==="string"&&b!=="__proto__"){z=this.vv -if(z==null)return -y=z[b] -return y==null?null:y.gS4()}else if(typeof b==="number"&&(b&0x3ffffff)===b){x=this.OX -if(x==null)return -y=x[b] -return y==null?null:y.gS4()}else{w=this.OB -if(w==null)return -v=w[this.nm(b)] -u=this.aH(v,b) -if(u<0)return -return v[u].gS4()}}, -u:function(a,b,c){var z,y,x,w,v,u -if(typeof b==="string"&&b!=="__proto__"){z=this.vv -if(z==null){z=P.Qs() -this.vv=z}this.dg(z,b,c)}else if(typeof b==="number"&&(b&0x3ffffff)===b){y=this.OX -if(y==null){y=P.Qs() -this.OX=y}this.dg(y,b,c)}else{x=this.OB -if(x==null){x=P.Qs() -this.OB=x}w=this.nm(b) -v=x[w] -if(v==null)x[w]=[this.pE(b,c)] -else{u=this.aH(v,b) -if(u>=0)v[u].sS4(c) -else v.push(this.pE(b,c))}}}, -Rz:function(a,b){var z,y,x,w -if(typeof b==="string"&&b!=="__proto__")return this.Nv(this.vv,b) -else if(typeof b==="number"&&(b&0x3ffffff)===b)return this.Nv(this.OX,b) -else{z=this.OB -if(z==null)return -y=z[this.nm(b)] -x=this.aH(y,b) -if(x<0)return -w=y.splice(x,1)[0] -this.Vb(w) -return w.gS4()}}, -aN:function(a,b){var z,y -z=this.H9 -y=this.zN -for(;z!=null;){b.call$2(z.gkh(),z.S4) -if(y!==this.zN)throw H.b(P.a4(this)) -z=z.DG}}, -dg:function(a,b,c){var z=a[b] -if(z==null)a[b]=this.pE(b,c) -else z.sS4(c)}, -Nv:function(a,b){var z -if(a==null)return -z=a[b] -if(z==null)return -this.Vb(z) -delete a[b] -return z.gS4()}, -pE:function(a,b){var z,y -z=new P.db(a,b,null,null) -if(this.H9==null){this.lX=z -this.H9=z}else{y=this.lX -z.zQ=y -y.sDG(z) -this.lX=z}this.X5=this.X5+1 -this.zN=this.zN+1&67108863 -return z}, -Vb:function(a){var z,y -z=a.gzQ() -y=a.gDG() -if(z==null)this.H9=y -else z.sDG(y) -if(y==null)this.lX=z -else y.szQ(z) -this.X5=this.X5-1 -this.zN=this.zN+1&67108863}, -nm:function(a){return J.v1(a)&0x3ffffff}, -aH:function(a,b){var z,y -if(a==null)return-1 -z=a.length -for(y=0;y"]=z -delete z[""] -return z}}},a1:{"":"Tp;a", -call$1:function(a){var z=this.a -return z.t(z,a)}, -$is_aB:true},S9:{"":"Tp;a", -call$2:function(a,b){var z=this.a -z.u(z,a,b)}, -$is_bh:true},db:{"":"a;kh<,S4@,DG@,zQ@"},i5:{"":"mW;Fb", -gB:function(a){return this.Fb.X5}, -gl0:function(a){return this.Fb.X5===0}, -gA:function(a){var z=this.Fb -z=new P.N6(z,z.zN,null,null) -z.zq=z.Fb.H9 -return z}, -tg:function(a,b){return this.Fb.x4(b)}, -aN:function(a,b){var z,y,x -z=this.Fb -y=z.H9 -x=z.zN -for(;y!=null;){b.call$1(y.gkh()) -if(x!==z.zN)throw H.b(P.a4(z)) -y=y.DG}}, -$asmW:null, -$isqC:true},N6:{"":"a;Fb,zN,zq,fD", -gl:function(){return this.fD}, -G:function(){var z=this.Fb -if(this.zN!==z.zN)throw H.b(P.a4(z)) -else{z=this.zq -if(z==null){this.fD=null -return!1}else{this.fD=z.gkh() -this.zq=this.zq.gDG() -return!0}}}},jg:{"":"u3;", -gA:function(a){return new P.oz(this,this.Zl(),0,null)}, -gB:function(a){return this.X5}, -gl0:function(a){return this.X5===0}, -tg:function(a,b){var z,y,x -if(typeof b==="string"&&b!=="__proto__"){z=this.vv -return z==null?!1:z[b]!=null}else if(typeof b==="number"&&(b&0x3ffffff)===b){y=this.OX -return y==null?!1:y[b]!=null}else{x=this.OB -if(x==null)return!1 -return this.aH(x[this.nm(b)],b)>=0}}, -Zt:function(a){var z,y,x,w -if(!(typeof a==="string"&&a!=="__proto__"))z=typeof a==="number"&&(a&0x3ffffff)===a -else z=!0 -if(z)return this.tg(this,a)?a:null -y=this.OB -if(y==null)return -x=y[this.nm(a)] -w=this.aH(x,a) -if(w<0)return -return J.UQ(x,w)}, -h:function(a,b){var z,y,x,w,v,u -if(typeof b==="string"&&b!=="__proto__"){z=this.vv -if(z==null){y=Object.create(null) -y[""]=y -delete y[""] -this.vv=y -z=y}return this.cA(z,b)}else if(typeof b==="number"&&(b&0x3ffffff)===b){x=this.OX -if(x==null){y=Object.create(null) -y[""]=y -delete y[""] -this.OX=y -x=y}return this.cA(x,b)}else{w=this.OB -if(w==null){y=Object.create(null) -y[""]=y -delete y[""] -this.OB=y -w=y}v=this.nm(b) -u=w[v] -if(u==null)w[v]=[b] -else{if(this.aH(u,b)>=0)return!1 -u.push(b)}this.X5=this.X5+1 -this.DM=null -return!0}}, -FV:function(a,b){var z -for(z=new H.a7(b,b.length,0,null);z.G();)this.h(this,z.mD)}, -Rz:function(a,b){var z,y,x -if(typeof b==="string"&&b!=="__proto__")return this.Nv(this.vv,b) -else if(typeof b==="number"&&(b&0x3ffffff)===b)return this.Nv(this.OX,b) -else{z=this.OB -if(z==null)return!1 -y=z[this.nm(b)] -x=this.aH(y,b) -if(x<0)return!1 -this.X5=this.X5-1 -this.DM=null -y.splice(x,1) -return!0}}, -Zl:function(){var z,y,x,w,v,u,t,s,r,q,p,o -z=this.DM -if(z!=null)return z -y=P.A(this.X5,null) -x=this.vv -if(x!=null){w=Object.getOwnPropertyNames(x) -v=w.length -for(u=0,t=0;t=z.length){this.fD=null -return!1}else{this.fD=z[y] -this.zi=y+1 -return!0}}},b6:{"":"u3;X5,vv,OX,OB,H9,lX,zN", -gA:function(a){var z=new P.zQ(this,this.zN,null,null) -z.zq=z.O2.H9 -return z}, -gB:function(a){return this.X5}, -gl0:function(a){return this.X5===0}, -tg:function(a,b){var z,y,x -if(typeof b==="string"&&b!=="__proto__"){z=this.vv -if(z==null)return!1 -return z[b]!=null}else if(typeof b==="number"&&(b&0x3ffffff)===b){y=this.OX -if(y==null)return!1 -return y[b]!=null}else{x=this.OB -if(x==null)return!1 -return this.aH(x[this.nm(b)],b)>=0}}, -Zt:function(a){var z,y,x,w -if(!(typeof a==="string"&&a!=="__proto__"))z=typeof a==="number"&&(a&0x3ffffff)===a -else z=!0 -if(z)return this.tg(this,a)?a:null -else{y=this.OB -if(y==null)return -x=y[this.nm(a)] -w=this.aH(x,a) -if(w<0)return -return J.UQ(x,w).gGc()}}, -aN:function(a,b){var z,y -z=this.H9 -y=this.zN -for(;z!=null;){b.call$1(z.gGc()) -if(y!==this.zN)throw H.b(P.a4(this)) -z=z.DG}}, -h:function(a,b){var z,y,x,w,v,u -if(typeof b==="string"&&b!=="__proto__"){z=this.vv -if(z==null){y=Object.create(null) -y[""]=y -delete y[""] -this.vv=y -z=y}return this.cA(z,b)}else if(typeof b==="number"&&(b&0x3ffffff)===b){x=this.OX -if(x==null){y=Object.create(null) -y[""]=y -delete y[""] -this.OX=y -x=y}return this.cA(x,b)}else{w=this.OB -if(w==null){y=Object.create(null) -y[""]=y -delete y[""] -this.OB=y -w=y}v=this.nm(b) -u=w[v] -if(u==null)w[v]=[this.xf(b)] -else{if(this.aH(u,b)>=0)return!1 -u.push(this.xf(b))}return!0}}, -FV:function(a,b){var z -for(z=J.GP(b);z.G();)this.h(this,z.mD)}, -Rz:function(a,b){var z,y,x -if(b!=="__proto__")return this.Nv(this.vv,b) -else{z=this.OB -if(z==null)return!1 -y=z[this.nm(b)] -x=this.aH(y,b) -if(x<0)return!1 -this.Vb(y.splice(x,1)[0]) -return!0}}, -cA:function(a,b){if(a[b]!=null)return!1 -a[b]=this.xf(b) -return!0}, -Nv:function(a,b){var z -if(a==null)return!1 -z=a[b] -if(z==null)return!1 -this.Vb(z) -delete a[b] -return!0}, -xf:function(a){var z,y -z=new P.tj(a,null,null) -if(this.H9==null){this.lX=z -this.H9=z}else{y=this.lX -z.zQ=y -y.sDG(z) -this.lX=z}this.X5=this.X5+1 -this.zN=this.zN+1&67108863 -return z}, -Vb:function(a){var z,y -z=a.gzQ() -y=a.gDG() -if(z==null)this.H9=y -else z.sDG(y) -if(y==null)this.lX=z -else y.szQ(z) -this.X5=this.X5-1 -this.zN=this.zN+1&67108863}, -nm:function(a){return J.v1(a)&0x3ffffff}, -aH:function(a,b){var z,y -if(a==null)return-1 -z=a.length -for(y=0;y=this.gB(a))return-1 -if(c<0)c=0 -for(z=c;z>>0){x=this.v5 -if(y<0||y>=x.length)throw H.e(x,y) -b.call$1(x[y]) -if(z!==this.qT)H.vh(P.a4(this))}}, -gl0:function(a){return this.av===this.HV}, -gB:function(a){return(this.HV-this.av&this.v5.length-1)>>>0}, -h:function(a,b){this.NZ(b)}, -FV:function(a,b){var z,y,x,w,v,u,t -z=b.length -y=this.gB(this) -x=y+z -w=this.v5 -v=w.length -if(x>=v){this.vz(x) -w=this.v5 -H.qG(w,y,x,b,0) -this.HV=this.HV+z}else{x=this.HV -u=v-x -if(z=x)throw H.e(z,y) -w=z[y] -this.av=(y+1&x-1)>>>0 -return w}, -NZ:function(a){var z,y,x -z=this.v5 -y=this.HV -x=z.length -if(y<0||y>=x)throw H.e(z,y) -z[y]=a -this.HV=(y+1&x-1)>>>0 -if(this.av===this.HV)this.VW() -this.qT=this.qT+1}, -VW:function(){var z,y,x,w -z=P.A(this.v5.length*2,H.W8(this,"Sw",0)) -H.VM(z,[H.W8(this,"Sw",0)]) -y=this.v5 -x=this.av -w=y.length-x -H.qG(z,0,w,y,x) -y=this.av -x=this.v5 -H.qG(z,w,w+y,x,0) -this.av=0 -this.HV=this.v5.length -this.v5=z}, -e4:function(a){var z,y,x,w,v -z=this.av -y=this.HV -x=this.v5 -if(z<=y){w=y-z -H.qG(a,0,w,x,z) -return w}else{v=x.length-z -H.qG(a,0,v,x,z) -z=this.HV -y=this.v5 -H.qG(a,v,v+z,y,0) -return this.HV+v}}, -vz:function(a){var z=P.A(P.ua(a),H.W8(this,"Sw",0)) -H.VM(z,[H.W8(this,"Sw",0)]) -this.HV=this.e4(z) -this.v5=z -this.av=0}, -Eo:function(a,b){var z=P.A(8,b) -H.VM(z,[b]) -this.v5=z}, -$asmW:null, -$isqC:true, -static:{"":"TN",NZ:function(a,b){var z=new P.Sw(null,0,0,0) -H.VM(z,[b]) -z.Eo(a,b) -return z},ua:function(a){var z -if(typeof a!=="number")throw a.O() -a=(a<<2>>>0)-1 -for(;!0;a=z){z=(a&a-1)>>>0 -if(z===0)return a}}}},o0:{"":"a;Lz,pP,qT,Dc,fD", -gl:function(){return this.fD}, -G:function(){var z,y,x -z=this.Lz -if(this.qT!==z.qT)H.vh(P.a4(z)) -y=this.Dc -if(y===this.pP){this.fD=null -return!1}x=z.v5 -if(y<0||y>=x.length)throw H.e(x,y) -this.fD=x[y] -this.Dc=(this.Dc+1&z.v5.length-1)>>>0 -return!0}, -static:{MW:function(a){return new P.o0(a,a.HV,a.qT,a.av,null)}}}}],["dart.convert","dart:convert",,P,{VQ:function(a,b){var z=new P.JC() -return z.call$2(null,new P.f1(z).call$1(a))},BS:function(a,b){var z,y,x,w -x=a -if(typeof x!=="string")throw H.b(new P.AT(a)) -z=null -try{z=JSON.parse(a)}catch(w){x=H.Ru(w) -y=x -throw H.b(P.cD(String(y)))}return P.VQ(z,b)},tp:function(a){return a.Lt()},JC:{"":"Tp;", -call$2:function(a,b){return b}, -$is_bh:true},f1:{"":"Tp;a", -call$1:function(a){var z,y,x,w,v,u,t -if(a==null||typeof a!="object")return a -if(Object.getPrototypeOf(a)===Array.prototype){z=a -for(y=this.a,x=0;x0){this.C7(y.t(a,0)) -for(x=1;x=y)throw H.e(z,v) -w[v]=z[v]}return w},JS:function(a){var z=J.AG(a) -H.LJ(z)},HM:function(a){return H.eT(a)},CL:{"":"Tp;a", -call$2:function(a,b){var z=this.a -if(z.b>0)z.a.KF(", ") -z.a.KF(P.Hp(a))}, -$is_bh:true},iP:{"":"a;rq,aL", -n:function(a,b){var z -if(b==null)return!1 -z=J.x(b) -if(typeof b!=="object"||b===null||!z.$isiP)return!1 -return this.rq===b.rq&&this.aL===b.aL}, -giO:function(a){return this.rq}, -bu:function(a){var z,y,x,w,v,u,t,s -z=new P.pl() -y=new P.Hn().call$1(H.tJ(this)) -x=z.call$1(H.NS(this)) -w=z.call$1(H.jA(this)) -v=z.call$1(H.KL(this)) -u=z.call$1(H.ch(this)) -t=z.call$1(H.Jd(this)) -s=new P.Zl().call$1(H.o1(this)) -if(this.aL)return H.d(y)+"-"+H.d(x)+"-"+H.d(w)+" "+H.d(v)+":"+H.d(u)+":"+H.d(t)+"."+H.d(s)+"Z" -else return H.d(y)+"-"+H.d(x)+"-"+H.d(w)+" "+H.d(v)+":"+H.d(u)+":"+H.d(t)+"."+H.d(s)}, -h:function(a,b){return P.Wu(C.CD.g(this.rq,b.gVs()),this.aL)}, -RM:function(a,b){if(Math.abs(a)>8640000000000000)throw H.b(new P.AT(a))}, -EK:function(){H.o2(this)}, -$isiP:true, -static:{"":"Oj,Vp,df,p2,h2,QC,nm,Yp,kc,Xs,k3,cR,E0,Ke,lT,Nr,bm,o4,Kz,ek,yf,Fk",Wu:function(a,b){var z=new P.iP(a,b) -z.RM(a,b) -return z},Gi:function(){var z=new P.iP(Date.now(),!1) -z.EK() -return z}}},Hn:{"":"Tp;", -call$1:function(a){var z,y -z=J.dX(a) -y=a<0?"-":"" -if(z>=1000)return H.d(a) -if(z>=100)return y+"0"+H.d(z) -if(z>=10)return y+"00"+H.d(z) -return y+"000"+H.d(z)}, -$is_aB:true},Zl:{"":"Tp;", -call$1:function(a){var z=J.Wx(a) -if(z.F(a,100))return H.d(a) -if(z.F(a,10))return"0"+H.d(a) -return"00"+H.d(a)}, -$is_aB:true},pl:{"":"Tp;", -call$1:function(a){if(J.J5(a,10))return H.d(a) -return"0"+H.d(a)}, -$is_aB:true},a6:{"":"a;Fq<", -g:function(a,b){return P.k5(0,0,this.Fq+b.gFq(),0,0,0)}, -C:function(a,b){return C.CD.C(this.Fq,b.gFq())}, -D:function(a,b){return C.CD.D(this.Fq,b.gFq())}, -F:function(a,b){return C.CD.F(this.Fq,b.gFq())}, -n:function(a,b){var z -if(b==null)return!1 -z=J.x(b) -if(typeof b!=="object"||b===null||!z.$isa6)return!1 -return this.Fq===b.Fq}, -giO:function(a){return this.Fq&0x1FFFFFFF}, -bu:function(a){var z,y,x,w,v -z=new P.DW() -y=this.Fq -if(y<0)return"-"+H.d(P.k5(0,0,-y,0,0,0)) -x=z.call$1(C.CD.JV(C.CD.Z(y,60000000),60)) -w=z.call$1(C.CD.JV(C.CD.Z(y,1000000),60)) -v=new P.P7().call$1(C.CD.JV(y,1000000)) -return H.d(C.CD.Z(y,3600000000))+":"+H.d(x)+":"+H.d(w)+"."+H.d(v)}, -$isa6:true, -static:{"":"Bp,S4,dk,Lo,zj,b2,q9,Ie,Do,f4,kT,IJ,V6,Vk,S8,rG",k5:function(a,b,c,d,e,f){return new P.a6(a*86400000000+b*3600000000+e*60000000+f*1000000+d*1000+c)}}},P7:{"":"Tp;", -call$1:function(a){var z=J.Wx(a) -if(z.F(a,100000))return H.d(a) -if(z.F(a,10000))return"0"+H.d(a) -if(z.F(a,1000))return"00"+H.d(a) -if(z.F(a,100))return"000"+H.d(a) -if(z.D(a,10))return"0000"+H.d(a) -return"00000"+H.d(a)}, -$is_aB:true},DW:{"":"Tp;", -call$1:function(a){if(J.J5(a,10))return H.d(a) -return"0"+H.d(a)}, -$is_aB:true},Ge:{"":"a;", -gI4:function(){return new H.XO(this.$thrownJsError,null)}, -$isGe:true},LK:{"":"Ge;", -bu:function(a){return"Throw of null."}},AT:{"":"Ge;G1", -bu:function(a){var z=this.G1 -if(z!=null)return"Illegal argument(s): "+H.d(z) -return"Illegal argument(s)"}, -static:{u:function(a){return new P.AT(a)}}},bJ:{"":"AT;G1", -bu:function(a){return"RangeError: "+H.d(this.G1)}, -static:{N:function(a){return new P.bJ("value "+H.d(a))},TE:function(a,b,c){return new P.bJ("value "+H.d(a)+" not in range "+b+".."+H.d(c))}}},ub:{"":"Ge;G1", -bu:function(a){return"Unsupported operation: "+this.G1}, -static:{f:function(a){return new P.ub(a)}}},ds:{"":"Ge;G1", -bu:function(a){var z=this.G1 -return z!=null?"UnimplementedError: "+H.d(z):"UnimplementedError"}, -$isGe:true, -static:{SY:function(a){return new P.ds(a)}}},lj:{"":"Ge;G1", -bu:function(a){return"Bad state: "+this.G1}, -static:{w:function(a){return new P.lj(a)}}},UV:{"":"Ge;YA", -bu:function(a){var z=this.YA -if(z==null)return"Concurrent modification during iteration." -return"Concurrent modification during iteration: "+H.d(P.hl(z))+"."}, -static:{a4:function(a){return new P.UV(a)}}},VS:{"":"a;", -bu:function(a){return"Stack Overflow"}, -gI4:function(){return}, -$isGe:true},t7:{"":"Ge;Wo", -bu:function(a){return"Reading static variable '"+this.Wo+"' during its initialization"}, -static:{Gz:function(a){return new P.t7(a)}}},HG:{"":"a;G1", -bu:function(a){var z=this.G1 -if(z==null)return"Exception" -return"Exception: "+H.d(z)}},oe:{"":"a;G1", -bu:function(a){return"FormatException: "+this.G1}, -static:{cD:function(a){return new P.oe(a)}}},kM:{"":"a;oc", -bu:function(a){return"Expando:"+H.d(this.oc)}, -t:function(a,b){var z=H.of(b,"expando$values") -return z==null?null:H.of(z,this.J4())}, -u:function(a,b,c){var z=H.of(b,"expando$values") -if(z==null){z=new P.a() -H.aw(b,"expando$values",z)}H.aw(z,this.J4(),c)}, -J4:function(){var z,y -z=H.of(this,"expando$key") -if(z==null){y=$.Ss -$.Ss=y+1 -z="expando$key$"+y -H.aw(this,"expando$key",z)}return z}, -static:{"":"bZ,rl,Ss",}},EH:{"":"a;"},An:{"":"a;"},c8:{"":"a;", -bu:function(a){return"null"}},a:{"":";", -n:function(a,b){return this===b}, -giO:function(a){return H.eQ(this)}, -bu:function(a){return H.a5(this)}},Od:{"":"a;"},mE:{"":"a;"},Rn:{"":"a;vM<", -gB:function(a){return this.vM.length}, -gl0:function(a){return this.vM.length===0}, -KF:function(a){var z=typeof a==="string"?a:H.d(a) -this.vM=this.vM+z}, -We:function(a,b){var z,y -z=J.GP(a) -if(!z.G())return -if(b.length===0)do{y=z.gl() -y=typeof y==="string"?y:H.d(y) -this.vM=this.vM+y}while(z.G()) -else{this.KF(z.gl()) -for(;z.G();){this.vM=this.vM+b -y=z.gl() -y=typeof y==="string"?y:H.d(y) -this.vM=this.vM+y}}}, -bu:function(a){return this.vM}, -PD:function(a){this.vM=a}, -static:{p9:function(a){var z=new P.Rn("") -z.PD(a) -return z}}},wv:{"":"a;"}}],["dart.dom.html","dart:html",,W,{J6:function(a){var z=document.createElement("a",null) -return z},U9:function(a,b,c){var z,y -z=J.kp(document.body,a,b,c) -z.toString -y=new W.e7(z) -y=y.ev(y,new W.Cv()) -return y.gr8(y)},Yb:function(a){return new FormData()},Kn:function(a,b,c){return W.GN(a,null,null,b,null,null,null,c).ml(new W.Kx())},GN:function(a,b,c,d,e,f,g,h){var z,y,x,w -z=W.zU -y=new P.Zf(P.Dt(z)) -H.VM(y,[z]) -x=new XMLHttpRequest() -C.W3.eo(x,"GET",a,!0) -z=new W.RO(x,C.fK.Ph,!1) -H.VM(z,[null]) -w=new W.Ov(0,z.uv,z.Ph,W.aF(new W.bU(y,x)),z.Sg) -H.VM(w,[H.W8(z,"RO",0)]) -w.Zz() -w=new W.RO(x,C.MD.Ph,!1) -H.VM(w,[null]) -z=y.gYJ() -z=new W.Ov(0,w.uv,w.Ph,W.aF(z),w.Sg) -H.VM(z,[H.W8(w,"RO",0)]) -z.Zz() -x.send() -return y.MM},dy:function(a){var z,y -z=document.createElement("input",null) -if(a!=null)try{J.cW(z,a)}catch(y){H.Ru(y)}return z},uC:function(a){var z,y,x -try{z=a -y=J.x(z) -return typeof z==="object"&&z!==null&&!!y.$isu8}catch(x){H.Ru(x) -return!1}},qc:function(a){var z,y -if(a==null)return -if("setInterval" in a){z=W.P1(a) -y=J.x(z) -if(typeof z==="object"&&z!==null&&!!y.$isD0)return z -return}else return a},aF:function(a){var z=$.X3 -if(z===C.NU)return a -return z.oj(a,!0)},qE:{"":"cv;","%":"HTMLAppletElement|HTMLBRElement|HTMLBaseFontElement|HTMLCanvasElement|HTMLContentElement|HTMLDListElement|HTMLDataListElement|HTMLDetailsElement|HTMLDialogElement|HTMLDirectoryElement|HTMLDivElement|HTMLFontElement|HTMLFrameElement|HTMLFrameSetElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLImageElement|HTMLLabelElement|HTMLLegendElement|HTMLMarqueeElement|HTMLMenuElement|HTMLModElement|HTMLOptGroupElement|HTMLParagraphElement|HTMLPreElement|HTMLQuoteElement|HTMLShadowElement|HTMLSpanElement|HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableHeaderCellElement|HTMLTitleElement|HTMLUListElement|HTMLUnknownElement;HTMLElement"},Gh:{"":"qE;y0:hostname=,LU:href},tp:port=,A8:protocol=,N:target=,t5:type}", -bu:function(a){return a.toString()}, -"%":"HTMLAnchorElement"},fY:{"":"qE;y0:hostname=,LU:href},tp:port=,A8:protocol=,N:target=","%":"HTMLAreaElement"},nB:{"":"qE;LU:href},N:target=","%":"HTMLBaseElement"},Az:{"":"Gv;","%":";Blob"},QP:{"":"qE;",$isQP:true,"%":"HTMLBodyElement"},IF:{"":"qE;oc:name%,t5:type},P:value%",$isIF:true,"%":"HTMLButtonElement"},OM:{"":"KV;B:length=","%":"CDATASection|Comment|Text;CharacterData"},oJ:{"":"BV;B:length=", -T2:function(a,b){var z=a.getPropertyValue(b) -return z!=null?z:""}, -hV:function(a,b,c,d){var z -try{if(d==null)d="" -a.setProperty(b,c,d) -if(!!a.setAttribute)a.setAttribute(b,c)}catch(z){H.Ru(z)}}, -"%":"CSS2Properties|CSSStyleDeclaration|MSStyleCSSProperties"},QF:{"":"KV;Im:readyState=","%":"Document|HTMLDocument|SVGDocument"},Nh:{"":"Gv;", -bu:function(a){return a.toString()}, -"%":"DOMException"},cv:{"":"KV;", -gQg:function(a){return new W.E9(a)}, -gDD:function(a){return new W.I4(a)}, -bu:function(a){return a.localName}, -r6:function(a,b,c,d){var z,y,x,w,v -if(c==null){if($.lt==null){z=[] -H.VM(z,[W.kF]) -z=new W.vD(z) -y=z.YM -y.push(W.Tw(null)) -y.push(W.Bl()) -$.lt=z}d=$.lt -z=$.EU -if(z==null)$.EU=new W.MM(d) -else z.zl=d -c=$.EU}if($.xo==null){$.xo=document.implementation.createHTMLDocument("") -$.BO=$.xo.createRange() -x=$.xo.createElement("base",null) -J.r0(x,document.baseURI) -$.xo.head.appendChild(x)}z=$.xo -if(!!this.$isQP)w=z.body -else{w=z.createElement(a.tagName,null) -$.xo.body.appendChild(w)}if("createContextualFragment" in window.Range.prototype){$.BO.selectNodeContents(w) -v=$.BO.createContextualFragment(b)}else{w.innerHTML=b -v=$.xo.createDocumentFragment() -for(;z=w.firstChild,z!=null;)v.appendChild(z)}z=$.xo.body -if(w==null?z!=null:w!==z)J.Mp(w) -c.Jt(v) -document.adoptNode(v) -return v}, -AH:function(a,b,c){return this.r6(a,b,c,null)}, -shf:function(a,b){this.YC(a,b)}, -Fe:function(a,b,c,d){a.textContent=null -a.appendChild(this.r6(a,b,c,d))}, -YC:function(a,b){return this.Fe(a,b,null,null)}, -$iscv:true, -"%":";Element"},Fs:{"":"qE;oc:name%,t5:type}","%":"HTMLEmbedElement"},hY:{"":"ea;kc:error=","%":"ErrorEvent"},ea:{"":"Gv;", -gSd:function(a){return W.qc(a.currentTarget)}, -gN:function(a){return W.qc(a.target)}, -"%":"AudioProcessingEvent|AutocompleteErrorEvent|BeforeLoadEvent|BeforeUnloadEvent|CSSFontFaceLoadEvent|CloseEvent|CustomEvent|DeviceMotionEvent|DeviceOrientationEvent|HashChangeEvent|IDBVersionChangeEvent|MIDIConnectionEvent|MIDIMessageEvent|MediaKeyEvent|MediaKeyMessageEvent|MediaKeyNeededEvent|MediaStreamEvent|MediaStreamTrackEvent|MessageEvent|MutationEvent|OfflineAudioCompletionEvent|OverflowEvent|PageTransitionEvent|PopStateEvent|RTCDTMFToneChangeEvent|RTCDataChannelEvent|RTCIceCandidateEvent|SecurityPolicyViolationEvent|SpeechInputEvent|SpeechRecognitionEvent|SpeechSynthesisEvent|StorageEvent|TrackEvent|TransitionEvent|WebGLContextEvent|WebKitAnimationEvent|WebKitTransitionEvent;Event"},D0:{"":"Gv;", -On:function(a,b,c,d){return a.addEventListener(b,H.tR(c,1),d)}, -Y9:function(a,b,c,d){return a.removeEventListener(b,H.tR(c,1),d)}, -$isD0:true, -"%":"MediaStream;EventTarget"},as:{"":"qE;oc:name%","%":"HTMLFieldSetElement"},dU:{"":"Az;","%":"File"},XV:{"":"ec;", -gB:function(a){return a.length}, -t:function(a,b){var z=a.length -if(b>>>0!==b||b>=z)throw H.b(P.TE(b,0,z)) -return a[b]}, -u:function(a,b,c){throw H.b(P.f("Cannot assign element of immutable List."))}, -sB:function(a,b){throw H.b(P.f("Cannot resize immutable List."))}, -Zv:function(a,b){if(b<0||b>=a.length)throw H.e(a,b) -return a[b]}, -$aszM:function(){return[W.dU]}, -$isList:true, -$isqC:true, -$isXj:true, -"%":"FileList"},Yu:{"":"qE;B:length=,oc:name%,N:target=","%":"HTMLFormElement"},zU:{"":"wa;Im:readyState=,il:responseText=", -gLs:function(a){var z,y,x,w,v,u,t,s,r -z=H.B7([],P.L5(null,null,null,null,null)) -H.VM(z,[J.O,J.O]) -y=a.getAllResponseHeaders() -if(y==null)return z -x=y.split("\r\n") -for(w=new H.a7(x,x.length,0,null);w.G();){v=w.mD -u=J.U6(v) -if(u.gl0(v)===!0)continue -t=u.u8(v,": ") -if(t===-1)continue -s=u.Nj(v,0,t).toLowerCase() -r=C.xB.yn(v,t+2) -if(z.x4(s))z.u(z,s,H.d(z.t(z,s))+", "+r) -else z.u(z,s,r)}return z}, -R3:function(a,b,c,d,e,f){return a.open(b,c,d,f,e)}, -EP:function(a,b,c){return a.open(b,c)}, -eo:function(a,b,c,d){return a.open(b,c,d)}, -wR:function(a,b){return a.send(b)}, -"%":"XMLHttpRequest"},wa:{"":"D0;","%":";XMLHttpRequestEventTarget"},tb:{"":"qE;oc:name%","%":"HTMLIFrameElement"},Mi:{"":"qE;oc:name%,bO:placeholder},SY:required},t5:type},P:value%",$isMi:true,$iscv:true,$isD0:true,"%":"HTMLInputElement"},MX:{"":"qE;oc:name%","%":"HTMLKeygenElement"},wP:{"":"qE;P:value%","%":"HTMLLIElement"},Og:{"":"qE;LU:href},t5:type}","%":"HTMLLinkElement"},u8:{"":"Gv;y0:hostname=,tp:port=,A8:protocol=", -bu:function(a){return a.toString()}, -$isu8:true, -"%":"Location"},M6:{"":"qE;oc:name%","%":"HTMLMapElement"},El:{"":"qE;kc:error=,Im:readyState=","%":"HTMLAudioElement|HTMLMediaElement|HTMLVideoElement"},Ee:{"":"qE;oc:name%","%":"HTMLMetaElement"},Qb:{"":"qE;P:value%","%":"HTMLMeterElement"},Lk:{"":"Ik;", -LV:function(a,b,c){return a.send(b,c)}, -wR:function(a,b){return a.send(b)}, -"%":"MIDIOutput"},Ik:{"":"D0;","%":"MIDIInput;MIDIPort"},Aj:{"":"w6;","%":"DragEvent|MSPointerEvent|MouseEvent|MouseScrollEvent|MouseWheelEvent|PointerEvent|WheelEvent"},KV:{"":"D0;nv:lastChild=,zp:nodeType=", -gni:function(a){return new W.e7(a)}, -wg:function(a){var z=a.parentNode -if(z!=null)z.removeChild(a)}, -bu:function(a){var z=a.nodeValue -return z==null?J.Gv.prototype.bu.call(this,a):z}, -tg:function(a,b){return a.contains(b)}, -"%":"DocumentFragment|DocumentType|Entity|Notation|ShadowRoot;Node"},BH:{"":"x5;", -gB:function(a){return a.length}, -t:function(a,b){var z=a.length -if(b>>>0!==b||b>=z)throw H.b(P.TE(b,0,z)) -return a[b]}, -u:function(a,b,c){throw H.b(P.f("Cannot assign element of immutable List."))}, -sB:function(a,b){throw H.b(P.f("Cannot resize immutable List."))}, -Zv:function(a,b){if(b<0||b>=a.length)throw H.e(a,b) -return a[b]}, -$aszM:function(){return[W.KV]}, -$isList:true, -$isqC:true, -$isXj:true, -"%":"NodeList|RadioNodeList"},KY:{"":"qE;t5:type}","%":"HTMLOListElement"},G7:{"":"qE;oc:name%,t5:type}","%":"HTMLObjectElement"},Ql:{"":"qE;P:value%","%":"HTMLOptionElement"},wL:{"":"qE;oc:name%,P:value%","%":"HTMLOutputElement"},HD:{"":"qE;oc:name%,P:value%","%":"HTMLParamElement"},nC:{"":"OM;N:target=","%":"ProcessingInstruction"},KR:{"":"qE;P:value%","%":"HTMLProgressElement"},ew:{"":"ea;","%":"ProgressEvent|ResourceProgressEvent|XMLHttpRequestProgressEvent"},u2:{"":"Gv;", -bu:function(a){return a.toString()}, -"%":"Range"},qI:{"":"qE;t5:type}","%":"HTMLScriptElement"},lp:{"":"qE;B:length=,oc:name%,SY:required},P:value%","%":"HTMLSelectElement"},yN:{"":"qE;t5:type}","%":"HTMLSourceElement"},zD:{"":"ea;kc:error=","%":"SpeechRecognitionError"},fq:{"":"qE;t5:type}","%":"HTMLStyleElement"},Tb:{"":"qE;", -r6:function(a,b,c,d){var z,y,x -if("createContextualFragment" in window.Range.prototype)return W.cv.prototype.r6.call(this,a,b,c,d) -z=W.U9(""+b+"
",c,d) -y=document.createDocumentFragment() -y.toString -x=new W.e7(y) -x.FV(x,J.ow(z)) -return y}, -"%":"HTMLTableElement"},Iv:{"":"qE;", -r6:function(a,b,c,d){var z,y,x,w -if("createContextualFragment" in window.Range.prototype)return W.cv.prototype.r6.call(this,a,b,c,d) -z=document.createDocumentFragment() -y=J.kp(document.createElement("table",null),b,c,d) -y.toString -y=new W.e7(y) -x=y.gr8(y) -x.toString -y=new W.e7(x) -w=y.gr8(y) -z.toString -y=new W.e7(z) -w.toString -y.FV(y,new W.e7(w)) -return z}, -"%":"HTMLTableRowElement"},BT:{"":"qE;", -r6:function(a,b,c,d){var z,y,x -if("createContextualFragment" in window.Range.prototype)return W.cv.prototype.r6.call(this,a,b,c,d) -z=document.createDocumentFragment() -y=J.kp(document.createElement("table",null),b,c,d) -y.toString -y=new W.e7(y) -x=y.gr8(y) -z.toString -y=new W.e7(z) -x.toString -y.FV(y,new W.e7(x)) -return z}, -"%":"HTMLTableSectionElement"},yY:{"":"qE;", -Fe:function(a,b,c,d){var z -a.textContent=null -z=this.r6(a,b,c,d) -a.content.appendChild(z)}, -YC:function(a,b){return this.Fe(a,b,null,null)}, -$isyY:true, -"%":"HTMLTemplateElement"},FB:{"":"qE;oc:name%,bO:placeholder},SY:required},P:value%","%":"HTMLTextAreaElement"},RH:{"":"qE;Im:readyState=","%":"HTMLTrackElement"},w6:{"":"ea;","%":"CompositionEvent|FocusEvent|KeyboardEvent|SVGZoomEvent|TextEvent|TouchEvent;UIEvent"},Oi:{"":"D0;", -gmW:function(a){var z=a.location -if(W.uC(z)===!0)return z -if(null==a._location_wrapper)a._location_wrapper=new W.rB(z) -return a._location_wrapper}, -bu:function(a){return a.toString()}, -$isD0:true, -"%":"DOMWindow|Window"},UM:{"":"KV;oc:name=,P:value=","%":"Attr"},rh:{"":"HR;", -gB:function(a){return a.length}, -t:function(a,b){var z=a.length -if(b>>>0!==b||b>=z)throw H.b(P.TE(b,0,z)) -return a[b]}, -u:function(a,b,c){throw H.b(P.f("Cannot assign element of immutable List."))}, -sB:function(a,b){throw H.b(P.f("Cannot resize immutable List."))}, -Zv:function(a,b){if(b<0||b>=a.length)throw H.e(a,b) -return a[b]}, -$aszM:function(){return[W.KV]}, -$isList:true, -$isqC:true, -$isXj:true, -"%":"MozNamedAttrMap|NamedNodeMap"},M0:{"":"a;", -Wt:function(a,b){return typeof console!="undefined"?console.error(b):null}, -gkc:function(a){return new W.C7(this,W.M0.prototype.Wt,a,"Wt")}, -static:{"":"wk",}},BV:{"":"Gv+id;"},id:{"":"a;", -guL:function(a){return this.T2(a,"display")}, -suL:function(a,b){this.hV(a,"display",b,"")}},Cv:{"":"Tp;", -call$1:function(a){var z=J.x(a) -return typeof a==="object"&&a!==null&&!!z.$iscv}, -$is_aB:true},nN:{"":"Gv+lD;",$isList:true,$aszM:null,$isqC:true},ec:{"":"nN+Gm;",$aszM:null,$isList:true,$isqC:true},Kx:{"":"Tp;", -call$1:function(a){return J.CA(a)}, -$is_aB:true},hH:{"":"Tp;a", -call$2:function(a,b){this.a.setRequestHeader(a,b)}, -$is_bh:true},bU:{"":"Tp;b,c", -call$1:function(a){var z,y,x -z=this.c -y=z.status -if(typeof y!=="number")throw y.F() -y=y>=200&&y<300||y===0||y===304 -x=this.b -if(y){y=x.MM -if(y.Gv!==0)H.vh(P.w("Future already completed")) -y.OH(z)}else x.pm(a)}, -$is_aB:true},e7:{"":"ar;NL", -gr8:function(a){var z,y -z=this.NL -y=z.childNodes.length -if(y===0)throw H.b(P.w("No elements")) -if(y>1)throw H.b(P.w("More than one element")) -return z.firstChild}, -h:function(a,b){this.NL.appendChild(b)}, -FV:function(a,b){var z,y,x,w -z=J.w1(b) -if(!!z.$ise7){z=b.NL -y=this.NL -if(z!==y)for(x=z.childNodes.length,w=0;w>>0!==b||b>=y.length)throw H.e(y,b) -z.replaceChild(c,y[b])}, -gA:function(a){return C.t5.gA(this.NL.childNodes)}, -gB:function(a){return this.NL.childNodes.length}, -sB:function(a,b){throw H.b(P.f("Cannot set length on immutable List."))}, -t:function(a,b){var z=this.NL.childNodes -if(b>>>0!==b||b>=z.length)throw H.e(z,b) -return z[b]}, -$ise7:true, -$aszM:function(){return[W.KV]}},yo:{"":"Gv+lD;",$isList:true,$aszM:null,$isqC:true},x5:{"":"yo+Gm;",$aszM:null,$isList:true,$isqC:true},zL:{"":"Gv+lD;",$isList:true,$aszM:null,$isqC:true},HR:{"":"zL+Gm;",$aszM:null,$isList:true,$isqC:true},D9:{"":"a;", -aN:function(a,b){var z,y -for(z=this.gvc(),z=new H.a7(z,z.length,0,null);z.G();){y=z.mD -b.call$2(y,this.t(this,y))}}, -gvc:function(){var z,y,x,w,v -z=this.MW.attributes -y=P.A(null,J.O) -H.VM(y,[J.O]) -for(x=z.length,w=0;w=z.length)throw H.e(z,w) -v=z[w] -if(this.mb(v))y.push(J.C9(v))}return y}, -gUQ:function(a){var z,y,x,w,v -z=this.MW.attributes -y=P.A(null,J.O) -H.VM(y,[J.O]) -for(x=z.length,w=0;w=z.length)throw H.e(z,w) -v=z[w] -if(this.mb(v))y.push(J.Vm(v))}return y}, -gl0:function(a){return this.gB(this)===0}, -$isZ0:true, -$asZ0:function(){return[J.O,J.O]}},E9:{"":"D9;MW", -t:function(a,b){return this.MW.getAttribute(b)}, -u:function(a,b,c){this.MW.setAttribute(b,c)}, -gB:function(a){return this.gvc().length}, -mb:function(a){return a.namespaceURI==null}},I4:{"":"As;MW", -lF:function(){var z,y,x -z=P.Ls(null,null,null,J.O) -for(y=this.MW.className.split(" "),y=new H.a7(y,y.length,0,null);y.G();){x=J.rr(y.mD) -if(x.length!==0)z.h(z,x)}return z}, -p5:function(a){P.F(a,!0,null) -this.MW.className=a.zV(a," ")}},I2:{"":"a;Ph"},RO:{"":"qh;uv,Ph,Sg", -KR:function(a,b,c,d){var z=new W.Ov(0,this.uv,this.Ph,W.aF(a),this.Sg) -H.VM(z,[H.W8(this,"RO",0)]) -z.Zz() -return z}, -$asqh:null},eu:{"":"RO;uv,Ph,Sg",$asRO:null},Ov:{"":"MO;VP,uv,Ph,u7,Sg", -ed:function(){if(this.uv==null)return -this.Ns() -this.uv=null -this.u7=null}, -Zz:function(){var z=this.u7 -if(z!=null&&this.VP<=0)J.qV(this.uv,this.Ph,z,this.Sg)}, -Ns:function(){var z=this.u7 -if(z!=null)J.GJ(this.uv,this.Ph,z,this.Sg)}, -$asMO:null},JQ:{"":"a;Ks<", -i0:function(a){var z=$.AM() -return z.tg(z,a.tagName)}, -Eb:function(a,b,c){var z,y,x -z=a.tagName -y=$.NJ() -x=y.t(y,z+"::"+b) -if(x==null){y=$.NJ() -x=y.t(y,"*::"+b)}if(x==null)return!1 -return x.call$4(a,b,c,this)}, -U5:function(a){var z,y,x -z=$.NJ() -if(z.gl0(z)){for(z=new H.a7(C.zm,261,0,null);z.G();){y=z.mD -x=$.NJ() -x.u(x,y,W.y3)}for(z=new H.a7(C.BI,12,0,null);z.G();){y=z.mD -x=$.NJ() -x.u(x,y,W.tc)}}}, -static:{"":"zX,pR,YA,or",Tw:function(a){var z=new W.mk(W.J6(null),C.ol.gmW(window)) -z=new W.JQ(z) -z.U5(a) -return z},qD:function(a,b,c,d){return!0},QW:function(a,b,c,d){return d.gKs().Dt(c)}}},Gm:{"":"a;", -gA:function(a){return W.yB(a)}, -h:function(a,b){throw H.b(P.f("Cannot add to immutable List."))}, -FV:function(a,b){throw H.b(P.f("Cannot add to immutable List."))}, -$isList:true, -$aszM:null, -$isqC:true},vD:{"":"a;YM", -h:function(a,b){this.YM.push(b)}, -i0:function(a){return H.Ck(this.YM,new W.mD(a))}, -Eb:function(a,b,c){return H.Ck(this.YM,new W.Eg(a,b,c))}},mD:{"":"Tp;a", -call$1:function(a){return a.i0(this.a)}, -$is_aB:true},Eg:{"":"Tp;a,b,c", -call$1:function(a){return a.Eb(this.a,this.b,this.c)}, -$is_aB:true},m6:{"":"a;Ks<", -i0:function(a){var z=this.zx -return z.tg(z,a.tagName)}, -Eb:function(a,b,c){var z,y -z=a.tagName -y=this.cd -if(y.tg(y,z+"::"+b))return this.Ks.Dt(c) -else if(y.tg(y,"*::"+b))return this.Ks.Dt(c) -else{y=this.fE -if(y.tg(y,z+"::"+b))return!0 -else if(y.tg(y,"*::"+b))return!0 -else if(y.tg(y,z+"::*"))return!0 -else if(y.tg(y,"*::*"))return!0}return!1}},ct:{"":"m6;Wg,zx,fE,cd,Ks", -Eb:function(a,b,c){var z -if(W.m6.prototype.Eb.call(this,a,b,c))return!0 -if(b==="template"&&c==="")return!0 -if(new W.E9(a).MW.getAttribute("template")===""){z=this.Wg -return z.tg(z,b)}return!1}, -static:{"":"Qr",Bl:function(){var z,y,x,w -z=new H.A8(C.Qx,new W.tE()) -H.VM(z,[null,null]) -y=P.Ls(null,null,null,null) -y.FV(y,["TEMPLATE"]) -x=P.Ls(null,null,null,null) -x.FV(x,z) -z=x -x=P.Ls(null,null,null,null) -w=P.Ls(null,null,null,J.O) -w.FV(w,C.Qx) -return new W.ct(w,y,z,x,null)}}},tE:{"":"Tp;", -call$1:function(a){return"TEMPLATE::"+H.d(a)}, -$is_aB:true},Ow:{"":"a;", -i0:function(a){var z=J.x(a) -if(!!z.$isj2)return!1 -if(!!z.$isd5)return!0 -return!1}, -Eb:function(a,b,c){if(b==="is"||C.xB.nC(b,"on"))return!1 -return this.i0(a)}},W9:{"":"a;nj,vN,Nq,QZ", -G:function(){var z,y -z=this.Nq+1 -y=this.vN -if(z" -x.toString -if(typeof console!="undefined")console.warn(w) -z.wg(a) -break}x=y.MW -v=x.getAttribute("is") -if(v!=null)if(!this.zl.Eb(a,"is",v)){window -x=$.UT() -w="Removing disallowed type extension <"+a.tagName+" is=\""+v+"\">" -x.toString -if(typeof console!="undefined")console.warn(w) -z.wg(a) -break}w=y.gvc() -u=P.F(w,!0,H.W8(w,"Q",0)) -for(t=y.gvc().length-1;t>=0;--t){if(t>=u.length)throw H.e(u,t) -s=u[t] -if(!this.zl.Eb(a,J.Mz(s),x.getAttribute(s))){window -w=$.UT() -r="Removing disallowed attribute <"+a.tagName+" "+s+"=\""+x.getAttribute(s)+"\">" -w.toString -if(typeof console!="undefined")console.warn(r) -x.getAttribute(s) -x.removeAttribute(s)}}if(typeof a==="object"&&a!==null&&!!z.$isyY)this.Jt(a.content) -break -case 8:case 11:case 3:case 4:break -default:z.wg(a)}}},fm:{"":"Tp;a", -call$1:function(a){var z,y -this.a.zk(a) -z=J.Gc(a) -for(;z!=null;z=y){y=z.previousSibling -this.call$1(z)}}, -$is_aB:true}}],["dart.dom.svg","dart:svg",,P,{Y0:{"":"zp;N:target=","%":"SVGAElement"},zp:{"":"d5;","%":"SVGAltGlyphElement|SVGCircleElement|SVGClipPathElement|SVGDefsElement|SVGEllipseElement|SVGForeignObjectElement|SVGGElement|SVGImageElement|SVGLineElement|SVGPathElement|SVGPolygonElement|SVGPolylineElement|SVGRectElement|SVGSVGElement|SVGSwitchElement|SVGTSpanElement|SVGTextContentElement|SVGTextElement|SVGTextPathElement|SVGTextPositioningElement|SVGUseElement;SVGGraphicsElement"},j2:{"":"d5;t5:type}",$isj2:true,"%":"SVGScriptElement"},Lx:{"":"d5;t5:type}","%":"SVGStyleElement"},d5:{"":"cv;", -gDD:function(a){if(a._cssClassSet==null)a._cssClassSet=new P.O7(a) -return a._cssClassSet}, -shf:function(a,b){a.textContent=null -a.appendChild(this.r6(a,b,null,null))}, -r6:function(a,b,c,d){var z,y,x,w,v -z=[] -H.VM(z,[W.kF]) -d=new W.vD(z) -z=d.YM -z.push(W.Tw(null)) -z.push(W.Bl()) -z.push(new W.Ow()) -c=new W.MM(d) -y=""+b+"" -x=J.kV(document.body,y,c) -w=document.createDocumentFragment() -x.toString -z=new W.e7(x) -v=z.gr8(z) -for(;z=v.firstChild,z!=null;)w.appendChild(z) -return w}, -$isd5:true, -"%":"SVGAltGlyphDefElement|SVGAltGlyphItemElement|SVGAnimateColorElement|SVGAnimateElement|SVGAnimateMotionElement|SVGAnimateTransformElement|SVGAnimationElement|SVGComponentTransferFunctionElement|SVGCursorElement|SVGDescElement|SVGFEBlendElement|SVGFEColorMatrixElement|SVGFEComponentTransferElement|SVGFECompositeElement|SVGFEConvolveMatrixElement|SVGFEDiffuseLightingElement|SVGFEDisplacementMapElement|SVGFEDistantLightElement|SVGFEDropShadowElement|SVGFEFloodElement|SVGFEFuncAElement|SVGFEFuncBElement|SVGFEFuncGElement|SVGFEFuncRElement|SVGFEGaussianBlurElement|SVGFEImageElement|SVGFEMergeElement|SVGFEMergeNodeElement|SVGFEMorphologyElement|SVGFEOffsetElement|SVGFEPointLightElement|SVGFESpecularLightingElement|SVGFESpotLightElement|SVGFETileElement|SVGFETurbulenceElement|SVGFilterElement|SVGFontElement|SVGFontFaceElement|SVGFontFaceFormatElement|SVGFontFaceNameElement|SVGFontFaceSrcElement|SVGFontFaceUriElement|SVGGlyphElement|SVGGlyphRefElement|SVGGradientElement|SVGHKernElement|SVGLinearGradientElement|SVGMPathElement|SVGMarkerElement|SVGMaskElement|SVGMetadataElement|SVGMissingGlyphElement|SVGPatternElement|SVGRadialGradientElement|SVGSetElement|SVGStopElement|SVGSymbolElement|SVGTitleElement|SVGVKernElement|SVGViewElement;SVGElement"},O7:{"":"As;CE", -lF:function(){var z,y,x,w -z=new W.E9(this.CE).MW.getAttribute("class") -y=P.Ls(null,null,null,J.O) -if(z==null)return y -for(x=z.split(" "),x=new H.a7(x,x.length,0,null);x.G();){w=J.rr(x.mD) -if(w.length!==0)y.h(y,w)}return y}, -p5:function(a){new W.E9(this.CE).MW.setAttribute("class",a.zV(a," "))}}}],["dart.isolate","dart:isolate",,P,{rR:{"":"a;"}}],["dart.typed_data","dart:typed_data",,P,{AS:{"":"Gv;", -aq:function(a,b,c){var z=J.Wx(b) -if(z.C(b,0)||z.F(b,c))throw H.b(P.TE(b,0,c)) -else throw H.b(P.u("Invalid list index "+H.d(b)))}, -"%":";ArrayBufferView;xG|Vj"},F0:{"":"Vj;", -gB:function(a){return C.i7(a)}, -t:function(a,b){var z,y -z=C.i7(a) -if(!(b>>>0!=b)){if(typeof b!=="number")throw b.F() -y=b>=z}else y=!0 -if(y)this.aq(a,b,z) -return a[b]}, -u:function(a,b,c){var z=C.i7(a) -if(b>>>0!=b||J.J5(b,z))this.aq(a,b,z) -a[b]=c}, -$aszM:function(){return[J.im]}, -$isList:true, -$isqC:true, -$isXj:true, -"%":";Uint8Array"},xG:{"":"AS+lD;",$isList:true,$aszM:null,$isqC:true},Vj:{"":"xG+SU;",$aszM:null}}],["html_common","dart:html_common",,P,{As:{"":"a;", -bu:function(a){var z=this.lF() -return z.zV(z," ")}, -gA:function(a){var z=this.lF() -z=new P.zQ(z,z.zN,null,null) -z.zq=z.O2.H9 -return z}, -aN:function(a,b){var z=this.lF() -z.aN(z,b)}, -gl0:function(a){return this.lF().X5===0}, -gB:function(a){return this.lF().X5}, -tg:function(a,b){var z=this.lF() -return z.tg(z,b)}, -Zt:function(a){var z=this.lF() -return z.tg(z,a)?a:null}, -h:function(a,b){return this.OS(new P.GE(b))}, -Rz:function(a,b){var z,y -z=this.lF() -y=z.Rz(z,b) -this.p5(z) -return y}, -FV:function(a,b){this.OS(new P.N7(b))}, -OS:function(a){var z,y -z=this.lF() -y=a.call$1(z) -this.p5(z) -return y}, -$isqC:true},GE:{"":"Tp;a", -call$1:function(a){return J.hv(a,this.a)}, -$is_aB:true},N7:{"":"Tp;a", -call$1:function(a){return J.bj(a,this.a)}, -$is_aB:true}}],]) -I.$finishClasses($$,$,null) -$$=null -init.globalFunctions.NB=H.NB=new H.Wv(H.Mg,"NB") -init.globalFunctions.Eu=H.Eu=new H.yh(H.Ju,"Eu") -init.globalFunctions.eH=H.eH=new H.Pz(H.ft,"eH") -init.globalFunctions.lS=T.lS=new H.yh(T.E2,"lS") -init.globalFunctions.TM=T.TM=new T.vE(T.Fa,"TM") -init.globalFunctions.bn=T.bn=new T.vE(T.qP,"bn") -init.globalFunctions.qZ=P.qZ=new H.yh(P.BG,"qZ") -init.globalFunctions.QN=P.QN=new T.vE(P.QE,"QN") -init.globalFunctions.AY=P.AY=new P.zy(P.SZ,"AY") -init.globalFunctions.v3=P.v3=new H.yh(P.dL,"v3") -init.globalFunctions.iv=P.iv=new H.Wv(P.Ou,"iv") -init.globalFunctions.rm=P.rm=new T.vE(P.T9,"rm") -init.globalFunctions.DY=P.DY=new T.vE(P.tp,"DY") -init.globalFunctions.n0=P.n0=new H.Wv(P.ad,"n0") -init.globalFunctions.J2=P.J2=new T.vE(P.xv,"J2") -init.globalFunctions.y3=W.y3=new W.kq(W.qD,"y3") -init.globalFunctions.tc=W.tc=new W.kq(W.QW,"tc") -J.im.$isint=true -J.im.$isa=true -W.KV.$isKV=true -W.KV.$isa=true -W.dU.$isa=true -J.O.$isString=true -J.O.$isa=true -J.P.$isa=true -P.a.$isa=true -P.a6.$isa=true -P.Od.$isa=true -W.Aj.$isa=true -W.ew.$isa=true -W.kF.$isa=true -J.kn.$isbool=true -J.kn.$isa=true -W.ea.$isa=true -W.zU.$isa=true -P.rR.$isa=true -H.IY.$isa=true -H.aX.$isa=true -J.Q.$isa=true -P.wv.$iswv=true -P.wv.$isa=true -P.mE.$ismE=true -P.mE.$isa=true -P.Ge.$isGe=true -P.Ge.$isa=true -P.EH.$isEH=true -P.EH.$isa=true -W.cv.$iscv=true -W.cv.$isKV=true -W.cv.$isa=true -W.JQ.$isJQ=true -W.JQ.$isa=true -P.nP.$isnP=true -P.nP.$isa=true -P.b8.$isb8=true -P.b8.$isa=true -P.MO.$isMO=true -P.MO.$isa=true -J.Qc=function(a){if(typeof a=="number")return J.P.prototype -if(typeof a=="string")return J.O.prototype -if(a==null)return a -if(!(a instanceof P.a))return J.is.prototype -return a} -J.RE=function(a){if(a==null)return a -if(typeof a!="object")return a -if(a instanceof P.a)return a -return J.ks(a)} -J.U6=function(a){if(typeof a=="string")return J.O.prototype -if(a==null)return a -if(a.constructor==Array)return J.Q.prototype -if(typeof a!="object")return a -if(a instanceof P.a)return a -return J.ks(a)} -J.Wx=function(a){if(typeof a=="number")return J.P.prototype -if(a==null)return a -if(!(a instanceof P.a))return J.is.prototype -return a} -J.rY=function(a){if(typeof a=="string")return J.O.prototype -if(a==null)return a -if(!(a instanceof P.a))return J.is.prototype -return a} -J.w1=function(a){if(a==null)return a -if(a.constructor==Array)return J.Q.prototype -if(typeof a!="object")return a -if(a instanceof P.a)return a -return J.ks(a)} -J.x=function(a){if(typeof a=="number"){if(Math.floor(a)==a)return J.im.prototype -return J.VA.prototype}if(typeof a=="string")return J.O.prototype -if(a==null)return J.PE.prototype -if(typeof a=="boolean")return J.kn.prototype -if(a.constructor==Array)return J.Q.prototype -if(typeof a!="object")return a -if(a instanceof P.a)return a -return J.ks(a)} -C.Ct=new P.by() -C.Wj=new P.dp() -C.NU=new P.R8() -C.RT=new P.a6(0) -C.mt=new W.I2("change") -C.T1=new W.I2("click") -C.MD=new W.I2("error") -C.fK=new W.I2("load") -C.tF=new W.I2("loadend") -C.W3=W.zU.prototype -C.Nm=J.Q.prototype -C.jn=J.im.prototype -C.CD=J.P.prototype -C.xB=J.O.prototype -C.Mc=function(hooks) { - if (typeof dartExperimentalFixupGetTag != "function") return hooks; - hooks.getTag = dartExperimentalFixupGetTag(hooks.getTag); -} -C.dE=function(hooks) { - var userAgent = typeof navigator == "object" ? navigator.userAgent : ""; - if (userAgent.indexOf("Firefox") == -1) return hooks; - var getTag = hooks.getTag; - var quickMap = { - "BeforeUnloadEvent": "Event", - "DataTransfer": "Clipboard", - "GeoGeolocation": "Geolocation", - "WorkerMessageEvent": "MessageEvent", - "XMLDocument": "Document"}; - function getTagFirefox(o) { - var tag = getTag(o); - return quickMap[tag] || tag; - } - hooks.getTag = getTagFirefox; -} -C.Mo=function getTagFallback(o) { - if (o == null) return "Null"; - var constructor = o.constructor; - if (typeof constructor == "function") { - var name = constructor.builtin$cls; - if (typeof name == "string") return name; - name = constructor.name; - if (typeof name == "string" - && name !== "" - && name !== "Object" - && name !== "Function.prototype") { - return name; - } - } - var s = Object.prototype.toString.call(o); - return s.substring(8, s.length - 1); -} -C.dK=function(getTagFallback) { - return function(hooks) { - if (typeof navigator != "object") return hooks; - var userAgent = navigator.userAgent; - if (userAgent.indexOf("Chrome") >= 0 || - userAgent.indexOf("DumpRenderTree") >= 0) { - return hooks; - } - hooks.getTag = getTagFallback; - }; -} -C.XQ=function(hooks) { return hooks; } - -C.HX=function() { - function typeNameInChrome(obj) { return obj.constructor.name; } - function getUnknownTag(object, tag) { - if (/^HTML[A-Z].*Element$/.test(tag)) { - var name = Object.prototype.toString.call(object); - if (name == "[object Object]") return null; - return "HTMLElement"; - } - } - function getUnknownTagGenericBrowser(object, tag) { - if (object instanceof HTMLElement) return "HTMLElement"; - return getUnknownTag(object, tag); - } - function prototypeForTag(tag) { - if (typeof window == "undefined") return null; - if (typeof window[tag] == "undefined") return null; - var constructor = window[tag]; - if (typeof constructor != "function") return null; - return constructor.prototype; - } - function discriminator(tag) { return null; } - var isBrowser = typeof navigator == "object"; - return { - getTag: typeNameInChrome, - getUnknownTag: isBrowser ? getUnknownTagGenericBrowser : getUnknownTag, - prototypeForTag: prototypeForTag, - discriminator: discriminator }; -} -C.i7= ((typeof version == "function" && typeof os == "object" && "system" in os) - || (typeof navigator == "object" - && navigator.userAgent.indexOf('Chrome') != -1)) - ? function(x) { return x.$dartCachedLength || x.length; } - : function(x) { return x.length; }; - -C.Px=function(hooks) { - var userAgent = typeof navigator == "object" ? navigator.userAgent : ""; - if (userAgent.indexOf("Trident/") == -1) return hooks; - var getTag = hooks.getTag; - var quickMap = { - "BeforeUnloadEvent": "Event", - "DataTransfer": "Clipboard", - "HTMLDDElement": "HTMLElement", - "HTMLDTElement": "HTMLElement", - "HTMLPhraseElement": "HTMLElement", - "Position": "Geoposition" - }; - function getTagIE(o) { - var tag = getTag(o); - var newTag = quickMap[tag]; - if (newTag) return newTag; - if (tag == "Document") { - if (!!o.xmlVersion) return "!Document"; - return "!HTMLDocument"; - } - if (tag == "Object") { - if (window.DataView && (o instanceof window.DataView)) return "DataView"; - } - return tag; - } - function prototypeForTagIE(tag) { - if (tag == "Document") return null; - var constructor = window[tag]; - if (constructor == null) return null; - return constructor.prototype; - } - hooks.getTag = getTagIE; - hooks.prototypeForTag = prototypeForTagIE; -} -C.A3=new P.QM(null) -C.Up=new P.oj(null) -I.makeConstantList = function(list) { - list.immutable$list = true; - list.fixed$length = true; - return list; -}; -C.zm=H.VM(I.makeConstantList(["*::class","*::dir","*::draggable","*::hidden","*::id","*::inert","*::itemprop","*::itemref","*::itemscope","*::lang","*::spellcheck","*::title","*::translate","A::accesskey","A::coords","A::hreflang","A::name","A::shape","A::tabindex","A::target","A::type","AREA::accesskey","AREA::alt","AREA::coords","AREA::nohref","AREA::shape","AREA::tabindex","AREA::target","AUDIO::controls","AUDIO::loop","AUDIO::mediagroup","AUDIO::muted","AUDIO::preload","BDO::dir","BODY::alink","BODY::bgcolor","BODY::link","BODY::text","BODY::vlink","BR::clear","BUTTON::accesskey","BUTTON::disabled","BUTTON::name","BUTTON::tabindex","BUTTON::type","BUTTON::value","CANVAS::height","CANVAS::width","CAPTION::align","COL::align","COL::char","COL::charoff","COL::span","COL::valign","COL::width","COLGROUP::align","COLGROUP::char","COLGROUP::charoff","COLGROUP::span","COLGROUP::valign","COLGROUP::width","COMMAND::checked","COMMAND::command","COMMAND::disabled","COMMAND::label","COMMAND::radiogroup","COMMAND::type","DATA::value","DEL::datetime","DETAILS::open","DIR::compact","DIV::align","DL::compact","FIELDSET::disabled","FONT::color","FONT::face","FONT::size","FORM::accept","FORM::autocomplete","FORM::enctype","FORM::method","FORM::name","FORM::novalidate","FORM::target","FRAME::name","H1::align","H2::align","H3::align","H4::align","H5::align","H6::align","HR::align","HR::noshade","HR::size","HR::width","HTML::version","IFRAME::align","IFRAME::frameborder","IFRAME::height","IFRAME::marginheight","IFRAME::marginwidth","IFRAME::width","IMG::align","IMG::alt","IMG::border","IMG::height","IMG::hspace","IMG::ismap","IMG::name","IMG::usemap","IMG::vspace","IMG::width","INPUT::accept","INPUT::accesskey","INPUT::align","INPUT::alt","INPUT::autocomplete","INPUT::checked","INPUT::disabled","INPUT::inputmode","INPUT::ismap","INPUT::list","INPUT::max","INPUT::maxlength","INPUT::min","INPUT::multiple","INPUT::name","INPUT::placeholder","INPUT::readonly","INPUT::required","INPUT::size","INPUT::step","INPUT::tabindex","INPUT::type","INPUT::usemap","INPUT::value","INS::datetime","KEYGEN::disabled","KEYGEN::keytype","KEYGEN::name","LABEL::accesskey","LABEL::for","LEGEND::accesskey","LEGEND::align","LI::type","LI::value","LINK::sizes","MAP::name","MENU::compact","MENU::label","MENU::type","METER::high","METER::low","METER::max","METER::min","METER::value","OBJECT::typemustmatch","OL::compact","OL::reversed","OL::start","OL::type","OPTGROUP::disabled","OPTGROUP::label","OPTION::disabled","OPTION::label","OPTION::selected","OPTION::value","OUTPUT::for","OUTPUT::name","P::align","PRE::width","PROGRESS::max","PROGRESS::min","PROGRESS::value","SELECT::autocomplete","SELECT::disabled","SELECT::multiple","SELECT::name","SELECT::required","SELECT::size","SELECT::tabindex","SOURCE::type","TABLE::align","TABLE::bgcolor","TABLE::border","TABLE::cellpadding","TABLE::cellspacing","TABLE::frame","TABLE::rules","TABLE::summary","TABLE::width","TBODY::align","TBODY::char","TBODY::charoff","TBODY::valign","TD::abbr","TD::align","TD::axis","TD::bgcolor","TD::char","TD::charoff","TD::colspan","TD::headers","TD::height","TD::nowrap","TD::rowspan","TD::scope","TD::valign","TD::width","TEXTAREA::accesskey","TEXTAREA::autocomplete","TEXTAREA::cols","TEXTAREA::disabled","TEXTAREA::inputmode","TEXTAREA::name","TEXTAREA::placeholder","TEXTAREA::readonly","TEXTAREA::required","TEXTAREA::rows","TEXTAREA::tabindex","TEXTAREA::wrap","TFOOT::align","TFOOT::char","TFOOT::charoff","TFOOT::valign","TH::abbr","TH::align","TH::axis","TH::bgcolor","TH::char","TH::charoff","TH::colspan","TH::headers","TH::height","TH::nowrap","TH::rowspan","TH::scope","TH::valign","TH::width","THEAD::align","THEAD::char","THEAD::charoff","THEAD::valign","TR::align","TR::bgcolor","TR::char","TR::charoff","TR::valign","TRACK::default","TRACK::kind","TRACK::label","TRACK::srclang","UL::compact","UL::type","VIDEO::controls","VIDEO::height","VIDEO::loop","VIDEO::mediagroup","VIDEO::muted","VIDEO::preload","VIDEO::width"]),[J.O]) -C.xD=I.makeConstantList([]) -C.Qx=H.VM(I.makeConstantList(["bind","if","ref","repeat","syntax"]),[J.O]) -C.BI=H.VM(I.makeConstantList(["A::href","AREA::href","BLOCKQUOTE::cite","BODY::background","COMMAND::icon","DEL::cite","FORM::action","IMG::src","INPUT::src","INS::cite","Q::cite","VIDEO::poster"]),[J.O]) -C.t5=W.BH.prototype -C.vB=J.is.prototype -C.ol=W.Oi.prototype -$.Dz=null -$.b9=1 -$.te="$cachedFunction" -$.eb="$cachedInvocation" -$.NF=null -$.TX=null -$.x7=null -$.nw=null -$.vv=null -$.Bv=null -$.XS=null -$.oK=null -$.TH=!1 -$.X3=C.NU -$.Ss=0 -$.xo=null -$.BO=null -$.lt=null -$.EU=null -$.L4=null -$.PN=null -J.AG=function(a){return J.x(a).bu(a)} -J.BC=function(a){return J.RE(a).gSd(a)} -J.C9=function(a){return J.RE(a).goc(a)} -J.CA=function(a){return J.RE(a).gil(a)} -J.DA=function(a){return J.RE(a).gIm(a)} -J.GJ=function(a,b,c,d){return J.RE(a).Y9(a,b,c,d)} -J.GP=function(a){return J.w1(a).gA(a)} -J.Gc=function(a){return J.RE(a).gnv(a)} -J.J5=function(a,b){if(typeof a=="number"&&typeof b=="number")return a>=b -return J.Wx(a).F(a,b)} -J.JA=function(a,b,c){return J.rY(a).h8(a,b,c)} -J.Mp=function(a){return J.w1(a).wg(a)} -J.Mz=function(a){return J.rY(a).hc(a)} -J.Qy=function(a,b){return J.RE(a).shf(a,b)} -J.UQ=function(a,b){if(a.constructor==Array||typeof a=="string"||H.wV(a,a[init.dispatchPropertyName]))if(b>>>0===b&&b>>0===b&&bParameterValueTypeDescription") -return z}) -I.$lazy($,"_toStringList","Ml","RM",function(){return P.A(null,null)}) -I.$lazy($,"_asyncCallbacks","r1","P8",function(){return P.NZ(null,{func:"X0",void:true})}) -I.$lazy($,"_toStringVisiting","xg","xb",function(){return P.yv(null)}) -I.$lazy($,"_toStringList","yu","tw",function(){return P.A(null,null)}) -I.$lazy($,"_safeConsole","wk","UT",function(){return new W.M0()}) -I.$lazy($,"_allowedElements","zX","AM",function(){var z=P.Ls(null,null,null,null) -z.FV(z,["A","ABBR","ACRONYM","ADDRESS","AREA","ARTICLE","ASIDE","AUDIO","B","BDI","BDO","BIG","BLOCKQUOTE","BR","BUTTON","CANVAS","CAPTION","CENTER","CITE","CODE","COL","COLGROUP","COMMAND","DATA","DATALIST","DD","DEL","DETAILS","DFN","DIR","DIV","DL","DT","EM","FIELDSET","FIGCAPTION","FIGURE","FONT","FOOTER","FORM","H1","H2","H3","H4","H5","H6","HEADER","HGROUP","HR","I","IFRAME","IMG","INPUT","INS","KBD","LABEL","LEGEND","LI","MAP","MARK","MENU","METER","NAV","NOBR","OL","OPTGROUP","OPTION","OUTPUT","P","PRE","PROGRESS","Q","S","SAMP","SECTION","SELECT","SMALL","SOURCE","SPAN","STRIKE","STRONG","SUB","SUMMARY","SUP","TABLE","TBODY","TD","TEXTAREA","TFOOT","TH","THEAD","TIME","TR","TRACK","TT","U","UL","VAR","VIDEO","WBR"]) -return z}) -I.$lazy($,"_attributeValidators","or","NJ",function(){return H.B7([],P.L5(null,null,null,null,null))}) - -init.functionAliases={} -init.metadata=[];$=null -I = I.$finishIsolateConstructor(I) -$=new I() -function convertToFastObject(properties) { - function MyClass() {}; - MyClass.prototype = properties; - new MyClass(); - return properties; -} -A = convertToFastObject(A) -B = convertToFastObject(B) -C = convertToFastObject(C) -D = convertToFastObject(D) -E = convertToFastObject(E) -F = convertToFastObject(F) -G = convertToFastObject(G) -H = convertToFastObject(H) -J = convertToFastObject(J) -K = convertToFastObject(K) -L = convertToFastObject(L) -M = convertToFastObject(M) -N = convertToFastObject(N) -O = convertToFastObject(O) -P = convertToFastObject(P) -Q = convertToFastObject(Q) -R = convertToFastObject(R) -S = convertToFastObject(S) -T = convertToFastObject(T) -U = convertToFastObject(U) -V = convertToFastObject(V) -W = convertToFastObject(W) -X = convertToFastObject(X) -Y = convertToFastObject(Y) -Z = convertToFastObject(Z) -!function(){var z=Object.prototype -for(var y=0;;y++){var x="___dart_dispatch_record_ZxYxX_0_" -if(y>0)x=rootProperty+"_"+y -if(!(x in z))return init.dispatchPropertyName=x}}() -;(function (callback) { - if (typeof document === "undefined") { - callback(null); - return; - } - if (document.currentScript) { - callback(document.currentScript); - return; - } - - var scripts = document.scripts; - function onLoad(event) { - for (var i = 0; i < scripts.length; ++i) { - scripts[i].removeEventListener("load", onLoad, false); - } - callback(event.target); - } - for (var i = 0; i < scripts.length; ++i) { - scripts[i].addEventListener("load", onLoad, false); - } -})(function(currentScript) { - init.currentScript = currentScript; - - if (typeof dartMainRunner === "function") { - dartMainRunner(function() { H.Rq(T.lS); }); - } else { - H.Rq(T.lS); - } -}) -function init(){I.p={} -function generateAccessor(a,b,c){var y=a.length -var x=a.charCodeAt(y-1) -var w=false -if(x==45){y-- -x=a.charCodeAt(y-1) -a=a.substring(0,y) -w=true}x=x>=60&&x<=64?x-59:x>=123&&x<=126?x-117:x>=37&&x<=43?x-27:0 -if(x){var v=x&3 -var u=x>>2 -var t=a=a.substring(0,y-1) -var s=a.indexOf(":") -if(s>0){t=a.substring(0,s) -a=a.substring(s+1)}if(v){var r=v&2?"r":"" -var q=v&1?"this":"r" -var p="return "+q+"."+a -var o=c+".prototype.g"+t+"=" -var n="function("+r+"){"+p+"}" -if(w)b.push(o+"$reflectable("+n+");\n") -else b.push(o+n+";\n")}if(u){var r=u&2?"r,v":"v" -var q=u&1?"this":"r" -var p=q+"."+a+"=v" -var o=c+".prototype.s"+t+"=" -var n="function("+r+"){"+p+"}" -if(w)b.push(o+"$reflectable("+n+");\n") -else b.push(o+n+";\n")}}return a}I.p.$generateAccessor=generateAccessor -function defineClass(a,b,c){var y=[] -var x="function "+b+"(" -var w="" -for(var v=0;v0){l=p.split("+") -p=l[0] -var k=a[l[1]] -if(k instanceof Array)k=k[1] -for(var j in k){if(w.call(k,j)&&!w.call(r,j))r[j]=k[j]}}if(typeof dart_precompiled!="function"){u+=defineClass(o,s,n) -t.push(s)}if(p)y[s]=p}}if(typeof dart_precompiled!="function"){u+="return [\n "+t.join(",\n ")+"\n]" -var v=new Function("$collectedClasses",u)(a) -u=null}for(var i=0;i= 0; i--) { $scope.myallPois[i].buname=$scope.myBuildingsnames[$scope.myallPois[i].buid]; } - }, function (resp) { if (letters=="") { @@ -236,7 +236,7 @@ app.controller('LocationSearchController', ['$scope', '$compile', 'GMapService', // on success var data = resp.data; //var bs = JSON.parse( data.buildings ); - $scope.myBuildings = data.buildings; + $scope.myBuildings = data.spaces; $scope.greeklish = data.greeklish; var infowindow = new google.maps.InfoWindow({ diff --git a/server/public/anyplace_viewer/controllers/PoiController.js b/server/public/anyplace_viewer/controllers/PoiController.js index 348aeb843..329228804 100644 --- a/server/public/anyplace_viewer/controllers/PoiController.js +++ b/server/public/anyplace_viewer/controllers/PoiController.js @@ -94,7 +94,10 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS } $scope.fetchAllPoi = function (letters , buid) { - var jsonReq = { "access-control-allow-origin": "", "content-encoding": "gzip", "access-control-allow-credentials": "true", "content-length": "17516", "content-type": "application/json" , "buid":buid, "cuid":"", "letters":letters, "greeklish":$scope.greeklish }; + var jsonReq = { "access-control-allow-origin": "", "content-encoding": "gzip", + "access-control-allow-credentials": "true", "content-length": "17516", + "content-type": "application/json" , "buid":buid, "cuid":"", "letters":letters, "greeklish":$scope.greeklish }; + if (jsonReq.greeklish == null) jsonReq.greeklish = "true"; var promise = AnyplaceAPIService.retrieveALLPois(jsonReq); promise.then( function (resp) { @@ -403,51 +406,39 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS }; $scope.retrieveRouteFromPoiToPoi = function (from, to) { - if (!from || !from.puid) { _err($scope, "Source POI is corrupted."); return; } - if (!to || !to.puid) { _err($scope, "Source POI is corrupted."); return; } - var jsonReq = $scope.creds; - jsonReq.pois_from = from.puid; jsonReq.pois_to = to.puid; - var promise = AnyplaceAPIService.retrieveRouteFromPoiToPoi(jsonReq); promise.then( function (resp) { var data = resp.data; - var listPois = data.pois; - _clearPoiRoutePolyline(); - for (var i = 0; i < listPois.length; i++) { if (listPois[i].lat && listPois[i].lon && listPois[i].floor_number) { var fl = listPois[i].floor_number; - if (!poiRoutePolyline.hasOwnProperty(fl)) { poiRoutePolyline[fl] = { flightPlanCoordinates: [] }; } - poiRoutePolyline[fl].flightPlanCoordinates.push(new google.maps.LatLng( parseFloat(listPois[i].lat), parseFloat(listPois[i].lon) )); } } - for (var fkey in poiRoutePolyline) { if (poiRoutePolyline.hasOwnProperty(fkey)) { - poiRoutePolyline[fkey].polyline = new google.maps.Polyline({ path: poiRoutePolyline[fkey].flightPlanCoordinates, geodesic: true, @@ -455,21 +446,17 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS strokeOpacity: 0.75, strokeWeight: 6 }); - if ($scope.anyService.selectedFloor.floor_number === fkey) poiRoutePolyline[fkey].polyline.setMap($scope.gmapService.gmap); } } - // user is in the building if (poiClosestToUserPos) { - var lineSymbol = { path: 'M 0,-1 0,1', strokeOpacity: 0.75, scale: 4 }; - userToPoiPolyline = new google.maps.Polyline({ path: [ new google.maps.LatLng(parseFloat(from.coordinates_lat), parseFloat(from.coordinates_lon)), @@ -485,9 +472,7 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS repeat: '20px' }] }); - userToPoiPolyline.setMap($scope.gmapService.gmap); - poiClosestToUserPos = undefined; } }, @@ -674,9 +659,7 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS } } poiClosestToUserPos = minP; - $scope.retrieveRouteFromPoiToPoi(minP, targetPoi); - if (!$scope.getIsUserLocVisible()) { $scope.displayMyLocMarker({lat: lat, lng: lng}); } diff --git a/server/public/anyplace_viewer_campus/Gruntfile.js b/server/public/anyplace_viewer_campus/Gruntfile.js index f95959875..2c47001b6 100644 --- a/server/public/anyplace_viewer_campus/Gruntfile.js +++ b/server/public/anyplace_viewer_campus/Gruntfile.js @@ -7,9 +7,9 @@ module.exports = function (grunt) { concat: { js: { src: [ - 'app.js', - '../js/shared.js', - '../js/anyplace-core-js/*.js', // Anyplace JS lib + '../shared/js/*.js', // FIRST + 'app.js', // SECOND + '../shared/js/anyplace-core-js/*.js', 'scripts/*.js', 'controllers/*.js' ], @@ -18,7 +18,7 @@ module.exports = function (grunt) { css: { src: [ 'style/*.css', - '../style/*.css' + '../shared/css/*.css' ], dest: 'build/css/anyplace.css' } @@ -51,54 +51,44 @@ module.exports = function (grunt) { src: ['**/*.{png,jpg,gif,svg}'], dest: 'build/images/' }, - // shared images folder - { + { // shared images folder expand: true, - cwd: '../images/', + cwd: '../shared/images/', src: ['**/*.{png,jpg,gif,svg}'], dest: 'build/images/' } - ] } }, - //compress: { - // main: { - // options: { - // mode: 'gzip' - // }, - // files: [ - // {expand: true, src: ['build/js/*.min.js'], dest: '.', ext: '.min.js.gz'}, - // {expand: true, src: ['build/css/*.min.css'], dest: '.', ext: '.min.css.gz'} - // ] - // } - //}, - watch: { js: { - files: ['app.js', '../js/shared.js', 'scripts/*.js', 'controllers/*.js'], + files: [ + 'app.js', + '../shared/js/*.js', + '../shared/js/anyplace-core-js/*.js', + 'scripts/*.js', + 'controllers/*.js'], tasks: ['concat:js', 'uglify'], options: { spawn: false } }, css: { - files: ['style/*.css', '../style/*.css'], + files: ['style/*.css', '../shared/css/*.css'], tasks: ['concat:css', 'cssmin'], options: { spawn: false } }, images: { - files: ['../images/*'], + files: ['../shared/images/*'], tasks: ['imagemin'], options: { spawn: false } } } - }); // 3. Where we tell Grunt we plan to use this plug-in. diff --git a/server/public/anyplace_viewer_campus/README.md b/server/public/anyplace_viewer_campus/README.md index ba40e96a0..5bb702451 100644 --- a/server/public/anyplace_viewer_campus/README.md +++ b/server/public/anyplace_viewer_campus/README.md @@ -1,59 +1,2 @@ -## Anyplace Viewer - -### Installing dependencies - -Install [Bower](http://bower.io/) dependencies: -``` -bower install -``` - -Install [Grunt](http://gruntjs.com/) tasks (requires [npm](https://www.npmjs.com/)): - -``` -npm install -``` - -Or (for Windows) - -``` -npm install -g grunt-cli -``` - -### Building the app - -#### Development: -``` -grunt -``` - -#### Deployment: -``` -grunt deploy -``` - -The built files will be in the *build* folder with the following structure: - - . - ├── build - │ ├── css - │ │ └── anyplace.min.css # Concatenated and minified CSS - │ ├── images - │ │ └── ... # Optimized images - │ └── js - │ └── anyplace.min.js # Concatenated and minified JS files - ├── bower_components - │ └── ... # Bower dependencies - └── index.html - - -Once the *build* folder is ready, we need to access the index.html file through the http protocol. An easy way to do that is to start a Python [SimpleHTTPServer](https://docs.python.org/2/library/simplehttpserver.html) in the directory were the index.html is located. - -``` -$ python -m SimpleHTTPServer 9000 -``` - -Then hit *http://localhost:9000/* in your browser to launch AnyplaceViewer. - -(The index.html file cannot be simply opened through the file system because the browser will throw security errors.) - -**The port number is important**. For security purposes, AnyplaceServer accepts Cross-Origin requests from *localhost* only on ports 3030, 8080 and 9000. +# Viewer (CampusMode) +See [here](../README.md) for build instructions. \ No newline at end of file diff --git a/server/public/anyplace_viewer_campus/app.js b/server/public/anyplace_viewer_campus/app.js index ad51362b9..932e5ecde 100644 --- a/server/public/anyplace_viewer_campus/app.js +++ b/server/public/anyplace_viewer_campus/app.js @@ -142,16 +142,13 @@ app.service('GMapService', function () { return tile; }; - - var mapTypeId = "roadmap"; + var mapTypeId = DEFAULT_MAP_TILES; if (typeof(Storage) !== "undefined" && localStorage) { - if (localStorage.getItem('mapTypeId')) - mapTypeId = localStorage.getItem('mapTypeId'); - else - localStorage.setItem("mapTypeId", "roadmap"); + localStorage.setItem("mapTypeId", DEFAULT_MAP_TILES);// FORCE OSM + // if (localStorage.getItem('mapTypeId')) mapTypeId = localStorage.getItem('mapTypeId'); + // else localStorage.setItem("mapTypeId", DEFAULT_MAP_TILES); } - self.gmap = new google.maps.Map(element, { center: new google.maps.LatLng(57, 21), zoomControl: true, diff --git a/server/public/anyplace_viewer_campus/bower.json b/server/public/anyplace_viewer_campus/bower.json index 088047d22..9cc8bf123 100644 --- a/server/public/anyplace_viewer_campus/bower.json +++ b/server/public/anyplace_viewer_campus/bower.json @@ -1,6 +1,6 @@ { "name": "AnyplaceViewer", - "version": "3.2.0", + "version": "4.2.0", "homepage": "http://anyplace.cs.ucy.ac.cy/viewer/", "authors": [ "Costantinos Costa", @@ -31,7 +31,7 @@ "jqueryui-touch-punch": "*", "select2": "~3.5.2", "angular-aria": "1.5.8", - "angular-animate": "1.5.8", + "angular-animate": "1.7.2", "angular-material": "^1.1.4" }, "resolutions": { diff --git a/server/public/anyplace_viewer_campus/controllers/BuildingController.js b/server/public/anyplace_viewer_campus/controllers/BuildingController.js index f59f01620..36db2c3fc 100644 --- a/server/public/anyplace_viewer_campus/controllers/BuildingController.js +++ b/server/public/anyplace_viewer_campus/controllers/BuildingController.js @@ -48,7 +48,9 @@ app.controller('BuildingController', ['$scope', '$compile', 'GMapService', 'Anyp name: undefined, email: undefined, username: undefined, - password: undefined + password: undefined, + owner_id: undefined, + access_token: undefined } $scope.myBuildings = []; @@ -65,9 +67,13 @@ app.controller('BuildingController', ['$scope', '$compile', 'GMapService', 'Anyp promise.then( function (resp) { // on success var data = resp.data; - // console.log("VERSION: " + data); + var prettyVersion=data.version; + if(data.variant !== "") { + data+="-"+data.variant; + } + console.log("VERSION:: " + data); var element = document.getElementById("anyplace-version"); - element.textContent = "v"+data; + element.textContent = "v"+prettyVersion; }, function (resp) { console.log("Failed to get version: " + resp.data); } ); @@ -236,13 +242,9 @@ app.controller('BuildingController', ['$scope', '$compile', 'GMapService', 'Anyp $scope.fetchAllBuildings = function () { var jsonReq = { "access-control-allow-origin": "", "content-encoding": "gzip", "access-control-allow-credentials": "true", "content-length": "17516", "content-type": "application/json" , "cuid":$scope.urlCampus}; - jsonReq.username = $scope.creds.username; - jsonReq.password = $scope.creds.password; - var promise = $scope.anyAPI.allCucodeCampus(jsonReq); promise.then( - function (resp) { - // on success + function (resp) { // on success var data = resp.data; //var bs = JSON.parse( data.buildings ); $scope.myBuildings = data.spaces; @@ -251,41 +253,32 @@ app.controller('BuildingController', ['$scope', '$compile', 'GMapService', 'Anyp content: '-', maxWidth: 500 }); - var localStoredBuildingIndex = -1; var localStoredBuildingId = undefined; - try { if (typeof(Storage) !== "undefined" && localStorage && localStorage.getItem('lastBuilding')) { localStoredBuildingId = localStorage.getItem('lastBuilding'); } } catch (e) { - } - var loadBuidFromUrl = -1; - for (var i = 0; i < $scope.myBuildings.length; i++) { var b = $scope.myBuildings[i]; if (i==0){ $scope.gmapService.gmap.panTo(_latLngFromBuilding(b)); $scope.gmapService.gmap.setZoom(13); } - if (localStoredBuildingId && localStoredBuildingId === b.buid) { localStoredBuildingIndex = i; } - if (b.is_published === 'true' || b.is_published == true) { b.is_published = true; } else { b.is_published = false; } - if ($scope.urlBuid && $scope.urlBuid == b.buid) { loadBuidFromUrl = i; } - // var s = new google.maps.Size(55, 80); // if ($scope.isFirefox) // s = new google.maps.Size(110, 160); diff --git a/server/public/anyplace_viewer_campus/controllers/BuildingSearchController.js b/server/public/anyplace_viewer_campus/controllers/BuildingSearchController.js index 0755a237f..56ccfc07f 100644 --- a/server/public/anyplace_viewer_campus/controllers/BuildingSearchController.js +++ b/server/public/anyplace_viewer_campus/controllers/BuildingSearchController.js @@ -48,10 +48,11 @@ app.controller('BuildingSearchController', ['$scope', '$compile', 'GMapService', name: undefined, email: undefined, username: undefined, - password: undefined + password: undefined, + owner_id: undefined, + access_token: undefined } - $scope.myBuildings = []; $scope.myBuildingsnames = {}; @@ -104,13 +105,10 @@ app.controller('BuildingSearchController', ['$scope', '$compile', 'GMapService', function (resp) { var data = resp.data; $scope.myallPois = data.pois; - var sz = $scope.myallPois.length; - for (var i = sz - 1; i >= 0; i--) { $scope.myallPois[i].buname=$scope.myBuildingsnames[$scope.myallPois[i].buid]; } - }, function (resp) { var data = resp.data; @@ -134,11 +132,9 @@ app.controller('BuildingSearchController', ['$scope', '$compile', 'GMapService', var promise = $scope.anyAPI.allBuildings(jsonReq); promise.then( - function (resp) { - // on success + function (resp) { // on success var data = resp.data; - //var bs = JSON.parse( data.buildings ); - $scope.myBuildings = data.buildings; + $scope.myBuildings = data.spaces; $scope.greeklish = data.greeklish; for (var i = 0; i < $scope.myBuildings.length; i++) { diff --git a/server/public/anyplace_viewer_campus/controllers/ControlBarController.js b/server/public/anyplace_viewer_campus/controllers/ControlBarController.js index a49ad7552..465315898 100644 --- a/server/public/anyplace_viewer_campus/controllers/ControlBarController.js +++ b/server/public/anyplace_viewer_campus/controllers/ControlBarController.js @@ -41,7 +41,9 @@ app.controller('ControlBarController', ['$scope', '$rootScope', '$routeParams', name: undefined, email: undefined, username: undefined, - password: undefined + password: undefined, + owner_id: undefined, + access_token: undefined } $scope.tab = 1; diff --git a/server/public/anyplace_viewer_campus/controllers/PoiController.js b/server/public/anyplace_viewer_campus/controllers/PoiController.js index f0d5692ff..18f975976 100644 --- a/server/public/anyplace_viewer_campus/controllers/PoiController.js +++ b/server/public/anyplace_viewer_campus/controllers/PoiController.js @@ -105,9 +105,10 @@ app.controller('PoiController', ['$scope', '$compile', 'GMapService', 'AnyplaceS } $scope.fetchAllPoi = function (letters , buid) { - - var jsonReq = { "access-control-allow-origin": "", "content-encoding": "gzip", "access-control-allow-credentials": "true", "content-length": "17516", "content-type": "application/json" , "buid":buid, "cuid":"", "letters":letters , "greeklish":$scope.greeklish}; - LOG.D2(jsonReq); + var jsonReq = { "access-control-allow-origin": "", "content-encoding": "gzip", + "access-control-allow-credentials": "true", "content-length": "17516", + "content-type": "application/json" , "buid":buid, "cuid":"", "letters":letters , "greeklish":$scope.greeklish}; + if (jsonReq.greeklish == null) jsonReq.greeklish = "true"; var promise = AnyplaceAPIService.retrieveALLPois(jsonReq); promise.then( function (resp) { diff --git a/server/public/developers/css/swagger-ui.css b/server/public/developers/css/swagger-ui.css new file mode 100644 index 000000000..df81c06ea --- /dev/null +++ b/server/public/developers/css/swagger-ui.css @@ -0,0 +1,11085 @@ +.swagger-ui { + /*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui html { + line-height: 1.15; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100% +} + +.swagger-ui body { + margin: 0 +} + +.swagger-ui article, .swagger-ui aside, .swagger-ui footer, .swagger-ui header, .swagger-ui nav, .swagger-ui section { + display: block +} + +.swagger-ui h1 { + font-size: 2em; + margin: .67em 0 +} + +.swagger-ui figcaption, .swagger-ui figure, .swagger-ui main { + display: block +} + +.swagger-ui figure { + margin: 1em 40px +} + +.swagger-ui hr { + box-sizing: content-box; + height: 0; + overflow: visible +} + +.swagger-ui pre { + font-family: monospace, monospace; + font-size: 1em +} + +.swagger-ui a { + background-color: transparent; + -webkit-text-decoration-skip: objects +} + +.swagger-ui abbr[title] { + border-bottom: none; + text-decoration: underline; + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted +} + +.swagger-ui b, .swagger-ui strong { + font-weight: inherit; + font-weight: bolder +} + +.swagger-ui code, .swagger-ui kbd, .swagger-ui samp { + font-family: monospace, monospace; + font-size: 1em +} + +.swagger-ui dfn { + font-style: italic +} + +.swagger-ui mark { + background-color: #ff0; + color: #000 +} + +.swagger-ui small { + font-size: 80% +} + +.swagger-ui sub, .swagger-ui sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline +} + +.swagger-ui sub { + bottom: -.25em +} + +.swagger-ui sup { + top: -.5em +} + +.anyplaceText:before { + content: "Anyplace (Under development)"; + color: white; + font-size: large; + max-width: max-content; + text-align: left; +} + +.admtCopyright:before { + /*https://dmsl.cs.ucy.ac.cy/*/ + content: "DMSL Copyright 2021"; + padding-left: 100px; + align-content: center; + color: white; + font-size: medium; + max-width: max-content; +} + +.swagger-ui audio, .swagger-ui video { + display: inline-block +} + +.swagger-ui audio:not([controls]) { + display: none; + height: 0 +} + +.swagger-ui img { + border-style: none +} + +.swagger-ui svg:not(:root) { + overflow: hidden +} + +.swagger-ui button, .swagger-ui input, .swagger-ui optgroup, .swagger-ui select, .swagger-ui textarea { + font-family: sans-serif; + font-size: 100%; + line-height: 1.15; + margin: 0 +} + +.swagger-ui button, .swagger-ui input { + overflow: visible +} + +.swagger-ui button, .swagger-ui select { + text-transform: none +} + +.swagger-ui [type=reset], .swagger-ui [type=submit], .swagger-ui button, .swagger-ui html [type=button] { + -webkit-appearance: button +} + +.swagger-ui [type=button]::-moz-focus-inner, .swagger-ui [type=reset]::-moz-focus-inner, .swagger-ui [type=submit]::-moz-focus-inner, .swagger-ui button::-moz-focus-inner { + border-style: none; + padding: 0 +} + +.swagger-ui [type=button]:-moz-focusring, .swagger-ui [type=reset]:-moz-focusring, .swagger-ui [type=submit]:-moz-focusring, .swagger-ui button:-moz-focusring { + outline: 1px dotted ButtonText +} + +.swagger-ui fieldset { + padding: .35em .75em .625em +} + +.swagger-ui legend { + box-sizing: border-box; + color: inherit; + display: table; + max-width: 100%; + padding: 0; + white-space: normal +} + +.swagger-ui progress { + display: inline-block; + vertical-align: baseline +} + +.swagger-ui textarea { + overflow: auto +} + +.swagger-ui [type=checkbox], .swagger-ui [type=radio] { + box-sizing: border-box; + padding: 0 +} + +.swagger-ui [type=number]::-webkit-inner-spin-button, .swagger-ui [type=number]::-webkit-outer-spin-button { + height: auto +} + +.swagger-ui [type=search] { + -webkit-appearance: textfield; + outline-offset: -2px +} + +.swagger-ui [type=search]::-webkit-search-cancel-button, .swagger-ui [type=search]::-webkit-search-decoration { + -webkit-appearance: none +} + +.swagger-ui ::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit +} + +.swagger-ui details, .swagger-ui menu { + display: block +} + +.swagger-ui summary { + display: list-item +} + +.swagger-ui canvas { + display: inline-block +} + +.swagger-ui template { + display: none +} + +.swagger-ui [hidden] { + display: none +} + +.swagger-ui .debug * { + outline: 1px solid gold +} + +.swagger-ui .debug-white * { + outline: 1px solid #fff +} + +.swagger-ui .debug-black * { + outline: 1px solid #000 +} + +.swagger-ui .debug-grid { + background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTRDOTY4N0U2N0VFMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTRDOTY4N0Q2N0VFMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3NjY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3NzY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsBS+GMAAAAjSURBVHjaYvz//z8DLsD4gcGXiYEAGBIKGBne//fFpwAgwAB98AaF2pjlUQAAAABJRU5ErkJggg==) repeat 0 0 +} + +.swagger-ui .debug-grid-16 { + background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODYyRjhERDU2N0YyMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODYyRjhERDQ2N0YyMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3QTY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3QjY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvCS01IAAABMSURBVHjaYmR4/5+BFPBfAMFm/MBgx8RAGWCn1AAmSg34Q6kBDKMGMDCwICeMIemF/5QawEipAWwUhwEjMDvbAWlWkvVBwu8vQIABAEwBCph8U6c0AAAAAElFTkSuQmCC) repeat 0 0 +} + +.swagger-ui .debug-grid-8-solid { + background: #fff url(data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAAAAAD/4QMxaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzExMSA3OS4xNTgzMjUsIDIwMTUvMDkvMTAtMDE6MTA6MjAgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE1IChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkIxMjI0OTczNjdCMzExRTZCMkJDRTI0MDgxMDAyMTcxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkIxMjI0OTc0NjdCMzExRTZCMkJDRTI0MDgxMDAyMTcxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QjEyMjQ5NzE2N0IzMTFFNkIyQkNFMjQwODEwMDIxNzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QjEyMjQ5NzI2N0IzMTFFNkIyQkNFMjQwODEwMDIxNzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAbGhopHSlBJiZBQi8vL0JHPz4+P0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHAR0pKTQmND8oKD9HPzU/R0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0f/wAARCAAIAAgDASIAAhEBAxEB/8QAWQABAQAAAAAAAAAAAAAAAAAAAAYBAQEAAAAAAAAAAAAAAAAAAAIEEAEBAAMBAAAAAAAAAAAAAAABADECA0ERAAEDBQAAAAAAAAAAAAAAAAARITFBUWESIv/aAAwDAQACEQMRAD8AoOnTV1QTD7JJshP3vSM3P//Z) repeat 0 0 +} + +.swagger-ui .debug-grid-16-solid { + background: #fff url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzY3MkJEN0U2N0M1MTFFNkIyQkNFMjQwODEwMDIxNzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzY3MkJEN0Y2N0M1MTFFNkIyQkNFMjQwODEwMDIxNzEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3QzY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3RDY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pve6J3kAAAAzSURBVHjaYvz//z8D0UDsMwMjSRoYP5Gq4SPNbRjVMEQ1fCRDg+in/6+J1AJUxsgAEGAA31BAJMS0GYEAAAAASUVORK5CYII=) repeat 0 0 +} + +.swagger-ui .border-box, .swagger-ui a, .swagger-ui article, .swagger-ui body, .swagger-ui code, .swagger-ui dd, .swagger-ui div, .swagger-ui dl, .swagger-ui dt, .swagger-ui fieldset, .swagger-ui footer, .swagger-ui form, .swagger-ui h1, .swagger-ui h2, .swagger-ui h3, .swagger-ui h4, .swagger-ui h5, .swagger-ui h6, .swagger-ui header, .swagger-ui html, .swagger-ui input[type=email], .swagger-ui input[type=number], .swagger-ui input[type=password], .swagger-ui input[type=tel], .swagger-ui input[type=text], .swagger-ui input[type=url], .swagger-ui legend, .swagger-ui li, .swagger-ui main, .swagger-ui ol, .swagger-ui p, .swagger-ui pre, .swagger-ui section, .swagger-ui table, .swagger-ui td, .swagger-ui textarea, .swagger-ui th, .swagger-ui tr, .swagger-ui ul { + box-sizing: border-box +} + +.swagger-ui .aspect-ratio { + height: 0; + position: relative +} + +.swagger-ui .aspect-ratio--16x9 { + padding-bottom: 56.25% +} + +.swagger-ui .aspect-ratio--9x16 { + padding-bottom: 177.77% +} + +.swagger-ui .aspect-ratio--4x3 { + padding-bottom: 75% +} + +.swagger-ui .aspect-ratio--3x4 { + padding-bottom: 133.33% +} + +.swagger-ui .aspect-ratio--6x4 { + padding-bottom: 66.6% +} + +.swagger-ui .aspect-ratio--4x6 { + padding-bottom: 150% +} + +.swagger-ui .aspect-ratio--8x5 { + padding-bottom: 62.5% +} + +.swagger-ui .aspect-ratio--5x8 { + padding-bottom: 160% +} + +.swagger-ui .aspect-ratio--7x5 { + padding-bottom: 71.42% +} + +.swagger-ui .aspect-ratio--5x7 { + padding-bottom: 140% +} + +.swagger-ui .aspect-ratio--1x1 { + padding-bottom: 100% +} + +.swagger-ui .aspect-ratio--object { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 100 +} + +@media screen and (min-width: 30em) { + .swagger-ui .aspect-ratio-ns { + height: 0; + position: relative + } + + .swagger-ui .aspect-ratio--16x9-ns { + padding-bottom: 56.25% + } + + .swagger-ui .aspect-ratio--9x16-ns { + padding-bottom: 177.77% + } + + .swagger-ui .aspect-ratio--4x3-ns { + padding-bottom: 75% + } + + .swagger-ui .aspect-ratio--3x4-ns { + padding-bottom: 133.33% + } + + .swagger-ui .aspect-ratio--6x4-ns { + padding-bottom: 66.6% + } + + .swagger-ui .aspect-ratio--4x6-ns { + padding-bottom: 150% + } + + .swagger-ui .aspect-ratio--8x5-ns { + padding-bottom: 62.5% + } + + .swagger-ui .aspect-ratio--5x8-ns { + padding-bottom: 160% + } + + .swagger-ui .aspect-ratio--7x5-ns { + padding-bottom: 71.42% + } + + .swagger-ui .aspect-ratio--5x7-ns { + padding-bottom: 140% + } + + .swagger-ui .aspect-ratio--1x1-ns { + padding-bottom: 100% + } + + .swagger-ui .aspect-ratio--object-ns { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 100 + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .aspect-ratio-m { + height: 0; + position: relative + } + + .swagger-ui .aspect-ratio--16x9-m { + padding-bottom: 56.25% + } + + .swagger-ui .aspect-ratio--9x16-m { + padding-bottom: 177.77% + } + + .swagger-ui .aspect-ratio--4x3-m { + padding-bottom: 75% + } + + .swagger-ui .aspect-ratio--3x4-m { + padding-bottom: 133.33% + } + + .swagger-ui .aspect-ratio--6x4-m { + padding-bottom: 66.6% + } + + .swagger-ui .aspect-ratio--4x6-m { + padding-bottom: 150% + } + + .swagger-ui .aspect-ratio--8x5-m { + padding-bottom: 62.5% + } + + .swagger-ui .aspect-ratio--5x8-m { + padding-bottom: 160% + } + + .swagger-ui .aspect-ratio--7x5-m { + padding-bottom: 71.42% + } + + .swagger-ui .aspect-ratio--5x7-m { + padding-bottom: 140% + } + + .swagger-ui .aspect-ratio--1x1-m { + padding-bottom: 100% + } + + .swagger-ui .aspect-ratio--object-m { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 100 + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .aspect-ratio-l { + height: 0; + position: relative + } + + .swagger-ui .aspect-ratio--16x9-l { + padding-bottom: 56.25% + } + + .swagger-ui .aspect-ratio--9x16-l { + padding-bottom: 177.77% + } + + .swagger-ui .aspect-ratio--4x3-l { + padding-bottom: 75% + } + + .swagger-ui .aspect-ratio--3x4-l { + padding-bottom: 133.33% + } + + .swagger-ui .aspect-ratio--6x4-l { + padding-bottom: 66.6% + } + + .swagger-ui .aspect-ratio--4x6-l { + padding-bottom: 150% + } + + .swagger-ui .aspect-ratio--8x5-l { + padding-bottom: 62.5% + } + + .swagger-ui .aspect-ratio--5x8-l { + padding-bottom: 160% + } + + .swagger-ui .aspect-ratio--7x5-l { + padding-bottom: 71.42% + } + + .swagger-ui .aspect-ratio--5x7-l { + padding-bottom: 140% + } + + .swagger-ui .aspect-ratio--1x1-l { + padding-bottom: 100% + } + + .swagger-ui .aspect-ratio--object-l { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 100 + } +} + +.swagger-ui img { + max-width: 100% +} + +.swagger-ui .cover { + background-size: cover !important +} + +.swagger-ui .contain { + background-size: contain !important +} + +@media screen and (min-width: 30em) { + .swagger-ui .cover-ns { + background-size: cover !important + } + + .swagger-ui .contain-ns { + background-size: contain !important + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .cover-m { + background-size: cover !important + } + + .swagger-ui .contain-m { + background-size: contain !important + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .cover-l { + background-size: cover !important + } + + .swagger-ui .contain-l { + background-size: contain !important + } +} + +.swagger-ui .bg-center { + background-repeat: no-repeat; + background-position: 50% +} + +.swagger-ui .bg-top { + background-repeat: no-repeat; + background-position: top +} + +.swagger-ui .bg-right { + background-repeat: no-repeat; + background-position: 100% +} + +.swagger-ui .bg-bottom { + background-repeat: no-repeat; + background-position: bottom +} + +.swagger-ui .bg-left { + background-repeat: no-repeat; + background-position: 0 +} + +@media screen and (min-width: 30em) { + .swagger-ui .bg-center-ns { + background-repeat: no-repeat; + background-position: 50% + } + + .swagger-ui .bg-top-ns { + background-repeat: no-repeat; + background-position: top + } + + .swagger-ui .bg-right-ns { + background-repeat: no-repeat; + background-position: 100% + } + + .swagger-ui .bg-bottom-ns { + background-repeat: no-repeat; + background-position: bottom + } + + .swagger-ui .bg-left-ns { + background-repeat: no-repeat; + background-position: 0 + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .bg-center-m { + background-repeat: no-repeat; + background-position: 50% + } + + .swagger-ui .bg-top-m { + background-repeat: no-repeat; + background-position: top + } + + .swagger-ui .bg-right-m { + background-repeat: no-repeat; + background-position: 100% + } + + .swagger-ui .bg-bottom-m { + background-repeat: no-repeat; + background-position: bottom + } + + .swagger-ui .bg-left-m { + background-repeat: no-repeat; + background-position: 0 + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .bg-center-l { + background-repeat: no-repeat; + background-position: 50% + } + + .swagger-ui .bg-top-l { + background-repeat: no-repeat; + background-position: top + } + + .swagger-ui .bg-right-l { + background-repeat: no-repeat; + background-position: 100% + } + + .swagger-ui .bg-bottom-l { + background-repeat: no-repeat; + background-position: bottom + } + + .swagger-ui .bg-left-l { + background-repeat: no-repeat; + background-position: 0 + } +} + +.swagger-ui .outline { + outline: 1px solid +} + +.swagger-ui .outline-transparent { + outline: 1px solid transparent +} + +.swagger-ui .outline-0 { + outline: 0 +} + +@media screen and (min-width: 30em) { + .swagger-ui .outline-ns { + outline: 1px solid + } + + .swagger-ui .outline-transparent-ns { + outline: 1px solid transparent + } + + .swagger-ui .outline-0-ns { + outline: 0 + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .outline-m { + outline: 1px solid + } + + .swagger-ui .outline-transparent-m { + outline: 1px solid transparent + } + + .swagger-ui .outline-0-m { + outline: 0 + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .outline-l { + outline: 1px solid + } + + .swagger-ui .outline-transparent-l { + outline: 1px solid transparent + } + + .swagger-ui .outline-0-l { + outline: 0 + } +} + +.swagger-ui .ba { + border-style: solid; + border-width: 1px +} + +.swagger-ui .bt { + border-top-style: solid; + border-top-width: 1px +} + +.swagger-ui .br { + border-right-style: solid; + border-right-width: 1px +} + +.swagger-ui .bb { + border-bottom-style: solid; + border-bottom-width: 1px +} + +.swagger-ui .bl { + border-left-style: solid; + border-left-width: 1px +} + +.swagger-ui .bn { + border-style: none; + border-width: 0 +} + +@media screen and (min-width: 30em) { + .swagger-ui .ba-ns { + border-style: solid; + border-width: 1px + } + + .swagger-ui .bt-ns { + border-top-style: solid; + border-top-width: 1px + } + + .swagger-ui .br-ns { + border-right-style: solid; + border-right-width: 1px + } + + .swagger-ui .bb-ns { + border-bottom-style: solid; + border-bottom-width: 1px + } + + .swagger-ui .bl-ns { + border-left-style: solid; + border-left-width: 1px + } + + .swagger-ui .bn-ns { + border-style: none; + border-width: 0 + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .ba-m { + border-style: solid; + border-width: 1px + } + + .swagger-ui .bt-m { + border-top-style: solid; + border-top-width: 1px + } + + .swagger-ui .br-m { + border-right-style: solid; + border-right-width: 1px + } + + .swagger-ui .bb-m { + border-bottom-style: solid; + border-bottom-width: 1px + } + + .swagger-ui .bl-m { + border-left-style: solid; + border-left-width: 1px + } + + .swagger-ui .bn-m { + border-style: none; + border-width: 0 + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .ba-l { + border-style: solid; + border-width: 1px + } + + .swagger-ui .bt-l { + border-top-style: solid; + border-top-width: 1px + } + + .swagger-ui .br-l { + border-right-style: solid; + border-right-width: 1px + } + + .swagger-ui .bb-l { + border-bottom-style: solid; + border-bottom-width: 1px + } + + .swagger-ui .bl-l { + border-left-style: solid; + border-left-width: 1px + } + + .swagger-ui .bn-l { + border-style: none; + border-width: 0 + } +} + +.swagger-ui .b--black { + border-color: #000 +} + +.swagger-ui .b--near-black { + border-color: #111 +} + +.swagger-ui .b--dark-gray { + border-color: #333 +} + +.swagger-ui .b--mid-gray { + border-color: #555 +} + +.swagger-ui .b--gray { + border-color: #777 +} + +.swagger-ui .b--silver { + border-color: #999 +} + +.swagger-ui .b--light-silver { + border-color: #aaa +} + +.swagger-ui .b--moon-gray { + border-color: #ccc +} + +.swagger-ui .b--light-gray { + border-color: #eee +} + +.swagger-ui .b--near-white { + border-color: #f4f4f4 +} + +.swagger-ui .b--white { + border-color: #fff +} + +.swagger-ui .b--white-90 { + border-color: hsla(0, 0%, 100%, .9) +} + +.swagger-ui .b--white-80 { + border-color: hsla(0, 0%, 100%, .8) +} + +.swagger-ui .b--white-70 { + border-color: hsla(0, 0%, 100%, .7) +} + +.swagger-ui .b--white-60 { + border-color: hsla(0, 0%, 100%, .6) +} + +.swagger-ui .b--white-50 { + border-color: hsla(0, 0%, 100%, .5) +} + +.swagger-ui .b--white-40 { + border-color: hsla(0, 0%, 100%, .4) +} + +.swagger-ui .b--white-30 { + border-color: hsla(0, 0%, 100%, .3) +} + +.swagger-ui .b--white-20 { + border-color: hsla(0, 0%, 100%, .2) +} + +.swagger-ui .b--white-10 { + border-color: hsla(0, 0%, 100%, .1) +} + +.swagger-ui .b--white-05 { + border-color: hsla(0, 0%, 100%, .05) +} + +.swagger-ui .b--white-025 { + border-color: hsla(0, 0%, 100%, .025) +} + +.swagger-ui .b--white-0125 { + border-color: hsla(0, 0%, 100%, .0125) +} + +.swagger-ui .b--black-90 { + border-color: rgba(0, 0, 0, .9) +} + +.swagger-ui .b--black-80 { + border-color: rgba(0, 0, 0, .8) +} + +.swagger-ui .b--black-70 { + border-color: rgba(0, 0, 0, .7) +} + +.swagger-ui .b--black-60 { + border-color: rgba(0, 0, 0, .6) +} + +.swagger-ui .b--black-50 { + border-color: rgba(0, 0, 0, .5) +} + +.swagger-ui .b--black-40 { + border-color: rgba(0, 0, 0, .4) +} + +.swagger-ui .b--black-30 { + border-color: rgba(0, 0, 0, .3) +} + +.swagger-ui .b--black-20 { + border-color: rgba(0, 0, 0, .2) +} + +.swagger-ui .b--black-10 { + border-color: rgba(0, 0, 0, .1) +} + +.swagger-ui .b--black-05 { + border-color: rgba(0, 0, 0, .05) +} + +.swagger-ui .b--black-025 { + border-color: rgba(0, 0, 0, .025) +} + +.swagger-ui .b--black-0125 { + border-color: rgba(0, 0, 0, .0125) +} + +.swagger-ui .b--dark-red { + border-color: #e7040f +} + +.swagger-ui .b--red { + border-color: #ff4136 +} + +.swagger-ui .b--light-red { + border-color: #ff725c +} + +.swagger-ui .b--orange { + border-color: #ff6300 +} + +.swagger-ui .b--gold { + border-color: #ffb700 +} + +.swagger-ui .b--yellow { + border-color: gold +} + +.swagger-ui .b--light-yellow { + border-color: #fbf1a9 +} + +.swagger-ui .b--purple { + border-color: #5e2ca5 +} + +.swagger-ui .b--light-purple { + border-color: #a463f2 +} + +.swagger-ui .b--dark-pink { + border-color: #d5008f +} + +.swagger-ui .b--hot-pink { + border-color: #ff41b4 +} + +.swagger-ui .b--pink { + border-color: #ff80cc +} + +.swagger-ui .b--light-pink { + border-color: #ffa3d7 +} + +.swagger-ui .b--dark-green { + border-color: #137752 +} + +.swagger-ui .b--green { + border-color: #19a974 +} + +.swagger-ui .b--light-green { + border-color: #9eebcf +} + +.swagger-ui .b--navy { + border-color: #001b44 +} + +.swagger-ui .b--dark-blue { + border-color: #00449e +} + +.swagger-ui .b--blue { + border-color: #357edd +} + +.swagger-ui .b--light-blue { + border-color: #96ccff +} + +.swagger-ui .b--lightest-blue { + border-color: #cdecff +} + +.swagger-ui .b--washed-blue { + border-color: #f6fffe +} + +.swagger-ui .b--washed-green { + border-color: #e8fdf5 +} + +.swagger-ui .b--washed-yellow { + border-color: #fffceb +} + +.swagger-ui .b--washed-red { + border-color: #ffdfdf +} + +.swagger-ui .b--transparent { + border-color: transparent +} + +.swagger-ui .b--inherit { + border-color: inherit +} + +.swagger-ui .br0 { + border-radius: 0 +} + +.swagger-ui .br1 { + border-radius: .125rem +} + +.swagger-ui .br2 { + border-radius: .25rem +} + +.swagger-ui .br3 { + border-radius: .5rem +} + +.swagger-ui .br4 { + border-radius: 1rem +} + +.swagger-ui .br-100 { + border-radius: 100% +} + +.swagger-ui .br-pill { + border-radius: 9999px +} + +.swagger-ui .br--bottom { + border-top-left-radius: 0; + border-top-right-radius: 0 +} + +.swagger-ui .br--top { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0 +} + +.swagger-ui .br--right { + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} + +.swagger-ui .br--left { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} + +@media screen and (min-width: 30em) { + .swagger-ui .br0-ns { + border-radius: 0 + } + + .swagger-ui .br1-ns { + border-radius: .125rem + } + + .swagger-ui .br2-ns { + border-radius: .25rem + } + + .swagger-ui .br3-ns { + border-radius: .5rem + } + + .swagger-ui .br4-ns { + border-radius: 1rem + } + + .swagger-ui .br-100-ns { + border-radius: 100% + } + + .swagger-ui .br-pill-ns { + border-radius: 9999px + } + + .swagger-ui .br--bottom-ns { + border-top-left-radius: 0; + border-top-right-radius: 0 + } + + .swagger-ui .br--top-ns { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0 + } + + .swagger-ui .br--right-ns { + border-top-left-radius: 0; + border-bottom-left-radius: 0 + } + + .swagger-ui .br--left-ns { + border-top-right-radius: 0; + border-bottom-right-radius: 0 + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .br0-m { + border-radius: 0 + } + + .swagger-ui .br1-m { + border-radius: .125rem + } + + .swagger-ui .br2-m { + border-radius: .25rem + } + + .swagger-ui .br3-m { + border-radius: .5rem + } + + .swagger-ui .br4-m { + border-radius: 1rem + } + + .swagger-ui .br-100-m { + border-radius: 100% + } + + .swagger-ui .br-pill-m { + border-radius: 9999px + } + + .swagger-ui .br--bottom-m { + border-top-left-radius: 0; + border-top-right-radius: 0 + } + + .swagger-ui .br--top-m { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0 + } + + .swagger-ui .br--right-m { + border-top-left-radius: 0; + border-bottom-left-radius: 0 + } + + .swagger-ui .br--left-m { + border-top-right-radius: 0; + border-bottom-right-radius: 0 + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .br0-l { + border-radius: 0 + } + + .swagger-ui .br1-l { + border-radius: .125rem + } + + .swagger-ui .br2-l { + border-radius: .25rem + } + + .swagger-ui .br3-l { + border-radius: .5rem + } + + .swagger-ui .br4-l { + border-radius: 1rem + } + + .swagger-ui .br-100-l { + border-radius: 100% + } + + .swagger-ui .br-pill-l { + border-radius: 9999px + } + + .swagger-ui .br--bottom-l { + border-top-left-radius: 0; + border-top-right-radius: 0 + } + + .swagger-ui .br--top-l { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0 + } + + .swagger-ui .br--right-l { + border-top-left-radius: 0; + border-bottom-left-radius: 0 + } + + .swagger-ui .br--left-l { + border-top-right-radius: 0; + border-bottom-right-radius: 0 + } +} + +.swagger-ui .b--dotted { + border-style: dotted +} + +.swagger-ui .b--dashed { + border-style: dashed +} + +.swagger-ui .b--solid { + border-style: solid +} + +.swagger-ui .b--none { + border-style: none +} + +@media screen and (min-width: 30em) { + .swagger-ui .b--dotted-ns { + border-style: dotted + } + + .swagger-ui .b--dashed-ns { + border-style: dashed + } + + .swagger-ui .b--solid-ns { + border-style: solid + } + + .swagger-ui .b--none-ns { + border-style: none + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .b--dotted-m { + border-style: dotted + } + + .swagger-ui .b--dashed-m { + border-style: dashed + } + + .swagger-ui .b--solid-m { + border-style: solid + } + + .swagger-ui .b--none-m { + border-style: none + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .b--dotted-l { + border-style: dotted + } + + .swagger-ui .b--dashed-l { + border-style: dashed + } + + .swagger-ui .b--solid-l { + border-style: solid + } + + .swagger-ui .b--none-l { + border-style: none + } +} + +.swagger-ui .bw0 { + border-width: 0 +} + +.swagger-ui .bw1 { + border-width: .125rem +} + +.swagger-ui .bw2 { + border-width: .25rem +} + +.swagger-ui .bw3 { + border-width: .5rem +} + +.swagger-ui .bw4 { + border-width: 1rem +} + +.swagger-ui .bw5 { + border-width: 2rem +} + +.swagger-ui .bt-0 { + border-top-width: 0 +} + +.swagger-ui .br-0 { + border-right-width: 0 +} + +.swagger-ui .bb-0 { + border-bottom-width: 0 +} + +.swagger-ui .bl-0 { + border-left-width: 0 +} + +@media screen and (min-width: 30em) { + .swagger-ui .bw0-ns { + border-width: 0 + } + + .swagger-ui .bw1-ns { + border-width: .125rem + } + + .swagger-ui .bw2-ns { + border-width: .25rem + } + + .swagger-ui .bw3-ns { + border-width: .5rem + } + + .swagger-ui .bw4-ns { + border-width: 1rem + } + + .swagger-ui .bw5-ns { + border-width: 2rem + } + + .swagger-ui .bt-0-ns { + border-top-width: 0 + } + + .swagger-ui .br-0-ns { + border-right-width: 0 + } + + .swagger-ui .bb-0-ns { + border-bottom-width: 0 + } + + .swagger-ui .bl-0-ns { + border-left-width: 0 + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .bw0-m { + border-width: 0 + } + + .swagger-ui .bw1-m { + border-width: .125rem + } + + .swagger-ui .bw2-m { + border-width: .25rem + } + + .swagger-ui .bw3-m { + border-width: .5rem + } + + .swagger-ui .bw4-m { + border-width: 1rem + } + + .swagger-ui .bw5-m { + border-width: 2rem + } + + .swagger-ui .bt-0-m { + border-top-width: 0 + } + + .swagger-ui .br-0-m { + border-right-width: 0 + } + + .swagger-ui .bb-0-m { + border-bottom-width: 0 + } + + .swagger-ui .bl-0-m { + border-left-width: 0 + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .bw0-l { + border-width: 0 + } + + .swagger-ui .bw1-l { + border-width: .125rem + } + + .swagger-ui .bw2-l { + border-width: .25rem + } + + .swagger-ui .bw3-l { + border-width: .5rem + } + + .swagger-ui .bw4-l { + border-width: 1rem + } + + .swagger-ui .bw5-l { + border-width: 2rem + } + + .swagger-ui .bt-0-l { + border-top-width: 0 + } + + .swagger-ui .br-0-l { + border-right-width: 0 + } + + .swagger-ui .bb-0-l { + border-bottom-width: 0 + } + + .swagger-ui .bl-0-l { + border-left-width: 0 + } +} + +.swagger-ui .shadow-1 { + box-shadow: 0 0 4px 2px rgba(0, 0, 0, .2) +} + +.swagger-ui .shadow-2 { + box-shadow: 0 0 8px 2px rgba(0, 0, 0, .2) +} + +.swagger-ui .shadow-3 { + box-shadow: 2px 2px 4px 2px rgba(0, 0, 0, .2) +} + +.swagger-ui .shadow-4 { + box-shadow: 2px 2px 8px 0 rgba(0, 0, 0, .2) +} + +.swagger-ui .shadow-5 { + box-shadow: 4px 4px 8px 0 rgba(0, 0, 0, .2) +} + +@media screen and (min-width: 30em) { + .swagger-ui .shadow-1-ns { + box-shadow: 0 0 4px 2px rgba(0, 0, 0, .2) + } + + .swagger-ui .shadow-2-ns { + box-shadow: 0 0 8px 2px rgba(0, 0, 0, .2) + } + + .swagger-ui .shadow-3-ns { + box-shadow: 2px 2px 4px 2px rgba(0, 0, 0, .2) + } + + .swagger-ui .shadow-4-ns { + box-shadow: 2px 2px 8px 0 rgba(0, 0, 0, .2) + } + + .swagger-ui .shadow-5-ns { + box-shadow: 4px 4px 8px 0 rgba(0, 0, 0, .2) + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .shadow-1-m { + box-shadow: 0 0 4px 2px rgba(0, 0, 0, .2) + } + + .swagger-ui .shadow-2-m { + box-shadow: 0 0 8px 2px rgba(0, 0, 0, .2) + } + + .swagger-ui .shadow-3-m { + box-shadow: 2px 2px 4px 2px rgba(0, 0, 0, .2) + } + + .swagger-ui .shadow-4-m { + box-shadow: 2px 2px 8px 0 rgba(0, 0, 0, .2) + } + + .swagger-ui .shadow-5-m { + box-shadow: 4px 4px 8px 0 rgba(0, 0, 0, .2) + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .shadow-1-l { + box-shadow: 0 0 4px 2px rgba(0, 0, 0, .2) + } + + .swagger-ui .shadow-2-l { + box-shadow: 0 0 8px 2px rgba(0, 0, 0, .2) + } + + .swagger-ui .shadow-3-l { + box-shadow: 2px 2px 4px 2px rgba(0, 0, 0, .2) + } + + .swagger-ui .shadow-4-l { + box-shadow: 2px 2px 8px 0 rgba(0, 0, 0, .2) + } + + .swagger-ui .shadow-5-l { + box-shadow: 4px 4px 8px 0 rgba(0, 0, 0, .2) + } +} + +.swagger-ui .pre { + overflow-x: auto; + overflow-y: hidden; + overflow: scroll +} + +.swagger-ui .top-0 { + top: 0 +} + +.swagger-ui .right-0 { + right: 0 +} + +.swagger-ui .bottom-0 { + bottom: 0 +} + +.swagger-ui .left-0 { + left: 0 +} + +.swagger-ui .top-1 { + top: 1rem +} + +.swagger-ui .right-1 { + right: 1rem +} + +.swagger-ui .bottom-1 { + bottom: 1rem +} + +.swagger-ui .left-1 { + left: 1rem +} + +.swagger-ui .top-2 { + top: 2rem +} + +.swagger-ui .right-2 { + right: 2rem +} + +.swagger-ui .bottom-2 { + bottom: 2rem +} + +.swagger-ui .left-2 { + left: 2rem +} + +.swagger-ui .top--1 { + top: -1rem +} + +.swagger-ui .right--1 { + right: -1rem +} + +.swagger-ui .bottom--1 { + bottom: -1rem +} + +.swagger-ui .left--1 { + left: -1rem +} + +.swagger-ui .top--2 { + top: -2rem +} + +.swagger-ui .right--2 { + right: -2rem +} + +.swagger-ui .bottom--2 { + bottom: -2rem +} + +.swagger-ui .left--2 { + left: -2rem +} + +.swagger-ui .absolute--fill { + top: 0; + right: 0; + bottom: 0; + left: 0 +} + +@media screen and (min-width: 30em) { + .swagger-ui .top-0-ns { + top: 0 + } + + .swagger-ui .left-0-ns { + left: 0 + } + + .swagger-ui .right-0-ns { + right: 0 + } + + .swagger-ui .bottom-0-ns { + bottom: 0 + } + + .swagger-ui .top-1-ns { + top: 1rem + } + + .swagger-ui .left-1-ns { + left: 1rem + } + + .swagger-ui .right-1-ns { + right: 1rem + } + + .swagger-ui .bottom-1-ns { + bottom: 1rem + } + + .swagger-ui .top-2-ns { + top: 2rem + } + + .swagger-ui .left-2-ns { + left: 2rem + } + + .swagger-ui .right-2-ns { + right: 2rem + } + + .swagger-ui .bottom-2-ns { + bottom: 2rem + } + + .swagger-ui .top--1-ns { + top: -1rem + } + + .swagger-ui .right--1-ns { + right: -1rem + } + + .swagger-ui .bottom--1-ns { + bottom: -1rem + } + + .swagger-ui .left--1-ns { + left: -1rem + } + + .swagger-ui .top--2-ns { + top: -2rem + } + + .swagger-ui .right--2-ns { + right: -2rem + } + + .swagger-ui .bottom--2-ns { + bottom: -2rem + } + + .swagger-ui .left--2-ns { + left: -2rem + } + + .swagger-ui .absolute--fill-ns { + top: 0; + right: 0; + bottom: 0; + left: 0 + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .top-0-m { + top: 0 + } + + .swagger-ui .left-0-m { + left: 0 + } + + .swagger-ui .right-0-m { + right: 0 + } + + .swagger-ui .bottom-0-m { + bottom: 0 + } + + .swagger-ui .top-1-m { + top: 1rem + } + + .swagger-ui .left-1-m { + left: 1rem + } + + .swagger-ui .right-1-m { + right: 1rem + } + + .swagger-ui .bottom-1-m { + bottom: 1rem + } + + .swagger-ui .top-2-m { + top: 2rem + } + + .swagger-ui .left-2-m { + left: 2rem + } + + .swagger-ui .right-2-m { + right: 2rem + } + + .swagger-ui .bottom-2-m { + bottom: 2rem + } + + .swagger-ui .top--1-m { + top: -1rem + } + + .swagger-ui .right--1-m { + right: -1rem + } + + .swagger-ui .bottom--1-m { + bottom: -1rem + } + + .swagger-ui .left--1-m { + left: -1rem + } + + .swagger-ui .top--2-m { + top: -2rem + } + + .swagger-ui .right--2-m { + right: -2rem + } + + .swagger-ui .bottom--2-m { + bottom: -2rem + } + + .swagger-ui .left--2-m { + left: -2rem + } + + .swagger-ui .absolute--fill-m { + top: 0; + right: 0; + bottom: 0; + left: 0 + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .top-0-l { + top: 0 + } + + .swagger-ui .left-0-l { + left: 0 + } + + .swagger-ui .right-0-l { + right: 0 + } + + .swagger-ui .bottom-0-l { + bottom: 0 + } + + .swagger-ui .top-1-l { + top: 1rem + } + + .swagger-ui .left-1-l { + left: 1rem + } + + .swagger-ui .right-1-l { + right: 1rem + } + + .swagger-ui .bottom-1-l { + bottom: 1rem + } + + .swagger-ui .top-2-l { + top: 2rem + } + + .swagger-ui .left-2-l { + left: 2rem + } + + .swagger-ui .right-2-l { + right: 2rem + } + + .swagger-ui .bottom-2-l { + bottom: 2rem + } + + .swagger-ui .top--1-l { + top: -1rem + } + + .swagger-ui .right--1-l { + right: -1rem + } + + .swagger-ui .bottom--1-l { + bottom: -1rem + } + + .swagger-ui .left--1-l { + left: -1rem + } + + .swagger-ui .top--2-l { + top: -2rem + } + + .swagger-ui .right--2-l { + right: -2rem + } + + .swagger-ui .bottom--2-l { + bottom: -2rem + } + + .swagger-ui .left--2-l { + left: -2rem + } + + .swagger-ui .absolute--fill-l { + top: 0; + right: 0; + bottom: 0; + left: 0 + } +} + +.swagger-ui .cf:after, .swagger-ui .cf:before { + content: " "; + display: table +} + +.swagger-ui .cf:after { + clear: both +} + +.swagger-ui .cf { + *zoom: 1 +} + +.swagger-ui .cl { + clear: left +} + +.swagger-ui .cr { + clear: right +} + +.swagger-ui .cb { + clear: both +} + +.swagger-ui .cn { + clear: none +} + +@media screen and (min-width: 30em) { + .swagger-ui .cl-ns { + clear: left + } + + .swagger-ui .cr-ns { + clear: right + } + + .swagger-ui .cb-ns { + clear: both + } + + .swagger-ui .cn-ns { + clear: none + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .cl-m { + clear: left + } + + .swagger-ui .cr-m { + clear: right + } + + .swagger-ui .cb-m { + clear: both + } + + .swagger-ui .cn-m { + clear: none + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .cl-l { + clear: left + } + + .swagger-ui .cr-l { + clear: right + } + + .swagger-ui .cb-l { + clear: both + } + + .swagger-ui .cn-l { + clear: none + } +} + +.swagger-ui .flex { + display: flex +} + +.swagger-ui .inline-flex { + display: inline-flex +} + +.swagger-ui .flex-auto { + flex: 1 1 auto; + min-width: 0; + min-height: 0 +} + +.swagger-ui .flex-none { + flex: none +} + +.swagger-ui .flex-column { + flex-direction: column +} + +.swagger-ui .flex-row { + flex-direction: row +} + +.swagger-ui .flex-wrap { + flex-wrap: wrap +} + +.swagger-ui .flex-nowrap { + flex-wrap: nowrap +} + +.swagger-ui .flex-wrap-reverse { + flex-wrap: wrap-reverse +} + +.swagger-ui .flex-column-reverse { + flex-direction: column-reverse +} + +.swagger-ui .flex-row-reverse { + flex-direction: row-reverse +} + +.swagger-ui .items-start { + align-items: flex-start +} + +.swagger-ui .items-end { + align-items: flex-end +} + +.swagger-ui .items-center { + align-items: center +} + +.swagger-ui .items-baseline { + align-items: baseline +} + +.swagger-ui .items-stretch { + align-items: stretch +} + +.swagger-ui .self-start { + align-self: flex-start +} + +.swagger-ui .self-end { + align-self: flex-end +} + +.swagger-ui .self-center { + align-self: center +} + +.swagger-ui .self-baseline { + align-self: baseline +} + +.swagger-ui .self-stretch { + align-self: stretch +} + +.swagger-ui .justify-start { + justify-content: flex-start +} + +.swagger-ui .justify-end { + justify-content: flex-end +} + +.swagger-ui .justify-center { + justify-content: center +} + +.swagger-ui .justify-between { + justify-content: space-between +} + +.swagger-ui .justify-around { + justify-content: space-around +} + +.swagger-ui .content-start { + align-content: flex-start +} + +.swagger-ui .content-end { + align-content: flex-end +} + +.swagger-ui .content-center { + align-content: center +} + +.swagger-ui .content-between { + align-content: space-between +} + +.swagger-ui .content-around { + align-content: space-around +} + +.swagger-ui .content-stretch { + align-content: stretch +} + +.swagger-ui .order-0 { + order: 0 +} + +.swagger-ui .order-1 { + order: 1 +} + +.swagger-ui .order-2 { + order: 2 +} + +.swagger-ui .order-3 { + order: 3 +} + +.swagger-ui .order-4 { + order: 4 +} + +.swagger-ui .order-5 { + order: 5 +} + +.swagger-ui .order-6 { + order: 6 +} + +.swagger-ui .order-7 { + order: 7 +} + +.swagger-ui .order-8 { + order: 8 +} + +.swagger-ui .order-last { + order: 99999 +} + +.swagger-ui .flex-grow-0 { + flex-grow: 0 +} + +.swagger-ui .flex-grow-1 { + flex-grow: 1 +} + +.swagger-ui .flex-shrink-0 { + flex-shrink: 0 +} + +.swagger-ui .flex-shrink-1 { + flex-shrink: 1 +} + +@media screen and (min-width: 30em) { + .swagger-ui .flex-ns { + display: flex + } + + .swagger-ui .inline-flex-ns { + display: inline-flex + } + + .swagger-ui .flex-auto-ns { + flex: 1 1 auto; + min-width: 0; + min-height: 0 + } + + .swagger-ui .flex-none-ns { + flex: none + } + + .swagger-ui .flex-column-ns { + flex-direction: column + } + + .swagger-ui .flex-row-ns { + flex-direction: row + } + + .swagger-ui .flex-wrap-ns { + flex-wrap: wrap + } + + .swagger-ui .flex-nowrap-ns { + flex-wrap: nowrap + } + + .swagger-ui .flex-wrap-reverse-ns { + flex-wrap: wrap-reverse + } + + .swagger-ui .flex-column-reverse-ns { + flex-direction: column-reverse + } + + .swagger-ui .flex-row-reverse-ns { + flex-direction: row-reverse + } + + .swagger-ui .items-start-ns { + align-items: flex-start + } + + .swagger-ui .items-end-ns { + align-items: flex-end + } + + .swagger-ui .items-center-ns { + align-items: center + } + + .swagger-ui .items-baseline-ns { + align-items: baseline + } + + .swagger-ui .items-stretch-ns { + align-items: stretch + } + + .swagger-ui .self-start-ns { + align-self: flex-start + } + + .swagger-ui .self-end-ns { + align-self: flex-end + } + + .swagger-ui .self-center-ns { + align-self: center + } + + .swagger-ui .self-baseline-ns { + align-self: baseline + } + + .swagger-ui .self-stretch-ns { + align-self: stretch + } + + .swagger-ui .justify-start-ns { + justify-content: flex-start + } + + .swagger-ui .justify-end-ns { + justify-content: flex-end + } + + .swagger-ui .justify-center-ns { + justify-content: center + } + + .swagger-ui .justify-between-ns { + justify-content: space-between + } + + .swagger-ui .justify-around-ns { + justify-content: space-around + } + + .swagger-ui .content-start-ns { + align-content: flex-start + } + + .swagger-ui .content-end-ns { + align-content: flex-end + } + + .swagger-ui .content-center-ns { + align-content: center + } + + .swagger-ui .content-between-ns { + align-content: space-between + } + + .swagger-ui .content-around-ns { + align-content: space-around + } + + .swagger-ui .content-stretch-ns { + align-content: stretch + } + + .swagger-ui .order-0-ns { + order: 0 + } + + .swagger-ui .order-1-ns { + order: 1 + } + + .swagger-ui .order-2-ns { + order: 2 + } + + .swagger-ui .order-3-ns { + order: 3 + } + + .swagger-ui .order-4-ns { + order: 4 + } + + .swagger-ui .order-5-ns { + order: 5 + } + + .swagger-ui .order-6-ns { + order: 6 + } + + .swagger-ui .order-7-ns { + order: 7 + } + + .swagger-ui .order-8-ns { + order: 8 + } + + .swagger-ui .order-last-ns { + order: 99999 + } + + .swagger-ui .flex-grow-0-ns { + flex-grow: 0 + } + + .swagger-ui .flex-grow-1-ns { + flex-grow: 1 + } + + .swagger-ui .flex-shrink-0-ns { + flex-shrink: 0 + } + + .swagger-ui .flex-shrink-1-ns { + flex-shrink: 1 + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .flex-m { + display: flex + } + + .swagger-ui .inline-flex-m { + display: inline-flex + } + + .swagger-ui .flex-auto-m { + flex: 1 1 auto; + min-width: 0; + min-height: 0 + } + + .swagger-ui .flex-none-m { + flex: none + } + + .swagger-ui .flex-column-m { + flex-direction: column + } + + .swagger-ui .flex-row-m { + flex-direction: row + } + + .swagger-ui .flex-wrap-m { + flex-wrap: wrap + } + + .swagger-ui .flex-nowrap-m { + flex-wrap: nowrap + } + + .swagger-ui .flex-wrap-reverse-m { + flex-wrap: wrap-reverse + } + + .swagger-ui .flex-column-reverse-m { + flex-direction: column-reverse + } + + .swagger-ui .flex-row-reverse-m { + flex-direction: row-reverse + } + + .swagger-ui .items-start-m { + align-items: flex-start + } + + .swagger-ui .items-end-m { + align-items: flex-end + } + + .swagger-ui .items-center-m { + align-items: center + } + + .swagger-ui .items-baseline-m { + align-items: baseline + } + + .swagger-ui .items-stretch-m { + align-items: stretch + } + + .swagger-ui .self-start-m { + align-self: flex-start + } + + .swagger-ui .self-end-m { + align-self: flex-end + } + + .swagger-ui .self-center-m { + align-self: center + } + + .swagger-ui .self-baseline-m { + align-self: baseline + } + + .swagger-ui .self-stretch-m { + align-self: stretch + } + + .swagger-ui .justify-start-m { + justify-content: flex-start + } + + .swagger-ui .justify-end-m { + justify-content: flex-end + } + + .swagger-ui .justify-center-m { + justify-content: center + } + + .swagger-ui .justify-between-m { + justify-content: space-between + } + + .swagger-ui .justify-around-m { + justify-content: space-around + } + + .swagger-ui .content-start-m { + align-content: flex-start + } + + .swagger-ui .content-end-m { + align-content: flex-end + } + + .swagger-ui .content-center-m { + align-content: center + } + + .swagger-ui .content-between-m { + align-content: space-between + } + + .swagger-ui .content-around-m { + align-content: space-around + } + + .swagger-ui .content-stretch-m { + align-content: stretch + } + + .swagger-ui .order-0-m { + order: 0 + } + + .swagger-ui .order-1-m { + order: 1 + } + + .swagger-ui .order-2-m { + order: 2 + } + + .swagger-ui .order-3-m { + order: 3 + } + + .swagger-ui .order-4-m { + order: 4 + } + + .swagger-ui .order-5-m { + order: 5 + } + + .swagger-ui .order-6-m { + order: 6 + } + + .swagger-ui .order-7-m { + order: 7 + } + + .swagger-ui .order-8-m { + order: 8 + } + + .swagger-ui .order-last-m { + order: 99999 + } + + .swagger-ui .flex-grow-0-m { + flex-grow: 0 + } + + .swagger-ui .flex-grow-1-m { + flex-grow: 1 + } + + .swagger-ui .flex-shrink-0-m { + flex-shrink: 0 + } + + .swagger-ui .flex-shrink-1-m { + flex-shrink: 1 + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .flex-l { + display: flex + } + + .swagger-ui .inline-flex-l { + display: inline-flex + } + + .swagger-ui .flex-auto-l { + flex: 1 1 auto; + min-width: 0; + min-height: 0 + } + + .swagger-ui .flex-none-l { + flex: none + } + + .swagger-ui .flex-column-l { + flex-direction: column + } + + .swagger-ui .flex-row-l { + flex-direction: row + } + + .swagger-ui .flex-wrap-l { + flex-wrap: wrap + } + + .swagger-ui .flex-nowrap-l { + flex-wrap: nowrap + } + + .swagger-ui .flex-wrap-reverse-l { + flex-wrap: wrap-reverse + } + + .swagger-ui .flex-column-reverse-l { + flex-direction: column-reverse + } + + .swagger-ui .flex-row-reverse-l { + flex-direction: row-reverse + } + + .swagger-ui .items-start-l { + align-items: flex-start + } + + .swagger-ui .items-end-l { + align-items: flex-end + } + + .swagger-ui .items-center-l { + align-items: center + } + + .swagger-ui .items-baseline-l { + align-items: baseline + } + + .swagger-ui .items-stretch-l { + align-items: stretch + } + + .swagger-ui .self-start-l { + align-self: flex-start + } + + .swagger-ui .self-end-l { + align-self: flex-end + } + + .swagger-ui .self-center-l { + align-self: center + } + + .swagger-ui .self-baseline-l { + align-self: baseline + } + + .swagger-ui .self-stretch-l { + align-self: stretch + } + + .swagger-ui .justify-start-l { + justify-content: flex-start + } + + .swagger-ui .justify-end-l { + justify-content: flex-end + } + + .swagger-ui .justify-center-l { + justify-content: center + } + + .swagger-ui .justify-between-l { + justify-content: space-between + } + + .swagger-ui .justify-around-l { + justify-content: space-around + } + + .swagger-ui .content-start-l { + align-content: flex-start + } + + .swagger-ui .content-end-l { + align-content: flex-end + } + + .swagger-ui .content-center-l { + align-content: center + } + + .swagger-ui .content-between-l { + align-content: space-between + } + + .swagger-ui .content-around-l { + align-content: space-around + } + + .swagger-ui .content-stretch-l { + align-content: stretch + } + + .swagger-ui .order-0-l { + order: 0 + } + + .swagger-ui .order-1-l { + order: 1 + } + + .swagger-ui .order-2-l { + order: 2 + } + + .swagger-ui .order-3-l { + order: 3 + } + + .swagger-ui .order-4-l { + order: 4 + } + + .swagger-ui .order-5-l { + order: 5 + } + + .swagger-ui .order-6-l { + order: 6 + } + + .swagger-ui .order-7-l { + order: 7 + } + + .swagger-ui .order-8-l { + order: 8 + } + + .swagger-ui .order-last-l { + order: 99999 + } + + .swagger-ui .flex-grow-0-l { + flex-grow: 0 + } + + .swagger-ui .flex-grow-1-l { + flex-grow: 1 + } + + .swagger-ui .flex-shrink-0-l { + flex-shrink: 0 + } + + .swagger-ui .flex-shrink-1-l { + flex-shrink: 1 + } +} + +.swagger-ui .dn { + display: none +} + +.swagger-ui .di { + display: inline +} + +.swagger-ui .db { + display: block +} + +.swagger-ui .dib { + display: inline-block +} + +.swagger-ui .dit { + display: inline-table +} + +.swagger-ui .dt { + display: table +} + +.swagger-ui .dtc { + display: table-cell +} + +.swagger-ui .dt-row { + display: table-row +} + +.swagger-ui .dt-row-group { + display: table-row-group +} + +.swagger-ui .dt-column { + display: table-column +} + +.swagger-ui .dt-column-group { + display: table-column-group +} + +.swagger-ui .dt--fixed { + table-layout: fixed; + width: 100% +} + +@media screen and (min-width: 30em) { + .swagger-ui .dn-ns { + display: none + } + + .swagger-ui .di-ns { + display: inline + } + + .swagger-ui .db-ns { + display: block + } + + .swagger-ui .dib-ns { + display: inline-block + } + + .swagger-ui .dit-ns { + display: inline-table + } + + .swagger-ui .dt-ns { + display: table + } + + .swagger-ui .dtc-ns { + display: table-cell + } + + .swagger-ui .dt-row-ns { + display: table-row + } + + .swagger-ui .dt-row-group-ns { + display: table-row-group + } + + .swagger-ui .dt-column-ns { + display: table-column + } + + .swagger-ui .dt-column-group-ns { + display: table-column-group + } + + .swagger-ui .dt--fixed-ns { + table-layout: fixed; + width: 100% + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .dn-m { + display: none + } + + .swagger-ui .di-m { + display: inline + } + + .swagger-ui .db-m { + display: block + } + + .swagger-ui .dib-m { + display: inline-block + } + + .swagger-ui .dit-m { + display: inline-table + } + + .swagger-ui .dt-m { + display: table + } + + .swagger-ui .dtc-m { + display: table-cell + } + + .swagger-ui .dt-row-m { + display: table-row + } + + .swagger-ui .dt-row-group-m { + display: table-row-group + } + + .swagger-ui .dt-column-m { + display: table-column + } + + .swagger-ui .dt-column-group-m { + display: table-column-group + } + + .swagger-ui .dt--fixed-m { + table-layout: fixed; + width: 100% + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .dn-l { + display: none + } + + .swagger-ui .di-l { + display: inline + } + + .swagger-ui .db-l { + display: block + } + + .swagger-ui .dib-l { + display: inline-block + } + + .swagger-ui .dit-l { + display: inline-table + } + + .swagger-ui .dt-l { + display: table + } + + .swagger-ui .dtc-l { + display: table-cell + } + + .swagger-ui .dt-row-l { + display: table-row + } + + .swagger-ui .dt-row-group-l { + display: table-row-group + } + + .swagger-ui .dt-column-l { + display: table-column + } + + .swagger-ui .dt-column-group-l { + display: table-column-group + } + + .swagger-ui .dt--fixed-l { + table-layout: fixed; + width: 100% + } +} + +.swagger-ui .fl { + float: left; + _display: inline +} + +.swagger-ui .fr { + float: right; + _display: inline +} + +.swagger-ui .fn { + float: none +} + +@media screen and (min-width: 30em) { + .swagger-ui .fl-ns { + float: left; + _display: inline + } + + .swagger-ui .fr-ns { + float: right; + _display: inline + } + + .swagger-ui .fn-ns { + float: none + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .fl-m { + float: left; + _display: inline + } + + .swagger-ui .fr-m { + float: right; + _display: inline + } + + .swagger-ui .fn-m { + float: none + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .fl-l { + float: left; + _display: inline + } + + .swagger-ui .fr-l { + float: right; + _display: inline + } + + .swagger-ui .fn-l { + float: none + } +} + +.swagger-ui .sans-serif { + font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica, helvetica neue, ubuntu, roboto, noto, segoe ui, arial, sans-serif +} + +.swagger-ui .serif { + font-family: georgia, serif +} + +.swagger-ui .system-sans-serif { + font-family: sans-serif +} + +.swagger-ui .system-serif { + font-family: serif +} + +.swagger-ui .code, .swagger-ui code { + font-family: Consolas, monaco, monospace +} + +.swagger-ui .courier { + font-family: Courier Next, courier, monospace +} + +.swagger-ui .helvetica { + font-family: helvetica neue, helvetica, sans-serif +} + +.swagger-ui .avenir { + font-family: avenir next, avenir, sans-serif +} + +.swagger-ui .athelas { + font-family: athelas, georgia, serif +} + +.swagger-ui .georgia { + font-family: georgia, serif +} + +.swagger-ui .times { + font-family: times, serif +} + +.swagger-ui .bodoni { + font-family: Bodoni MT, serif +} + +.swagger-ui .calisto { + font-family: Calisto MT, serif +} + +.swagger-ui .garamond { + font-family: garamond, serif +} + +.swagger-ui .baskerville { + font-family: baskerville, serif +} + +.swagger-ui .i { + font-style: italic +} + +.swagger-ui .fs-normal { + font-style: normal +} + +@media screen and (min-width: 30em) { + .swagger-ui .i-ns { + font-style: italic + } + + .swagger-ui .fs-normal-ns { + font-style: normal + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .i-m { + font-style: italic + } + + .swagger-ui .fs-normal-m { + font-style: normal + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .i-l { + font-style: italic + } + + .swagger-ui .fs-normal-l { + font-style: normal + } +} + +.swagger-ui .normal { + font-weight: 400 +} + +.swagger-ui .b { + font-weight: 700 +} + +.swagger-ui .fw1 { + font-weight: 100 +} + +.swagger-ui .fw2 { + font-weight: 200 +} + +.swagger-ui .fw3 { + font-weight: 300 +} + +.swagger-ui .fw4 { + font-weight: 400 +} + +.swagger-ui .fw5 { + font-weight: 500 +} + +.swagger-ui .fw6 { + font-weight: 600 +} + +.swagger-ui .fw7 { + font-weight: 700 +} + +.swagger-ui .fw8 { + font-weight: 800 +} + +.swagger-ui .fw9 { + font-weight: 900 +} + +@media screen and (min-width: 30em) { + .swagger-ui .normal-ns { + font-weight: 400 + } + + .swagger-ui .b-ns { + font-weight: 700 + } + + .swagger-ui .fw1-ns { + font-weight: 100 + } + + .swagger-ui .fw2-ns { + font-weight: 200 + } + + .swagger-ui .fw3-ns { + font-weight: 300 + } + + .swagger-ui .fw4-ns { + font-weight: 400 + } + + .swagger-ui .fw5-ns { + font-weight: 500 + } + + .swagger-ui .fw6-ns { + font-weight: 600 + } + + .swagger-ui .fw7-ns { + font-weight: 700 + } + + .swagger-ui .fw8-ns { + font-weight: 800 + } + + .swagger-ui .fw9-ns { + font-weight: 900 + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .normal-m { + font-weight: 400 + } + + .swagger-ui .b-m { + font-weight: 700 + } + + .swagger-ui .fw1-m { + font-weight: 100 + } + + .swagger-ui .fw2-m { + font-weight: 200 + } + + .swagger-ui .fw3-m { + font-weight: 300 + } + + .swagger-ui .fw4-m { + font-weight: 400 + } + + .swagger-ui .fw5-m { + font-weight: 500 + } + + .swagger-ui .fw6-m { + font-weight: 600 + } + + .swagger-ui .fw7-m { + font-weight: 700 + } + + .swagger-ui .fw8-m { + font-weight: 800 + } + + .swagger-ui .fw9-m { + font-weight: 900 + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .normal-l { + font-weight: 400 + } + + .swagger-ui .b-l { + font-weight: 700 + } + + .swagger-ui .fw1-l { + font-weight: 100 + } + + .swagger-ui .fw2-l { + font-weight: 200 + } + + .swagger-ui .fw3-l { + font-weight: 300 + } + + .swagger-ui .fw4-l { + font-weight: 400 + } + + .swagger-ui .fw5-l { + font-weight: 500 + } + + .swagger-ui .fw6-l { + font-weight: 600 + } + + .swagger-ui .fw7-l { + font-weight: 700 + } + + .swagger-ui .fw8-l { + font-weight: 800 + } + + .swagger-ui .fw9-l { + font-weight: 900 + } +} + +.swagger-ui .input-reset { + -webkit-appearance: none; + -moz-appearance: none +} + +.swagger-ui .button-reset::-moz-focus-inner, .swagger-ui .input-reset::-moz-focus-inner { + border: 0; + padding: 0 +} + +.swagger-ui .h1 { + height: 1rem +} + +.swagger-ui .h2 { + height: 2rem +} + +.swagger-ui .h3 { + height: 4rem +} + +.swagger-ui .h4 { + height: 8rem +} + +.swagger-ui .h5 { + height: 16rem +} + +.swagger-ui .h-25 { + height: 25% +} + +.swagger-ui .h-50 { + height: 50% +} + +.swagger-ui .h-75 { + height: 75% +} + +.swagger-ui .h-100 { + height: 100% +} + +.swagger-ui .min-h-100 { + min-height: 100% +} + +.swagger-ui .vh-25 { + height: 25vh +} + +.swagger-ui .vh-50 { + height: 50vh +} + +.swagger-ui .vh-75 { + height: 75vh +} + +.swagger-ui .vh-100 { + height: 100vh +} + +.swagger-ui .min-vh-100 { + min-height: 100vh +} + +.swagger-ui .h-auto { + height: auto +} + +.swagger-ui .h-inherit { + height: inherit +} + +@media screen and (min-width: 30em) { + .swagger-ui .h1-ns { + height: 1rem + } + + .swagger-ui .h2-ns { + height: 2rem + } + + .swagger-ui .h3-ns { + height: 4rem + } + + .swagger-ui .h4-ns { + height: 8rem + } + + .swagger-ui .h5-ns { + height: 16rem + } + + .swagger-ui .h-25-ns { + height: 25% + } + + .swagger-ui .h-50-ns { + height: 50% + } + + .swagger-ui .h-75-ns { + height: 75% + } + + .swagger-ui .h-100-ns { + height: 100% + } + + .swagger-ui .min-h-100-ns { + min-height: 100% + } + + .swagger-ui .vh-25-ns { + height: 25vh + } + + .swagger-ui .vh-50-ns { + height: 50vh + } + + .swagger-ui .vh-75-ns { + height: 75vh + } + + .swagger-ui .vh-100-ns { + height: 100vh + } + + .swagger-ui .min-vh-100-ns { + min-height: 100vh + } + + .swagger-ui .h-auto-ns { + height: auto + } + + .swagger-ui .h-inherit-ns { + height: inherit + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .h1-m { + height: 1rem + } + + .swagger-ui .h2-m { + height: 2rem + } + + .swagger-ui .h3-m { + height: 4rem + } + + .swagger-ui .h4-m { + height: 8rem + } + + .swagger-ui .h5-m { + height: 16rem + } + + .swagger-ui .h-25-m { + height: 25% + } + + .swagger-ui .h-50-m { + height: 50% + } + + .swagger-ui .h-75-m { + height: 75% + } + + .swagger-ui .h-100-m { + height: 100% + } + + .swagger-ui .min-h-100-m { + min-height: 100% + } + + .swagger-ui .vh-25-m { + height: 25vh + } + + .swagger-ui .vh-50-m { + height: 50vh + } + + .swagger-ui .vh-75-m { + height: 75vh + } + + .swagger-ui .vh-100-m { + height: 100vh + } + + .swagger-ui .min-vh-100-m { + min-height: 100vh + } + + .swagger-ui .h-auto-m { + height: auto + } + + .swagger-ui .h-inherit-m { + height: inherit + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .h1-l { + height: 1rem + } + + .swagger-ui .h2-l { + height: 2rem + } + + .swagger-ui .h3-l { + height: 4rem + } + + .swagger-ui .h4-l { + height: 8rem + } + + .swagger-ui .h5-l { + height: 16rem + } + + .swagger-ui .h-25-l { + height: 25% + } + + .swagger-ui .h-50-l { + height: 50% + } + + .swagger-ui .h-75-l { + height: 75% + } + + .swagger-ui .h-100-l { + height: 100% + } + + .swagger-ui .min-h-100-l { + min-height: 100% + } + + .swagger-ui .vh-25-l { + height: 25vh + } + + .swagger-ui .vh-50-l { + height: 50vh + } + + .swagger-ui .vh-75-l { + height: 75vh + } + + .swagger-ui .vh-100-l { + height: 100vh + } + + .swagger-ui .min-vh-100-l { + min-height: 100vh + } + + .swagger-ui .h-auto-l { + height: auto + } + + .swagger-ui .h-inherit-l { + height: inherit + } +} + +.swagger-ui .tracked { + letter-spacing: .1em +} + +.swagger-ui .tracked-tight { + letter-spacing: -.05em +} + +.swagger-ui .tracked-mega { + letter-spacing: .25em +} + +@media screen and (min-width: 30em) { + .swagger-ui .tracked-ns { + letter-spacing: .1em + } + + .swagger-ui .tracked-tight-ns { + letter-spacing: -.05em + } + + .swagger-ui .tracked-mega-ns { + letter-spacing: .25em + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .tracked-m { + letter-spacing: .1em + } + + .swagger-ui .tracked-tight-m { + letter-spacing: -.05em + } + + .swagger-ui .tracked-mega-m { + letter-spacing: .25em + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .tracked-l { + letter-spacing: .1em + } + + .swagger-ui .tracked-tight-l { + letter-spacing: -.05em + } + + .swagger-ui .tracked-mega-l { + letter-spacing: .25em + } +} + +.swagger-ui .lh-solid { + line-height: 1 +} + +.swagger-ui .lh-title { + line-height: 1.25 +} + +.swagger-ui .lh-copy { + line-height: 1.5 +} + +@media screen and (min-width: 30em) { + .swagger-ui .lh-solid-ns { + line-height: 1 + } + + .swagger-ui .lh-title-ns { + line-height: 1.25 + } + + .swagger-ui .lh-copy-ns { + line-height: 1.5 + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .lh-solid-m { + line-height: 1 + } + + .swagger-ui .lh-title-m { + line-height: 1.25 + } + + .swagger-ui .lh-copy-m { + line-height: 1.5 + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .lh-solid-l { + line-height: 1 + } + + .swagger-ui .lh-title-l { + line-height: 1.25 + } + + .swagger-ui .lh-copy-l { + line-height: 1.5 + } +} + +.swagger-ui .link { + text-decoration: none; +} + + +.swagger-ui .link, .swagger-ui .link:link, .swagger-ui .link:visited { + transition: color .15s ease-in +} + +.swagger-ui .link:hover { + transition: color .15s ease-in +} + +.swagger-ui .link:active { + transition: color .15s ease-in +} + +.swagger-ui .link:focus { + transition: color .15s ease-in; + outline: 1px dotted currentColor +} + +.swagger-ui .list { + list-style-type: none +} + +.swagger-ui .mw-100 { + max-width: 100% +} + +.swagger-ui .mw1 { + max-width: 1rem +} + +.swagger-ui .mw2 { + max-width: 2rem +} + +.swagger-ui .mw3 { + max-width: 4rem +} + +.swagger-ui .mw4 { + max-width: 8rem +} + +.swagger-ui .mw5 { + max-width: 16rem +} + +.swagger-ui .mw6 { + max-width: 32rem +} + +.swagger-ui .mw7 { + max-width: 48rem +} + +.swagger-ui .mw8 { + max-width: 64rem +} + +.swagger-ui .mw9 { + max-width: 96rem +} + +.swagger-ui .mw-none { + max-width: none +} + +@media screen and (min-width: 30em) { + .swagger-ui .mw-100-ns { + max-width: 100% + } + + .swagger-ui .mw1-ns { + max-width: 1rem + } + + .swagger-ui .mw2-ns { + max-width: 2rem + } + + .swagger-ui .mw3-ns { + max-width: 4rem + } + + .swagger-ui .mw4-ns { + max-width: 8rem + } + + .swagger-ui .mw5-ns { + max-width: 16rem + } + + .swagger-ui .mw6-ns { + max-width: 32rem + } + + .swagger-ui .mw7-ns { + max-width: 48rem + } + + .swagger-ui .mw8-ns { + max-width: 64rem + } + + .swagger-ui .mw9-ns { + max-width: 96rem + } + + .swagger-ui .mw-none-ns { + max-width: none + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .mw-100-m { + max-width: 100% + } + + .swagger-ui .mw1-m { + max-width: 1rem + } + + .swagger-ui .mw2-m { + max-width: 2rem + } + + .swagger-ui .mw3-m { + max-width: 4rem + } + + .swagger-ui .mw4-m { + max-width: 8rem + } + + .swagger-ui .mw5-m { + max-width: 16rem + } + + .swagger-ui .mw6-m { + max-width: 32rem + } + + .swagger-ui .mw7-m { + max-width: 48rem + } + + .swagger-ui .mw8-m { + max-width: 64rem + } + + .swagger-ui .mw9-m { + max-width: 96rem + } + + .swagger-ui .mw-none-m { + max-width: none + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .mw-100-l { + max-width: 100% + } + + .swagger-ui .mw1-l { + max-width: 1rem + } + + .swagger-ui .mw2-l { + max-width: 2rem + } + + .swagger-ui .mw3-l { + max-width: 4rem + } + + .swagger-ui .mw4-l { + max-width: 8rem + } + + .swagger-ui .mw5-l { + max-width: 16rem + } + + .swagger-ui .mw6-l { + max-width: 32rem + } + + .swagger-ui .mw7-l { + max-width: 48rem + } + + .swagger-ui .mw8-l { + max-width: 64rem + } + + .swagger-ui .mw9-l { + max-width: 96rem + } + + .swagger-ui .mw-none-l { + max-width: none + } +} + +.swagger-ui .w1 { + width: 1rem +} + +.swagger-ui .w2 { + width: 2rem +} + +.swagger-ui .w3 { + width: 4rem +} + +.swagger-ui .w4 { + width: 8rem +} + +.swagger-ui .w5 { + width: 16rem +} + +.swagger-ui .w-10 { + width: 10% +} + +.swagger-ui .w-20 { + width: 20% +} + +.swagger-ui .w-25 { + width: 25% +} + +.swagger-ui .w-30 { + width: 30% +} + +.swagger-ui .w-33 { + width: 33% +} + +.swagger-ui .w-34 { + width: 34% +} + +.swagger-ui .w-40 { + width: 40% +} + +.swagger-ui .w-50 { + width: 50% +} + +.swagger-ui .w-60 { + width: 60% +} + +.swagger-ui .w-70 { + width: 70% +} + +.swagger-ui .w-75 { + width: 75% +} + +.swagger-ui .w-80 { + width: 80% +} + +.swagger-ui .w-90 { + width: 90% +} + +.swagger-ui .w-100 { + width: 100% +} + +.swagger-ui .w-third { + width: 33.33333% +} + +.swagger-ui .w-two-thirds { + width: 66.66667% +} + +.swagger-ui .w-auto { + width: auto +} + +@media screen and (min-width: 30em) { + .swagger-ui .w1-ns { + width: 1rem + } + + .swagger-ui .w2-ns { + width: 2rem + } + + .swagger-ui .w3-ns { + width: 4rem + } + + .swagger-ui .w4-ns { + width: 8rem + } + + .swagger-ui .w5-ns { + width: 16rem + } + + .swagger-ui .w-10-ns { + width: 10% + } + + .swagger-ui .w-20-ns { + width: 20% + } + + .swagger-ui .w-25-ns { + width: 25% + } + + .swagger-ui .w-30-ns { + width: 30% + } + + .swagger-ui .w-33-ns { + width: 33% + } + + .swagger-ui .w-34-ns { + width: 34% + } + + .swagger-ui .w-40-ns { + width: 40% + } + + .swagger-ui .w-50-ns { + width: 50% + } + + .swagger-ui .w-60-ns { + width: 60% + } + + .swagger-ui .w-70-ns { + width: 70% + } + + .swagger-ui .w-75-ns { + width: 75% + } + + .swagger-ui .w-80-ns { + width: 80% + } + + .swagger-ui .w-90-ns { + width: 90% + } + + .swagger-ui .w-100-ns { + width: 100% + } + + .swagger-ui .w-third-ns { + width: 33.33333% + } + + .swagger-ui .w-two-thirds-ns { + width: 66.66667% + } + + .swagger-ui .w-auto-ns { + width: auto + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .w1-m { + width: 1rem + } + + .swagger-ui .w2-m { + width: 2rem + } + + .swagger-ui .w3-m { + width: 4rem + } + + .swagger-ui .w4-m { + width: 8rem + } + + .swagger-ui .w5-m { + width: 16rem + } + + .swagger-ui .w-10-m { + width: 10% + } + + .swagger-ui .w-20-m { + width: 20% + } + + .swagger-ui .w-25-m { + width: 25% + } + + .swagger-ui .w-30-m { + width: 30% + } + + .swagger-ui .w-33-m { + width: 33% + } + + .swagger-ui .w-34-m { + width: 34% + } + + .swagger-ui .w-40-m { + width: 40% + } + + .swagger-ui .w-50-m { + width: 50% + } + + .swagger-ui .w-60-m { + width: 60% + } + + .swagger-ui .w-70-m { + width: 70% + } + + .swagger-ui .w-75-m { + width: 75% + } + + .swagger-ui .w-80-m { + width: 80% + } + + .swagger-ui .w-90-m { + width: 90% + } + + .swagger-ui .w-100-m { + width: 100% + } + + .swagger-ui .w-third-m { + width: 33.33333% + } + + .swagger-ui .w-two-thirds-m { + width: 66.66667% + } + + .swagger-ui .w-auto-m { + width: auto + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .w1-l { + width: 1rem + } + + .swagger-ui .w2-l { + width: 2rem + } + + .swagger-ui .w3-l { + width: 4rem + } + + .swagger-ui .w4-l { + width: 8rem + } + + .swagger-ui .w5-l { + width: 16rem + } + + .swagger-ui .w-10-l { + width: 10% + } + + .swagger-ui .w-20-l { + width: 20% + } + + .swagger-ui .w-25-l { + width: 25% + } + + .swagger-ui .w-30-l { + width: 30% + } + + .swagger-ui .w-33-l { + width: 33% + } + + .swagger-ui .w-34-l { + width: 34% + } + + .swagger-ui .w-40-l { + width: 40% + } + + .swagger-ui .w-50-l { + width: 50% + } + + .swagger-ui .w-60-l { + width: 60% + } + + .swagger-ui .w-70-l { + width: 70% + } + + .swagger-ui .w-75-l { + width: 75% + } + + .swagger-ui .w-80-l { + width: 80% + } + + .swagger-ui .w-90-l { + width: 90% + } + + .swagger-ui .w-100-l { + width: 100% + } + + .swagger-ui .w-third-l { + width: 33.33333% + } + + .swagger-ui .w-two-thirds-l { + width: 66.66667% + } + + .swagger-ui .w-auto-l { + width: auto + } +} + +.swagger-ui .overflow-visible { + overflow: visible +} + +.swagger-ui .overflow-hidden { + overflow: hidden +} + +.swagger-ui .overflow-scroll { + overflow: scroll +} + +.swagger-ui .overflow-auto { + overflow: auto +} + +.swagger-ui .overflow-x-visible { + overflow-x: visible +} + +.swagger-ui .overflow-x-hidden { + overflow-x: hidden +} + +.swagger-ui .overflow-x-scroll { + overflow-x: scroll +} + +.swagger-ui .overflow-x-auto { + overflow-x: auto +} + +.swagger-ui .overflow-y-visible { + overflow-y: visible +} + +.swagger-ui .overflow-y-hidden { + overflow-y: hidden +} + +.swagger-ui .overflow-y-scroll { + overflow-y: scroll +} + +.swagger-ui .overflow-y-auto { + overflow-y: auto +} + +@media screen and (min-width: 30em) { + .swagger-ui .overflow-visible-ns { + overflow: visible + } + + .swagger-ui .overflow-hidden-ns { + overflow: hidden + } + + .swagger-ui .overflow-scroll-ns { + overflow: scroll + } + + .swagger-ui .overflow-auto-ns { + overflow: auto + } + + .swagger-ui .overflow-x-visible-ns { + overflow-x: visible + } + + .swagger-ui .overflow-x-hidden-ns { + overflow-x: hidden + } + + .swagger-ui .overflow-x-scroll-ns { + overflow-x: scroll + } + + .swagger-ui .overflow-x-auto-ns { + overflow-x: auto + } + + .swagger-ui .overflow-y-visible-ns { + overflow-y: visible + } + + .swagger-ui .overflow-y-hidden-ns { + overflow-y: hidden + } + + .swagger-ui .overflow-y-scroll-ns { + overflow-y: scroll + } + + .swagger-ui .overflow-y-auto-ns { + overflow-y: auto + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .overflow-visible-m { + overflow: visible + } + + .swagger-ui .overflow-hidden-m { + overflow: hidden + } + + .swagger-ui .overflow-scroll-m { + overflow: scroll + } + + .swagger-ui .overflow-auto-m { + overflow: auto + } + + .swagger-ui .overflow-x-visible-m { + overflow-x: visible + } + + .swagger-ui .overflow-x-hidden-m { + overflow-x: hidden + } + + .swagger-ui .overflow-x-scroll-m { + overflow-x: scroll + } + + .swagger-ui .overflow-x-auto-m { + overflow-x: auto + } + + .swagger-ui .overflow-y-visible-m { + overflow-y: visible + } + + .swagger-ui .overflow-y-hidden-m { + overflow-y: hidden + } + + .swagger-ui .overflow-y-scroll-m { + overflow-y: scroll + } + + .swagger-ui .overflow-y-auto-m { + overflow-y: auto + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .overflow-visible-l { + overflow: visible + } + + .swagger-ui .overflow-hidden-l { + overflow: hidden + } + + .swagger-ui .overflow-scroll-l { + overflow: scroll + } + + .swagger-ui .overflow-auto-l { + overflow: auto + } + + .swagger-ui .overflow-x-visible-l { + overflow-x: visible + } + + .swagger-ui .overflow-x-hidden-l { + overflow-x: hidden + } + + .swagger-ui .overflow-x-scroll-l { + overflow-x: scroll + } + + .swagger-ui .overflow-x-auto-l { + overflow-x: auto + } + + .swagger-ui .overflow-y-visible-l { + overflow-y: visible + } + + .swagger-ui .overflow-y-hidden-l { + overflow-y: hidden + } + + .swagger-ui .overflow-y-scroll-l { + overflow-y: scroll + } + + .swagger-ui .overflow-y-auto-l { + overflow-y: auto + } +} + +.swagger-ui .static { + position: static +} + +.swagger-ui .relative { + position: relative +} + +.swagger-ui .absolute { + position: absolute +} + +.swagger-ui .fixed { + position: fixed +} + +@media screen and (min-width: 30em) { + .swagger-ui .static-ns { + position: static + } + + .swagger-ui .relative-ns { + position: relative + } + + .swagger-ui .absolute-ns { + position: absolute + } + + .swagger-ui .fixed-ns { + position: fixed + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .static-m { + position: static + } + + .swagger-ui .relative-m { + position: relative + } + + .swagger-ui .absolute-m { + position: absolute + } + + .swagger-ui .fixed-m { + position: fixed + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .static-l { + position: static + } + + .swagger-ui .relative-l { + position: relative + } + + .swagger-ui .absolute-l { + position: absolute + } + + .swagger-ui .fixed-l { + position: fixed + } +} + +.swagger-ui .o-100 { + opacity: 1 +} + +.swagger-ui .o-90 { + opacity: .9 +} + +.swagger-ui .o-80 { + opacity: .8 +} + +.swagger-ui .o-70 { + opacity: .7 +} + +.swagger-ui .o-60 { + opacity: .6 +} + +.swagger-ui .o-50 { + opacity: .5 +} + +.swagger-ui .o-40 { + opacity: .4 +} + +.swagger-ui .o-30 { + opacity: .3 +} + +.swagger-ui .o-20 { + opacity: .2 +} + +.swagger-ui .o-10 { + opacity: .1 +} + +.swagger-ui .o-05 { + opacity: .05 +} + +.swagger-ui .o-025 { + opacity: .025 +} + +.swagger-ui .o-0 { + opacity: 0 +} + +.swagger-ui .rotate-45 { + transform: rotate(45deg) +} + +.swagger-ui .rotate-90 { + transform: rotate(90deg) +} + +.swagger-ui .rotate-135 { + transform: rotate(135deg) +} + +.swagger-ui .rotate-180 { + transform: rotate(180deg) +} + +.swagger-ui .rotate-225 { + transform: rotate(225deg) +} + +.swagger-ui .rotate-270 { + transform: rotate(270deg) +} + +.swagger-ui .rotate-315 { + transform: rotate(315deg) +} + +@media screen and (min-width: 30em) { + .swagger-ui .rotate-45-ns { + transform: rotate(45deg) + } + + .swagger-ui .rotate-90-ns { + transform: rotate(90deg) + } + + .swagger-ui .rotate-135-ns { + transform: rotate(135deg) + } + + .swagger-ui .rotate-180-ns { + transform: rotate(180deg) + } + + .swagger-ui .rotate-225-ns { + transform: rotate(225deg) + } + + .swagger-ui .rotate-270-ns { + transform: rotate(270deg) + } + + .swagger-ui .rotate-315-ns { + transform: rotate(315deg) + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .rotate-45-m { + transform: rotate(45deg) + } + + .swagger-ui .rotate-90-m { + transform: rotate(90deg) + } + + .swagger-ui .rotate-135-m { + transform: rotate(135deg) + } + + .swagger-ui .rotate-180-m { + transform: rotate(180deg) + } + + .swagger-ui .rotate-225-m { + transform: rotate(225deg) + } + + .swagger-ui .rotate-270-m { + transform: rotate(270deg) + } + + .swagger-ui .rotate-315-m { + transform: rotate(315deg) + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .rotate-45-l { + transform: rotate(45deg) + } + + .swagger-ui .rotate-90-l { + transform: rotate(90deg) + } + + .swagger-ui .rotate-135-l { + transform: rotate(135deg) + } + + .swagger-ui .rotate-180-l { + transform: rotate(180deg) + } + + .swagger-ui .rotate-225-l { + transform: rotate(225deg) + } + + .swagger-ui .rotate-270-l { + transform: rotate(270deg) + } + + .swagger-ui .rotate-315-l { + transform: rotate(315deg) + } +} + +.swagger-ui .black-90 { + color: rgba(0, 0, 0, .9) +} + +.swagger-ui .black-80 { + color: rgba(0, 0, 0, .8) +} + +.swagger-ui .black-70 { + color: rgba(0, 0, 0, .7) +} + +.swagger-ui .black-60 { + color: rgba(0, 0, 0, .6) +} + +.swagger-ui .black-50 { + color: rgba(0, 0, 0, .5) +} + +.swagger-ui .black-40 { + color: rgba(0, 0, 0, .4) +} + +.swagger-ui .black-30 { + color: rgba(0, 0, 0, .3) +} + +.swagger-ui .black-20 { + color: rgba(0, 0, 0, .2) +} + +.swagger-ui .black-10 { + color: rgba(0, 0, 0, .1) +} + +.swagger-ui .black-05 { + color: rgba(0, 0, 0, .05) +} + +.swagger-ui .white-90 { + color: hsla(0, 0%, 100%, .9) +} + +.swagger-ui .white-80 { + color: hsla(0, 0%, 100%, .8) +} + +.swagger-ui .white-70 { + color: hsla(0, 0%, 100%, .7) +} + +.swagger-ui .white-60 { + color: hsla(0, 0%, 100%, .6) +} + +.swagger-ui .white-50 { + color: hsla(0, 0%, 100%, .5) +} + +.swagger-ui .white-40 { + color: hsla(0, 0%, 100%, .4) +} + +.swagger-ui .white-30 { + color: hsla(0, 0%, 100%, .3) +} + +.swagger-ui .white-20 { + color: hsla(0, 0%, 100%, .2) +} + +.swagger-ui .white-10 { + color: hsla(0, 0%, 100%, .1) +} + +.swagger-ui .black { + color: #000 +} + +.swagger-ui .near-black { + color: #111 +} + +.swagger-ui .dark-gray { + color: #333 +} + +.swagger-ui .mid-gray { + color: #555 +} + +.swagger-ui .gray { + color: #777 +} + +.swagger-ui .silver { + color: #999 +} + +.swagger-ui .light-silver { + color: #aaa +} + +.swagger-ui .moon-gray { + color: #ccc +} + +.swagger-ui .light-gray { + color: #eee +} + +.swagger-ui .near-white { + color: #f4f4f4 +} + +.swagger-ui .white { + color: #fff +} + +.swagger-ui .dark-red { + color: #e7040f +} + +.swagger-ui .red { + color: #ff4136 +} + +.swagger-ui .light-red { + color: #ff725c +} + +.swagger-ui .orange { + color: #ff6300 +} + +.swagger-ui .gold { + color: #ffb700 +} + +.swagger-ui .yellow { + color: gold +} + +.swagger-ui .light-yellow { + color: #fbf1a9 +} + +.swagger-ui .purple { + color: #5e2ca5 +} + +.swagger-ui .light-purple { + color: #a463f2 +} + +.swagger-ui .dark-pink { + color: #d5008f +} + +.swagger-ui .hot-pink { + color: #ff41b4 +} + +.swagger-ui .pink { + color: #ff80cc +} + +.swagger-ui .light-pink { + color: #ffa3d7 +} + +.swagger-ui .dark-green { + color: #137752 +} + +.swagger-ui .green { + color: #19a974 +} + +.swagger-ui .light-green { + color: #9eebcf +} + +.swagger-ui .navy { + color: #001b44 +} + +.swagger-ui .dark-blue { + color: #00449e +} + +.swagger-ui .blue { + color: #357edd +} + +.swagger-ui .light-blue { + color: #96ccff +} + +.swagger-ui .lightest-blue { + color: #cdecff +} + +.swagger-ui .washed-blue { + color: #f6fffe +} + +.swagger-ui .washed-green { + color: #e8fdf5 +} + +.swagger-ui .washed-yellow { + color: #fffceb +} + +.swagger-ui .washed-red { + color: #ffdfdf +} + +.swagger-ui .color-inherit { + color: inherit +} + +.swagger-ui .bg-black-90 { + background-color: rgba(0, 0, 0, .9) +} + +.swagger-ui .bg-black-80 { + background-color: rgba(0, 0, 0, .8) +} + +.swagger-ui .bg-black-70 { + background-color: rgba(0, 0, 0, .7) +} + +.swagger-ui .bg-black-60 { + background-color: rgba(0, 0, 0, .6) +} + +.swagger-ui .bg-black-50 { + background-color: rgba(0, 0, 0, .5) +} + +.swagger-ui .bg-black-40 { + background-color: rgba(0, 0, 0, .4) +} + +.swagger-ui .bg-black-30 { + background-color: rgba(0, 0, 0, .3) +} + +.swagger-ui .bg-black-20 { + background-color: rgba(0, 0, 0, .2) +} + +.swagger-ui .bg-black-10 { + background-color: rgba(0, 0, 0, .1) +} + +.swagger-ui .bg-black-05 { + background-color: rgba(0, 0, 0, .05) +} + +.swagger-ui .bg-white-90 { + background-color: hsla(0, 0%, 100%, .9) +} + +.swagger-ui .bg-white-80 { + background-color: hsla(0, 0%, 100%, .8) +} + +.swagger-ui .bg-white-70 { + background-color: hsla(0, 0%, 100%, .7) +} + +.swagger-ui .bg-white-60 { + background-color: hsla(0, 0%, 100%, .6) +} + +.swagger-ui .bg-white-50 { + background-color: hsla(0, 0%, 100%, .5) +} + +.swagger-ui .bg-white-40 { + background-color: hsla(0, 0%, 100%, .4) +} + +.swagger-ui .bg-white-30 { + background-color: hsla(0, 0%, 100%, .3) +} + +.swagger-ui .bg-white-20 { + background-color: hsla(0, 0%, 100%, .2) +} + +.swagger-ui .bg-white-10 { + background-color: hsla(0, 0%, 100%, .1) +} + +.swagger-ui .bg-black { + background-color: #000 +} + +.swagger-ui .bg-near-black { + background-color: #111 +} + +.swagger-ui .bg-dark-gray { + background-color: #333 +} + +.swagger-ui .bg-mid-gray { + background-color: #555 +} + +.swagger-ui .bg-gray { + background-color: #777 +} + +.swagger-ui .bg-silver { + background-color: #999 +} + +.swagger-ui .bg-light-silver { + background-color: #aaa +} + +.swagger-ui .bg-moon-gray { + background-color: #ccc +} + +.swagger-ui .bg-light-gray { + background-color: #eee +} + +.swagger-ui .bg-near-white { + background-color: #f4f4f4 +} + +.swagger-ui .bg-white { + background-color: #fff +} + +.swagger-ui .bg-transparent { + background-color: transparent +} + +.swagger-ui .bg-dark-red { + background-color: #e7040f +} + +.swagger-ui .bg-red { + background-color: #ff4136 +} + +.swagger-ui .bg-light-red { + background-color: #ff725c +} + +.swagger-ui .bg-orange { + background-color: #ff6300 +} + +.swagger-ui .bg-gold { + background-color: #ffb700 +} + +.swagger-ui .bg-yellow { + background-color: gold +} + +.swagger-ui .bg-light-yellow { + background-color: #fbf1a9 +} + +.swagger-ui .bg-purple { + background-color: #5e2ca5 +} + +.swagger-ui .bg-light-purple { + background-color: #a463f2 +} + +.swagger-ui .bg-dark-pink { + background-color: #d5008f +} + +.swagger-ui .bg-hot-pink { + background-color: #ff41b4 +} + +.swagger-ui .bg-pink { + background-color: #ff80cc +} + +.swagger-ui .bg-light-pink { + background-color: #ffa3d7 +} + +.swagger-ui .bg-dark-green { + background-color: #137752 +} + +.swagger-ui .bg-green { + background-color: #19a974 +} + +.swagger-ui .bg-light-green { + background-color: #9eebcf +} + +.swagger-ui .bg-navy { + background-color: #001b44 +} + +.swagger-ui .bg-dark-blue { + background-color: #00449e +} + +.swagger-ui .bg-blue { + background-color: #357edd +} + +.swagger-ui .bg-light-blue { + background-color: #96ccff +} + +.swagger-ui .bg-lightest-blue { + background-color: #cdecff +} + +.swagger-ui .bg-washed-blue { + background-color: #f6fffe +} + +.swagger-ui .bg-washed-green { + background-color: #e8fdf5 +} + +.swagger-ui .bg-washed-yellow { + background-color: #fffceb +} + +.swagger-ui .bg-washed-red { + background-color: #ffdfdf +} + +.swagger-ui .bg-inherit { + background-color: inherit +} + +.swagger-ui .hover-black:focus, .swagger-ui .hover-black:hover { + color: #000 +} + +.swagger-ui .hover-near-black:focus, .swagger-ui .hover-near-black:hover { + color: #111 +} + +.swagger-ui .hover-dark-gray:focus, .swagger-ui .hover-dark-gray:hover { + color: #333 +} + +.swagger-ui .hover-mid-gray:focus, .swagger-ui .hover-mid-gray:hover { + color: #555 +} + +.swagger-ui .hover-gray:focus, .swagger-ui .hover-gray:hover { + color: #777 +} + +.swagger-ui .hover-silver:focus, .swagger-ui .hover-silver:hover { + color: #999 +} + +.swagger-ui .hover-light-silver:focus, .swagger-ui .hover-light-silver:hover { + color: #aaa +} + +.swagger-ui .hover-moon-gray:focus, .swagger-ui .hover-moon-gray:hover { + color: #ccc +} + +.swagger-ui .hover-light-gray:focus, .swagger-ui .hover-light-gray:hover { + color: #eee +} + +.swagger-ui .hover-near-white:focus, .swagger-ui .hover-near-white:hover { + color: #f4f4f4 +} + +.swagger-ui .hover-white:focus, .swagger-ui .hover-white:hover { + color: #fff +} + +.swagger-ui .hover-black-90:focus, .swagger-ui .hover-black-90:hover { + color: rgba(0, 0, 0, .9) +} + +.swagger-ui .hover-black-80:focus, .swagger-ui .hover-black-80:hover { + color: rgba(0, 0, 0, .8) +} + +.swagger-ui .hover-black-70:focus, .swagger-ui .hover-black-70:hover { + color: rgba(0, 0, 0, .7) +} + +.swagger-ui .hover-black-60:focus, .swagger-ui .hover-black-60:hover { + color: rgba(0, 0, 0, .6) +} + +.swagger-ui .hover-black-50:focus, .swagger-ui .hover-black-50:hover { + color: rgba(0, 0, 0, .5) +} + +.swagger-ui .hover-black-40:focus, .swagger-ui .hover-black-40:hover { + color: rgba(0, 0, 0, .4) +} + +.swagger-ui .hover-black-30:focus, .swagger-ui .hover-black-30:hover { + color: rgba(0, 0, 0, .3) +} + +.swagger-ui .hover-black-20:focus, .swagger-ui .hover-black-20:hover { + color: rgba(0, 0, 0, .2) +} + +.swagger-ui .hover-black-10:focus, .swagger-ui .hover-black-10:hover { + color: rgba(0, 0, 0, .1) +} + +.swagger-ui .hover-white-90:focus, .swagger-ui .hover-white-90:hover { + color: hsla(0, 0%, 100%, .9) +} + +.swagger-ui .hover-white-80:focus, .swagger-ui .hover-white-80:hover { + color: hsla(0, 0%, 100%, .8) +} + +.swagger-ui .hover-white-70:focus, .swagger-ui .hover-white-70:hover { + color: hsla(0, 0%, 100%, .7) +} + +.swagger-ui .hover-white-60:focus, .swagger-ui .hover-white-60:hover { + color: hsla(0, 0%, 100%, .6) +} + +.swagger-ui .hover-white-50:focus, .swagger-ui .hover-white-50:hover { + color: hsla(0, 0%, 100%, .5) +} + +.swagger-ui .hover-white-40:focus, .swagger-ui .hover-white-40:hover { + color: hsla(0, 0%, 100%, .4) +} + +.swagger-ui .hover-white-30:focus, .swagger-ui .hover-white-30:hover { + color: hsla(0, 0%, 100%, .3) +} + +.swagger-ui .hover-white-20:focus, .swagger-ui .hover-white-20:hover { + color: hsla(0, 0%, 100%, .2) +} + +.swagger-ui .hover-white-10:focus, .swagger-ui .hover-white-10:hover { + color: hsla(0, 0%, 100%, .1) +} + +.swagger-ui .hover-inherit:focus, .swagger-ui .hover-inherit:hover { + color: inherit +} + +.swagger-ui .hover-bg-black:focus, .swagger-ui .hover-bg-black:hover { + background-color: #000 +} + +.swagger-ui .hover-bg-near-black:focus, .swagger-ui .hover-bg-near-black:hover { + background-color: #111 +} + +.swagger-ui .hover-bg-dark-gray:focus, .swagger-ui .hover-bg-dark-gray:hover { + background-color: #333 +} + +.swagger-ui .hover-bg-mid-gray:focus, .swagger-ui .hover-bg-mid-gray:hover { + background-color: #555 +} + +.swagger-ui .hover-bg-gray:focus, .swagger-ui .hover-bg-gray:hover { + background-color: #777 +} + +.swagger-ui .hover-bg-silver:focus, .swagger-ui .hover-bg-silver:hover { + background-color: #999 +} + +.swagger-ui .hover-bg-light-silver:focus, .swagger-ui .hover-bg-light-silver:hover { + background-color: #aaa +} + +.swagger-ui .hover-bg-moon-gray:focus, .swagger-ui .hover-bg-moon-gray:hover { + background-color: #ccc +} + +.swagger-ui .hover-bg-light-gray:focus, .swagger-ui .hover-bg-light-gray:hover { + background-color: #eee +} + +.swagger-ui .hover-bg-near-white:focus, .swagger-ui .hover-bg-near-white:hover { + background-color: #f4f4f4 +} + +.swagger-ui .hover-bg-white:focus, .swagger-ui .hover-bg-white:hover { + background-color: #fff +} + +.swagger-ui .hover-bg-transparent:focus, .swagger-ui .hover-bg-transparent:hover { + background-color: transparent +} + +.swagger-ui .hover-bg-black-90:focus, .swagger-ui .hover-bg-black-90:hover { + background-color: rgba(0, 0, 0, .9) +} + +.swagger-ui .hover-bg-black-80:focus, .swagger-ui .hover-bg-black-80:hover { + background-color: rgba(0, 0, 0, .8) +} + +.swagger-ui .hover-bg-black-70:focus, .swagger-ui .hover-bg-black-70:hover { + background-color: rgba(0, 0, 0, .7) +} + +.swagger-ui .hover-bg-black-60:focus, .swagger-ui .hover-bg-black-60:hover { + background-color: rgba(0, 0, 0, .6) +} + +.swagger-ui .hover-bg-black-50:focus, .swagger-ui .hover-bg-black-50:hover { + background-color: rgba(0, 0, 0, .5) +} + +.swagger-ui .hover-bg-black-40:focus, .swagger-ui .hover-bg-black-40:hover { + background-color: rgba(0, 0, 0, .4) +} + +.swagger-ui .hover-bg-black-30:focus, .swagger-ui .hover-bg-black-30:hover { + background-color: rgba(0, 0, 0, .3) +} + +.swagger-ui .hover-bg-black-20:focus, .swagger-ui .hover-bg-black-20:hover { + background-color: rgba(0, 0, 0, .2) +} + +.swagger-ui .hover-bg-black-10:focus, .swagger-ui .hover-bg-black-10:hover { + background-color: rgba(0, 0, 0, .1) +} + +.swagger-ui .hover-bg-white-90:focus, .swagger-ui .hover-bg-white-90:hover { + background-color: hsla(0, 0%, 100%, .9) +} + +.swagger-ui .hover-bg-white-80:focus, .swagger-ui .hover-bg-white-80:hover { + background-color: hsla(0, 0%, 100%, .8) +} + +.swagger-ui .hover-bg-white-70:focus, .swagger-ui .hover-bg-white-70:hover { + background-color: hsla(0, 0%, 100%, .7) +} + +.swagger-ui .hover-bg-white-60:focus, .swagger-ui .hover-bg-white-60:hover { + background-color: hsla(0, 0%, 100%, .6) +} + +.swagger-ui .hover-bg-white-50:focus, .swagger-ui .hover-bg-white-50:hover { + background-color: hsla(0, 0%, 100%, .5) +} + +.swagger-ui .hover-bg-white-40:focus, .swagger-ui .hover-bg-white-40:hover { + background-color: hsla(0, 0%, 100%, .4) +} + +.swagger-ui .hover-bg-white-30:focus, .swagger-ui .hover-bg-white-30:hover { + background-color: hsla(0, 0%, 100%, .3) +} + +.swagger-ui .hover-bg-white-20:focus, .swagger-ui .hover-bg-white-20:hover { + background-color: hsla(0, 0%, 100%, .2) +} + +.swagger-ui .hover-bg-white-10:focus, .swagger-ui .hover-bg-white-10:hover { + background-color: hsla(0, 0%, 100%, .1) +} + +.swagger-ui .hover-dark-red:focus, .swagger-ui .hover-dark-red:hover { + color: #e7040f +} + +.swagger-ui .hover-red:focus, .swagger-ui .hover-red:hover { + color: #ff4136 +} + +.swagger-ui .hover-light-red:focus, .swagger-ui .hover-light-red:hover { + color: #ff725c +} + +.swagger-ui .hover-orange:focus, .swagger-ui .hover-orange:hover { + color: #ff6300 +} + +.swagger-ui .hover-gold:focus, .swagger-ui .hover-gold:hover { + color: #ffb700 +} + +.swagger-ui .hover-yellow:focus, .swagger-ui .hover-yellow:hover { + color: gold +} + +.swagger-ui .hover-light-yellow:focus, .swagger-ui .hover-light-yellow:hover { + color: #fbf1a9 +} + +.swagger-ui .hover-purple:focus, .swagger-ui .hover-purple:hover { + color: #5e2ca5 +} + +.swagger-ui .hover-light-purple:focus, .swagger-ui .hover-light-purple:hover { + color: #a463f2 +} + +.swagger-ui .hover-dark-pink:focus, .swagger-ui .hover-dark-pink:hover { + color: #d5008f +} + +.swagger-ui .hover-hot-pink:focus, .swagger-ui .hover-hot-pink:hover { + color: #ff41b4 +} + +.swagger-ui .hover-pink:focus, .swagger-ui .hover-pink:hover { + color: #ff80cc +} + +.swagger-ui .hover-light-pink:focus, .swagger-ui .hover-light-pink:hover { + color: #ffa3d7 +} + +.swagger-ui .hover-dark-green:focus, .swagger-ui .hover-dark-green:hover { + color: #137752 +} + +.swagger-ui .hover-green:focus, .swagger-ui .hover-green:hover { + color: #19a974 +} + +.swagger-ui .hover-light-green:focus, .swagger-ui .hover-light-green:hover { + color: #9eebcf +} + +.swagger-ui .hover-navy:focus, .swagger-ui .hover-navy:hover { + color: #001b44 +} + +.swagger-ui .hover-dark-blue:focus, .swagger-ui .hover-dark-blue:hover { + color: #00449e +} + +.swagger-ui .hover-blue:focus, .swagger-ui .hover-blue:hover { + color: #357edd +} + +.swagger-ui .hover-light-blue:focus, .swagger-ui .hover-light-blue:hover { + color: #96ccff +} + +.swagger-ui .hover-lightest-blue:focus, .swagger-ui .hover-lightest-blue:hover { + color: #cdecff +} + +.swagger-ui .hover-washed-blue:focus, .swagger-ui .hover-washed-blue:hover { + color: #f6fffe +} + +.swagger-ui .hover-washed-green:focus, .swagger-ui .hover-washed-green:hover { + color: #e8fdf5 +} + +.swagger-ui .hover-washed-yellow:focus, .swagger-ui .hover-washed-yellow:hover { + color: #fffceb +} + +.swagger-ui .hover-washed-red:focus, .swagger-ui .hover-washed-red:hover { + color: #ffdfdf +} + +.swagger-ui .hover-bg-dark-red:focus, .swagger-ui .hover-bg-dark-red:hover { + background-color: #e7040f +} + +.swagger-ui .hover-bg-red:focus, .swagger-ui .hover-bg-red:hover { + background-color: #ff4136 +} + +.swagger-ui .hover-bg-light-red:focus, .swagger-ui .hover-bg-light-red:hover { + background-color: #ff725c +} + +.swagger-ui .hover-bg-orange:focus, .swagger-ui .hover-bg-orange:hover { + background-color: #ff6300 +} + +.swagger-ui .hover-bg-gold:focus, .swagger-ui .hover-bg-gold:hover { + background-color: #ffb700 +} + +.swagger-ui .hover-bg-yellow:focus, .swagger-ui .hover-bg-yellow:hover { + background-color: gold +} + +.swagger-ui .hover-bg-light-yellow:focus, .swagger-ui .hover-bg-light-yellow:hover { + background-color: #fbf1a9 +} + +.swagger-ui .hover-bg-purple:focus, .swagger-ui .hover-bg-purple:hover { + background-color: #5e2ca5 +} + +.swagger-ui .hover-bg-light-purple:focus, .swagger-ui .hover-bg-light-purple:hover { + background-color: #a463f2 +} + +.swagger-ui .hover-bg-dark-pink:focus, .swagger-ui .hover-bg-dark-pink:hover { + background-color: #d5008f +} + +.swagger-ui .hover-bg-hot-pink:focus, .swagger-ui .hover-bg-hot-pink:hover { + background-color: #ff41b4 +} + +.swagger-ui .hover-bg-pink:focus, .swagger-ui .hover-bg-pink:hover { + background-color: #ff80cc +} + +.swagger-ui .hover-bg-light-pink:focus, .swagger-ui .hover-bg-light-pink:hover { + background-color: #ffa3d7 +} + +.swagger-ui .hover-bg-dark-green:focus, .swagger-ui .hover-bg-dark-green:hover { + background-color: #137752 +} + +.swagger-ui .hover-bg-green:focus, .swagger-ui .hover-bg-green:hover { + background-color: #19a974 +} + +.swagger-ui .hover-bg-light-green:focus, .swagger-ui .hover-bg-light-green:hover { + background-color: #9eebcf +} + +.swagger-ui .hover-bg-navy:focus, .swagger-ui .hover-bg-navy:hover { + background-color: #001b44 +} + +.swagger-ui .hover-bg-dark-blue:focus, .swagger-ui .hover-bg-dark-blue:hover { + background-color: #00449e +} + +.swagger-ui .hover-bg-blue:focus, .swagger-ui .hover-bg-blue:hover { + background-color: #357edd +} + +.swagger-ui .hover-bg-light-blue:focus, .swagger-ui .hover-bg-light-blue:hover { + background-color: #96ccff +} + +.swagger-ui .hover-bg-lightest-blue:focus, .swagger-ui .hover-bg-lightest-blue:hover { + background-color: #cdecff +} + +.swagger-ui .hover-bg-washed-blue:focus, .swagger-ui .hover-bg-washed-blue:hover { + background-color: #f6fffe +} + +.swagger-ui .hover-bg-washed-green:focus, .swagger-ui .hover-bg-washed-green:hover { + background-color: #e8fdf5 +} + +.swagger-ui .hover-bg-washed-yellow:focus, .swagger-ui .hover-bg-washed-yellow:hover { + background-color: #fffceb +} + +.swagger-ui .hover-bg-washed-red:focus, .swagger-ui .hover-bg-washed-red:hover { + background-color: #ffdfdf +} + +.swagger-ui .hover-bg-inherit:focus, .swagger-ui .hover-bg-inherit:hover { + background-color: inherit +} + +.swagger-ui .pa0 { + padding: 0 +} + +.swagger-ui .pa1 { + padding: .25rem +} + +.swagger-ui .pa2 { + padding: .5rem +} + +.swagger-ui .pa3 { + padding: 1rem +} + +.swagger-ui .pa4 { + padding: 2rem +} + +.swagger-ui .pa5 { + padding: 4rem +} + +.swagger-ui .pa6 { + padding: 8rem +} + +.swagger-ui .pa7 { + padding: 16rem +} + +.swagger-ui .pl0 { + padding-left: 0 +} + +.swagger-ui .pl1 { + padding-left: .25rem +} + +.swagger-ui .pl2 { + padding-left: .5rem +} + +.swagger-ui .pl3 { + padding-left: 1rem +} + +.swagger-ui .pl4 { + padding-left: 2rem +} + +.swagger-ui .pl5 { + padding-left: 4rem +} + +.swagger-ui .pl6 { + padding-left: 8rem +} + +.swagger-ui .pl7 { + padding-left: 16rem +} + +.swagger-ui .pr0 { + padding-right: 0 +} + +.swagger-ui .pr1 { + padding-right: .25rem +} + +.swagger-ui .pr2 { + padding-right: .5rem +} + +.swagger-ui .pr3 { + padding-right: 1rem +} + +.swagger-ui .pr4 { + padding-right: 2rem +} + +.swagger-ui .pr5 { + padding-right: 4rem +} + +.swagger-ui .pr6 { + padding-right: 8rem +} + +.swagger-ui .pr7 { + padding-right: 16rem +} + +.swagger-ui .pb0 { + padding-bottom: 0 +} + +.swagger-ui .pb1 { + padding-bottom: .25rem +} + +.swagger-ui .pb2 { + padding-bottom: .5rem +} + +.swagger-ui .pb3 { + padding-bottom: 1rem +} + +.swagger-ui .pb4 { + padding-bottom: 2rem +} + +.swagger-ui .pb5 { + padding-bottom: 4rem +} + +.swagger-ui .pb6 { + padding-bottom: 8rem +} + +.swagger-ui .pb7 { + padding-bottom: 16rem +} + +.swagger-ui .pt0 { + padding-top: 0 +} + +.swagger-ui .pt1 { + padding-top: .25rem +} + +.swagger-ui .pt2 { + padding-top: .5rem +} + +.swagger-ui .pt3 { + padding-top: 1rem +} + +.swagger-ui .pt4 { + padding-top: 2rem +} + +.swagger-ui .pt5 { + padding-top: 4rem +} + +.swagger-ui .pt6 { + padding-top: 8rem +} + +.swagger-ui .pt7 { + padding-top: 16rem +} + +.swagger-ui .pv0 { + padding-top: 0; + padding-bottom: 0 +} + +.swagger-ui .pv1 { + padding-top: .25rem; + padding-bottom: .25rem +} + +.swagger-ui .pv2 { + padding-top: .5rem; + padding-bottom: .5rem +} + +.swagger-ui .pv3 { + padding-top: 1rem; + padding-bottom: 1rem +} + +.swagger-ui .pv4 { + padding-top: 2rem; + padding-bottom: 2rem +} + +.swagger-ui .pv5 { + padding-top: 4rem; + padding-bottom: 4rem +} + +.swagger-ui .pv6 { + padding-top: 8rem; + padding-bottom: 8rem +} + +.swagger-ui .pv7 { + padding-top: 16rem; + padding-bottom: 16rem +} + +.swagger-ui .ph0 { + padding-left: 0; + padding-right: 0 +} + +.swagger-ui .ph1 { + padding-left: .25rem; + padding-right: .25rem +} + +.swagger-ui .ph2 { + padding-left: .5rem; + padding-right: .5rem +} + +.swagger-ui .ph3 { + padding-left: 1rem; + padding-right: 1rem +} + +.swagger-ui .ph4 { + padding-left: 2rem; + padding-right: 2rem +} + +.swagger-ui .ph5 { + padding-left: 4rem; + padding-right: 4rem +} + +.swagger-ui .ph6 { + padding-left: 8rem; + padding-right: 8rem +} + +.swagger-ui .ph7 { + padding-left: 16rem; + padding-right: 16rem +} + +.swagger-ui .ma0 { + margin: 0 +} + +.swagger-ui .ma1 { + margin: .25rem +} + +.swagger-ui .ma2 { + margin: .5rem +} + +.swagger-ui .ma3 { + margin: 1rem +} + +.swagger-ui .ma4 { + margin: 2rem +} + +.swagger-ui .ma5 { + margin: 4rem +} + +.swagger-ui .ma6 { + margin: 8rem +} + +.swagger-ui .ma7 { + margin: 16rem +} + +.swagger-ui .ml0 { + margin-left: 0 +} + +.swagger-ui .ml1 { + margin-left: .25rem +} + +.swagger-ui .ml2 { + margin-left: .5rem +} + +.swagger-ui .ml3 { + margin-left: 1rem +} + +.swagger-ui .ml4 { + margin-left: 2rem +} + +.swagger-ui .ml5 { + margin-left: 4rem +} + +.swagger-ui .ml6 { + margin-left: 8rem +} + +.swagger-ui .ml7 { + margin-left: 16rem +} + +.swagger-ui .mr0 { + margin-right: 0 +} + +.swagger-ui .mr1 { + margin-right: .25rem +} + +.swagger-ui .mr2 { + margin-right: .5rem +} + +.swagger-ui .mr3 { + margin-right: 1rem +} + +.swagger-ui .mr4 { + margin-right: 2rem +} + +.swagger-ui .mr5 { + margin-right: 4rem +} + +.swagger-ui .mr6 { + margin-right: 8rem +} + +.swagger-ui .mr7 { + margin-right: 16rem +} + +.swagger-ui .mb0 { + margin-bottom: 0 +} + +.swagger-ui .mb1 { + margin-bottom: .25rem +} + +.swagger-ui .mb2 { + margin-bottom: .5rem +} + +.swagger-ui .mb3 { + margin-bottom: 1rem +} + +.swagger-ui .mb4 { + margin-bottom: 2rem +} + +.swagger-ui .mb5 { + margin-bottom: 4rem +} + +.swagger-ui .mb6 { + margin-bottom: 8rem +} + +.swagger-ui .mb7 { + margin-bottom: 16rem +} + +.swagger-ui .mt0 { + margin-top: 0 +} + +.swagger-ui .mt1 { + margin-top: .25rem +} + +.swagger-ui .mt2 { + margin-top: .5rem +} + +.swagger-ui .mt3 { + margin-top: 1rem +} + +.swagger-ui .mt4 { + margin-top: 2rem +} + +.swagger-ui .mt5 { + margin-top: 4rem +} + +.swagger-ui .mt6 { + margin-top: 8rem +} + +.swagger-ui .mt7 { + margin-top: 16rem +} + +.swagger-ui .mv0 { + margin-top: 0; + margin-bottom: 0 +} + +.swagger-ui .mv1 { + margin-top: .25rem; + margin-bottom: .25rem +} + +.swagger-ui .mv2 { + margin-top: .5rem; + margin-bottom: .5rem +} + +.swagger-ui .mv3 { + margin-top: 1rem; + margin-bottom: 1rem +} + +.swagger-ui .mv4 { + margin-top: 2rem; + margin-bottom: 2rem +} + +.swagger-ui .mv5 { + margin-top: 4rem; + margin-bottom: 4rem +} + +.swagger-ui .mv6 { + margin-top: 8rem; + margin-bottom: 8rem +} + +.swagger-ui .mv7 { + margin-top: 16rem; + margin-bottom: 16rem +} + +.swagger-ui .mh0 { + margin-left: 0; + margin-right: 0 +} + +.swagger-ui .mh1 { + margin-left: .25rem; + margin-right: .25rem +} + +.swagger-ui .mh2 { + margin-left: .5rem; + margin-right: .5rem +} + +.swagger-ui .mh3 { + margin-left: 1rem; + margin-right: 1rem +} + +.swagger-ui .mh4 { + margin-left: 2rem; + margin-right: 2rem +} + +.swagger-ui .mh5 { + margin-left: 4rem; + margin-right: 4rem +} + +.swagger-ui .mh6 { + margin-left: 8rem; + margin-right: 8rem +} + +.swagger-ui .mh7 { + margin-left: 16rem; + margin-right: 16rem +} + +@media screen and (min-width: 30em) { + .swagger-ui .pa0-ns { + padding: 0 + } + + .swagger-ui .pa1-ns { + padding: .25rem + } + + .swagger-ui .pa2-ns { + padding: .5rem + } + + .swagger-ui .pa3-ns { + padding: 1rem + } + + .swagger-ui .pa4-ns { + padding: 2rem + } + + .swagger-ui .pa5-ns { + padding: 4rem + } + + .swagger-ui .pa6-ns { + padding: 8rem + } + + .swagger-ui .pa7-ns { + padding: 16rem + } + + .swagger-ui .pl0-ns { + padding-left: 0 + } + + .swagger-ui .pl1-ns { + padding-left: .25rem + } + + .swagger-ui .pl2-ns { + padding-left: .5rem + } + + .swagger-ui .pl3-ns { + padding-left: 1rem + } + + .swagger-ui .pl4-ns { + padding-left: 2rem + } + + .swagger-ui .pl5-ns { + padding-left: 4rem + } + + .swagger-ui .pl6-ns { + padding-left: 8rem + } + + .swagger-ui .pl7-ns { + padding-left: 16rem + } + + .swagger-ui .pr0-ns { + padding-right: 0 + } + + .swagger-ui .pr1-ns { + padding-right: .25rem + } + + .swagger-ui .pr2-ns { + padding-right: .5rem + } + + .swagger-ui .pr3-ns { + padding-right: 1rem + } + + .swagger-ui .pr4-ns { + padding-right: 2rem + } + + .swagger-ui .pr5-ns { + padding-right: 4rem + } + + .swagger-ui .pr6-ns { + padding-right: 8rem + } + + .swagger-ui .pr7-ns { + padding-right: 16rem + } + + .swagger-ui .pb0-ns { + padding-bottom: 0 + } + + .swagger-ui .pb1-ns { + padding-bottom: .25rem + } + + .swagger-ui .pb2-ns { + padding-bottom: .5rem + } + + .swagger-ui .pb3-ns { + padding-bottom: 1rem + } + + .swagger-ui .pb4-ns { + padding-bottom: 2rem + } + + .swagger-ui .pb5-ns { + padding-bottom: 4rem + } + + .swagger-ui .pb6-ns { + padding-bottom: 8rem + } + + .swagger-ui .pb7-ns { + padding-bottom: 16rem + } + + .swagger-ui .pt0-ns { + padding-top: 0 + } + + .swagger-ui .pt1-ns { + padding-top: .25rem + } + + .swagger-ui .pt2-ns { + padding-top: .5rem + } + + .swagger-ui .pt3-ns { + padding-top: 1rem + } + + .swagger-ui .pt4-ns { + padding-top: 2rem + } + + .swagger-ui .pt5-ns { + padding-top: 4rem + } + + .swagger-ui .pt6-ns { + padding-top: 8rem + } + + .swagger-ui .pt7-ns { + padding-top: 16rem + } + + .swagger-ui .pv0-ns { + padding-top: 0; + padding-bottom: 0 + } + + .swagger-ui .pv1-ns { + padding-top: .25rem; + padding-bottom: .25rem + } + + .swagger-ui .pv2-ns { + padding-top: .5rem; + padding-bottom: .5rem + } + + .swagger-ui .pv3-ns { + padding-top: 1rem; + padding-bottom: 1rem + } + + .swagger-ui .pv4-ns { + padding-top: 2rem; + padding-bottom: 2rem + } + + .swagger-ui .pv5-ns { + padding-top: 4rem; + padding-bottom: 4rem + } + + .swagger-ui .pv6-ns { + padding-top: 8rem; + padding-bottom: 8rem + } + + .swagger-ui .pv7-ns { + padding-top: 16rem; + padding-bottom: 16rem + } + + .swagger-ui .ph0-ns { + padding-left: 0; + padding-right: 0 + } + + .swagger-ui .ph1-ns { + padding-left: .25rem; + padding-right: .25rem + } + + .swagger-ui .ph2-ns { + padding-left: .5rem; + padding-right: .5rem + } + + .swagger-ui .ph3-ns { + padding-left: 1rem; + padding-right: 1rem + } + + .swagger-ui .ph4-ns { + padding-left: 2rem; + padding-right: 2rem + } + + .swagger-ui .ph5-ns { + padding-left: 4rem; + padding-right: 4rem + } + + .swagger-ui .ph6-ns { + padding-left: 8rem; + padding-right: 8rem + } + + .swagger-ui .ph7-ns { + padding-left: 16rem; + padding-right: 16rem + } + + .swagger-ui .ma0-ns { + margin: 0 + } + + .swagger-ui .ma1-ns { + margin: .25rem + } + + .swagger-ui .ma2-ns { + margin: .5rem + } + + .swagger-ui .ma3-ns { + margin: 1rem + } + + .swagger-ui .ma4-ns { + margin: 2rem + } + + .swagger-ui .ma5-ns { + margin: 4rem + } + + .swagger-ui .ma6-ns { + margin: 8rem + } + + .swagger-ui .ma7-ns { + margin: 16rem + } + + .swagger-ui .ml0-ns { + margin-left: 0 + } + + .swagger-ui .ml1-ns { + margin-left: .25rem + } + + .swagger-ui .ml2-ns { + margin-left: .5rem + } + + .swagger-ui .ml3-ns { + margin-left: 1rem + } + + .swagger-ui .ml4-ns { + margin-left: 2rem + } + + .swagger-ui .ml5-ns { + margin-left: 4rem + } + + .swagger-ui .ml6-ns { + margin-left: 8rem + } + + .swagger-ui .ml7-ns { + margin-left: 16rem + } + + .swagger-ui .mr0-ns { + margin-right: 0 + } + + .swagger-ui .mr1-ns { + margin-right: .25rem + } + + .swagger-ui .mr2-ns { + margin-right: .5rem + } + + .swagger-ui .mr3-ns { + margin-right: 1rem + } + + .swagger-ui .mr4-ns { + margin-right: 2rem + } + + .swagger-ui .mr5-ns { + margin-right: 4rem + } + + .swagger-ui .mr6-ns { + margin-right: 8rem + } + + .swagger-ui .mr7-ns { + margin-right: 16rem + } + + .swagger-ui .mb0-ns { + margin-bottom: 0 + } + + .swagger-ui .mb1-ns { + margin-bottom: .25rem + } + + .swagger-ui .mb2-ns { + margin-bottom: .5rem + } + + .swagger-ui .mb3-ns { + margin-bottom: 1rem + } + + .swagger-ui .mb4-ns { + margin-bottom: 2rem + } + + .swagger-ui .mb5-ns { + margin-bottom: 4rem + } + + .swagger-ui .mb6-ns { + margin-bottom: 8rem + } + + .swagger-ui .mb7-ns { + margin-bottom: 16rem + } + + .swagger-ui .mt0-ns { + margin-top: 0 + } + + .swagger-ui .mt1-ns { + margin-top: .25rem + } + + .swagger-ui .mt2-ns { + margin-top: .5rem + } + + .swagger-ui .mt3-ns { + margin-top: 1rem + } + + .swagger-ui .mt4-ns { + margin-top: 2rem + } + + .swagger-ui .mt5-ns { + margin-top: 4rem + } + + .swagger-ui .mt6-ns { + margin-top: 8rem + } + + .swagger-ui .mt7-ns { + margin-top: 16rem + } + + .swagger-ui .mv0-ns { + margin-top: 0; + margin-bottom: 0 + } + + .swagger-ui .mv1-ns { + margin-top: .25rem; + margin-bottom: .25rem + } + + .swagger-ui .mv2-ns { + margin-top: .5rem; + margin-bottom: .5rem + } + + .swagger-ui .mv3-ns { + margin-top: 1rem; + margin-bottom: 1rem + } + + .swagger-ui .mv4-ns { + margin-top: 2rem; + margin-bottom: 2rem + } + + .swagger-ui .mv5-ns { + margin-top: 4rem; + margin-bottom: 4rem + } + + .swagger-ui .mv6-ns { + margin-top: 8rem; + margin-bottom: 8rem + } + + .swagger-ui .mv7-ns { + margin-top: 16rem; + margin-bottom: 16rem + } + + .swagger-ui .mh0-ns { + margin-left: 0; + margin-right: 0 + } + + .swagger-ui .mh1-ns { + margin-left: .25rem; + margin-right: .25rem + } + + .swagger-ui .mh2-ns { + margin-left: .5rem; + margin-right: .5rem + } + + .swagger-ui .mh3-ns { + margin-left: 1rem; + margin-right: 1rem + } + + .swagger-ui .mh4-ns { + margin-left: 2rem; + margin-right: 2rem + } + + .swagger-ui .mh5-ns { + margin-left: 4rem; + margin-right: 4rem + } + + .swagger-ui .mh6-ns { + margin-left: 8rem; + margin-right: 8rem + } + + .swagger-ui .mh7-ns { + margin-left: 16rem; + margin-right: 16rem + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .pa0-m { + padding: 0 + } + + .swagger-ui .pa1-m { + padding: .25rem + } + + .swagger-ui .pa2-m { + padding: .5rem + } + + .swagger-ui .pa3-m { + padding: 1rem + } + + .swagger-ui .pa4-m { + padding: 2rem + } + + .swagger-ui .pa5-m { + padding: 4rem + } + + .swagger-ui .pa6-m { + padding: 8rem + } + + .swagger-ui .pa7-m { + padding: 16rem + } + + .swagger-ui .pl0-m { + padding-left: 0 + } + + .swagger-ui .pl1-m { + padding-left: .25rem + } + + .swagger-ui .pl2-m { + padding-left: .5rem + } + + .swagger-ui .pl3-m { + padding-left: 1rem + } + + .swagger-ui .pl4-m { + padding-left: 2rem + } + + .swagger-ui .pl5-m { + padding-left: 4rem + } + + .swagger-ui .pl6-m { + padding-left: 8rem + } + + .swagger-ui .pl7-m { + padding-left: 16rem + } + + .swagger-ui .pr0-m { + padding-right: 0 + } + + .swagger-ui .pr1-m { + padding-right: .25rem + } + + .swagger-ui .pr2-m { + padding-right: .5rem + } + + .swagger-ui .pr3-m { + padding-right: 1rem + } + + .swagger-ui .pr4-m { + padding-right: 2rem + } + + .swagger-ui .pr5-m { + padding-right: 4rem + } + + .swagger-ui .pr6-m { + padding-right: 8rem + } + + .swagger-ui .pr7-m { + padding-right: 16rem + } + + .swagger-ui .pb0-m { + padding-bottom: 0 + } + + .swagger-ui .pb1-m { + padding-bottom: .25rem + } + + .swagger-ui .pb2-m { + padding-bottom: .5rem + } + + .swagger-ui .pb3-m { + padding-bottom: 1rem + } + + .swagger-ui .pb4-m { + padding-bottom: 2rem + } + + .swagger-ui .pb5-m { + padding-bottom: 4rem + } + + .swagger-ui .pb6-m { + padding-bottom: 8rem + } + + .swagger-ui .pb7-m { + padding-bottom: 16rem + } + + .swagger-ui .pt0-m { + padding-top: 0 + } + + .swagger-ui .pt1-m { + padding-top: .25rem + } + + .swagger-ui .pt2-m { + padding-top: .5rem + } + + .swagger-ui .pt3-m { + padding-top: 1rem + } + + .swagger-ui .pt4-m { + padding-top: 2rem + } + + .swagger-ui .pt5-m { + padding-top: 4rem + } + + .swagger-ui .pt6-m { + padding-top: 8rem + } + + .swagger-ui .pt7-m { + padding-top: 16rem + } + + .swagger-ui .pv0-m { + padding-top: 0; + padding-bottom: 0 + } + + .swagger-ui .pv1-m { + padding-top: .25rem; + padding-bottom: .25rem + } + + .swagger-ui .pv2-m { + padding-top: .5rem; + padding-bottom: .5rem + } + + .swagger-ui .pv3-m { + padding-top: 1rem; + padding-bottom: 1rem + } + + .swagger-ui .pv4-m { + padding-top: 2rem; + padding-bottom: 2rem + } + + .swagger-ui .pv5-m { + padding-top: 4rem; + padding-bottom: 4rem + } + + .swagger-ui .pv6-m { + padding-top: 8rem; + padding-bottom: 8rem + } + + .swagger-ui .pv7-m { + padding-top: 16rem; + padding-bottom: 16rem + } + + .swagger-ui .ph0-m { + padding-left: 0; + padding-right: 0 + } + + .swagger-ui .ph1-m { + padding-left: .25rem; + padding-right: .25rem + } + + .swagger-ui .ph2-m { + padding-left: .5rem; + padding-right: .5rem + } + + .swagger-ui .ph3-m { + padding-left: 1rem; + padding-right: 1rem + } + + .swagger-ui .ph4-m { + padding-left: 2rem; + padding-right: 2rem + } + + .swagger-ui .ph5-m { + padding-left: 4rem; + padding-right: 4rem + } + + .swagger-ui .ph6-m { + padding-left: 8rem; + padding-right: 8rem + } + + .swagger-ui .ph7-m { + padding-left: 16rem; + padding-right: 16rem + } + + .swagger-ui .ma0-m { + margin: 0 + } + + .swagger-ui .ma1-m { + margin: .25rem + } + + .swagger-ui .ma2-m { + margin: .5rem + } + + .swagger-ui .ma3-m { + margin: 1rem + } + + .swagger-ui .ma4-m { + margin: 2rem + } + + .swagger-ui .ma5-m { + margin: 4rem + } + + .swagger-ui .ma6-m { + margin: 8rem + } + + .swagger-ui .ma7-m { + margin: 16rem + } + + .swagger-ui .ml0-m { + margin-left: 0 + } + + .swagger-ui .ml1-m { + margin-left: .25rem + } + + .swagger-ui .ml2-m { + margin-left: .5rem + } + + .swagger-ui .ml3-m { + margin-left: 1rem + } + + .swagger-ui .ml4-m { + margin-left: 2rem + } + + .swagger-ui .ml5-m { + margin-left: 4rem + } + + .swagger-ui .ml6-m { + margin-left: 8rem + } + + .swagger-ui .ml7-m { + margin-left: 16rem + } + + .swagger-ui .mr0-m { + margin-right: 0 + } + + .swagger-ui .mr1-m { + margin-right: .25rem + } + + .swagger-ui .mr2-m { + margin-right: .5rem + } + + .swagger-ui .mr3-m { + margin-right: 1rem + } + + .swagger-ui .mr4-m { + margin-right: 2rem + } + + .swagger-ui .mr5-m { + margin-right: 4rem + } + + .swagger-ui .mr6-m { + margin-right: 8rem + } + + .swagger-ui .mr7-m { + margin-right: 16rem + } + + .swagger-ui .mb0-m { + margin-bottom: 0 + } + + .swagger-ui .mb1-m { + margin-bottom: .25rem + } + + .swagger-ui .mb2-m { + margin-bottom: .5rem + } + + .swagger-ui .mb3-m { + margin-bottom: 1rem + } + + .swagger-ui .mb4-m { + margin-bottom: 2rem + } + + .swagger-ui .mb5-m { + margin-bottom: 4rem + } + + .swagger-ui .mb6-m { + margin-bottom: 8rem + } + + .swagger-ui .mb7-m { + margin-bottom: 16rem + } + + .swagger-ui .mt0-m { + margin-top: 0 + } + + .swagger-ui .mt1-m { + margin-top: .25rem + } + + .swagger-ui .mt2-m { + margin-top: .5rem + } + + .swagger-ui .mt3-m { + margin-top: 1rem + } + + .swagger-ui .mt4-m { + margin-top: 2rem + } + + .swagger-ui .mt5-m { + margin-top: 4rem + } + + .swagger-ui .mt6-m { + margin-top: 8rem + } + + .swagger-ui .mt7-m { + margin-top: 16rem + } + + .swagger-ui .mv0-m { + margin-top: 0; + margin-bottom: 0 + } + + .swagger-ui .mv1-m { + margin-top: .25rem; + margin-bottom: .25rem + } + + .swagger-ui .mv2-m { + margin-top: .5rem; + margin-bottom: .5rem + } + + .swagger-ui .mv3-m { + margin-top: 1rem; + margin-bottom: 1rem + } + + .swagger-ui .mv4-m { + margin-top: 2rem; + margin-bottom: 2rem + } + + .swagger-ui .mv5-m { + margin-top: 4rem; + margin-bottom: 4rem + } + + .swagger-ui .mv6-m { + margin-top: 8rem; + margin-bottom: 8rem + } + + .swagger-ui .mv7-m { + margin-top: 16rem; + margin-bottom: 16rem + } + + .swagger-ui .mh0-m { + margin-left: 0; + margin-right: 0 + } + + .swagger-ui .mh1-m { + margin-left: .25rem; + margin-right: .25rem + } + + .swagger-ui .mh2-m { + margin-left: .5rem; + margin-right: .5rem + } + + .swagger-ui .mh3-m { + margin-left: 1rem; + margin-right: 1rem + } + + .swagger-ui .mh4-m { + margin-left: 2rem; + margin-right: 2rem + } + + .swagger-ui .mh5-m { + margin-left: 4rem; + margin-right: 4rem + } + + .swagger-ui .mh6-m { + margin-left: 8rem; + margin-right: 8rem + } + + .swagger-ui .mh7-m { + margin-left: 16rem; + margin-right: 16rem + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .pa0-l { + padding: 0 + } + + .swagger-ui .pa1-l { + padding: .25rem + } + + .swagger-ui .pa2-l { + padding: .5rem + } + + .swagger-ui .pa3-l { + padding: 1rem + } + + .swagger-ui .pa4-l { + padding: 2rem + } + + .swagger-ui .pa5-l { + padding: 4rem + } + + .swagger-ui .pa6-l { + padding: 8rem + } + + .swagger-ui .pa7-l { + padding: 16rem + } + + .swagger-ui .pl0-l { + padding-left: 0 + } + + .swagger-ui .pl1-l { + padding-left: .25rem + } + + .swagger-ui .pl2-l { + padding-left: .5rem + } + + .swagger-ui .pl3-l { + padding-left: 1rem + } + + .swagger-ui .pl4-l { + padding-left: 2rem + } + + .swagger-ui .pl5-l { + padding-left: 4rem + } + + .swagger-ui .pl6-l { + padding-left: 8rem + } + + .swagger-ui .pl7-l { + padding-left: 16rem + } + + .swagger-ui .pr0-l { + padding-right: 0 + } + + .swagger-ui .pr1-l { + padding-right: .25rem + } + + .swagger-ui .pr2-l { + padding-right: .5rem + } + + .swagger-ui .pr3-l { + padding-right: 1rem + } + + .swagger-ui .pr4-l { + padding-right: 2rem + } + + .swagger-ui .pr5-l { + padding-right: 4rem + } + + .swagger-ui .pr6-l { + padding-right: 8rem + } + + .swagger-ui .pr7-l { + padding-right: 16rem + } + + .swagger-ui .pb0-l { + padding-bottom: 0 + } + + .swagger-ui .pb1-l { + padding-bottom: .25rem + } + + .swagger-ui .pb2-l { + padding-bottom: .5rem + } + + .swagger-ui .pb3-l { + padding-bottom: 1rem + } + + .swagger-ui .pb4-l { + padding-bottom: 2rem + } + + .swagger-ui .pb5-l { + padding-bottom: 4rem + } + + .swagger-ui .pb6-l { + padding-bottom: 8rem + } + + .swagger-ui .pb7-l { + padding-bottom: 16rem + } + + .swagger-ui .pt0-l { + padding-top: 0 + } + + .swagger-ui .pt1-l { + padding-top: .25rem + } + + .swagger-ui .pt2-l { + padding-top: .5rem + } + + .swagger-ui .pt3-l { + padding-top: 1rem + } + + .swagger-ui .pt4-l { + padding-top: 2rem + } + + .swagger-ui .pt5-l { + padding-top: 4rem + } + + .swagger-ui .pt6-l { + padding-top: 8rem + } + + .swagger-ui .pt7-l { + padding-top: 16rem + } + + .swagger-ui .pv0-l { + padding-top: 0; + padding-bottom: 0 + } + + .swagger-ui .pv1-l { + padding-top: .25rem; + padding-bottom: .25rem + } + + .swagger-ui .pv2-l { + padding-top: .5rem; + padding-bottom: .5rem + } + + .swagger-ui .pv3-l { + padding-top: 1rem; + padding-bottom: 1rem + } + + .swagger-ui .pv4-l { + padding-top: 2rem; + padding-bottom: 2rem + } + + .swagger-ui .pv5-l { + padding-top: 4rem; + padding-bottom: 4rem + } + + .swagger-ui .pv6-l { + padding-top: 8rem; + padding-bottom: 8rem + } + + .swagger-ui .pv7-l { + padding-top: 16rem; + padding-bottom: 16rem + } + + .swagger-ui .ph0-l { + padding-left: 0; + padding-right: 0 + } + + .swagger-ui .ph1-l { + padding-left: .25rem; + padding-right: .25rem + } + + .swagger-ui .ph2-l { + padding-left: .5rem; + padding-right: .5rem + } + + .swagger-ui .ph3-l { + padding-left: 1rem; + padding-right: 1rem + } + + .swagger-ui .ph4-l { + padding-left: 2rem; + padding-right: 2rem + } + + .swagger-ui .ph5-l { + padding-left: 4rem; + padding-right: 4rem + } + + .swagger-ui .ph6-l { + padding-left: 8rem; + padding-right: 8rem + } + + .swagger-ui .ph7-l { + padding-left: 16rem; + padding-right: 16rem + } + + .swagger-ui .ma0-l { + margin: 0 + } + + .swagger-ui .ma1-l { + margin: .25rem + } + + .swagger-ui .ma2-l { + margin: .5rem + } + + .swagger-ui .ma3-l { + margin: 1rem + } + + .swagger-ui .ma4-l { + margin: 2rem + } + + .swagger-ui .ma5-l { + margin: 4rem + } + + .swagger-ui .ma6-l { + margin: 8rem + } + + .swagger-ui .ma7-l { + margin: 16rem + } + + .swagger-ui .ml0-l { + margin-left: 0 + } + + .swagger-ui .ml1-l { + margin-left: .25rem + } + + .swagger-ui .ml2-l { + margin-left: .5rem + } + + .swagger-ui .ml3-l { + margin-left: 1rem + } + + .swagger-ui .ml4-l { + margin-left: 2rem + } + + .swagger-ui .ml5-l { + margin-left: 4rem + } + + .swagger-ui .ml6-l { + margin-left: 8rem + } + + .swagger-ui .ml7-l { + margin-left: 16rem + } + + .swagger-ui .mr0-l { + margin-right: 0 + } + + .swagger-ui .mr1-l { + margin-right: .25rem + } + + .swagger-ui .mr2-l { + margin-right: .5rem + } + + .swagger-ui .mr3-l { + margin-right: 1rem + } + + .swagger-ui .mr4-l { + margin-right: 2rem + } + + .swagger-ui .mr5-l { + margin-right: 4rem + } + + .swagger-ui .mr6-l { + margin-right: 8rem + } + + .swagger-ui .mr7-l { + margin-right: 16rem + } + + .swagger-ui .mb0-l { + margin-bottom: 0 + } + + .swagger-ui .mb1-l { + margin-bottom: .25rem + } + + .swagger-ui .mb2-l { + margin-bottom: .5rem + } + + .swagger-ui .mb3-l { + margin-bottom: 1rem + } + + .swagger-ui .mb4-l { + margin-bottom: 2rem + } + + .swagger-ui .mb5-l { + margin-bottom: 4rem + } + + .swagger-ui .mb6-l { + margin-bottom: 8rem + } + + .swagger-ui .mb7-l { + margin-bottom: 16rem + } + + .swagger-ui .mt0-l { + margin-top: 0 + } + + .swagger-ui .mt1-l { + margin-top: .25rem + } + + .swagger-ui .mt2-l { + margin-top: .5rem + } + + .swagger-ui .mt3-l { + margin-top: 1rem + } + + .swagger-ui .mt4-l { + margin-top: 2rem + } + + .swagger-ui .mt5-l { + margin-top: 4rem + } + + .swagger-ui .mt6-l { + margin-top: 8rem + } + + .swagger-ui .mt7-l { + margin-top: 16rem + } + + .swagger-ui .mv0-l { + margin-top: 0; + margin-bottom: 0 + } + + .swagger-ui .mv1-l { + margin-top: .25rem; + margin-bottom: .25rem + } + + .swagger-ui .mv2-l { + margin-top: .5rem; + margin-bottom: .5rem + } + + .swagger-ui .mv3-l { + margin-top: 1rem; + margin-bottom: 1rem + } + + .swagger-ui .mv4-l { + margin-top: 2rem; + margin-bottom: 2rem + } + + .swagger-ui .mv5-l { + margin-top: 4rem; + margin-bottom: 4rem + } + + .swagger-ui .mv6-l { + margin-top: 8rem; + margin-bottom: 8rem + } + + .swagger-ui .mv7-l { + margin-top: 16rem; + margin-bottom: 16rem + } + + .swagger-ui .mh0-l { + margin-left: 0; + margin-right: 0 + } + + .swagger-ui .mh1-l { + margin-left: .25rem; + margin-right: .25rem + } + + .swagger-ui .mh2-l { + margin-left: .5rem; + margin-right: .5rem + } + + .swagger-ui .mh3-l { + margin-left: 1rem; + margin-right: 1rem + } + + .swagger-ui .mh4-l { + margin-left: 2rem; + margin-right: 2rem + } + + .swagger-ui .mh5-l { + margin-left: 4rem; + margin-right: 4rem + } + + .swagger-ui .mh6-l { + margin-left: 8rem; + margin-right: 8rem + } + + .swagger-ui .mh7-l { + margin-left: 16rem; + margin-right: 16rem + } +} + +.swagger-ui .na1 { + margin: -.25rem +} + +.swagger-ui .na2 { + margin: -.5rem +} + +.swagger-ui .na3 { + margin: -1rem +} + +.swagger-ui .na4 { + margin: -2rem +} + +.swagger-ui .na5 { + margin: -4rem +} + +.swagger-ui .na6 { + margin: -8rem +} + +.swagger-ui .na7 { + margin: -16rem +} + +.swagger-ui .nl1 { + margin-left: -.25rem +} + +.swagger-ui .nl2 { + margin-left: -.5rem +} + +.swagger-ui .nl3 { + margin-left: -1rem +} + +.swagger-ui .nl4 { + margin-left: -2rem +} + +.swagger-ui .nl5 { + margin-left: -4rem +} + +.swagger-ui .nl6 { + margin-left: -8rem +} + +.swagger-ui .nl7 { + margin-left: -16rem +} + +.swagger-ui .nr1 { + margin-right: -.25rem +} + +.swagger-ui .nr2 { + margin-right: -.5rem +} + +.swagger-ui .nr3 { + margin-right: -1rem +} + +.swagger-ui .nr4 { + margin-right: -2rem +} + +.swagger-ui .nr5 { + margin-right: -4rem +} + +.swagger-ui .nr6 { + margin-right: -8rem +} + +.swagger-ui .nr7 { + margin-right: -16rem +} + +.swagger-ui .nb1 { + margin-bottom: -.25rem +} + +.swagger-ui .nb2 { + margin-bottom: -.5rem +} + +.swagger-ui .nb3 { + margin-bottom: -1rem +} + +.swagger-ui .nb4 { + margin-bottom: -2rem +} + +.swagger-ui .nb5 { + margin-bottom: -4rem +} + +.swagger-ui .nb6 { + margin-bottom: -8rem +} + +.swagger-ui .nb7 { + margin-bottom: -16rem +} + +.swagger-ui .nt1 { + margin-top: -.25rem +} + +.swagger-ui .nt2 { + margin-top: -.5rem +} + +.swagger-ui .nt3 { + margin-top: -1rem +} + +.swagger-ui .nt4 { + margin-top: -2rem +} + +.swagger-ui .nt5 { + margin-top: -4rem +} + +.swagger-ui .nt6 { + margin-top: -8rem +} + +.swagger-ui .nt7 { + margin-top: -16rem +} + +@media screen and (min-width: 30em) { + .swagger-ui .na1-ns { + margin: -.25rem + } + + .swagger-ui .na2-ns { + margin: -.5rem + } + + .swagger-ui .na3-ns { + margin: -1rem + } + + .swagger-ui .na4-ns { + margin: -2rem + } + + .swagger-ui .na5-ns { + margin: -4rem + } + + .swagger-ui .na6-ns { + margin: -8rem + } + + .swagger-ui .na7-ns { + margin: -16rem + } + + .swagger-ui .nl1-ns { + margin-left: -.25rem + } + + .swagger-ui .nl2-ns { + margin-left: -.5rem + } + + .swagger-ui .nl3-ns { + margin-left: -1rem + } + + .swagger-ui .nl4-ns { + margin-left: -2rem + } + + .swagger-ui .nl5-ns { + margin-left: -4rem + } + + .swagger-ui .nl6-ns { + margin-left: -8rem + } + + .swagger-ui .nl7-ns { + margin-left: -16rem + } + + .swagger-ui .nr1-ns { + margin-right: -.25rem + } + + .swagger-ui .nr2-ns { + margin-right: -.5rem + } + + .swagger-ui .nr3-ns { + margin-right: -1rem + } + + .swagger-ui .nr4-ns { + margin-right: -2rem + } + + .swagger-ui .nr5-ns { + margin-right: -4rem + } + + .swagger-ui .nr6-ns { + margin-right: -8rem + } + + .swagger-ui .nr7-ns { + margin-right: -16rem + } + + .swagger-ui .nb1-ns { + margin-bottom: -.25rem + } + + .swagger-ui .nb2-ns { + margin-bottom: -.5rem + } + + .swagger-ui .nb3-ns { + margin-bottom: -1rem + } + + .swagger-ui .nb4-ns { + margin-bottom: -2rem + } + + .swagger-ui .nb5-ns { + margin-bottom: -4rem + } + + .swagger-ui .nb6-ns { + margin-bottom: -8rem + } + + .swagger-ui .nb7-ns { + margin-bottom: -16rem + } + + .swagger-ui .nt1-ns { + margin-top: -.25rem + } + + .swagger-ui .nt2-ns { + margin-top: -.5rem + } + + .swagger-ui .nt3-ns { + margin-top: -1rem + } + + .swagger-ui .nt4-ns { + margin-top: -2rem + } + + .swagger-ui .nt5-ns { + margin-top: -4rem + } + + .swagger-ui .nt6-ns { + margin-top: -8rem + } + + .swagger-ui .nt7-ns { + margin-top: -16rem + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .na1-m { + margin: -.25rem + } + + .swagger-ui .na2-m { + margin: -.5rem + } + + .swagger-ui .na3-m { + margin: -1rem + } + + .swagger-ui .na4-m { + margin: -2rem + } + + .swagger-ui .na5-m { + margin: -4rem + } + + .swagger-ui .na6-m { + margin: -8rem + } + + .swagger-ui .na7-m { + margin: -16rem + } + + .swagger-ui .nl1-m { + margin-left: -.25rem + } + + .swagger-ui .nl2-m { + margin-left: -.5rem + } + + .swagger-ui .nl3-m { + margin-left: -1rem + } + + .swagger-ui .nl4-m { + margin-left: -2rem + } + + .swagger-ui .nl5-m { + margin-left: -4rem + } + + .swagger-ui .nl6-m { + margin-left: -8rem + } + + .swagger-ui .nl7-m { + margin-left: -16rem + } + + .swagger-ui .nr1-m { + margin-right: -.25rem + } + + .swagger-ui .nr2-m { + margin-right: -.5rem + } + + .swagger-ui .nr3-m { + margin-right: -1rem + } + + .swagger-ui .nr4-m { + margin-right: -2rem + } + + .swagger-ui .nr5-m { + margin-right: -4rem + } + + .swagger-ui .nr6-m { + margin-right: -8rem + } + + .swagger-ui .nr7-m { + margin-right: -16rem + } + + .swagger-ui .nb1-m { + margin-bottom: -.25rem + } + + .swagger-ui .nb2-m { + margin-bottom: -.5rem + } + + .swagger-ui .nb3-m { + margin-bottom: -1rem + } + + .swagger-ui .nb4-m { + margin-bottom: -2rem + } + + .swagger-ui .nb5-m { + margin-bottom: -4rem + } + + .swagger-ui .nb6-m { + margin-bottom: -8rem + } + + .swagger-ui .nb7-m { + margin-bottom: -16rem + } + + .swagger-ui .nt1-m { + margin-top: -.25rem + } + + .swagger-ui .nt2-m { + margin-top: -.5rem + } + + .swagger-ui .nt3-m { + margin-top: -1rem + } + + .swagger-ui .nt4-m { + margin-top: -2rem + } + + .swagger-ui .nt5-m { + margin-top: -4rem + } + + .swagger-ui .nt6-m { + margin-top: -8rem + } + + .swagger-ui .nt7-m { + margin-top: -16rem + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .na1-l { + margin: -.25rem + } + + .swagger-ui .na2-l { + margin: -.5rem + } + + .swagger-ui .na3-l { + margin: -1rem + } + + .swagger-ui .na4-l { + margin: -2rem + } + + .swagger-ui .na5-l { + margin: -4rem + } + + .swagger-ui .na6-l { + margin: -8rem + } + + .swagger-ui .na7-l { + margin: -16rem + } + + .swagger-ui .nl1-l { + margin-left: -.25rem + } + + .swagger-ui .nl2-l { + margin-left: -.5rem + } + + .swagger-ui .nl3-l { + margin-left: -1rem + } + + .swagger-ui .nl4-l { + margin-left: -2rem + } + + .swagger-ui .nl5-l { + margin-left: -4rem + } + + .swagger-ui .nl6-l { + margin-left: -8rem + } + + .swagger-ui .nl7-l { + margin-left: -16rem + } + + .swagger-ui .nr1-l { + margin-right: -.25rem + } + + .swagger-ui .nr2-l { + margin-right: -.5rem + } + + .swagger-ui .nr3-l { + margin-right: -1rem + } + + .swagger-ui .nr4-l { + margin-right: -2rem + } + + .swagger-ui .nr5-l { + margin-right: -4rem + } + + .swagger-ui .nr6-l { + margin-right: -8rem + } + + .swagger-ui .nr7-l { + margin-right: -16rem + } + + .swagger-ui .nb1-l { + margin-bottom: -.25rem + } + + .swagger-ui .nb2-l { + margin-bottom: -.5rem + } + + .swagger-ui .nb3-l { + margin-bottom: -1rem + } + + .swagger-ui .nb4-l { + margin-bottom: -2rem + } + + .swagger-ui .nb5-l { + margin-bottom: -4rem + } + + .swagger-ui .nb6-l { + margin-bottom: -8rem + } + + .swagger-ui .nb7-l { + margin-bottom: -16rem + } + + .swagger-ui .nt1-l { + margin-top: -.25rem + } + + .swagger-ui .nt2-l { + margin-top: -.5rem + } + + .swagger-ui .nt3-l { + margin-top: -1rem + } + + .swagger-ui .nt4-l { + margin-top: -2rem + } + + .swagger-ui .nt5-l { + margin-top: -4rem + } + + .swagger-ui .nt6-l { + margin-top: -8rem + } + + .swagger-ui .nt7-l { + margin-top: -16rem + } +} + +.swagger-ui .collapse { + border-collapse: collapse; + border-spacing: 0 +} + +.swagger-ui .striped--light-silver:nth-child(odd) { + background-color: #aaa +} + +.swagger-ui .striped--moon-gray:nth-child(odd) { + background-color: #ccc +} + +.swagger-ui .striped--light-gray:nth-child(odd) { + background-color: #eee +} + +.swagger-ui .striped--near-white:nth-child(odd) { + background-color: #f4f4f4 +} + +.swagger-ui .stripe-light:nth-child(odd) { + background-color: hsla(0, 0%, 100%, .1) +} + +.swagger-ui .stripe-dark:nth-child(odd) { + background-color: rgba(0, 0, 0, .1) +} + +.swagger-ui .strike { + text-decoration: line-through +} + +.swagger-ui .underline { + text-decoration: underline +} + +.swagger-ui .no-underline { + text-decoration: none +} + +@media screen and (min-width: 30em) { + .swagger-ui .strike-ns { + text-decoration: line-through + } + + .swagger-ui .underline-ns { + text-decoration: underline + } + + .swagger-ui .no-underline-ns { + text-decoration: none + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .strike-m { + text-decoration: line-through + } + + .swagger-ui .underline-m { + text-decoration: underline + } + + .swagger-ui .no-underline-m { + text-decoration: none + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .strike-l { + text-decoration: line-through + } + + .swagger-ui .underline-l { + text-decoration: underline + } + + .swagger-ui .no-underline-l { + text-decoration: none + } +} + +.swagger-ui .tl { + text-align: left +} + +.swagger-ui .tr { + text-align: right +} + +.swagger-ui .tc { + text-align: center +} + +.swagger-ui .tj { + text-align: justify +} + +@media screen and (min-width: 30em) { + .swagger-ui .tl-ns { + text-align: left + } + + .swagger-ui .tr-ns { + text-align: right + } + + .swagger-ui .tc-ns { + text-align: center + } + + .swagger-ui .tj-ns { + text-align: justify + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .tl-m { + text-align: left + } + + .swagger-ui .tr-m { + text-align: right + } + + .swagger-ui .tc-m { + text-align: center + } + + .swagger-ui .tj-m { + text-align: justify + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .tl-l { + text-align: left + } + + .swagger-ui .tr-l { + text-align: right + } + + .swagger-ui .tc-l { + text-align: center + } + + .swagger-ui .tj-l { + text-align: justify + } +} + +.swagger-ui .ttc { + text-transform: capitalize +} + +.swagger-ui .ttl { + text-transform: lowercase +} + +.swagger-ui .ttu { + text-transform: uppercase +} + +.swagger-ui .ttn { + text-transform: none +} + +@media screen and (min-width: 30em) { + .swagger-ui .ttc-ns { + text-transform: capitalize + } + + .swagger-ui .ttl-ns { + text-transform: lowercase + } + + .swagger-ui .ttu-ns { + text-transform: uppercase + } + + .swagger-ui .ttn-ns { + text-transform: none + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .ttc-m { + text-transform: capitalize + } + + .swagger-ui .ttl-m { + text-transform: lowercase + } + + .swagger-ui .ttu-m { + text-transform: uppercase + } + + .swagger-ui .ttn-m { + text-transform: none + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .ttc-l { + text-transform: capitalize + } + + .swagger-ui .ttl-l { + text-transform: lowercase + } + + .swagger-ui .ttu-l { + text-transform: uppercase + } + + .swagger-ui .ttn-l { + text-transform: none + } +} + +.swagger-ui .f-6, .swagger-ui .f-headline { + font-size: 6rem +} + +.swagger-ui .f-5, .swagger-ui .f-subheadline { + font-size: 5rem +} + +.swagger-ui .f1 { + font-size: 3rem +} + +.swagger-ui .f2 { + font-size: 2.25rem +} + +.swagger-ui .f3 { + font-size: 1.5rem +} + +.swagger-ui .f4 { + font-size: 1.25rem +} + +.swagger-ui .f5 { + font-size: 1rem +} + +.swagger-ui .f6 { + font-size: .875rem +} + +.swagger-ui .f7 { + font-size: .75rem +} + +@media screen and (min-width: 30em) { + .swagger-ui .f-6-ns, .swagger-ui .f-headline-ns { + font-size: 6rem + } + + .swagger-ui .f-5-ns, .swagger-ui .f-subheadline-ns { + font-size: 5rem + } + + .swagger-ui .f1-ns { + font-size: 3rem + } + + .swagger-ui .f2-ns { + font-size: 2.25rem + } + + .swagger-ui .f3-ns { + font-size: 1.5rem + } + + .swagger-ui .f4-ns { + font-size: 1.25rem + } + + .swagger-ui .f5-ns { + font-size: 1rem + } + + .swagger-ui .f6-ns { + font-size: .875rem + } + + .swagger-ui .f7-ns { + font-size: .75rem + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .f-6-m, .swagger-ui .f-headline-m { + font-size: 6rem + } + + .swagger-ui .f-5-m, .swagger-ui .f-subheadline-m { + font-size: 5rem + } + + .swagger-ui .f1-m { + font-size: 3rem + } + + .swagger-ui .f2-m { + font-size: 2.25rem + } + + .swagger-ui .f3-m { + font-size: 1.5rem + } + + .swagger-ui .f4-m { + font-size: 1.25rem + } + + .swagger-ui .f5-m { + font-size: 1rem + } + + .swagger-ui .f6-m { + font-size: .875rem + } + + .swagger-ui .f7-m { + font-size: .75rem + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .f-6-l, .swagger-ui .f-headline-l { + font-size: 6rem + } + + .swagger-ui .f-5-l, .swagger-ui .f-subheadline-l { + font-size: 5rem + } + + .swagger-ui .f1-l { + font-size: 3rem + } + + .swagger-ui .f2-l { + font-size: 2.25rem + } + + .swagger-ui .f3-l { + font-size: 1.5rem + } + + .swagger-ui .f4-l { + font-size: 1.25rem + } + + .swagger-ui .f5-l { + font-size: 1rem + } + + .swagger-ui .f6-l { + font-size: .875rem + } + + .swagger-ui .f7-l { + font-size: .75rem + } +} + +.swagger-ui .measure { + max-width: 30em +} + +.swagger-ui .measure-wide { + max-width: 34em +} + +.swagger-ui .measure-narrow { + max-width: 20em +} + +.swagger-ui .indent { + text-indent: 1em; + margin-top: 0; + margin-bottom: 0 +} + +.swagger-ui .small-caps { + font-variant: small-caps +} + +.swagger-ui .truncate { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis +} + +@media screen and (min-width: 30em) { + .swagger-ui .measure-ns { + max-width: 30em + } + + .swagger-ui .measure-wide-ns { + max-width: 34em + } + + .swagger-ui .measure-narrow-ns { + max-width: 20em + } + + .swagger-ui .indent-ns { + text-indent: 1em; + margin-top: 0; + margin-bottom: 0 + } + + .swagger-ui .small-caps-ns { + font-variant: small-caps + } + + .swagger-ui .truncate-ns { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .measure-m { + max-width: 30em + } + + .swagger-ui .measure-wide-m { + max-width: 34em + } + + .swagger-ui .measure-narrow-m { + max-width: 20em + } + + .swagger-ui .indent-m { + text-indent: 1em; + margin-top: 0; + margin-bottom: 0 + } + + .swagger-ui .small-caps-m { + font-variant: small-caps + } + + .swagger-ui .truncate-m { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .measure-l { + max-width: 30em + } + + .swagger-ui .measure-wide-l { + max-width: 34em + } + + .swagger-ui .measure-narrow-l { + max-width: 20em + } + + .swagger-ui .indent-l { + text-indent: 1em; + margin-top: 0; + margin-bottom: 0 + } + + .swagger-ui .small-caps-l { + font-variant: small-caps + } + + .swagger-ui .truncate-l { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis + } +} + +.swagger-ui .overflow-container { + overflow-y: scroll +} + +.swagger-ui .center { + margin-right: auto; + margin-left: auto +} + +.swagger-ui .mr-auto { + margin-right: auto +} + +.swagger-ui .ml-auto { + margin-left: auto +} + +@media screen and (min-width: 30em) { + .swagger-ui .center-ns { + margin-right: auto; + margin-left: auto + } + + .swagger-ui .mr-auto-ns { + margin-right: auto + } + + .swagger-ui .ml-auto-ns { + margin-left: auto + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .center-m { + margin-right: auto; + margin-left: auto + } + + .swagger-ui .mr-auto-m { + margin-right: auto + } + + .swagger-ui .ml-auto-m { + margin-left: auto + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .center-l { + margin-right: auto; + margin-left: auto + } + + .swagger-ui .mr-auto-l { + margin-right: auto + } + + .swagger-ui .ml-auto-l { + margin-left: auto + } +} + +.swagger-ui .clip { + position: fixed !important; + _position: absolute !important; + clip: rect(1px 1px 1px 1px); + clip: rect(1px, 1px, 1px, 1px) +} + +@media screen and (min-width: 30em) { + .swagger-ui .clip-ns { + position: fixed !important; + _position: absolute !important; + clip: rect(1px 1px 1px 1px); + clip: rect(1px, 1px, 1px, 1px) + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .clip-m { + position: fixed !important; + _position: absolute !important; + clip: rect(1px 1px 1px 1px); + clip: rect(1px, 1px, 1px, 1px) + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .clip-l { + position: fixed !important; + _position: absolute !important; + clip: rect(1px 1px 1px 1px); + clip: rect(1px, 1px, 1px, 1px) + } +} + +.swagger-ui .ws-normal { + white-space: normal +} + +.swagger-ui .nowrap { + white-space: nowrap +} + +.swagger-ui .pre { + white-space: pre +} + +@media screen and (min-width: 30em) { + .swagger-ui .ws-normal-ns { + white-space: normal + } + + .swagger-ui .nowrap-ns { + white-space: nowrap + } + + .swagger-ui .pre-ns { + white-space: pre + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .ws-normal-m { + white-space: normal + } + + .swagger-ui .nowrap-m { + white-space: nowrap + } + + .swagger-ui .pre-m { + white-space: pre + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .ws-normal-l { + white-space: normal + } + + .swagger-ui .nowrap-l { + white-space: nowrap + } + + .swagger-ui .pre-l { + white-space: pre + } +} + +.swagger-ui .v-base { + vertical-align: baseline +} + +.swagger-ui .v-mid { + vertical-align: middle +} + +.swagger-ui .v-top { + vertical-align: top +} + +.swagger-ui .v-btm { + vertical-align: bottom +} + +@media screen and (min-width: 30em) { + .swagger-ui .v-base-ns { + vertical-align: baseline + } + + .swagger-ui .v-mid-ns { + vertical-align: middle + } + + .swagger-ui .v-top-ns { + vertical-align: top + } + + .swagger-ui .v-btm-ns { + vertical-align: bottom + } +} + +@media screen and (min-width: 30em) and (max-width: 60em) { + .swagger-ui .v-base-m { + vertical-align: baseline + } + + .swagger-ui .v-mid-m { + vertical-align: middle + } + + .swagger-ui .v-top-m { + vertical-align: top + } + + .swagger-ui .v-btm-m { + vertical-align: bottom + } +} + +@media screen and (min-width: 60em) { + .swagger-ui .v-base-l { + vertical-align: baseline + } + + .swagger-ui .v-mid-l { + vertical-align: middle + } + + .swagger-ui .v-top-l { + vertical-align: top + } + + .swagger-ui .v-btm-l { + vertical-align: bottom + } +} + +.swagger-ui .dim { + opacity: 1; + transition: opacity .15s ease-in +} + +.swagger-ui .dim:focus, .swagger-ui .dim:hover { + opacity: .5; + transition: opacity .15s ease-in +} + +.swagger-ui .dim:active { + opacity: .8; + transition: opacity .15s ease-out +} + +.swagger-ui .glow { + transition: opacity .15s ease-in +} + +.swagger-ui .glow:focus, .swagger-ui .glow:hover { + opacity: 1; + transition: opacity .15s ease-in +} + +.swagger-ui .hide-child .child { + opacity: 0; + transition: opacity .15s ease-in +} + +.swagger-ui .hide-child:active .child, .swagger-ui .hide-child:focus .child, .swagger-ui .hide-child:hover .child { + opacity: 1; + transition: opacity .15s ease-in +} + +.swagger-ui .underline-hover:focus, .swagger-ui .underline-hover:hover { + text-decoration: underline +} + +.swagger-ui .grow { + -moz-osx-font-smoothing: grayscale; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + transform: translateZ(0); + transition: transform .25s ease-out +} + +.swagger-ui .grow:focus, .swagger-ui .grow:hover { + transform: scale(1.05) +} + +.swagger-ui .grow:active { + transform: scale(.9) +} + +.swagger-ui .grow-large { + -moz-osx-font-smoothing: grayscale; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + transform: translateZ(0); + transition: transform .25s ease-in-out +} + +.swagger-ui .grow-large:focus, .swagger-ui .grow-large:hover { + transform: scale(1.2) +} + +.swagger-ui .grow-large:active { + transform: scale(.95) +} + +.swagger-ui .pointer:hover { + cursor: pointer +} + +.swagger-ui .shadow-hover { + cursor: pointer; + position: relative; + transition: all .5s cubic-bezier(.165, .84, .44, 1) +} + +.swagger-ui .shadow-hover:after { + content: ""; + box-shadow: 0 0 16px 2px rgba(0, 0, 0, .2); + border-radius: inherit; + opacity: 0; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: -1; + transition: opacity .5s cubic-bezier(.165, .84, .44, 1) +} + +.swagger-ui .shadow-hover:focus:after, .swagger-ui .shadow-hover:hover:after { + opacity: 1 +} + +.swagger-ui .bg-animate, .swagger-ui .bg-animate:focus, .swagger-ui .bg-animate:hover { + transition: background-color .15s ease-in-out +} + +.swagger-ui .z-0 { + z-index: 0 +} + +.swagger-ui .z-1 { + z-index: 1 +} + +.swagger-ui .z-2 { + z-index: 2 +} + +.swagger-ui .z-3 { + z-index: 3 +} + +.swagger-ui .z-4 { + z-index: 4 +} + +.swagger-ui .z-5 { + z-index: 5 +} + +.swagger-ui .z-999 { + z-index: 999 +} + +.swagger-ui .z-9999 { + z-index: 9999 +} + +.swagger-ui .z-max { + z-index: 2147483647 +} + +.swagger-ui .z-inherit { + z-index: inherit +} + +.swagger-ui .z-initial { + z-index: auto +} + +.swagger-ui .z-unset { + z-index: unset +} + +.swagger-ui .nested-copy-line-height ol, .swagger-ui .nested-copy-line-height p, .swagger-ui .nested-copy-line-height ul { + line-height: 1.5 +} + +.swagger-ui .nested-headline-line-height h1, .swagger-ui .nested-headline-line-height h2, .swagger-ui .nested-headline-line-height h3, .swagger-ui .nested-headline-line-height h4, .swagger-ui .nested-headline-line-height h5, .swagger-ui .nested-headline-line-height h6 { + line-height: 1.25 +} + +.swagger-ui .nested-list-reset ol, .swagger-ui .nested-list-reset ul { + padding-left: 0; + margin-left: 0; + list-style-type: none +} + +.swagger-ui .nested-copy-indent p + p { + text-indent: .1em; + margin-top: 0; + margin-bottom: 0 +} + +.swagger-ui .nested-copy-seperator p + p { + margin-top: 1.5em +} + +.swagger-ui .nested-img img { + width: 100%; + max-width: 100%; + display: block +} + +.swagger-ui .nested-links a { + color: #357edd; + transition: color .15s ease-in +} + +.swagger-ui .nested-links a:focus, .swagger-ui .nested-links a:hover { + color: #96ccff; + transition: color .15s ease-in +} + +.swagger-ui .wrapper { + width: 100%; + max-width: 1460px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box +} + +.swagger-ui .opblock-tag-section { + display: flex; + flex-direction: column +} + +.swagger-ui .try-out.btn-group { + padding: 0 +} + +.swagger-ui .opblock-tag { + display: flex; + align-items: center; + padding: 10px 20px 10px 10px; + cursor: pointer; + transition: all .2s; + border-bottom: 1px solid rgba(59, 65, 81, .3) +} + +.swagger-ui .opblock-tag:hover { + background: rgba(0, 0, 0, .02) +} + +.swagger-ui .opblock-tag { + font-size: 24px; + margin: 0 0 5px; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .opblock-tag.no-desc span { + flex: 1 +} + +.swagger-ui .opblock-tag svg { + transition: all .4s +} + +.swagger-ui .opblock-tag small { + font-size: 14px; + font-weight: 400; + flex: 1; + padding: 0 10px; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .parameter__type { + font-size: 12px; + padding: 5px 0; + font-family: monospace; + font-weight: 600; + color: #3b4151 +} + +.swagger-ui .parameter-controls { + margin-top: .75em +} + +.swagger-ui .examples__title { + display: block; + font-size: 1.1em; + font-weight: 700; + margin-bottom: .75em +} + +.swagger-ui .examples__section { + margin-top: 1.5em +} + +.swagger-ui .examples__section-header { + font-weight: 700; + font-size: .9rem; + margin-bottom: .5rem +} + +.swagger-ui .examples-select { + margin-bottom: .75em +} + +.swagger-ui .examples-select__section-label { + font-weight: 700; + font-size: .9rem; + margin-right: .5rem +} + +.swagger-ui .example__section { + margin-top: 1.5em +} + +.swagger-ui .example__section-header { + font-weight: 700; + font-size: .9rem; + margin-bottom: .5rem +} + +.swagger-ui .view-line-link { + position: relative; + top: 3px; + width: 20px; + margin: 0 5px; + cursor: pointer; + transition: all .5s +} + +.swagger-ui .opblock { + margin: 0 0 15px; + border: 1px solid #000; + border-radius: 4px; + box-shadow: 0 0 3px rgba(0, 0, 0, .19) +} + +.swagger-ui .opblock .tab-header { + display: flex; + flex: 1 +} + +.swagger-ui .opblock .tab-header .tab-item { + padding: 0 40px; + cursor: pointer +} + +.swagger-ui .opblock .tab-header .tab-item:first-of-type { + padding: 0 40px 0 0 +} + +.swagger-ui .opblock .tab-header .tab-item.active h4 span { + position: relative +} + +.swagger-ui .opblock .tab-header .tab-item.active h4 span:after { + position: absolute; + bottom: -15px; + left: 50%; + width: 120%; + height: 4px; + content: ""; + transform: translateX(-50%); + background: grey +} + +.swagger-ui .opblock.is-open .opblock-summary { + border-bottom: 1px solid #000 +} + +.swagger-ui .opblock .opblock-section-header { + display: flex; + align-items: center; + padding: 8px 20px; + min-height: 50px; + background: hsla(0, 0%, 100%, .8); + box-shadow: 0 1px 2px rgba(0, 0, 0, .1) +} + +.swagger-ui .opblock .opblock-section-header > label { + font-size: 12px; + font-weight: 700; + display: flex; + align-items: center; + margin: 0 0 0 auto; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .opblock .opblock-section-header > label > span { + padding: 0 10px 0 0 +} + +.swagger-ui .opblock .opblock-section-header h4 { + font-size: 14px; + flex: 1; + margin: 0; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .opblock .opblock-summary-method { + font-size: 14px; + font-weight: 700; + min-width: 80px; + padding: 6px 15px; + text-align: center; + border-radius: 3px; + background: #000; + text-shadow: 0 1px 0 rgba(0, 0, 0, .1); + font-family: sans-serif; + color: #fff +} + +.swagger-ui .opblock .opblock-summary-operation-id, .swagger-ui .opblock .opblock-summary-path, .swagger-ui .opblock .opblock-summary-path__deprecated { + font-size: 16px; + display: flex; + align-items: center; + word-break: break-word; + padding: 0 10px; + font-family: monospace; + font-weight: 600; + color: #3b4151 +} + +@media (max-width: 768px) { + .swagger-ui .opblock .opblock-summary-operation-id, .swagger-ui .opblock .opblock-summary-path, .swagger-ui .opblock .opblock-summary-path__deprecated { + font-size: 12px + } +} + +.swagger-ui .opblock .opblock-summary-path { + flex-shrink: 0; + max-width: calc(100% - 110px - 15rem) +} + +.swagger-ui .opblock .opblock-summary-path__deprecated { + text-decoration: line-through +} + +.swagger-ui .opblock .opblock-summary-operation-id { + font-size: 14px +} + +.swagger-ui .opblock .opblock-summary-description { + font-size: 13px; + flex: 1 1 auto; + word-break: break-word; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .opblock .opblock-summary { + display: flex; + align-items: center; + padding: 5px; + cursor: pointer +} + +.swagger-ui .opblock .opblock-summary .view-line-link { + position: relative; + top: 2px; + width: 0; + margin: 0; + cursor: pointer; + transition: all .5s +} + +.swagger-ui .opblock .opblock-summary:hover .view-line-link { + width: 18px; + margin: 0 5px +} + +.swagger-ui .opblock.opblock-post { + border-color: #49cc90; + background: rgba(73, 204, 144, .1) +} + +.swagger-ui .opblock.opblock-post .opblock-summary-method { + background: #49cc90 +} + +.swagger-ui .opblock.opblock-post .opblock-summary { + border-color: #49cc90 +} + +.swagger-ui .opblock.opblock-post .tab-header .tab-item.active h4 span:after { + background: #49cc90 +} + +.swagger-ui .opblock.opblock-put { + border-color: #fca130; + background: rgba(252, 161, 48, .1) +} + +.swagger-ui .opblock.opblock-put .opblock-summary-method { + background: #fca130 +} + +.swagger-ui .opblock.opblock-put .opblock-summary { + border-color: #fca130 +} + +.swagger-ui .opblock.opblock-put .tab-header .tab-item.active h4 span:after { + background: #fca130 +} + +.swagger-ui .opblock.opblock-delete { + border-color: #f93e3e; + background: rgba(249, 62, 62, .1) +} + +.swagger-ui .opblock.opblock-delete .opblock-summary-method { + background: #f93e3e +} + +.swagger-ui .opblock.opblock-delete .opblock-summary { + border-color: #f93e3e +} + +.swagger-ui .opblock.opblock-delete .tab-header .tab-item.active h4 span:after { + background: #f93e3e +} + +.swagger-ui .opblock.opblock-get { + border-color: #61affe; + background: rgba(97, 175, 254, .1) +} + +.swagger-ui .opblock.opblock-get .opblock-summary-method { + background: #61affe +} + +.swagger-ui .opblock.opblock-get .opblock-summary { + border-color: #61affe +} + +.swagger-ui .opblock.opblock-get .tab-header .tab-item.active h4 span:after { + background: #61affe +} + +.swagger-ui .opblock.opblock-patch { + border-color: #50e3c2; + background: rgba(80, 227, 194, .1) +} + +.swagger-ui .opblock.opblock-patch .opblock-summary-method { + background: #50e3c2 +} + +.swagger-ui .opblock.opblock-patch .opblock-summary { + border-color: #50e3c2 +} + +.swagger-ui .opblock.opblock-patch .tab-header .tab-item.active h4 span:after { + background: #50e3c2 +} + +.swagger-ui .opblock.opblock-head { + border-color: #9012fe; + background: rgba(144, 18, 254, .1) +} + +.swagger-ui .opblock.opblock-head .opblock-summary-method { + background: #9012fe +} + +.swagger-ui .opblock.opblock-head .opblock-summary { + border-color: #9012fe +} + +.swagger-ui .opblock.opblock-head .tab-header .tab-item.active h4 span:after { + background: #9012fe +} + +.swagger-ui .opblock.opblock-options { + border-color: #0d5aa7; + background: rgba(13, 90, 167, .1) +} + +.swagger-ui .opblock.opblock-options .opblock-summary-method { + background: #0d5aa7 +} + +.swagger-ui .opblock.opblock-options .opblock-summary { + border-color: #0d5aa7 +} + +.swagger-ui .opblock.opblock-options .tab-header .tab-item.active h4 span:after { + background: #0d5aa7 +} + +.swagger-ui .opblock.opblock-deprecated { + opacity: .6; + border-color: #ebebeb; + background: hsla(0, 0%, 92.2%, .1) +} + +.swagger-ui .opblock.opblock-deprecated .opblock-summary-method { + background: #ebebeb +} + +.swagger-ui .opblock.opblock-deprecated .opblock-summary { + border-color: #ebebeb +} + +.swagger-ui .opblock.opblock-deprecated .tab-header .tab-item.active h4 span:after { + background: #ebebeb +} + +.swagger-ui .opblock .opblock-schemes { + padding: 8px 20px +} + +.swagger-ui .opblock .opblock-schemes .schemes-title { + padding: 0 10px 0 0 +} + +.swagger-ui .filter .operation-filter-input { + width: 100%; + margin: 20px 0; + padding: 10px; + border: 2px solid #d8dde7 +} + +.swagger-ui .download-url-wrapper .failed, .swagger-ui .filter .failed { + color: red +} + +.swagger-ui .download-url-wrapper .loading, .swagger-ui .filter .loading { + color: #aaa +} + +.swagger-ui .model-example { + margin-top: 1em +} + +.swagger-ui .tab { + display: flex; + padding: 0; + list-style: none +} + +.swagger-ui .tab li { + font-size: 12px; + min-width: 60px; + padding: 0; + cursor: pointer; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .tab li:first-of-type { + position: relative; + padding-left: 0; + padding-right: 12px +} + +.swagger-ui .tab li:first-of-type:after { + position: absolute; + top: 0; + right: 6px; + width: 1px; + height: 100%; + content: ""; + background: rgba(0, 0, 0, .2) +} + +.swagger-ui .tab li.active { + font-weight: 700 +} + +.swagger-ui .opblock-description-wrapper, .swagger-ui .opblock-external-docs-wrapper, .swagger-ui .opblock-title_normal { + font-size: 12px; + margin: 0 0 5px; + padding: 15px 20px; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .opblock-description-wrapper h4, .swagger-ui .opblock-external-docs-wrapper h4, .swagger-ui .opblock-title_normal h4 { + font-size: 12px; + margin: 0 0 5px; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .opblock-description-wrapper p, .swagger-ui .opblock-external-docs-wrapper p, .swagger-ui .opblock-title_normal p { + font-size: 14px; + margin: 0; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .opblock-external-docs-wrapper h4 { + padding-left: 0 +} + +.swagger-ui .execute-wrapper { + padding: 20px; + text-align: right +} + +.swagger-ui .execute-wrapper .btn { + width: 100%; + padding: 8px 40px +} + +.swagger-ui .body-param-options { + display: flex; + flex-direction: column +} + +.swagger-ui .body-param-options .body-param-edit { + padding: 10px 0 +} + +.swagger-ui .body-param-options label { + padding: 8px 0 +} + +.swagger-ui .body-param-options label select { + margin: 3px 0 0 +} + +.swagger-ui .responses-inner { + padding: 20px +} + +.swagger-ui .responses-inner h4, .swagger-ui .responses-inner h5 { + font-size: 12px; + margin: 10px 0 5px; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .responses-inner .curl { + white-space: normal +} + +.swagger-ui .response-col_status { + font-size: 14px; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .response-col_status .response-undocumented { + font-size: 11px; + font-family: monospace; + font-weight: 600; + color: #909090 +} + +.swagger-ui .response-col_links { + padding-left: 2em; + max-width: 40em; + font-size: 14px; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .response-col_links .response-undocumented { + font-size: 11px; + font-family: monospace; + font-weight: 600; + color: #909090 +} + +.swagger-ui .response-col_links .operation-link { + margin-bottom: 1.5em +} + +.swagger-ui .response-col_links .operation-link .description { + margin-bottom: .5em +} + +.swagger-ui .opblock-body .opblock-loading-animation { + display: block; + margin: 3em auto +} + +.swagger-ui .opblock-body pre.microlight { + font-size: 12px; + margin: 0; + padding: 10px; + white-space: pre-wrap; + word-wrap: break-word; + word-break: break-all; + word-break: break-word; + -webkit-hyphens: auto; + -ms-hyphens: auto; + hyphens: auto; + border-radius: 4px; + background: #333; + overflow-wrap: break-word; + font-family: monospace; + font-weight: 600; + color: #fff +} + +.swagger-ui .opblock-body pre.microlight .headerline { + display: block +} + +.swagger-ui .highlight-code { + position: relative +} + +.swagger-ui .highlight-code > .microlight { + overflow-y: auto; + max-height: 400px; + min-height: 6em +} + +.swagger-ui .highlight-code > .microlight code { + white-space: pre-wrap !important; + word-break: break-all +} + +.swagger-ui .curl-command { + position: relative +} + +.swagger-ui .download-contents { + position: absolute; + bottom: 10px; + right: 10px; + cursor: pointer; + background: #7d8293; + text-align: center; + padding: 5px; + border-radius: 4px; + font-family: sans-serif; + font-weight: 600; + color: #fff; + font-size: 14px; + height: 30px; + width: 75px +} + +.swagger-ui .scheme-container { + margin: 0 0 20px; + padding: 30px 0; + background: #fff; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .15) +} + +.swagger-ui .scheme-container .schemes { + display: flex; + align-items: flex-end +} + +.swagger-ui .scheme-container .schemes > label { + font-size: 12px; + font-weight: 700; + display: flex; + flex-direction: column; + margin: -20px 15px 0 0; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .scheme-container .schemes > label select { + min-width: 130px; + text-transform: uppercase +} + +.swagger-ui .loading-container { + padding: 40px 0 60px; + margin-top: 1em; + min-height: 1px; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column +} + +.swagger-ui .loading-container .loading { + position: relative +} + +.swagger-ui .loading-container .loading:after { + font-size: 10px; + font-weight: 700; + position: absolute; + top: 50%; + left: 50%; + content: "loading"; + transform: translate(-50%, -50%); + text-transform: uppercase; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .loading-container .loading:before { + position: absolute; + top: 50%; + left: 50%; + display: block; + width: 60px; + height: 60px; + margin: -30px; + content: ""; + -webkit-animation: rotation 1s linear infinite, opacity .5s; + animation: rotation 1s linear infinite, opacity .5s; + opacity: 1; + border: 2px solid rgba(85, 85, 85, .1); + border-top-color: rgba(0, 0, 0, .6); + border-radius: 100%; + -webkit-backface-visibility: hidden; + backface-visibility: hidden +} + +@-webkit-keyframes rotation { + to { + transform: rotate(1turn) + } +} + +@keyframes rotation { + to { + transform: rotate(1turn) + } +} + +.swagger-ui .response-controls { + padding-top: 1em; + display: flex +} + +.swagger-ui .response-control-media-type { + margin-right: 1em +} + +.swagger-ui .response-control-media-type--accept-controller select { + border-color: green +} + +.swagger-ui .response-control-media-type__accept-message { + color: green; + font-size: .7em +} + +.swagger-ui .response-control-examples__title, .swagger-ui .response-control-media-type__title { + display: block; + margin-bottom: .2em; + font-size: .7em +} + +@-webkit-keyframes blinker { + 50% { + opacity: 0 + } +} + +@keyframes blinker { + 50% { + opacity: 0 + } +} + +.swagger-ui .hidden { + display: none +} + +.swagger-ui .no-margin { + height: auto; + border: none; + margin: 0; + padding: 0 +} + +.swagger-ui .float-right { + float: right +} + +.swagger-ui img.full-width { + width: 100% +} + +.swagger-ui .svg-assets { + position: absolute; + width: 0; + height: 0 +} + +.swagger-ui section h3 { + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui a.nostyle { + display: inline +} + +.swagger-ui a.nostyle, .swagger-ui a.nostyle:visited { + text-decoration: inherit; + color: inherit; + cursor: pointer +} + +.swagger-ui .fallback { + padding: 1em; + color: #aaa +} + +.swagger-ui .version-pragma { + height: 100%; + padding: 5em 0 +} + +.swagger-ui .version-pragma__message { + display: flex; + justify-content: center; + height: 100%; + font-size: 1.2em; + text-align: center; + line-height: 1.5em; + padding: 0 .6em +} + +.swagger-ui .version-pragma__message > div { + max-width: 55ch; + flex: 1 +} + +.swagger-ui .version-pragma__message code { + background-color: #dedede; + padding: 4px 4px 2px; + white-space: pre +} + +.swagger-ui .opblock-link { + font-weight: 400 +} + +.swagger-ui .opblock-link.shown { + font-weight: 700 +} + +.swagger-ui span.token-string { + color: #555 +} + +.swagger-ui span.token-not-formatted { + color: #555; + font-weight: 700 +} + +.swagger-ui .btn { + font-size: 14px; + font-weight: 700; + padding: 5px 23px; + transition: all .3s; + border: 2px solid grey; + border-radius: 4px; + background: transparent; + box-shadow: 0 1px 2px rgba(0, 0, 0, .1); + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .btn.btn-sm { + font-size: 12px; + padding: 4px 23px +} + +.swagger-ui .btn[disabled] { + cursor: not-allowed; + opacity: .3 +} + +.swagger-ui .btn:hover { + box-shadow: 0 0 5px rgba(0, 0, 0, .3) +} + +.swagger-ui .btn.cancel { + border-color: #ff6060; + background-color: transparent; + font-family: sans-serif; + color: #ff6060 +} + +.swagger-ui .btn.authorize { + line-height: 1; + display: inline; + color: #49cc90; + border-color: #49cc90; + background-color: transparent +} + +.swagger-ui .btn.authorize span { + float: left; + padding: 4px 20px 0 0 +} + +.swagger-ui .btn.authorize svg { + fill: #49cc90 +} + +.swagger-ui .btn.execute { + background-color: #4990e2; + color: #fff; + border-color: #4990e2 +} + +.swagger-ui .btn-group { + display: flex; + padding: 30px +} + +.swagger-ui .btn-group .btn { + flex: 1 +} + +.swagger-ui .btn-group .btn:first-child { + border-radius: 4px 0 0 4px +} + +.swagger-ui .btn-group .btn:last-child { + border-radius: 0 4px 4px 0 +} + +.swagger-ui .authorization__btn { + padding: 0 10px; + border: none; + background: none +} + +.swagger-ui .authorization__btn.locked { + opacity: 1 +} + +.swagger-ui .authorization__btn.unlocked { + opacity: .4 +} + +.swagger-ui .expand-methods, .swagger-ui .expand-operation { + border: none; + background: none +} + +.swagger-ui .expand-methods svg, .swagger-ui .expand-operation svg { + width: 20px; + height: 20px +} + +.swagger-ui .expand-methods { + padding: 0 10px +} + +.swagger-ui .expand-methods:hover svg { + fill: #404040 +} + +.swagger-ui .expand-methods svg { + transition: all .3s; + fill: #707070 +} + +.swagger-ui button { + cursor: pointer; + outline: none +} + +.swagger-ui button.invalid { + -webkit-animation: shake .4s 1; + animation: shake .4s 1; + border-color: #f93e3e; + background: #feebeb +} + +.swagger-ui .copy-to-clipboard { + position: absolute; + bottom: 10px; + right: 100px; + width: 30px; + height: 30px; + background: #7d8293; + border-radius: 4px; + border: none +} + +.swagger-ui .copy-to-clipboard button { + padding-left: 25px; + border: none; + height: 25px; + background: url('data:image/svg+xml;charset=utf-8,') 50% no-repeat +} + +.swagger-ui .curl-command .copy-to-clipboard { + bottom: 5px; + right: 10px; + width: 20px; + height: 20px +} + +.swagger-ui .curl-command .copy-to-clipboard button { + padding-left: 18px; + height: 18px +} + +.swagger-ui select { + font-size: 14px; + font-weight: 700; + padding: 5px 40px 5px 10px; + border: 2px solid #41444e; + border-radius: 4px; + background: #f7f7f7 url('data:image/svg+xml;charset=utf-8,') right 10px center no-repeat; + background-size: 20px; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .25); + font-family: sans-serif; + color: #3b4151; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none +} + +.swagger-ui select[multiple] { + margin: 5px 0; + padding: 5px; + background: #f7f7f7 +} + +.swagger-ui select.invalid { + -webkit-animation: shake .4s 1; + animation: shake .4s 1; + border-color: #f93e3e; + background: #feebeb +} + +.swagger-ui .opblock-body select { + min-width: 230px +} + +@media (max-width: 768px) { + .swagger-ui .opblock-body select { + min-width: 180px + } +} + +.swagger-ui label { + font-size: 12px; + font-weight: 700; + margin: 0 0 5px; + font-family: sans-serif; + color: #3b4151 +} + +@media (max-width: 768px) { + .swagger-ui input[type=email], .swagger-ui input[type=file], .swagger-ui input[type=password], .swagger-ui input[type=search], .swagger-ui input[type=text] { + max-width: 175px + } +} + +.swagger-ui input[type=email], .swagger-ui input[type=file], .swagger-ui input[type=password], .swagger-ui input[type=search], .swagger-ui input[type=text], .swagger-ui textarea { + min-width: 100px; + margin: 5px 0; + padding: 8px 10px; + border: 1px solid #d9d9d9; + border-radius: 4px; + background: #fff +} + +.swagger-ui input[type=email].invalid, .swagger-ui input[type=file].invalid, .swagger-ui input[type=password].invalid, .swagger-ui input[type=search].invalid, .swagger-ui input[type=text].invalid, .swagger-ui textarea.invalid { + -webkit-animation: shake .4s 1; + animation: shake .4s 1; + border-color: #f93e3e; + background: #feebeb +} + +.swagger-ui input[disabled], .swagger-ui select[disabled], .swagger-ui textarea[disabled] { + background-color: #fafafa; + color: #888; + cursor: not-allowed +} + +.swagger-ui select[disabled] { + border-color: #888 +} + +.swagger-ui textarea[disabled] { + background-color: #41444e; + color: #fff +} + +@-webkit-keyframes shake { + 10%, 90% { + transform: translate3d(-1px, 0, 0) + } + 20%, 80% { + transform: translate3d(2px, 0, 0) + } + 30%, 50%, 70% { + transform: translate3d(-4px, 0, 0) + } + 40%, 60% { + transform: translate3d(4px, 0, 0) + } +} + +@keyframes shake { + 10%, 90% { + transform: translate3d(-1px, 0, 0) + } + 20%, 80% { + transform: translate3d(2px, 0, 0) + } + 30%, 50%, 70% { + transform: translate3d(-4px, 0, 0) + } + 40%, 60% { + transform: translate3d(4px, 0, 0) + } +} + +.swagger-ui textarea { + font-size: 12px; + width: 100%; + min-height: 280px; + padding: 10px; + border: none; + border-radius: 4px; + outline: none; + background: hsla(0, 0%, 100%, .8); + font-family: monospace; + font-weight: 600; + color: #3b4151 +} + +.swagger-ui textarea:focus { + border: 2px solid #61affe +} + +.swagger-ui textarea.curl { + font-size: 12px; + min-height: 100px; + margin: 0; + padding: 10px; + resize: none; + border-radius: 4px; + background: #41444e; + font-family: monospace; + font-weight: 600; + color: #fff +} + +.swagger-ui .checkbox { + padding: 5px 0 10px; + transition: opacity .5s; + color: #303030 +} + +.swagger-ui .checkbox label { + display: flex +} + +.swagger-ui .checkbox p { + font-weight: 400 !important; + font-style: italic; + margin: 0 !important; + font-family: monospace; + font-weight: 600; + color: #3b4151 +} + +.swagger-ui .checkbox input[type=checkbox] { + display: none +} + +.swagger-ui .checkbox input[type=checkbox] + label > .item { + position: relative; + top: 3px; + display: inline-block; + width: 16px; + height: 16px; + margin: 0 8px 0 0; + padding: 5px; + cursor: pointer; + border-radius: 1px; + background: #e8e8e8; + box-shadow: 0 0 0 2px #e8e8e8; + flex: none +} + +.swagger-ui .checkbox input[type=checkbox] + label > .item:active { + transform: scale(.9) +} + +.swagger-ui .checkbox input[type=checkbox]:checked + label > .item { + background: #e8e8e8 url('data:image/svg+xml;charset=utf-8,') 50% no-repeat +} + +.swagger-ui .dialog-ux { + position: fixed; + z-index: 9999; + top: 0; + right: 0; + bottom: 0; + left: 0 +} + +.swagger-ui .dialog-ux .backdrop-ux { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: rgba(0, 0, 0, .8) +} + +.swagger-ui .dialog-ux .modal-ux { + position: absolute; + z-index: 9999; + top: 50%; + left: 50%; + width: 100%; + min-width: 300px; + max-width: 650px; + transform: translate(-50%, -50%); + border: 1px solid #ebebeb; + border-radius: 4px; + background: #fff; + box-shadow: 0 10px 30px 0 rgba(0, 0, 0, .2) +} + +.swagger-ui .dialog-ux .modal-ux-content { + overflow-y: auto; + max-height: 540px; + padding: 20px +} + +.swagger-ui .dialog-ux .modal-ux-content p { + font-size: 12px; + margin: 0 0 5px; + color: #41444e; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .dialog-ux .modal-ux-content h4 { + font-size: 18px; + font-weight: 600; + margin: 15px 0 0; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .dialog-ux .modal-ux-header { + display: flex; + padding: 12px 0; + border-bottom: 1px solid #ebebeb; + align-items: center +} + +.swagger-ui .dialog-ux .modal-ux-header .close-modal { + padding: 0 10px; + border: none; + background: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none +} + +.swagger-ui .dialog-ux .modal-ux-header h3 { + font-size: 20px; + font-weight: 600; + margin: 0; + padding: 0 20px; + flex: 1; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .model { + font-size: 12px; + font-weight: 300; + font-family: monospace; + font-weight: 600; + color: #3b4151 +} + +.swagger-ui .model .deprecated span, .swagger-ui .model .deprecated td { + color: #a0a0a0 !important +} + +.swagger-ui .model .deprecated > td:first-of-type { + text-decoration: line-through +} + +.swagger-ui .model-toggle { + font-size: 10px; + position: relative; + top: 6px; + display: inline-block; + margin: auto .3em; + cursor: pointer; + transition: transform .15s ease-in; + transform: rotate(90deg); + transform-origin: 50% 50% +} + +.swagger-ui .model-toggle.collapsed { + transform: rotate(0deg) +} + +.swagger-ui .model-toggle:after { + display: block; + width: 20px; + height: 20px; + content: ""; + background: url('data:image/svg+xml;charset=utf-8,') 50% no-repeat; + background-size: 100% +} + +.swagger-ui .model-jump-to-path { + position: relative; + cursor: pointer +} + +.swagger-ui .model-jump-to-path .view-line-link { + position: absolute; + top: -.4em; + cursor: pointer +} + +.swagger-ui .model-title { + position: relative +} + +.swagger-ui .model-title:hover .model-hint { + visibility: visible +} + +.swagger-ui .model-hint { + position: absolute; + top: -1.8em; + visibility: hidden; + padding: .1em .5em; + white-space: nowrap; + color: #ebebeb; + border-radius: 4px; + background: rgba(0, 0, 0, .7) +} + +.swagger-ui .model p { + margin: 0 0 1em +} + +.swagger-ui .model .property { + color: #999; + font-style: italic +} + +.swagger-ui .model .property.primitive { + color: #6b6b6b +} + +.swagger-ui table.model tr.description { + color: #666; + font-weight: 400 +} + +.swagger-ui table.model tr.description td:first-child { + font-weight: 700 +} + +.swagger-ui table.model tr.property-row.required td:first-child { + font-weight: 700 +} + +.swagger-ui table.model tr.property-row td { + vertical-align: top +} + +.swagger-ui table.model tr.property-row td:first-child { + padding-right: .2em +} + +.swagger-ui table.model tr.property-row .star { + color: red +} + +.swagger-ui table.model tr.extension { + color: #777 +} + +.swagger-ui table.model tr.extension td:last-child { + vertical-align: top +} + +.swagger-ui section.models { + margin: 30px 0; + border: 1px solid rgba(59, 65, 81, .3); + border-radius: 4px +} + +.swagger-ui section.models .pointer { + cursor: pointer +} + +.swagger-ui section.models.is-open { + padding: 0 0 20px +} + +.swagger-ui section.models.is-open h4 { + margin: 0 0 5px; + border-bottom: 1px solid rgba(59, 65, 81, .3) +} + +.swagger-ui section.models h4 { + font-size: 16px; + display: flex; + align-items: center; + margin: 0; + padding: 10px 20px 10px 10px; + cursor: pointer; + transition: all .2s; + font-family: sans-serif; + color: #606060 +} + +.swagger-ui section.models h4 svg { + transition: all .4s +} + +.swagger-ui section.models h4 span { + flex: 1 +} + +.swagger-ui section.models h4:hover { + background: rgba(0, 0, 0, .02) +} + +.swagger-ui section.models h5 { + font-size: 16px; + margin: 0 0 10px; + font-family: sans-serif; + color: #707070 +} + +.swagger-ui section.models .model-jump-to-path { + position: relative; + top: 5px +} + +.swagger-ui section.models .model-container { + margin: 0 20px 15px; + position: relative; + transition: all .5s; + border-radius: 4px; + background: rgba(0, 0, 0, .05) +} + +.swagger-ui section.models .model-container:hover { + background: rgba(0, 0, 0, .07) +} + +.swagger-ui section.models .model-container:first-of-type { + margin: 20px +} + +.swagger-ui section.models .model-container:last-of-type { + margin: 0 20px +} + +.swagger-ui section.models .model-container .models-jump-to-path { + position: absolute; + top: 8px; + right: 5px; + opacity: .65 +} + +.swagger-ui section.models .model-box { + background: none +} + +.swagger-ui .model-box { + padding: 10px; + display: inline-block; + border-radius: 4px; + background: rgba(0, 0, 0, .1) +} + +.swagger-ui .model-box .model-jump-to-path { + position: relative; + top: 4px +} + +.swagger-ui .model-box.deprecated { + opacity: .5 +} + +.swagger-ui .model-title { + font-size: 16px; + font-family: sans-serif; + color: #505050 +} + +.swagger-ui .model-title img { + margin-left: 1em; + position: relative; + bottom: 0 +} + +.swagger-ui .model-deprecated-warning { + font-size: 16px; + font-weight: 600; + margin-right: 1em; + font-family: sans-serif; + color: #f93e3e +} + +.swagger-ui span > span.model .brace-close { + padding: 0 0 0 10px +} + +.swagger-ui .prop-name { + display: inline-block; + margin-right: 1em +} + +.swagger-ui .prop-type { + color: #55a +} + +.swagger-ui .prop-enum { + display: block +} + +.swagger-ui .prop-format { + color: #606060 +} + +.swagger-ui .servers > label { + font-size: 12px; + margin: -20px 15px 0 0; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .servers > label select { + min-width: 130px; + max-width: 100% +} + +.swagger-ui .servers h4.message { + padding-bottom: 2em +} + +.swagger-ui .servers table tr { + width: 30em +} + +.swagger-ui .servers table td { + display: inline-block; + max-width: 15em; + vertical-align: middle; + padding-top: 10px; + padding-bottom: 10px +} + +.swagger-ui .servers table td:first-of-type { + padding-right: 1em +} + +.swagger-ui .servers table td input { + width: 100%; + height: 100% +} + +.swagger-ui .servers .computed-url { + margin: 2em 0 +} + +.swagger-ui .servers .computed-url code { + display: inline-block; + padding: 4px; + font-size: 16px; + margin: 0 1em +} + +.swagger-ui .servers-title { + font-size: 12px; + font-weight: 700 +} + +.swagger-ui .operation-servers h4.message { + margin-bottom: 2em +} + +.swagger-ui table { + width: 100%; + padding: 0 10px; + border-collapse: collapse +} + +.swagger-ui table.model tbody tr td { + padding: 0; + vertical-align: top +} + +.swagger-ui table.model tbody tr td:first-of-type { + width: 174px; + padding: 0 0 0 2em +} + +.swagger-ui table.headers td { + font-size: 12px; + font-weight: 300; + vertical-align: middle; + font-family: monospace; + font-weight: 600; + color: #3b4151 +} + +.swagger-ui table.headers .header-example { + color: #999; + font-style: italic +} + +.swagger-ui table tbody tr td { + padding: 10px 0 0; + vertical-align: top +} + +.swagger-ui table tbody tr td:first-of-type { + min-width: 6em; + padding: 10px 0 +} + +.swagger-ui table thead tr td, .swagger-ui table thead tr th { + font-size: 12px; + font-weight: 700; + padding: 12px 0; + text-align: left; + border-bottom: 1px solid rgba(59, 65, 81, .2); + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .parameters-col_description { + width: 99%; + margin-bottom: 2em +} + +.swagger-ui .parameters-col_description input[type=text] { + width: 100%; + max-width: 340px +} + +.swagger-ui .parameters-col_description select { + border-width: 1px +} + +.swagger-ui .parameter__name { + font-size: 16px; + font-weight: 400; + margin-right: .75em; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .parameter__name.required { + font-weight: 700 +} + +.swagger-ui .parameter__name.required span { + color: red +} + +.swagger-ui .parameter__name.required:after { + font-size: 10px; + position: relative; + top: -6px; + padding: 5px; + content: "required"; + color: rgba(255, 0, 0, .6) +} + +.swagger-ui .parameter__extension, .swagger-ui .parameter__in { + font-size: 12px; + font-style: italic; + font-family: monospace; + font-weight: 600; + color: grey +} + +.swagger-ui .parameter__deprecated { + font-size: 12px; + font-style: italic; + font-family: monospace; + font-weight: 600; + color: red +} + +.swagger-ui .parameter__empty_value_toggle { + display: block; + font-size: 13px; + padding-top: 5px; + padding-bottom: 12px +} + +.swagger-ui .parameter__empty_value_toggle input { + margin-right: 7px +} + +.swagger-ui .parameter__empty_value_toggle.disabled { + opacity: .7 +} + +.swagger-ui .table-container { + padding: 20px +} + +.swagger-ui .response-col_description { + width: 99% +} + +.swagger-ui .response-col_links { + min-width: 6em +} + +.swagger-ui .response__extension { + font-size: 12px; + font-style: italic; + font-family: monospace; + font-weight: 600; + color: grey +} + +.swagger-ui .topbar { + padding: 10px 0; + background-color: #1b1b1b +} + +.swagger-ui .topbar .topbar-wrapper, .swagger-ui .topbar a { + display: flex; + align-items: center +} + +.swagger-ui .topbar a { + font-size: 1.5em; + font-weight: 700; + flex: 1; + max-width: 300px; + text-decoration: none; + font-family: sans-serif; + color: #fff +} + +.swagger-ui .topbar a span { + margin: 0; + padding: 0 10px +} + +.swagger-ui .topbar .download-url-wrapper { + display: flex; + flex: 3; + justify-content: flex-end +} + +.swagger-ui .topbar .download-url-wrapper input[type=text] { + width: 100%; + margin: 0; + border: 2px solid #62a03f; + border-radius: 4px 0 0 4px; + outline: none +} + +.swagger-ui .topbar .download-url-wrapper .select-label { + display: flex; + align-items: center; + width: 100%; + max-width: 600px; + margin: 0; + color: #f0f0f0 +} + +.swagger-ui .topbar .download-url-wrapper .select-label span { + font-size: 16px; + flex: 1; + padding: 0 10px 0 0; + text-align: right +} + +.swagger-ui .topbar .download-url-wrapper .select-label select { + flex: 2; + width: 100%; + border: 2px solid #62a03f; + outline: none; + box-shadow: none +} + +.swagger-ui .topbar .download-url-wrapper .download-url-button { + font-size: 16px; + font-weight: 700; + padding: 4px 30px; + border: none; + border-radius: 0 4px 4px 0; + background: #62a03f; + font-family: sans-serif; + color: #fff +} + +.swagger-ui .info { + margin: 50px 0 +} + +.swagger-ui .info.failed-config { + max-width: 880px; + margin-left: auto; + margin-right: auto; + text-align: center +} + +.swagger-ui .info hgroup.main { + margin: 0 0 20px +} + +.swagger-ui .info hgroup.main a { + font-size: 12px +} + +.swagger-ui .info pre { + font-size: 14px +} + +.swagger-ui .info li, .swagger-ui .info p, .swagger-ui .info table { + font-size: 14px; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .info h1, .swagger-ui .info h2, .swagger-ui .info h3, .swagger-ui .info h4, .swagger-ui .info h5 { + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .info a { + font-size: 14px; + transition: all .4s; + font-family: sans-serif; + color: #4990e2 +} + +.swagger-ui .info a:hover { + color: #1f69c0 +} + +.swagger-ui .info > div { + margin: 0 0 5px +} + +.swagger-ui .info .base-url { + font-size: 12px; + font-weight: 300 !important; + margin: 0; + font-family: monospace; + font-weight: 600; + color: #3b4151 +} + +.swagger-ui .info .title { + font-size: 36px; + margin: 0; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .info .title small { + font-size: 10px; + position: relative; + top: -5px; + display: inline-block; + margin: 0 0 0 5px; + padding: 2px 4px; + vertical-align: super; + border-radius: 57px; + background: #7d8492 +} + +.swagger-ui .info .title small.version-stamp { + background-color: #89bf04 +} + +.swagger-ui .info .title small pre { + margin: 0; + padding: 0; + font-family: sans-serif; + color: #fff +} + +.swagger-ui .auth-btn-wrapper { + display: flex; + padding: 10px 0; + justify-content: center +} + +.swagger-ui .auth-btn-wrapper .btn-done { + margin-right: 1em +} + +.swagger-ui .auth-wrapper { + display: flex; + flex: 1; + justify-content: flex-end +} + +.swagger-ui .auth-wrapper .authorize { + padding-right: 20px; + margin-right: 10px +} + +.swagger-ui .auth-container { + margin: 0 0 10px; + padding: 10px 20px; + border-bottom: 1px solid #ebebeb +} + +.swagger-ui .auth-container:last-of-type { + margin: 0; + padding: 10px 20px; + border: 0 +} + +.swagger-ui .auth-container h4 { + margin: 5px 0 15px !important +} + +.swagger-ui .auth-container .wrapper { + margin: 0; + padding: 0 +} + +.swagger-ui .auth-container input[type=password], .swagger-ui .auth-container input[type=text] { + min-width: 230px +} + +.swagger-ui .auth-container .errors { + font-size: 12px; + padding: 10px; + border-radius: 4px; + background-color: #fee; + color: red; + margin: 1em; + font-family: monospace; + font-weight: 600; + color: #3b4151 +} + +.swagger-ui .auth-container .errors b { + text-transform: capitalize; + margin-right: 1em +} + +.swagger-ui .scopes h2 { + font-size: 14px; + font-family: sans-serif; + color: #3b4151 +} + +.swagger-ui .scopes h2 a { + font-size: 12px; + color: #4990e2; + cursor: pointer; + padding-left: 10px; + text-decoration: underline +} + +.swagger-ui .scope-def { + padding: 0 0 20px +} + +.swagger-ui .errors-wrapper { + margin: 20px; + padding: 10px 20px; + -webkit-animation: scaleUp .5s; + animation: scaleUp .5s; + border: 2px solid #f93e3e; + border-radius: 4px; + background: rgba(249, 62, 62, .1) +} + +.swagger-ui .errors-wrapper .error-wrapper { + margin: 0 0 10px +} + +.swagger-ui .errors-wrapper .errors h4 { + font-size: 14px; + margin: 0; + font-family: monospace; + font-weight: 600; + color: #3b4151 +} + +.swagger-ui .errors-wrapper .errors small { + color: #606060 +} + +.swagger-ui .errors-wrapper .errors .message { + white-space: pre-line +} + +.swagger-ui .errors-wrapper .errors .message.thrown { + max-width: 100% +} + +.swagger-ui .errors-wrapper .errors .error-line { + text-decoration: underline; + cursor: pointer +} + +.swagger-ui .errors-wrapper hgroup { + display: flex; + align-items: center +} + +.swagger-ui .errors-wrapper hgroup h4 { + font-size: 20px; + margin: 0; + flex: 1; + font-family: sans-serif; + color: #3b4151 +} + +@-webkit-keyframes scaleUp { + 0% { + transform: scale(.8); + opacity: 0 + } + to { + transform: scale(1); + opacity: 1 + } +} + +@keyframes scaleUp { + 0% { + transform: scale(.8); + opacity: 0 + } + to { + transform: scale(1); + opacity: 1 + } +} + +.swagger-ui .Resizer.vertical.disabled { + display: none +} + +.swagger-ui .markdown p, .swagger-ui .markdown pre, .swagger-ui .renderedMarkdown p, .swagger-ui .renderedMarkdown pre { + margin: 1em auto; + word-break: break-all; + word-break: break-word +} + +.swagger-ui .markdown pre, .swagger-ui .renderedMarkdown pre { + color: #000; + font-weight: 400; + white-space: pre-wrap; + background: none; + padding: 0 +} + +.swagger-ui .markdown code, .swagger-ui .renderedMarkdown code { + font-size: 14px; + padding: 5px 7px; + border-radius: 4px; + background: rgba(0, 0, 0, .05); + font-family: monospace; + font-weight: 600; + color: #9012fe +} + +.swagger-ui .markdown pre > code, .swagger-ui .renderedMarkdown pre > code { + display: block +} + +/*# sourceMappingURL=swagger-ui.css.map*/ \ No newline at end of file diff --git a/server/public/developers/data/api.json b/server/public/developers/data/api.json new file mode 100644 index 000000000..af9e460ff --- /dev/null +++ b/server/public/developers/data/api.json @@ -0,0 +1,136 @@ +{ + "swagger": "2.0", + "info": { + "version": "4.2.1", + "title": "Anyplace" + }, + "host": "ap-dev.cs.ucy.ac.cy:9003", + "schemes": [ + "http", + "https" + ], + "paths": { + "/user/register": { + "post": { + "tags": [ + "Account" + ], + "summary": "Adds a new user", + "description": "Registers a local user.\n\n\nOne could use an external account (Google) to use the service.\nFor those see endpoint XXX.", + "operationId": "userRegister", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "Body", + "description": "Name and Surname", + "required": true, + "schema": { + "$ref": "#/definitions/User" + } + } + ], + "responses": { + "200": { + "description": "Successful operation" + }, + "405": { + "description": "Invalid input" + } + } + } + }, + "/user/login": { + "post": { + "tags": [ + "Account" + ], + "summary": "Login a local user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "Successful operation" + }, + "405": { + "description": "Invalid input" + } + } + } + }, + "/api/version": { + "get": { + "tags": [ + "Misc" + ], + "summary": "Returns the back-end's version", + "description": "", + "operationId": "miscVersion", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "Successful operation", + "schema": { + "$ref": "#/definitions/Version" + } + } + } + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "access_token", + "in": "header" + } + }, + "definitions": { + "Version": { + "type": "object", + "properties": { + "version": { + "type": "string", + "example": "1.0.0" + }, + "variant": { + "type": "string", + "description": "Values: alpha, or beta, or empty.", + "example": "alpha" + } + } + }, + "User": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "Alan Turing" + }, + "email": { + "type": "string", + "example": "my_email@gmail.com" + }, + "username": { + "type": "string", + "example": "username" + }, + "password": { + "type": "string", + "example": "password" + } + } + } + } +} \ No newline at end of file diff --git a/server/public/anyplace_developers/images/anyplace_logo_text_white3_4.png b/server/public/developers/images/anyplace_logo_text_white3_4.png similarity index 100% rename from server/public/anyplace_developers/images/anyplace_logo_text_white3_4.png rename to server/public/developers/images/anyplace_logo_text_white3_4.png diff --git a/server/public/developers/index.html b/server/public/developers/index.html new file mode 100644 index 000000000..83ebde67f --- /dev/null +++ b/server/public/developers/index.html @@ -0,0 +1,64 @@ + + + + + + Anyplace API + + + + + + +
+ + + +DMSL Copyright 2021
+ + + diff --git a/server/public/developers/js/swagger-ui-bundle.js b/server/public/developers/js/swagger-ui-bundle.js new file mode 100644 index 000000000..4baf2a490 --- /dev/null +++ b/server/public/developers/js/swagger-ui-bundle.js @@ -0,0 +1,36482 @@ +/*! For license information please see swagger-ui-bundle.js.LICENSE.txt */ +!function (e, t) { + "object" == typeof exports && "object" == typeof module ? module.exports = t(function () { + try { + return require("esprima") + } catch (e) { + } + }()) : "function" == typeof define && define.amd ? define(["esprima"], t) : "object" == typeof exports ? exports.SwaggerUIBundle = t(function () { + try { + return require("esprima") + } catch (e) { + } + }()) : e.SwaggerUIBundle = t(e.esprima) +}(this, (function (e) { + return function (e) { + var t = {}; + + function n(r) { + if (t[r]) return t[r].exports; + var o = t[r] = {i: r, l: !1, exports: {}}; + return e[r].call(o.exports, o, o.exports, n), o.l = !0, o.exports + } + + return n.m = e, n.c = t, n.d = function (e, t, r) { + n.o(e, t) || Object.defineProperty(e, t, {enumerable: !0, get: r}) + }, n.r = function (e) { + "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {value: "Module"}), Object.defineProperty(e, "__esModule", {value: !0}) + }, n.t = function (e, t) { + if (1 & t && (e = n(e)), 8 & t) return e; + if (4 & t && "object" == typeof e && e && e.__esModule) return e; + var r = Object.create(null); + if (n.r(r), Object.defineProperty(r, "default", { + enumerable: !0, + value: e + }), 2 & t && "string" != typeof e) for (var o in e) n.d(r, o, function (t) { + return e[t] + }.bind(null, o)); + return r + }, n.n = function (e) { + var t = e && e.__esModule ? function () { + return e.default + } : function () { + return e + }; + return n.d(t, "a", t), t + }, n.o = function (e, t) { + return Object.prototype.hasOwnProperty.call(e, t) + }, n.p = "/dist", n(n.s = 548) + }([function (e, t, n) { + "use strict"; + e.exports = n(129) + }, function (e, t, n) { + e.exports = function () { + "use strict"; + var e = Array.prototype.slice; + + function t(e, t) { + t && (e.prototype = Object.create(t.prototype)), e.prototype.constructor = e + } + + function n(e) { + return i(e) ? e : $(e) + } + + function r(e) { + return s(e) ? e : K(e) + } + + function o(e) { + return u(e) ? e : Y(e) + } + + function a(e) { + return i(e) && !c(e) ? e : G(e) + } + + function i(e) { + return !(!e || !e[p]) + } + + function s(e) { + return !(!e || !e[f]) + } + + function u(e) { + return !(!e || !e[h]) + } + + function c(e) { + return s(e) || u(e) + } + + function l(e) { + return !(!e || !e[d]) + } + + t(r, n), t(o, n), t(a, n), n.isIterable = i, n.isKeyed = s, n.isIndexed = u, n.isAssociative = c, n.isOrdered = l, n.Keyed = r, n.Indexed = o, n.Set = a; + var p = "@@__IMMUTABLE_ITERABLE__@@", f = "@@__IMMUTABLE_KEYED__@@", h = "@@__IMMUTABLE_INDEXED__@@", + d = "@@__IMMUTABLE_ORDERED__@@", m = "delete", v = 5, g = 1 << v, y = g - 1, b = {}, _ = {value: !1}, + w = {value: !1}; + + function x(e) { + return e.value = !1, e + } + + function E(e) { + e && (e.value = !0) + } + + function S() { + } + + function C(e, t) { + t = t || 0; + for (var n = Math.max(0, e.length - t), r = new Array(n), o = 0; o < n; o++) r[o] = e[o + t]; + return r + } + + function A(e) { + return void 0 === e.size && (e.size = e.__iterate(O)), e.size + } + + function k(e, t) { + if ("number" != typeof t) { + var n = t >>> 0; + if ("" + n !== t || 4294967295 === n) return NaN; + t = n + } + return t < 0 ? A(e) + t : t + } + + function O() { + return !0 + } + + function j(e, t, n) { + return (0 === e || void 0 !== n && e <= -n) && (void 0 === t || void 0 !== n && t >= n) + } + + function T(e, t) { + return P(e, t, 0) + } + + function I(e, t) { + return P(e, t, t) + } + + function P(e, t, n) { + return void 0 === e ? n : e < 0 ? Math.max(0, t + e) : void 0 === t ? e : Math.min(t, e) + } + + var N = 0, M = 1, R = 2, D = "function" == typeof Symbol && Symbol.iterator, L = "@@iterator", B = D || L; + + function F(e) { + this.next = e + } + + function U(e, t, n, r) { + var o = 0 === e ? t : 1 === e ? n : [t, n]; + return r ? r.value = o : r = {value: o, done: !1}, r + } + + function q() { + return {value: void 0, done: !0} + } + + function z(e) { + return !!H(e) + } + + function V(e) { + return e && "function" == typeof e.next + } + + function W(e) { + var t = H(e); + return t && t.call(e) + } + + function H(e) { + var t = e && (D && e[D] || e[L]); + if ("function" == typeof t) return t + } + + function J(e) { + return e && "number" == typeof e.length + } + + function $(e) { + return null == e ? ie() : i(e) ? e.toSeq() : ce(e) + } + + function K(e) { + return null == e ? ie().toKeyedSeq() : i(e) ? s(e) ? e.toSeq() : e.fromEntrySeq() : se(e) + } + + function Y(e) { + return null == e ? ie() : i(e) ? s(e) ? e.entrySeq() : e.toIndexedSeq() : ue(e) + } + + function G(e) { + return (null == e ? ie() : i(e) ? s(e) ? e.entrySeq() : e : ue(e)).toSetSeq() + } + + F.prototype.toString = function () { + return "[Iterator]" + }, F.KEYS = N, F.VALUES = M, F.ENTRIES = R, F.prototype.inspect = F.prototype.toSource = function () { + return this.toString() + }, F.prototype[B] = function () { + return this + }, t($, n), $.of = function () { + return $(arguments) + }, $.prototype.toSeq = function () { + return this + }, $.prototype.toString = function () { + return this.__toString("Seq {", "}") + }, $.prototype.cacheResult = function () { + return !this._cache && this.__iterateUncached && (this._cache = this.entrySeq().toArray(), this.size = this._cache.length), this + }, $.prototype.__iterate = function (e, t) { + return pe(this, e, t, !0) + }, $.prototype.__iterator = function (e, t) { + return fe(this, e, t, !0) + }, t(K, $), K.prototype.toKeyedSeq = function () { + return this + }, t(Y, $), Y.of = function () { + return Y(arguments) + }, Y.prototype.toIndexedSeq = function () { + return this + }, Y.prototype.toString = function () { + return this.__toString("Seq [", "]") + }, Y.prototype.__iterate = function (e, t) { + return pe(this, e, t, !1) + }, Y.prototype.__iterator = function (e, t) { + return fe(this, e, t, !1) + }, t(G, $), G.of = function () { + return G(arguments) + }, G.prototype.toSetSeq = function () { + return this + }, $.isSeq = ae, $.Keyed = K, $.Set = G, $.Indexed = Y; + var Z, X, Q, ee = "@@__IMMUTABLE_SEQ__@@"; + + function te(e) { + this._array = e, this.size = e.length + } + + function ne(e) { + var t = Object.keys(e); + this._object = e, this._keys = t, this.size = t.length + } + + function re(e) { + this._iterable = e, this.size = e.length || e.size + } + + function oe(e) { + this._iterator = e, this._iteratorCache = [] + } + + function ae(e) { + return !(!e || !e[ee]) + } + + function ie() { + return Z || (Z = new te([])) + } + + function se(e) { + var t = Array.isArray(e) ? new te(e).fromEntrySeq() : V(e) ? new oe(e).fromEntrySeq() : z(e) ? new re(e).fromEntrySeq() : "object" == typeof e ? new ne(e) : void 0; + if (!t) throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: " + e); + return t + } + + function ue(e) { + var t = le(e); + if (!t) throw new TypeError("Expected Array or iterable object of values: " + e); + return t + } + + function ce(e) { + var t = le(e) || "object" == typeof e && new ne(e); + if (!t) throw new TypeError("Expected Array or iterable object of values, or keyed object: " + e); + return t + } + + function le(e) { + return J(e) ? new te(e) : V(e) ? new oe(e) : z(e) ? new re(e) : void 0 + } + + function pe(e, t, n, r) { + var o = e._cache; + if (o) { + for (var a = o.length - 1, i = 0; i <= a; i++) { + var s = o[n ? a - i : i]; + if (!1 === t(s[1], r ? s[0] : i, e)) return i + 1 + } + return i + } + return e.__iterateUncached(t, n) + } + + function fe(e, t, n, r) { + var o = e._cache; + if (o) { + var a = o.length - 1, i = 0; + return new F((function () { + var e = o[n ? a - i : i]; + return i++ > a ? q() : U(t, r ? e[0] : i - 1, e[1]) + })) + } + return e.__iteratorUncached(t, n) + } + + function he(e, t) { + return t ? de(t, e, "", {"": e}) : me(e) + } + + function de(e, t, n, r) { + return Array.isArray(t) ? e.call(r, n, Y(t).map((function (n, r) { + return de(e, n, r, t) + }))) : ve(t) ? e.call(r, n, K(t).map((function (n, r) { + return de(e, n, r, t) + }))) : t + } + + function me(e) { + return Array.isArray(e) ? Y(e).map(me).toList() : ve(e) ? K(e).map(me).toMap() : e + } + + function ve(e) { + return e && (e.constructor === Object || void 0 === e.constructor) + } + + function ge(e, t) { + if (e === t || e != e && t != t) return !0; + if (!e || !t) return !1; + if ("function" == typeof e.valueOf && "function" == typeof t.valueOf) { + if ((e = e.valueOf()) === (t = t.valueOf()) || e != e && t != t) return !0; + if (!e || !t) return !1 + } + return !("function" != typeof e.equals || "function" != typeof t.equals || !e.equals(t)) + } + + function ye(e, t) { + if (e === t) return !0; + if (!i(t) || void 0 !== e.size && void 0 !== t.size && e.size !== t.size || void 0 !== e.__hash && void 0 !== t.__hash && e.__hash !== t.__hash || s(e) !== s(t) || u(e) !== u(t) || l(e) !== l(t)) return !1; + if (0 === e.size && 0 === t.size) return !0; + var n = !c(e); + if (l(e)) { + var r = e.entries(); + return t.every((function (e, t) { + var o = r.next().value; + return o && ge(o[1], e) && (n || ge(o[0], t)) + })) && r.next().done + } + var o = !1; + if (void 0 === e.size) if (void 0 === t.size) "function" == typeof e.cacheResult && e.cacheResult(); else { + o = !0; + var a = e; + e = t, t = a + } + var p = !0, f = t.__iterate((function (t, r) { + if (n ? !e.has(t) : o ? !ge(t, e.get(r, b)) : !ge(e.get(r, b), t)) return p = !1, !1 + })); + return p && e.size === f + } + + function be(e, t) { + if (!(this instanceof be)) return new be(e, t); + if (this._value = e, this.size = void 0 === t ? 1 / 0 : Math.max(0, t), 0 === this.size) { + if (X) return X; + X = this + } + } + + function _e(e, t) { + if (!e) throw new Error(t) + } + + function we(e, t, n) { + if (!(this instanceof we)) return new we(e, t, n); + if (_e(0 !== n, "Cannot step a Range by 0"), e = e || 0, void 0 === t && (t = 1 / 0), n = void 0 === n ? 1 : Math.abs(n), t < e && (n = -n), this._start = e, this._end = t, this._step = n, this.size = Math.max(0, Math.ceil((t - e) / n - 1) + 1), 0 === this.size) { + if (Q) return Q; + Q = this + } + } + + function xe() { + throw TypeError("Abstract") + } + + function Ee() { + } + + function Se() { + } + + function Ce() { + } + + $.prototype[ee] = !0, t(te, Y), te.prototype.get = function (e, t) { + return this.has(e) ? this._array[k(this, e)] : t + }, te.prototype.__iterate = function (e, t) { + for (var n = this._array, r = n.length - 1, o = 0; o <= r; o++) if (!1 === e(n[t ? r - o : o], o, this)) return o + 1; + return o + }, te.prototype.__iterator = function (e, t) { + var n = this._array, r = n.length - 1, o = 0; + return new F((function () { + return o > r ? q() : U(e, o, n[t ? r - o++ : o++]) + })) + }, t(ne, K), ne.prototype.get = function (e, t) { + return void 0 === t || this.has(e) ? this._object[e] : t + }, ne.prototype.has = function (e) { + return this._object.hasOwnProperty(e) + }, ne.prototype.__iterate = function (e, t) { + for (var n = this._object, r = this._keys, o = r.length - 1, a = 0; a <= o; a++) { + var i = r[t ? o - a : a]; + if (!1 === e(n[i], i, this)) return a + 1 + } + return a + }, ne.prototype.__iterator = function (e, t) { + var n = this._object, r = this._keys, o = r.length - 1, a = 0; + return new F((function () { + var i = r[t ? o - a : a]; + return a++ > o ? q() : U(e, i, n[i]) + })) + }, ne.prototype[d] = !0, t(re, Y), re.prototype.__iterateUncached = function (e, t) { + if (t) return this.cacheResult().__iterate(e, t); + var n = W(this._iterable), r = 0; + if (V(n)) for (var o; !(o = n.next()).done && !1 !== e(o.value, r++, this);) ; + return r + }, re.prototype.__iteratorUncached = function (e, t) { + if (t) return this.cacheResult().__iterator(e, t); + var n = W(this._iterable); + if (!V(n)) return new F(q); + var r = 0; + return new F((function () { + var t = n.next(); + return t.done ? t : U(e, r++, t.value) + })) + }, t(oe, Y), oe.prototype.__iterateUncached = function (e, t) { + if (t) return this.cacheResult().__iterate(e, t); + for (var n, r = this._iterator, o = this._iteratorCache, a = 0; a < o.length;) if (!1 === e(o[a], a++, this)) return a; + for (; !(n = r.next()).done;) { + var i = n.value; + if (o[a] = i, !1 === e(i, a++, this)) break + } + return a + }, oe.prototype.__iteratorUncached = function (e, t) { + if (t) return this.cacheResult().__iterator(e, t); + var n = this._iterator, r = this._iteratorCache, o = 0; + return new F((function () { + if (o >= r.length) { + var t = n.next(); + if (t.done) return t; + r[o] = t.value + } + return U(e, o, r[o++]) + })) + }, t(be, Y), be.prototype.toString = function () { + return 0 === this.size ? "Repeat []" : "Repeat [ " + this._value + " " + this.size + " times ]" + }, be.prototype.get = function (e, t) { + return this.has(e) ? this._value : t + }, be.prototype.includes = function (e) { + return ge(this._value, e) + }, be.prototype.slice = function (e, t) { + var n = this.size; + return j(e, t, n) ? this : new be(this._value, I(t, n) - T(e, n)) + }, be.prototype.reverse = function () { + return this + }, be.prototype.indexOf = function (e) { + return ge(this._value, e) ? 0 : -1 + }, be.prototype.lastIndexOf = function (e) { + return ge(this._value, e) ? this.size : -1 + }, be.prototype.__iterate = function (e, t) { + for (var n = 0; n < this.size; n++) if (!1 === e(this._value, n, this)) return n + 1; + return n + }, be.prototype.__iterator = function (e, t) { + var n = this, r = 0; + return new F((function () { + return r < n.size ? U(e, r++, n._value) : q() + })) + }, be.prototype.equals = function (e) { + return e instanceof be ? ge(this._value, e._value) : ye(e) + }, t(we, Y), we.prototype.toString = function () { + return 0 === this.size ? "Range []" : "Range [ " + this._start + "..." + this._end + (1 !== this._step ? " by " + this._step : "") + " ]" + }, we.prototype.get = function (e, t) { + return this.has(e) ? this._start + k(this, e) * this._step : t + }, we.prototype.includes = function (e) { + var t = (e - this._start) / this._step; + return t >= 0 && t < this.size && t === Math.floor(t) + }, we.prototype.slice = function (e, t) { + return j(e, t, this.size) ? this : (e = T(e, this.size), (t = I(t, this.size)) <= e ? new we(0, 0) : new we(this.get(e, this._end), this.get(t, this._end), this._step)) + }, we.prototype.indexOf = function (e) { + var t = e - this._start; + if (t % this._step == 0) { + var n = t / this._step; + if (n >= 0 && n < this.size) return n + } + return -1 + }, we.prototype.lastIndexOf = function (e) { + return this.indexOf(e) + }, we.prototype.__iterate = function (e, t) { + for (var n = this.size - 1, r = this._step, o = t ? this._start + n * r : this._start, a = 0; a <= n; a++) { + if (!1 === e(o, a, this)) return a + 1; + o += t ? -r : r + } + return a + }, we.prototype.__iterator = function (e, t) { + var n = this.size - 1, r = this._step, o = t ? this._start + n * r : this._start, a = 0; + return new F((function () { + var i = o; + return o += t ? -r : r, a > n ? q() : U(e, a++, i) + })) + }, we.prototype.equals = function (e) { + return e instanceof we ? this._start === e._start && this._end === e._end && this._step === e._step : ye(this, e) + }, t(xe, n), t(Ee, xe), t(Se, xe), t(Ce, xe), xe.Keyed = Ee, xe.Indexed = Se, xe.Set = Ce; + var Ae = "function" == typeof Math.imul && -2 === Math.imul(4294967295, 2) ? Math.imul : function (e, t) { + var n = 65535 & (e |= 0), r = 65535 & (t |= 0); + return n * r + ((e >>> 16) * r + n * (t >>> 16) << 16 >>> 0) | 0 + }; + + function ke(e) { + return e >>> 1 & 1073741824 | 3221225471 & e + } + + function Oe(e) { + if (!1 === e || null == e) return 0; + if ("function" == typeof e.valueOf && (!1 === (e = e.valueOf()) || null == e)) return 0; + if (!0 === e) return 1; + var t = typeof e; + if ("number" === t) { + if (e != e || e === 1 / 0) return 0; + var n = 0 | e; + for (n !== e && (n ^= 4294967295 * e); e > 4294967295;) n ^= e /= 4294967295; + return ke(n) + } + if ("string" === t) return e.length > Fe ? je(e) : Te(e); + if ("function" == typeof e.hashCode) return e.hashCode(); + if ("object" === t) return Ie(e); + if ("function" == typeof e.toString) return Te(e.toString()); + throw new Error("Value type " + t + " cannot be hashed.") + } + + function je(e) { + var t = ze[e]; + return void 0 === t && (t = Te(e), qe === Ue && (qe = 0, ze = {}), qe++, ze[e] = t), t + } + + function Te(e) { + for (var t = 0, n = 0; n < e.length; n++) t = 31 * t + e.charCodeAt(n) | 0; + return ke(t) + } + + function Ie(e) { + var t; + if (De && void 0 !== (t = Re.get(e))) return t; + if (void 0 !== (t = e[Be])) return t; + if (!Ne) { + if (void 0 !== (t = e.propertyIsEnumerable && e.propertyIsEnumerable[Be])) return t; + if (void 0 !== (t = Me(e))) return t + } + if (t = ++Le, 1073741824 & Le && (Le = 0), De) Re.set(e, t); else { + if (void 0 !== Pe && !1 === Pe(e)) throw new Error("Non-extensible objects are not allowed as keys."); + if (Ne) Object.defineProperty(e, Be, { + enumerable: !1, + configurable: !1, + writable: !1, + value: t + }); else if (void 0 !== e.propertyIsEnumerable && e.propertyIsEnumerable === e.constructor.prototype.propertyIsEnumerable) e.propertyIsEnumerable = function () { + return this.constructor.prototype.propertyIsEnumerable.apply(this, arguments) + }, e.propertyIsEnumerable[Be] = t; else { + if (void 0 === e.nodeType) throw new Error("Unable to set a non-enumerable property on object."); + e[Be] = t + } + } + return t + } + + var Pe = Object.isExtensible, Ne = function () { + try { + return Object.defineProperty({}, "@", {}), !0 + } catch (e) { + return !1 + } + }(); + + function Me(e) { + if (e && e.nodeType > 0) switch (e.nodeType) { + case 1: + return e.uniqueID; + case 9: + return e.documentElement && e.documentElement.uniqueID + } + } + + var Re, De = "function" == typeof WeakMap; + De && (Re = new WeakMap); + var Le = 0, Be = "__immutablehash__"; + "function" == typeof Symbol && (Be = Symbol(Be)); + var Fe = 16, Ue = 255, qe = 0, ze = {}; + + function Ve(e) { + _e(e !== 1 / 0, "Cannot perform this action with an infinite size.") + } + + function We(e) { + return null == e ? ot() : He(e) && !l(e) ? e : ot().withMutations((function (t) { + var n = r(e); + Ve(n.size), n.forEach((function (e, n) { + return t.set(n, e) + })) + })) + } + + function He(e) { + return !(!e || !e[$e]) + } + + t(We, Ee), We.of = function () { + var t = e.call(arguments, 0); + return ot().withMutations((function (e) { + for (var n = 0; n < t.length; n += 2) { + if (n + 1 >= t.length) throw new Error("Missing value for key: " + t[n]); + e.set(t[n], t[n + 1]) + } + })) + }, We.prototype.toString = function () { + return this.__toString("Map {", "}") + }, We.prototype.get = function (e, t) { + return this._root ? this._root.get(0, void 0, e, t) : t + }, We.prototype.set = function (e, t) { + return at(this, e, t) + }, We.prototype.setIn = function (e, t) { + return this.updateIn(e, b, (function () { + return t + })) + }, We.prototype.remove = function (e) { + return at(this, e, b) + }, We.prototype.deleteIn = function (e) { + return this.updateIn(e, (function () { + return b + })) + }, We.prototype.update = function (e, t, n) { + return 1 === arguments.length ? e(this) : this.updateIn([e], t, n) + }, We.prototype.updateIn = function (e, t, n) { + n || (n = t, t = void 0); + var r = vt(this, xn(e), t, n); + return r === b ? void 0 : r + }, We.prototype.clear = function () { + return 0 === this.size ? this : this.__ownerID ? (this.size = 0, this._root = null, this.__hash = void 0, this.__altered = !0, this) : ot() + }, We.prototype.merge = function () { + return ft(this, void 0, arguments) + }, We.prototype.mergeWith = function (t) { + return ft(this, t, e.call(arguments, 1)) + }, We.prototype.mergeIn = function (t) { + var n = e.call(arguments, 1); + return this.updateIn(t, ot(), (function (e) { + return "function" == typeof e.merge ? e.merge.apply(e, n) : n[n.length - 1] + })) + }, We.prototype.mergeDeep = function () { + return ft(this, ht, arguments) + }, We.prototype.mergeDeepWith = function (t) { + var n = e.call(arguments, 1); + return ft(this, dt(t), n) + }, We.prototype.mergeDeepIn = function (t) { + var n = e.call(arguments, 1); + return this.updateIn(t, ot(), (function (e) { + return "function" == typeof e.mergeDeep ? e.mergeDeep.apply(e, n) : n[n.length - 1] + })) + }, We.prototype.sort = function (e) { + return zt(pn(this, e)) + }, We.prototype.sortBy = function (e, t) { + return zt(pn(this, t, e)) + }, We.prototype.withMutations = function (e) { + var t = this.asMutable(); + return e(t), t.wasAltered() ? t.__ensureOwner(this.__ownerID) : this + }, We.prototype.asMutable = function () { + return this.__ownerID ? this : this.__ensureOwner(new S) + }, We.prototype.asImmutable = function () { + return this.__ensureOwner() + }, We.prototype.wasAltered = function () { + return this.__altered + }, We.prototype.__iterator = function (e, t) { + return new et(this, e, t) + }, We.prototype.__iterate = function (e, t) { + var n = this, r = 0; + return this._root && this._root.iterate((function (t) { + return r++, e(t[1], t[0], n) + }), t), r + }, We.prototype.__ensureOwner = function (e) { + return e === this.__ownerID ? this : e ? rt(this.size, this._root, e, this.__hash) : (this.__ownerID = e, this.__altered = !1, this) + }, We.isMap = He; + var Je, $e = "@@__IMMUTABLE_MAP__@@", Ke = We.prototype; + + function Ye(e, t) { + this.ownerID = e, this.entries = t + } + + function Ge(e, t, n) { + this.ownerID = e, this.bitmap = t, this.nodes = n + } + + function Ze(e, t, n) { + this.ownerID = e, this.count = t, this.nodes = n + } + + function Xe(e, t, n) { + this.ownerID = e, this.keyHash = t, this.entries = n + } + + function Qe(e, t, n) { + this.ownerID = e, this.keyHash = t, this.entry = n + } + + function et(e, t, n) { + this._type = t, this._reverse = n, this._stack = e._root && nt(e._root) + } + + function tt(e, t) { + return U(e, t[0], t[1]) + } + + function nt(e, t) { + return {node: e, index: 0, __prev: t} + } + + function rt(e, t, n, r) { + var o = Object.create(Ke); + return o.size = e, o._root = t, o.__ownerID = n, o.__hash = r, o.__altered = !1, o + } + + function ot() { + return Je || (Je = rt(0)) + } + + function at(e, t, n) { + var r, o; + if (e._root) { + var a = x(_), i = x(w); + if (r = it(e._root, e.__ownerID, 0, void 0, t, n, a, i), !i.value) return e; + o = e.size + (a.value ? n === b ? -1 : 1 : 0) + } else { + if (n === b) return e; + o = 1, r = new Ye(e.__ownerID, [[t, n]]) + } + return e.__ownerID ? (e.size = o, e._root = r, e.__hash = void 0, e.__altered = !0, e) : r ? rt(o, r) : ot() + } + + function it(e, t, n, r, o, a, i, s) { + return e ? e.update(t, n, r, o, a, i, s) : a === b ? e : (E(s), E(i), new Qe(t, r, [o, a])) + } + + function st(e) { + return e.constructor === Qe || e.constructor === Xe + } + + function ut(e, t, n, r, o) { + if (e.keyHash === r) return new Xe(t, r, [e.entry, o]); + var a, i = (0 === n ? e.keyHash : e.keyHash >>> n) & y, s = (0 === n ? r : r >>> n) & y; + return new Ge(t, 1 << i | 1 << s, i === s ? [ut(e, t, n + v, r, o)] : (a = new Qe(t, r, o), i < s ? [e, a] : [a, e])) + } + + function ct(e, t, n, r) { + e || (e = new S); + for (var o = new Qe(e, Oe(n), [n, r]), a = 0; a < t.length; a++) { + var i = t[a]; + o = o.update(e, 0, void 0, i[0], i[1]) + } + return o + } + + function lt(e, t, n, r) { + for (var o = 0, a = 0, i = new Array(n), s = 0, u = 1, c = t.length; s < c; s++, u <<= 1) { + var l = t[s]; + void 0 !== l && s !== r && (o |= u, i[a++] = l) + } + return new Ge(e, o, i) + } + + function pt(e, t, n, r, o) { + for (var a = 0, i = new Array(g), s = 0; 0 !== n; s++, n >>>= 1) i[s] = 1 & n ? t[a++] : void 0; + return i[r] = o, new Ze(e, a + 1, i) + } + + function ft(e, t, n) { + for (var o = [], a = 0; a < n.length; a++) { + var s = n[a], u = r(s); + i(s) || (u = u.map((function (e) { + return he(e) + }))), o.push(u) + } + return mt(e, t, o) + } + + function ht(e, t, n) { + return e && e.mergeDeep && i(t) ? e.mergeDeep(t) : ge(e, t) ? e : t + } + + function dt(e) { + return function (t, n, r) { + if (t && t.mergeDeepWith && i(n)) return t.mergeDeepWith(e, n); + var o = e(t, n, r); + return ge(t, o) ? t : o + } + } + + function mt(e, t, n) { + return 0 === (n = n.filter((function (e) { + return 0 !== e.size + }))).length ? e : 0 !== e.size || e.__ownerID || 1 !== n.length ? e.withMutations((function (e) { + for (var r = t ? function (n, r) { + e.update(r, b, (function (e) { + return e === b ? n : t(e, n, r) + })) + } : function (t, n) { + e.set(n, t) + }, o = 0; o < n.length; o++) n[o].forEach(r) + })) : e.constructor(n[0]) + } + + function vt(e, t, n, r) { + var o = e === b, a = t.next(); + if (a.done) { + var i = o ? n : e, s = r(i); + return s === i ? e : s + } + _e(o || e && e.set, "invalid keyPath"); + var u = a.value, c = o ? b : e.get(u, b), l = vt(c, t, n, r); + return l === c ? e : l === b ? e.remove(u) : (o ? ot() : e).set(u, l) + } + + function gt(e) { + return e = (e = (858993459 & (e -= e >> 1 & 1431655765)) + (e >> 2 & 858993459)) + (e >> 4) & 252645135, e += e >> 8, 127 & (e += e >> 16) + } + + function yt(e, t, n, r) { + var o = r ? e : C(e); + return o[t] = n, o + } + + function bt(e, t, n, r) { + var o = e.length + 1; + if (r && t + 1 === o) return e[t] = n, e; + for (var a = new Array(o), i = 0, s = 0; s < o; s++) s === t ? (a[s] = n, i = -1) : a[s] = e[s + i]; + return a + } + + function _t(e, t, n) { + var r = e.length - 1; + if (n && t === r) return e.pop(), e; + for (var o = new Array(r), a = 0, i = 0; i < r; i++) i === t && (a = 1), o[i] = e[i + a]; + return o + } + + Ke[$e] = !0, Ke[m] = Ke.remove, Ke.removeIn = Ke.deleteIn, Ye.prototype.get = function (e, t, n, r) { + for (var o = this.entries, a = 0, i = o.length; a < i; a++) if (ge(n, o[a][0])) return o[a][1]; + return r + }, Ye.prototype.update = function (e, t, n, r, o, a, i) { + for (var s = o === b, u = this.entries, c = 0, l = u.length; c < l && !ge(r, u[c][0]); c++) ; + var p = c < l; + if (p ? u[c][1] === o : s) return this; + if (E(i), (s || !p) && E(a), !s || 1 !== u.length) { + if (!p && !s && u.length >= wt) return ct(e, u, r, o); + var f = e && e === this.ownerID, h = f ? u : C(u); + return p ? s ? c === l - 1 ? h.pop() : h[c] = h.pop() : h[c] = [r, o] : h.push([r, o]), f ? (this.entries = h, this) : new Ye(e, h) + } + }, Ge.prototype.get = function (e, t, n, r) { + void 0 === t && (t = Oe(n)); + var o = 1 << ((0 === e ? t : t >>> e) & y), a = this.bitmap; + return 0 == (a & o) ? r : this.nodes[gt(a & o - 1)].get(e + v, t, n, r) + }, Ge.prototype.update = function (e, t, n, r, o, a, i) { + void 0 === n && (n = Oe(r)); + var s = (0 === t ? n : n >>> t) & y, u = 1 << s, c = this.bitmap, l = 0 != (c & u); + if (!l && o === b) return this; + var p = gt(c & u - 1), f = this.nodes, h = l ? f[p] : void 0, d = it(h, e, t + v, n, r, o, a, i); + if (d === h) return this; + if (!l && d && f.length >= xt) return pt(e, f, c, s, d); + if (l && !d && 2 === f.length && st(f[1 ^ p])) return f[1 ^ p]; + if (l && d && 1 === f.length && st(d)) return d; + var m = e && e === this.ownerID, g = l ? d ? c : c ^ u : c | u, + _ = l ? d ? yt(f, p, d, m) : _t(f, p, m) : bt(f, p, d, m); + return m ? (this.bitmap = g, this.nodes = _, this) : new Ge(e, g, _) + }, Ze.prototype.get = function (e, t, n, r) { + void 0 === t && (t = Oe(n)); + var o = (0 === e ? t : t >>> e) & y, a = this.nodes[o]; + return a ? a.get(e + v, t, n, r) : r + }, Ze.prototype.update = function (e, t, n, r, o, a, i) { + void 0 === n && (n = Oe(r)); + var s = (0 === t ? n : n >>> t) & y, u = o === b, c = this.nodes, l = c[s]; + if (u && !l) return this; + var p = it(l, e, t + v, n, r, o, a, i); + if (p === l) return this; + var f = this.count; + if (l) { + if (!p && --f < Et) return lt(e, c, f, s) + } else f++; + var h = e && e === this.ownerID, d = yt(c, s, p, h); + return h ? (this.count = f, this.nodes = d, this) : new Ze(e, f, d) + }, Xe.prototype.get = function (e, t, n, r) { + for (var o = this.entries, a = 0, i = o.length; a < i; a++) if (ge(n, o[a][0])) return o[a][1]; + return r + }, Xe.prototype.update = function (e, t, n, r, o, a, i) { + void 0 === n && (n = Oe(r)); + var s = o === b; + if (n !== this.keyHash) return s ? this : (E(i), E(a), ut(this, e, t, n, [r, o])); + for (var u = this.entries, c = 0, l = u.length; c < l && !ge(r, u[c][0]); c++) ; + var p = c < l; + if (p ? u[c][1] === o : s) return this; + if (E(i), (s || !p) && E(a), s && 2 === l) return new Qe(e, this.keyHash, u[1 ^ c]); + var f = e && e === this.ownerID, h = f ? u : C(u); + return p ? s ? c === l - 1 ? h.pop() : h[c] = h.pop() : h[c] = [r, o] : h.push([r, o]), f ? (this.entries = h, this) : new Xe(e, this.keyHash, h) + }, Qe.prototype.get = function (e, t, n, r) { + return ge(n, this.entry[0]) ? this.entry[1] : r + }, Qe.prototype.update = function (e, t, n, r, o, a, i) { + var s = o === b, u = ge(r, this.entry[0]); + return (u ? o === this.entry[1] : s) ? this : (E(i), s ? void E(a) : u ? e && e === this.ownerID ? (this.entry[1] = o, this) : new Qe(e, this.keyHash, [r, o]) : (E(a), ut(this, e, t, Oe(r), [r, o]))) + }, Ye.prototype.iterate = Xe.prototype.iterate = function (e, t) { + for (var n = this.entries, r = 0, o = n.length - 1; r <= o; r++) if (!1 === e(n[t ? o - r : r])) return !1 + }, Ge.prototype.iterate = Ze.prototype.iterate = function (e, t) { + for (var n = this.nodes, r = 0, o = n.length - 1; r <= o; r++) { + var a = n[t ? o - r : r]; + if (a && !1 === a.iterate(e, t)) return !1 + } + }, Qe.prototype.iterate = function (e, t) { + return e(this.entry) + }, t(et, F), et.prototype.next = function () { + for (var e = this._type, t = this._stack; t;) { + var n, r = t.node, o = t.index++; + if (r.entry) { + if (0 === o) return tt(e, r.entry) + } else if (r.entries) { + if (o <= (n = r.entries.length - 1)) return tt(e, r.entries[this._reverse ? n - o : o]) + } else if (o <= (n = r.nodes.length - 1)) { + var a = r.nodes[this._reverse ? n - o : o]; + if (a) { + if (a.entry) return tt(e, a.entry); + t = this._stack = nt(a, t) + } + continue + } + t = this._stack = this._stack.__prev + } + return q() + }; + var wt = g / 4, xt = g / 2, Et = g / 4; + + function St(e) { + var t = Mt(); + if (null == e) return t; + if (Ct(e)) return e; + var n = o(e), r = n.size; + return 0 === r ? t : (Ve(r), r > 0 && r < g ? Nt(0, r, v, null, new Ot(n.toArray())) : t.withMutations((function (e) { + e.setSize(r), n.forEach((function (t, n) { + return e.set(n, t) + })) + }))) + } + + function Ct(e) { + return !(!e || !e[At]) + } + + t(St, Se), St.of = function () { + return this(arguments) + }, St.prototype.toString = function () { + return this.__toString("List [", "]") + }, St.prototype.get = function (e, t) { + if ((e = k(this, e)) >= 0 && e < this.size) { + var n = Bt(this, e += this._origin); + return n && n.array[e & y] + } + return t + }, St.prototype.set = function (e, t) { + return Rt(this, e, t) + }, St.prototype.remove = function (e) { + return this.has(e) ? 0 === e ? this.shift() : e === this.size - 1 ? this.pop() : this.splice(e, 1) : this + }, St.prototype.insert = function (e, t) { + return this.splice(e, 0, t) + }, St.prototype.clear = function () { + return 0 === this.size ? this : this.__ownerID ? (this.size = this._origin = this._capacity = 0, this._level = v, this._root = this._tail = null, this.__hash = void 0, this.__altered = !0, this) : Mt() + }, St.prototype.push = function () { + var e = arguments, t = this.size; + return this.withMutations((function (n) { + Ft(n, 0, t + e.length); + for (var r = 0; r < e.length; r++) n.set(t + r, e[r]) + })) + }, St.prototype.pop = function () { + return Ft(this, 0, -1) + }, St.prototype.unshift = function () { + var e = arguments; + return this.withMutations((function (t) { + Ft(t, -e.length); + for (var n = 0; n < e.length; n++) t.set(n, e[n]) + })) + }, St.prototype.shift = function () { + return Ft(this, 1) + }, St.prototype.merge = function () { + return Ut(this, void 0, arguments) + }, St.prototype.mergeWith = function (t) { + return Ut(this, t, e.call(arguments, 1)) + }, St.prototype.mergeDeep = function () { + return Ut(this, ht, arguments) + }, St.prototype.mergeDeepWith = function (t) { + var n = e.call(arguments, 1); + return Ut(this, dt(t), n) + }, St.prototype.setSize = function (e) { + return Ft(this, 0, e) + }, St.prototype.slice = function (e, t) { + var n = this.size; + return j(e, t, n) ? this : Ft(this, T(e, n), I(t, n)) + }, St.prototype.__iterator = function (e, t) { + var n = 0, r = Pt(this, t); + return new F((function () { + var t = r(); + return t === It ? q() : U(e, n++, t) + })) + }, St.prototype.__iterate = function (e, t) { + for (var n, r = 0, o = Pt(this, t); (n = o()) !== It && !1 !== e(n, r++, this);) ; + return r + }, St.prototype.__ensureOwner = function (e) { + return e === this.__ownerID ? this : e ? Nt(this._origin, this._capacity, this._level, this._root, this._tail, e, this.__hash) : (this.__ownerID = e, this) + }, St.isList = Ct; + var At = "@@__IMMUTABLE_LIST__@@", kt = St.prototype; + + function Ot(e, t) { + this.array = e, this.ownerID = t + } + + kt[At] = !0, kt[m] = kt.remove, kt.setIn = Ke.setIn, kt.deleteIn = kt.removeIn = Ke.removeIn, kt.update = Ke.update, kt.updateIn = Ke.updateIn, kt.mergeIn = Ke.mergeIn, kt.mergeDeepIn = Ke.mergeDeepIn, kt.withMutations = Ke.withMutations, kt.asMutable = Ke.asMutable, kt.asImmutable = Ke.asImmutable, kt.wasAltered = Ke.wasAltered, Ot.prototype.removeBefore = function (e, t, n) { + if (n === t ? 1 << t : 0 === this.array.length) return this; + var r = n >>> t & y; + if (r >= this.array.length) return new Ot([], e); + var o, a = 0 === r; + if (t > 0) { + var i = this.array[r]; + if ((o = i && i.removeBefore(e, t - v, n)) === i && a) return this + } + if (a && !o) return this; + var s = Lt(this, e); + if (!a) for (var u = 0; u < r; u++) s.array[u] = void 0; + return o && (s.array[r] = o), s + }, Ot.prototype.removeAfter = function (e, t, n) { + if (n === (t ? 1 << t : 0) || 0 === this.array.length) return this; + var r, o = n - 1 >>> t & y; + if (o >= this.array.length) return this; + if (t > 0) { + var a = this.array[o]; + if ((r = a && a.removeAfter(e, t - v, n)) === a && o === this.array.length - 1) return this + } + var i = Lt(this, e); + return i.array.splice(o + 1), r && (i.array[o] = r), i + }; + var jt, Tt, It = {}; + + function Pt(e, t) { + var n = e._origin, r = e._capacity, o = qt(r), a = e._tail; + return i(e._root, e._level, 0); + + function i(e, t, n) { + return 0 === t ? s(e, n) : u(e, t, n) + } + + function s(e, i) { + var s = i === o ? a && a.array : e && e.array, u = i > n ? 0 : n - i, c = r - i; + return c > g && (c = g), function () { + if (u === c) return It; + var e = t ? --c : u++; + return s && s[e] + } + } + + function u(e, o, a) { + var s, u = e && e.array, c = a > n ? 0 : n - a >> o, l = 1 + (r - a >> o); + return l > g && (l = g), function () { + for (; ;) { + if (s) { + var e = s(); + if (e !== It) return e; + s = null + } + if (c === l) return It; + var n = t ? --l : c++; + s = i(u && u[n], o - v, a + (n << o)) + } + } + } + } + + function Nt(e, t, n, r, o, a, i) { + var s = Object.create(kt); + return s.size = t - e, s._origin = e, s._capacity = t, s._level = n, s._root = r, s._tail = o, s.__ownerID = a, s.__hash = i, s.__altered = !1, s + } + + function Mt() { + return jt || (jt = Nt(0, 0, v)) + } + + function Rt(e, t, n) { + if ((t = k(e, t)) != t) return e; + if (t >= e.size || t < 0) return e.withMutations((function (e) { + t < 0 ? Ft(e, t).set(0, n) : Ft(e, 0, t + 1).set(t, n) + })); + t += e._origin; + var r = e._tail, o = e._root, a = x(w); + return t >= qt(e._capacity) ? r = Dt(r, e.__ownerID, 0, t, n, a) : o = Dt(o, e.__ownerID, e._level, t, n, a), a.value ? e.__ownerID ? (e._root = o, e._tail = r, e.__hash = void 0, e.__altered = !0, e) : Nt(e._origin, e._capacity, e._level, o, r) : e + } + + function Dt(e, t, n, r, o, a) { + var i, s = r >>> n & y, u = e && s < e.array.length; + if (!u && void 0 === o) return e; + if (n > 0) { + var c = e && e.array[s], l = Dt(c, t, n - v, r, o, a); + return l === c ? e : ((i = Lt(e, t)).array[s] = l, i) + } + return u && e.array[s] === o ? e : (E(a), i = Lt(e, t), void 0 === o && s === i.array.length - 1 ? i.array.pop() : i.array[s] = o, i) + } + + function Lt(e, t) { + return t && e && t === e.ownerID ? e : new Ot(e ? e.array.slice() : [], t) + } + + function Bt(e, t) { + if (t >= qt(e._capacity)) return e._tail; + if (t < 1 << e._level + v) { + for (var n = e._root, r = e._level; n && r > 0;) n = n.array[t >>> r & y], r -= v; + return n + } + } + + function Ft(e, t, n) { + void 0 !== t && (t |= 0), void 0 !== n && (n |= 0); + var r = e.__ownerID || new S, o = e._origin, a = e._capacity, i = o + t, + s = void 0 === n ? a : n < 0 ? a + n : o + n; + if (i === o && s === a) return e; + if (i >= s) return e.clear(); + for (var u = e._level, c = e._root, l = 0; i + l < 0;) c = new Ot(c && c.array.length ? [void 0, c] : [], r), l += 1 << (u += v); + l && (i += l, o += l, s += l, a += l); + for (var p = qt(a), f = qt(s); f >= 1 << u + v;) c = new Ot(c && c.array.length ? [c] : [], r), u += v; + var h = e._tail, d = f < p ? Bt(e, s - 1) : f > p ? new Ot([], r) : h; + if (h && f > p && i < a && h.array.length) { + for (var m = c = Lt(c, r), g = u; g > v; g -= v) { + var b = p >>> g & y; + m = m.array[b] = Lt(m.array[b], r) + } + m.array[p >>> v & y] = h + } + if (s < a && (d = d && d.removeAfter(r, 0, s)), i >= f) i -= f, s -= f, u = v, c = null, d = d && d.removeBefore(r, 0, i); else if (i > o || f < p) { + for (l = 0; c;) { + var _ = i >>> u & y; + if (_ !== f >>> u & y) break; + _ && (l += (1 << u) * _), u -= v, c = c.array[_] + } + c && i > o && (c = c.removeBefore(r, u, i - l)), c && f < p && (c = c.removeAfter(r, u, f - l)), l && (i -= l, s -= l) + } + return e.__ownerID ? (e.size = s - i, e._origin = i, e._capacity = s, e._level = u, e._root = c, e._tail = d, e.__hash = void 0, e.__altered = !0, e) : Nt(i, s, u, c, d) + } + + function Ut(e, t, n) { + for (var r = [], a = 0, s = 0; s < n.length; s++) { + var u = n[s], c = o(u); + c.size > a && (a = c.size), i(u) || (c = c.map((function (e) { + return he(e) + }))), r.push(c) + } + return a > e.size && (e = e.setSize(a)), mt(e, t, r) + } + + function qt(e) { + return e < g ? 0 : e - 1 >>> v << v + } + + function zt(e) { + return null == e ? Ht() : Vt(e) ? e : Ht().withMutations((function (t) { + var n = r(e); + Ve(n.size), n.forEach((function (e, n) { + return t.set(n, e) + })) + })) + } + + function Vt(e) { + return He(e) && l(e) + } + + function Wt(e, t, n, r) { + var o = Object.create(zt.prototype); + return o.size = e ? e.size : 0, o._map = e, o._list = t, o.__ownerID = n, o.__hash = r, o + } + + function Ht() { + return Tt || (Tt = Wt(ot(), Mt())) + } + + function Jt(e, t, n) { + var r, o, a = e._map, i = e._list, s = a.get(t), u = void 0 !== s; + if (n === b) { + if (!u) return e; + i.size >= g && i.size >= 2 * a.size ? (r = (o = i.filter((function (e, t) { + return void 0 !== e && s !== t + }))).toKeyedSeq().map((function (e) { + return e[0] + })).flip().toMap(), e.__ownerID && (r.__ownerID = o.__ownerID = e.__ownerID)) : (r = a.remove(t), o = s === i.size - 1 ? i.pop() : i.set(s, void 0)) + } else if (u) { + if (n === i.get(s)[1]) return e; + r = a, o = i.set(s, [t, n]) + } else r = a.set(t, i.size), o = i.set(i.size, [t, n]); + return e.__ownerID ? (e.size = r.size, e._map = r, e._list = o, e.__hash = void 0, e) : Wt(r, o) + } + + function $t(e, t) { + this._iter = e, this._useKeys = t, this.size = e.size + } + + function Kt(e) { + this._iter = e, this.size = e.size + } + + function Yt(e) { + this._iter = e, this.size = e.size + } + + function Gt(e) { + this._iter = e, this.size = e.size + } + + function Zt(e) { + var t = bn(e); + return t._iter = e, t.size = e.size, t.flip = function () { + return e + }, t.reverse = function () { + var t = e.reverse.apply(this); + return t.flip = function () { + return e.reverse() + }, t + }, t.has = function (t) { + return e.includes(t) + }, t.includes = function (t) { + return e.has(t) + }, t.cacheResult = _n, t.__iterateUncached = function (t, n) { + var r = this; + return e.__iterate((function (e, n) { + return !1 !== t(n, e, r) + }), n) + }, t.__iteratorUncached = function (t, n) { + if (t === R) { + var r = e.__iterator(t, n); + return new F((function () { + var e = r.next(); + if (!e.done) { + var t = e.value[0]; + e.value[0] = e.value[1], e.value[1] = t + } + return e + })) + } + return e.__iterator(t === M ? N : M, n) + }, t + } + + function Xt(e, t, n) { + var r = bn(e); + return r.size = e.size, r.has = function (t) { + return e.has(t) + }, r.get = function (r, o) { + var a = e.get(r, b); + return a === b ? o : t.call(n, a, r, e) + }, r.__iterateUncached = function (r, o) { + var a = this; + return e.__iterate((function (e, o, i) { + return !1 !== r(t.call(n, e, o, i), o, a) + }), o) + }, r.__iteratorUncached = function (r, o) { + var a = e.__iterator(R, o); + return new F((function () { + var o = a.next(); + if (o.done) return o; + var i = o.value, s = i[0]; + return U(r, s, t.call(n, i[1], s, e), o) + })) + }, r + } + + function Qt(e, t) { + var n = bn(e); + return n._iter = e, n.size = e.size, n.reverse = function () { + return e + }, e.flip && (n.flip = function () { + var t = Zt(e); + return t.reverse = function () { + return e.flip() + }, t + }), n.get = function (n, r) { + return e.get(t ? n : -1 - n, r) + }, n.has = function (n) { + return e.has(t ? n : -1 - n) + }, n.includes = function (t) { + return e.includes(t) + }, n.cacheResult = _n, n.__iterate = function (t, n) { + var r = this; + return e.__iterate((function (e, n) { + return t(e, n, r) + }), !n) + }, n.__iterator = function (t, n) { + return e.__iterator(t, !n) + }, n + } + + function en(e, t, n, r) { + var o = bn(e); + return r && (o.has = function (r) { + var o = e.get(r, b); + return o !== b && !!t.call(n, o, r, e) + }, o.get = function (r, o) { + var a = e.get(r, b); + return a !== b && t.call(n, a, r, e) ? a : o + }), o.__iterateUncached = function (o, a) { + var i = this, s = 0; + return e.__iterate((function (e, a, u) { + if (t.call(n, e, a, u)) return s++, o(e, r ? a : s - 1, i) + }), a), s + }, o.__iteratorUncached = function (o, a) { + var i = e.__iterator(R, a), s = 0; + return new F((function () { + for (; ;) { + var a = i.next(); + if (a.done) return a; + var u = a.value, c = u[0], l = u[1]; + if (t.call(n, l, c, e)) return U(o, r ? c : s++, l, a) + } + })) + }, o + } + + function tn(e, t, n) { + var r = We().asMutable(); + return e.__iterate((function (o, a) { + r.update(t.call(n, o, a, e), 0, (function (e) { + return e + 1 + })) + })), r.asImmutable() + } + + function nn(e, t, n) { + var r = s(e), o = (l(e) ? zt() : We()).asMutable(); + e.__iterate((function (a, i) { + o.update(t.call(n, a, i, e), (function (e) { + return (e = e || []).push(r ? [i, a] : a), e + })) + })); + var a = yn(e); + return o.map((function (t) { + return mn(e, a(t)) + })) + } + + function rn(e, t, n, r) { + var o = e.size; + if (void 0 !== t && (t |= 0), void 0 !== n && (n === 1 / 0 ? n = o : n |= 0), j(t, n, o)) return e; + var a = T(t, o), i = I(n, o); + if (a != a || i != i) return rn(e.toSeq().cacheResult(), t, n, r); + var s, u = i - a; + u == u && (s = u < 0 ? 0 : u); + var c = bn(e); + return c.size = 0 === s ? s : e.size && s || void 0, !r && ae(e) && s >= 0 && (c.get = function (t, n) { + return (t = k(this, t)) >= 0 && t < s ? e.get(t + a, n) : n + }), c.__iterateUncached = function (t, n) { + var o = this; + if (0 === s) return 0; + if (n) return this.cacheResult().__iterate(t, n); + var i = 0, u = !0, c = 0; + return e.__iterate((function (e, n) { + if (!u || !(u = i++ < a)) return c++, !1 !== t(e, r ? n : c - 1, o) && c !== s + })), c + }, c.__iteratorUncached = function (t, n) { + if (0 !== s && n) return this.cacheResult().__iterator(t, n); + var o = 0 !== s && e.__iterator(t, n), i = 0, u = 0; + return new F((function () { + for (; i++ < a;) o.next(); + if (++u > s) return q(); + var e = o.next(); + return r || t === M ? e : U(t, u - 1, t === N ? void 0 : e.value[1], e) + })) + }, c + } + + function on(e, t, n) { + var r = bn(e); + return r.__iterateUncached = function (r, o) { + var a = this; + if (o) return this.cacheResult().__iterate(r, o); + var i = 0; + return e.__iterate((function (e, o, s) { + return t.call(n, e, o, s) && ++i && r(e, o, a) + })), i + }, r.__iteratorUncached = function (r, o) { + var a = this; + if (o) return this.cacheResult().__iterator(r, o); + var i = e.__iterator(R, o), s = !0; + return new F((function () { + if (!s) return q(); + var e = i.next(); + if (e.done) return e; + var o = e.value, u = o[0], c = o[1]; + return t.call(n, c, u, a) ? r === R ? e : U(r, u, c, e) : (s = !1, q()) + })) + }, r + } + + function an(e, t, n, r) { + var o = bn(e); + return o.__iterateUncached = function (o, a) { + var i = this; + if (a) return this.cacheResult().__iterate(o, a); + var s = !0, u = 0; + return e.__iterate((function (e, a, c) { + if (!s || !(s = t.call(n, e, a, c))) return u++, o(e, r ? a : u - 1, i) + })), u + }, o.__iteratorUncached = function (o, a) { + var i = this; + if (a) return this.cacheResult().__iterator(o, a); + var s = e.__iterator(R, a), u = !0, c = 0; + return new F((function () { + var e, a, l; + do { + if ((e = s.next()).done) return r || o === M ? e : U(o, c++, o === N ? void 0 : e.value[1], e); + var p = e.value; + a = p[0], l = p[1], u && (u = t.call(n, l, a, i)) + } while (u); + return o === R ? e : U(o, a, l, e) + })) + }, o + } + + function sn(e, t) { + var n = s(e), o = [e].concat(t).map((function (e) { + return i(e) ? n && (e = r(e)) : e = n ? se(e) : ue(Array.isArray(e) ? e : [e]), e + })).filter((function (e) { + return 0 !== e.size + })); + if (0 === o.length) return e; + if (1 === o.length) { + var a = o[0]; + if (a === e || n && s(a) || u(e) && u(a)) return a + } + var c = new te(o); + return n ? c = c.toKeyedSeq() : u(e) || (c = c.toSetSeq()), (c = c.flatten(!0)).size = o.reduce((function (e, t) { + if (void 0 !== e) { + var n = t.size; + if (void 0 !== n) return e + n + } + }), 0), c + } + + function un(e, t, n) { + var r = bn(e); + return r.__iterateUncached = function (r, o) { + var a = 0, s = !1; + + function u(e, c) { + var l = this; + e.__iterate((function (e, o) { + return (!t || c < t) && i(e) ? u(e, c + 1) : !1 === r(e, n ? o : a++, l) && (s = !0), !s + }), o) + } + + return u(e, 0), a + }, r.__iteratorUncached = function (r, o) { + var a = e.__iterator(r, o), s = [], u = 0; + return new F((function () { + for (; a;) { + var e = a.next(); + if (!1 === e.done) { + var c = e.value; + if (r === R && (c = c[1]), t && !(s.length < t) || !i(c)) return n ? e : U(r, u++, c, e); + s.push(a), a = c.__iterator(r, o) + } else a = s.pop() + } + return q() + })) + }, r + } + + function cn(e, t, n) { + var r = yn(e); + return e.toSeq().map((function (o, a) { + return r(t.call(n, o, a, e)) + })).flatten(!0) + } + + function ln(e, t) { + var n = bn(e); + return n.size = e.size && 2 * e.size - 1, n.__iterateUncached = function (n, r) { + var o = this, a = 0; + return e.__iterate((function (e, r) { + return (!a || !1 !== n(t, a++, o)) && !1 !== n(e, a++, o) + }), r), a + }, n.__iteratorUncached = function (n, r) { + var o, a = e.__iterator(M, r), i = 0; + return new F((function () { + return (!o || i % 2) && (o = a.next()).done ? o : i % 2 ? U(n, i++, t) : U(n, i++, o.value, o) + })) + }, n + } + + function pn(e, t, n) { + t || (t = wn); + var r = s(e), o = 0, a = e.toSeq().map((function (t, r) { + return [r, t, o++, n ? n(t, r, e) : t] + })).toArray(); + return a.sort((function (e, n) { + return t(e[3], n[3]) || e[2] - n[2] + })).forEach(r ? function (e, t) { + a[t].length = 2 + } : function (e, t) { + a[t] = e[1] + }), r ? K(a) : u(e) ? Y(a) : G(a) + } + + function fn(e, t, n) { + if (t || (t = wn), n) { + var r = e.toSeq().map((function (t, r) { + return [t, n(t, r, e)] + })).reduce((function (e, n) { + return hn(t, e[1], n[1]) ? n : e + })); + return r && r[0] + } + return e.reduce((function (e, n) { + return hn(t, e, n) ? n : e + })) + } + + function hn(e, t, n) { + var r = e(n, t); + return 0 === r && n !== t && (null == n || n != n) || r > 0 + } + + function dn(e, t, r) { + var o = bn(e); + return o.size = new te(r).map((function (e) { + return e.size + })).min(), o.__iterate = function (e, t) { + for (var n, r = this.__iterator(M, t), o = 0; !(n = r.next()).done && !1 !== e(n.value, o++, this);) ; + return o + }, o.__iteratorUncached = function (e, o) { + var a = r.map((function (e) { + return e = n(e), W(o ? e.reverse() : e) + })), i = 0, s = !1; + return new F((function () { + var n; + return s || (n = a.map((function (e) { + return e.next() + })), s = n.some((function (e) { + return e.done + }))), s ? q() : U(e, i++, t.apply(null, n.map((function (e) { + return e.value + })))) + })) + }, o + } + + function mn(e, t) { + return ae(e) ? t : e.constructor(t) + } + + function vn(e) { + if (e !== Object(e)) throw new TypeError("Expected [K, V] tuple: " + e) + } + + function gn(e) { + return Ve(e.size), A(e) + } + + function yn(e) { + return s(e) ? r : u(e) ? o : a + } + + function bn(e) { + return Object.create((s(e) ? K : u(e) ? Y : G).prototype) + } + + function _n() { + return this._iter.cacheResult ? (this._iter.cacheResult(), this.size = this._iter.size, this) : $.prototype.cacheResult.call(this) + } + + function wn(e, t) { + return e > t ? 1 : e < t ? -1 : 0 + } + + function xn(e) { + var t = W(e); + if (!t) { + if (!J(e)) throw new TypeError("Expected iterable or array-like: " + e); + t = W(n(e)) + } + return t + } + + function En(e, t) { + var n, r = function (a) { + if (a instanceof r) return a; + if (!(this instanceof r)) return new r(a); + if (!n) { + n = !0; + var i = Object.keys(e); + kn(o, i), o.size = i.length, o._name = t, o._keys = i, o._defaultValues = e + } + this._map = We(a) + }, o = r.prototype = Object.create(Sn); + return o.constructor = r, r + } + + t(zt, We), zt.of = function () { + return this(arguments) + }, zt.prototype.toString = function () { + return this.__toString("OrderedMap {", "}") + }, zt.prototype.get = function (e, t) { + var n = this._map.get(e); + return void 0 !== n ? this._list.get(n)[1] : t + }, zt.prototype.clear = function () { + return 0 === this.size ? this : this.__ownerID ? (this.size = 0, this._map.clear(), this._list.clear(), this) : Ht() + }, zt.prototype.set = function (e, t) { + return Jt(this, e, t) + }, zt.prototype.remove = function (e) { + return Jt(this, e, b) + }, zt.prototype.wasAltered = function () { + return this._map.wasAltered() || this._list.wasAltered() + }, zt.prototype.__iterate = function (e, t) { + var n = this; + return this._list.__iterate((function (t) { + return t && e(t[1], t[0], n) + }), t) + }, zt.prototype.__iterator = function (e, t) { + return this._list.fromEntrySeq().__iterator(e, t) + }, zt.prototype.__ensureOwner = function (e) { + if (e === this.__ownerID) return this; + var t = this._map.__ensureOwner(e), n = this._list.__ensureOwner(e); + return e ? Wt(t, n, e, this.__hash) : (this.__ownerID = e, this._map = t, this._list = n, this) + }, zt.isOrderedMap = Vt, zt.prototype[d] = !0, zt.prototype[m] = zt.prototype.remove, t($t, K), $t.prototype.get = function (e, t) { + return this._iter.get(e, t) + }, $t.prototype.has = function (e) { + return this._iter.has(e) + }, $t.prototype.valueSeq = function () { + return this._iter.valueSeq() + }, $t.prototype.reverse = function () { + var e = this, t = Qt(this, !0); + return this._useKeys || (t.valueSeq = function () { + return e._iter.toSeq().reverse() + }), t + }, $t.prototype.map = function (e, t) { + var n = this, r = Xt(this, e, t); + return this._useKeys || (r.valueSeq = function () { + return n._iter.toSeq().map(e, t) + }), r + }, $t.prototype.__iterate = function (e, t) { + var n, r = this; + return this._iter.__iterate(this._useKeys ? function (t, n) { + return e(t, n, r) + } : (n = t ? gn(this) : 0, function (o) { + return e(o, t ? --n : n++, r) + }), t) + }, $t.prototype.__iterator = function (e, t) { + if (this._useKeys) return this._iter.__iterator(e, t); + var n = this._iter.__iterator(M, t), r = t ? gn(this) : 0; + return new F((function () { + var o = n.next(); + return o.done ? o : U(e, t ? --r : r++, o.value, o) + })) + }, $t.prototype[d] = !0, t(Kt, Y), Kt.prototype.includes = function (e) { + return this._iter.includes(e) + }, Kt.prototype.__iterate = function (e, t) { + var n = this, r = 0; + return this._iter.__iterate((function (t) { + return e(t, r++, n) + }), t) + }, Kt.prototype.__iterator = function (e, t) { + var n = this._iter.__iterator(M, t), r = 0; + return new F((function () { + var t = n.next(); + return t.done ? t : U(e, r++, t.value, t) + })) + }, t(Yt, G), Yt.prototype.has = function (e) { + return this._iter.includes(e) + }, Yt.prototype.__iterate = function (e, t) { + var n = this; + return this._iter.__iterate((function (t) { + return e(t, t, n) + }), t) + }, Yt.prototype.__iterator = function (e, t) { + var n = this._iter.__iterator(M, t); + return new F((function () { + var t = n.next(); + return t.done ? t : U(e, t.value, t.value, t) + })) + }, t(Gt, K), Gt.prototype.entrySeq = function () { + return this._iter.toSeq() + }, Gt.prototype.__iterate = function (e, t) { + var n = this; + return this._iter.__iterate((function (t) { + if (t) { + vn(t); + var r = i(t); + return e(r ? t.get(1) : t[1], r ? t.get(0) : t[0], n) + } + }), t) + }, Gt.prototype.__iterator = function (e, t) { + var n = this._iter.__iterator(M, t); + return new F((function () { + for (; ;) { + var t = n.next(); + if (t.done) return t; + var r = t.value; + if (r) { + vn(r); + var o = i(r); + return U(e, o ? r.get(0) : r[0], o ? r.get(1) : r[1], t) + } + } + })) + }, Kt.prototype.cacheResult = $t.prototype.cacheResult = Yt.prototype.cacheResult = Gt.prototype.cacheResult = _n, t(En, Ee), En.prototype.toString = function () { + return this.__toString(An(this) + " {", "}") + }, En.prototype.has = function (e) { + return this._defaultValues.hasOwnProperty(e) + }, En.prototype.get = function (e, t) { + if (!this.has(e)) return t; + var n = this._defaultValues[e]; + return this._map ? this._map.get(e, n) : n + }, En.prototype.clear = function () { + if (this.__ownerID) return this._map && this._map.clear(), this; + var e = this.constructor; + return e._empty || (e._empty = Cn(this, ot())) + }, En.prototype.set = function (e, t) { + if (!this.has(e)) throw new Error('Cannot set unknown key "' + e + '" on ' + An(this)); + if (this._map && !this._map.has(e) && t === this._defaultValues[e]) return this; + var n = this._map && this._map.set(e, t); + return this.__ownerID || n === this._map ? this : Cn(this, n) + }, En.prototype.remove = function (e) { + if (!this.has(e)) return this; + var t = this._map && this._map.remove(e); + return this.__ownerID || t === this._map ? this : Cn(this, t) + }, En.prototype.wasAltered = function () { + return this._map.wasAltered() + }, En.prototype.__iterator = function (e, t) { + var n = this; + return r(this._defaultValues).map((function (e, t) { + return n.get(t) + })).__iterator(e, t) + }, En.prototype.__iterate = function (e, t) { + var n = this; + return r(this._defaultValues).map((function (e, t) { + return n.get(t) + })).__iterate(e, t) + }, En.prototype.__ensureOwner = function (e) { + if (e === this.__ownerID) return this; + var t = this._map && this._map.__ensureOwner(e); + return e ? Cn(this, t, e) : (this.__ownerID = e, this._map = t, this) + }; + var Sn = En.prototype; + + function Cn(e, t, n) { + var r = Object.create(Object.getPrototypeOf(e)); + return r._map = t, r.__ownerID = n, r + } + + function An(e) { + return e._name || e.constructor.name || "Record" + } + + function kn(e, t) { + try { + t.forEach(On.bind(void 0, e)) + } catch (e) { + } + } + + function On(e, t) { + Object.defineProperty(e, t, { + get: function () { + return this.get(t) + }, set: function (e) { + _e(this.__ownerID, "Cannot set on an immutable record."), this.set(t, e) + } + }) + } + + function jn(e) { + return null == e ? Dn() : Tn(e) && !l(e) ? e : Dn().withMutations((function (t) { + var n = a(e); + Ve(n.size), n.forEach((function (e) { + return t.add(e) + })) + })) + } + + function Tn(e) { + return !(!e || !e[Pn]) + } + + Sn[m] = Sn.remove, Sn.deleteIn = Sn.removeIn = Ke.removeIn, Sn.merge = Ke.merge, Sn.mergeWith = Ke.mergeWith, Sn.mergeIn = Ke.mergeIn, Sn.mergeDeep = Ke.mergeDeep, Sn.mergeDeepWith = Ke.mergeDeepWith, Sn.mergeDeepIn = Ke.mergeDeepIn, Sn.setIn = Ke.setIn, Sn.update = Ke.update, Sn.updateIn = Ke.updateIn, Sn.withMutations = Ke.withMutations, Sn.asMutable = Ke.asMutable, Sn.asImmutable = Ke.asImmutable, t(jn, Ce), jn.of = function () { + return this(arguments) + }, jn.fromKeys = function (e) { + return this(r(e).keySeq()) + }, jn.prototype.toString = function () { + return this.__toString("Set {", "}") + }, jn.prototype.has = function (e) { + return this._map.has(e) + }, jn.prototype.add = function (e) { + return Mn(this, this._map.set(e, !0)) + }, jn.prototype.remove = function (e) { + return Mn(this, this._map.remove(e)) + }, jn.prototype.clear = function () { + return Mn(this, this._map.clear()) + }, jn.prototype.union = function () { + var t = e.call(arguments, 0); + return 0 === (t = t.filter((function (e) { + return 0 !== e.size + }))).length ? this : 0 !== this.size || this.__ownerID || 1 !== t.length ? this.withMutations((function (e) { + for (var n = 0; n < t.length; n++) a(t[n]).forEach((function (t) { + return e.add(t) + })) + })) : this.constructor(t[0]) + }, jn.prototype.intersect = function () { + var t = e.call(arguments, 0); + if (0 === t.length) return this; + t = t.map((function (e) { + return a(e) + })); + var n = this; + return this.withMutations((function (e) { + n.forEach((function (n) { + t.every((function (e) { + return e.includes(n) + })) || e.remove(n) + })) + })) + }, jn.prototype.subtract = function () { + var t = e.call(arguments, 0); + if (0 === t.length) return this; + t = t.map((function (e) { + return a(e) + })); + var n = this; + return this.withMutations((function (e) { + n.forEach((function (n) { + t.some((function (e) { + return e.includes(n) + })) && e.remove(n) + })) + })) + }, jn.prototype.merge = function () { + return this.union.apply(this, arguments) + }, jn.prototype.mergeWith = function (t) { + var n = e.call(arguments, 1); + return this.union.apply(this, n) + }, jn.prototype.sort = function (e) { + return Ln(pn(this, e)) + }, jn.prototype.sortBy = function (e, t) { + return Ln(pn(this, t, e)) + }, jn.prototype.wasAltered = function () { + return this._map.wasAltered() + }, jn.prototype.__iterate = function (e, t) { + var n = this; + return this._map.__iterate((function (t, r) { + return e(r, r, n) + }), t) + }, jn.prototype.__iterator = function (e, t) { + return this._map.map((function (e, t) { + return t + })).__iterator(e, t) + }, jn.prototype.__ensureOwner = function (e) { + if (e === this.__ownerID) return this; + var t = this._map.__ensureOwner(e); + return e ? this.__make(t, e) : (this.__ownerID = e, this._map = t, this) + }, jn.isSet = Tn; + var In, Pn = "@@__IMMUTABLE_SET__@@", Nn = jn.prototype; + + function Mn(e, t) { + return e.__ownerID ? (e.size = t.size, e._map = t, e) : t === e._map ? e : 0 === t.size ? e.__empty() : e.__make(t) + } + + function Rn(e, t) { + var n = Object.create(Nn); + return n.size = e ? e.size : 0, n._map = e, n.__ownerID = t, n + } + + function Dn() { + return In || (In = Rn(ot())) + } + + function Ln(e) { + return null == e ? zn() : Bn(e) ? e : zn().withMutations((function (t) { + var n = a(e); + Ve(n.size), n.forEach((function (e) { + return t.add(e) + })) + })) + } + + function Bn(e) { + return Tn(e) && l(e) + } + + Nn[Pn] = !0, Nn[m] = Nn.remove, Nn.mergeDeep = Nn.merge, Nn.mergeDeepWith = Nn.mergeWith, Nn.withMutations = Ke.withMutations, Nn.asMutable = Ke.asMutable, Nn.asImmutable = Ke.asImmutable, Nn.__empty = Dn, Nn.__make = Rn, t(Ln, jn), Ln.of = function () { + return this(arguments) + }, Ln.fromKeys = function (e) { + return this(r(e).keySeq()) + }, Ln.prototype.toString = function () { + return this.__toString("OrderedSet {", "}") + }, Ln.isOrderedSet = Bn; + var Fn, Un = Ln.prototype; + + function qn(e, t) { + var n = Object.create(Un); + return n.size = e ? e.size : 0, n._map = e, n.__ownerID = t, n + } + + function zn() { + return Fn || (Fn = qn(Ht())) + } + + function Vn(e) { + return null == e ? Yn() : Wn(e) ? e : Yn().unshiftAll(e) + } + + function Wn(e) { + return !(!e || !e[Jn]) + } + + Un[d] = !0, Un.__empty = zn, Un.__make = qn, t(Vn, Se), Vn.of = function () { + return this(arguments) + }, Vn.prototype.toString = function () { + return this.__toString("Stack [", "]") + }, Vn.prototype.get = function (e, t) { + var n = this._head; + for (e = k(this, e); n && e--;) n = n.next; + return n ? n.value : t + }, Vn.prototype.peek = function () { + return this._head && this._head.value + }, Vn.prototype.push = function () { + if (0 === arguments.length) return this; + for (var e = this.size + arguments.length, t = this._head, n = arguments.length - 1; n >= 0; n--) t = { + value: arguments[n], + next: t + }; + return this.__ownerID ? (this.size = e, this._head = t, this.__hash = void 0, this.__altered = !0, this) : Kn(e, t) + }, Vn.prototype.pushAll = function (e) { + if (0 === (e = o(e)).size) return this; + Ve(e.size); + var t = this.size, n = this._head; + return e.reverse().forEach((function (e) { + t++, n = {value: e, next: n} + })), this.__ownerID ? (this.size = t, this._head = n, this.__hash = void 0, this.__altered = !0, this) : Kn(t, n) + }, Vn.prototype.pop = function () { + return this.slice(1) + }, Vn.prototype.unshift = function () { + return this.push.apply(this, arguments) + }, Vn.prototype.unshiftAll = function (e) { + return this.pushAll(e) + }, Vn.prototype.shift = function () { + return this.pop.apply(this, arguments) + }, Vn.prototype.clear = function () { + return 0 === this.size ? this : this.__ownerID ? (this.size = 0, this._head = void 0, this.__hash = void 0, this.__altered = !0, this) : Yn() + }, Vn.prototype.slice = function (e, t) { + if (j(e, t, this.size)) return this; + var n = T(e, this.size); + if (I(t, this.size) !== this.size) return Se.prototype.slice.call(this, e, t); + for (var r = this.size - n, o = this._head; n--;) o = o.next; + return this.__ownerID ? (this.size = r, this._head = o, this.__hash = void 0, this.__altered = !0, this) : Kn(r, o) + }, Vn.prototype.__ensureOwner = function (e) { + return e === this.__ownerID ? this : e ? Kn(this.size, this._head, e, this.__hash) : (this.__ownerID = e, this.__altered = !1, this) + }, Vn.prototype.__iterate = function (e, t) { + if (t) return this.reverse().__iterate(e); + for (var n = 0, r = this._head; r && !1 !== e(r.value, n++, this);) r = r.next; + return n + }, Vn.prototype.__iterator = function (e, t) { + if (t) return this.reverse().__iterator(e); + var n = 0, r = this._head; + return new F((function () { + if (r) { + var t = r.value; + return r = r.next, U(e, n++, t) + } + return q() + })) + }, Vn.isStack = Wn; + var Hn, Jn = "@@__IMMUTABLE_STACK__@@", $n = Vn.prototype; + + function Kn(e, t, n, r) { + var o = Object.create($n); + return o.size = e, o._head = t, o.__ownerID = n, o.__hash = r, o.__altered = !1, o + } + + function Yn() { + return Hn || (Hn = Kn(0)) + } + + function Gn(e, t) { + var n = function (n) { + e.prototype[n] = t[n] + }; + return Object.keys(t).forEach(n), Object.getOwnPropertySymbols && Object.getOwnPropertySymbols(t).forEach(n), e + } + + $n[Jn] = !0, $n.withMutations = Ke.withMutations, $n.asMutable = Ke.asMutable, $n.asImmutable = Ke.asImmutable, $n.wasAltered = Ke.wasAltered, n.Iterator = F, Gn(n, { + toArray: function () { + Ve(this.size); + var e = new Array(this.size || 0); + return this.valueSeq().__iterate((function (t, n) { + e[n] = t + })), e + }, toIndexedSeq: function () { + return new Kt(this) + }, toJS: function () { + return this.toSeq().map((function (e) { + return e && "function" == typeof e.toJS ? e.toJS() : e + })).__toJS() + }, toJSON: function () { + return this.toSeq().map((function (e) { + return e && "function" == typeof e.toJSON ? e.toJSON() : e + })).__toJS() + }, toKeyedSeq: function () { + return new $t(this, !0) + }, toMap: function () { + return We(this.toKeyedSeq()) + }, toObject: function () { + Ve(this.size); + var e = {}; + return this.__iterate((function (t, n) { + e[n] = t + })), e + }, toOrderedMap: function () { + return zt(this.toKeyedSeq()) + }, toOrderedSet: function () { + return Ln(s(this) ? this.valueSeq() : this) + }, toSet: function () { + return jn(s(this) ? this.valueSeq() : this) + }, toSetSeq: function () { + return new Yt(this) + }, toSeq: function () { + return u(this) ? this.toIndexedSeq() : s(this) ? this.toKeyedSeq() : this.toSetSeq() + }, toStack: function () { + return Vn(s(this) ? this.valueSeq() : this) + }, toList: function () { + return St(s(this) ? this.valueSeq() : this) + }, toString: function () { + return "[Iterable]" + }, __toString: function (e, t) { + return 0 === this.size ? e + t : e + " " + this.toSeq().map(this.__toStringMapper).join(", ") + " " + t + }, concat: function () { + return mn(this, sn(this, e.call(arguments, 0))) + }, includes: function (e) { + return this.some((function (t) { + return ge(t, e) + })) + }, entries: function () { + return this.__iterator(R) + }, every: function (e, t) { + Ve(this.size); + var n = !0; + return this.__iterate((function (r, o, a) { + if (!e.call(t, r, o, a)) return n = !1, !1 + })), n + }, filter: function (e, t) { + return mn(this, en(this, e, t, !0)) + }, find: function (e, t, n) { + var r = this.findEntry(e, t); + return r ? r[1] : n + }, forEach: function (e, t) { + return Ve(this.size), this.__iterate(t ? e.bind(t) : e) + }, join: function (e) { + Ve(this.size), e = void 0 !== e ? "" + e : ","; + var t = "", n = !0; + return this.__iterate((function (r) { + n ? n = !1 : t += e, t += null != r ? r.toString() : "" + })), t + }, keys: function () { + return this.__iterator(N) + }, map: function (e, t) { + return mn(this, Xt(this, e, t)) + }, reduce: function (e, t, n) { + var r, o; + return Ve(this.size), arguments.length < 2 ? o = !0 : r = t, this.__iterate((function (t, a, i) { + o ? (o = !1, r = t) : r = e.call(n, r, t, a, i) + })), r + }, reduceRight: function (e, t, n) { + var r = this.toKeyedSeq().reverse(); + return r.reduce.apply(r, arguments) + }, reverse: function () { + return mn(this, Qt(this, !0)) + }, slice: function (e, t) { + return mn(this, rn(this, e, t, !0)) + }, some: function (e, t) { + return !this.every(tr(e), t) + }, sort: function (e) { + return mn(this, pn(this, e)) + }, values: function () { + return this.__iterator(M) + }, butLast: function () { + return this.slice(0, -1) + }, isEmpty: function () { + return void 0 !== this.size ? 0 === this.size : !this.some((function () { + return !0 + })) + }, count: function (e, t) { + return A(e ? this.toSeq().filter(e, t) : this) + }, countBy: function (e, t) { + return tn(this, e, t) + }, equals: function (e) { + return ye(this, e) + }, entrySeq: function () { + var e = this; + if (e._cache) return new te(e._cache); + var t = e.toSeq().map(er).toIndexedSeq(); + return t.fromEntrySeq = function () { + return e.toSeq() + }, t + }, filterNot: function (e, t) { + return this.filter(tr(e), t) + }, findEntry: function (e, t, n) { + var r = n; + return this.__iterate((function (n, o, a) { + if (e.call(t, n, o, a)) return r = [o, n], !1 + })), r + }, findKey: function (e, t) { + var n = this.findEntry(e, t); + return n && n[0] + }, findLast: function (e, t, n) { + return this.toKeyedSeq().reverse().find(e, t, n) + }, findLastEntry: function (e, t, n) { + return this.toKeyedSeq().reverse().findEntry(e, t, n) + }, findLastKey: function (e, t) { + return this.toKeyedSeq().reverse().findKey(e, t) + }, first: function () { + return this.find(O) + }, flatMap: function (e, t) { + return mn(this, cn(this, e, t)) + }, flatten: function (e) { + return mn(this, un(this, e, !0)) + }, fromEntrySeq: function () { + return new Gt(this) + }, get: function (e, t) { + return this.find((function (t, n) { + return ge(n, e) + }), void 0, t) + }, getIn: function (e, t) { + for (var n, r = this, o = xn(e); !(n = o.next()).done;) { + var a = n.value; + if ((r = r && r.get ? r.get(a, b) : b) === b) return t + } + return r + }, groupBy: function (e, t) { + return nn(this, e, t) + }, has: function (e) { + return this.get(e, b) !== b + }, hasIn: function (e) { + return this.getIn(e, b) !== b + }, isSubset: function (e) { + return e = "function" == typeof e.includes ? e : n(e), this.every((function (t) { + return e.includes(t) + })) + }, isSuperset: function (e) { + return (e = "function" == typeof e.isSubset ? e : n(e)).isSubset(this) + }, keyOf: function (e) { + return this.findKey((function (t) { + return ge(t, e) + })) + }, keySeq: function () { + return this.toSeq().map(Qn).toIndexedSeq() + }, last: function () { + return this.toSeq().reverse().first() + }, lastKeyOf: function (e) { + return this.toKeyedSeq().reverse().keyOf(e) + }, max: function (e) { + return fn(this, e) + }, maxBy: function (e, t) { + return fn(this, t, e) + }, min: function (e) { + return fn(this, e ? nr(e) : ar) + }, minBy: function (e, t) { + return fn(this, t ? nr(t) : ar, e) + }, rest: function () { + return this.slice(1) + }, skip: function (e) { + return this.slice(Math.max(0, e)) + }, skipLast: function (e) { + return mn(this, this.toSeq().reverse().skip(e).reverse()) + }, skipWhile: function (e, t) { + return mn(this, an(this, e, t, !0)) + }, skipUntil: function (e, t) { + return this.skipWhile(tr(e), t) + }, sortBy: function (e, t) { + return mn(this, pn(this, t, e)) + }, take: function (e) { + return this.slice(0, Math.max(0, e)) + }, takeLast: function (e) { + return mn(this, this.toSeq().reverse().take(e).reverse()) + }, takeWhile: function (e, t) { + return mn(this, on(this, e, t)) + }, takeUntil: function (e, t) { + return this.takeWhile(tr(e), t) + }, valueSeq: function () { + return this.toIndexedSeq() + }, hashCode: function () { + return this.__hash || (this.__hash = ir(this)) + } + }); + var Zn = n.prototype; + Zn[p] = !0, Zn[B] = Zn.values, Zn.__toJS = Zn.toArray, Zn.__toStringMapper = rr, Zn.inspect = Zn.toSource = function () { + return this.toString() + }, Zn.chain = Zn.flatMap, Zn.contains = Zn.includes, Gn(r, { + flip: function () { + return mn(this, Zt(this)) + }, mapEntries: function (e, t) { + var n = this, r = 0; + return mn(this, this.toSeq().map((function (o, a) { + return e.call(t, [a, o], r++, n) + })).fromEntrySeq()) + }, mapKeys: function (e, t) { + var n = this; + return mn(this, this.toSeq().flip().map((function (r, o) { + return e.call(t, r, o, n) + })).flip()) + } + }); + var Xn = r.prototype; + + function Qn(e, t) { + return t + } + + function er(e, t) { + return [t, e] + } + + function tr(e) { + return function () { + return !e.apply(this, arguments) + } + } + + function nr(e) { + return function () { + return -e.apply(this, arguments) + } + } + + function rr(e) { + return "string" == typeof e ? JSON.stringify(e) : String(e) + } + + function or() { + return C(arguments) + } + + function ar(e, t) { + return e < t ? 1 : e > t ? -1 : 0 + } + + function ir(e) { + if (e.size === 1 / 0) return 0; + var t = l(e), n = s(e), r = t ? 1 : 0; + return sr(e.__iterate(n ? t ? function (e, t) { + r = 31 * r + ur(Oe(e), Oe(t)) | 0 + } : function (e, t) { + r = r + ur(Oe(e), Oe(t)) | 0 + } : t ? function (e) { + r = 31 * r + Oe(e) | 0 + } : function (e) { + r = r + Oe(e) | 0 + }), r) + } + + function sr(e, t) { + return t = Ae(t, 3432918353), t = Ae(t << 15 | t >>> -15, 461845907), t = Ae(t << 13 | t >>> -13, 5), t = Ae((t = (t + 3864292196 | 0) ^ e) ^ t >>> 16, 2246822507), t = ke((t = Ae(t ^ t >>> 13, 3266489909)) ^ t >>> 16) + } + + function ur(e, t) { + return e ^ t + 2654435769 + (e << 6) + (e >> 2) | 0 + } + + return Xn[f] = !0, Xn[B] = Zn.entries, Xn.__toJS = Zn.toObject, Xn.__toStringMapper = function (e, t) { + return JSON.stringify(t) + ": " + rr(e) + }, Gn(o, { + toKeyedSeq: function () { + return new $t(this, !1) + }, filter: function (e, t) { + return mn(this, en(this, e, t, !1)) + }, findIndex: function (e, t) { + var n = this.findEntry(e, t); + return n ? n[0] : -1 + }, indexOf: function (e) { + var t = this.keyOf(e); + return void 0 === t ? -1 : t + }, lastIndexOf: function (e) { + var t = this.lastKeyOf(e); + return void 0 === t ? -1 : t + }, reverse: function () { + return mn(this, Qt(this, !1)) + }, slice: function (e, t) { + return mn(this, rn(this, e, t, !1)) + }, splice: function (e, t) { + var n = arguments.length; + if (t = Math.max(0 | t, 0), 0 === n || 2 === n && !t) return this; + e = T(e, e < 0 ? this.count() : this.size); + var r = this.slice(0, e); + return mn(this, 1 === n ? r : r.concat(C(arguments, 2), this.slice(e + t))) + }, findLastIndex: function (e, t) { + var n = this.findLastEntry(e, t); + return n ? n[0] : -1 + }, first: function () { + return this.get(0) + }, flatten: function (e) { + return mn(this, un(this, e, !1)) + }, get: function (e, t) { + return (e = k(this, e)) < 0 || this.size === 1 / 0 || void 0 !== this.size && e > this.size ? t : this.find((function (t, n) { + return n === e + }), void 0, t) + }, has: function (e) { + return (e = k(this, e)) >= 0 && (void 0 !== this.size ? this.size === 1 / 0 || e < this.size : -1 !== this.indexOf(e)) + }, interpose: function (e) { + return mn(this, ln(this, e)) + }, interleave: function () { + var e = [this].concat(C(arguments)), t = dn(this.toSeq(), Y.of, e), n = t.flatten(!0); + return t.size && (n.size = t.size * e.length), mn(this, n) + }, keySeq: function () { + return we(0, this.size) + }, last: function () { + return this.get(-1) + }, skipWhile: function (e, t) { + return mn(this, an(this, e, t, !1)) + }, zip: function () { + return mn(this, dn(this, or, [this].concat(C(arguments)))) + }, zipWith: function (e) { + var t = C(arguments); + return t[0] = this, mn(this, dn(this, e, t)) + } + }), o.prototype[h] = !0, o.prototype[d] = !0, Gn(a, { + get: function (e, t) { + return this.has(e) ? e : t + }, includes: function (e) { + return this.has(e) + }, keySeq: function () { + return this.valueSeq() + } + }), a.prototype.has = Zn.includes, a.prototype.contains = a.prototype.includes, Gn(K, r.prototype), Gn(Y, o.prototype), Gn(G, a.prototype), Gn(Ee, r.prototype), Gn(Se, o.prototype), Gn(Ce, a.prototype), { + Iterable: n, + Seq: $, + Collection: xe, + Map: We, + OrderedMap: zt, + List: St, + Stack: Vn, + Set: jn, + OrderedSet: Ln, + Record: En, + Range: we, + Repeat: be, + is: ge, + fromJS: he + } + }() + }, function (e, t, n) { + e.exports = n(580) + }, function (e, t, n) { + var r = n(243); + e.exports = function (e, t, n) { + return t in e ? r(e, t, {value: n, enumerable: !0, configurable: !0, writable: !0}) : e[t] = n, e + }, e.exports.default = e.exports, e.exports.__esModule = !0 + }, function (e, t, n) { + e.exports = n(611) + }, function (e, t, n) { + "use strict"; + (function (e) { + n.d(t, "t", (function () { + return be + })), n.d(t, "A", (function () { + return _e + })), n.d(t, "i", (function () { + return we + })), n.d(t, "w", (function () { + return xe + })), n.d(t, "r", (function () { + return Ee + })), n.d(t, "u", (function () { + return Se + })), n.d(t, "s", (function () { + return Ce + })), n.d(t, "p", (function () { + return Ae + })), n.d(t, "v", (function () { + return ke + })), n.d(t, "y", (function () { + return Oe + })), n.d(t, "z", (function () { + return je + })), n.d(t, "K", (function () { + return Te + })), n.d(t, "f", (function () { + return Ie + })), n.d(t, "n", (function () { + return Pe + })), n.d(t, "h", (function () { + return Ne + })), n.d(t, "E", (function () { + return Me + })), n.d(t, "L", (function () { + return De + })), n.d(t, "o", (function () { + return ze + })), n.d(t, "D", (function () { + return Ve + })), n.d(t, "a", (function () { + return We + })), n.d(t, "I", (function () { + return He + })), n.d(t, "b", (function () { + return Je + })), n.d(t, "H", (function () { + return $e + })), n.d(t, "G", (function () { + return Ke + })), n.d(t, "F", (function () { + return Ye + })), n.d(t, "k", (function () { + return Ge + })), n.d(t, "d", (function () { + return Ze + })), n.d(t, "g", (function () { + return Xe + })), n.d(t, "m", (function () { + return Qe + })), n.d(t, "l", (function () { + return et + })), n.d(t, "e", (function () { + return tt + })), n.d(t, "J", (function () { + return nt + })), n.d(t, "x", (function () { + return rt + })), n.d(t, "B", (function () { + return ot + })), n.d(t, "C", (function () { + return at + })), n.d(t, "j", (function () { + return it + })), n.d(t, "c", (function () { + return st + })), n.d(t, "q", (function () { + return ct + })); + var r = n(15), o = n.n(r), a = (n(16), n(51)), i = n.n(a), s = n(19), u = n.n(s), c = n(13), l = n.n(c), + p = n(4), f = n.n(p), h = n(85), d = n.n(h), m = n(2), v = n.n(m), g = n(18), y = n.n(g), b = n(12), + _ = n.n(b), w = n(17), x = n.n(w), E = (n(30), n(21)), S = n.n(E), C = n(22), A = n.n(C), k = n(211), + O = n.n(k), j = n(23), T = n.n(j), I = n(36), P = n.n(I), N = (n(38), n(32)), M = n.n(N), R = n(14), + D = n.n(R), L = n(66), B = n.n(L), F = n(174), U = n.n(F), q = n(103), z = n.n(q), V = n(1), W = n.n(V), + H = n(513), J = n(514), $ = n.n(J), K = n(285), Y = n.n(K), G = n(286), Z = n.n(G), X = n(212), + Q = n.n(X), ee = n(343), te = n.n(ee), ne = n(125), re = n.n(ne), oe = n(65), ae = n.n(oe), ie = n(144), + se = n(27), ue = n(516), ce = n.n(ue), le = n(146), pe = n(517), fe = n.n(pe), he = n(518), + de = n.n(he), me = n(77), ve = n.n(me), ge = "default", ye = function (e) { + return W.a.Iterable.isIterable(e) + }; + + function be(e) { + try { + var t = JSON.parse(e); + if (t && "object" === u()(t)) return t + } catch (e) { + } + return !1 + } + + function _e(e) { + return Se(e) ? ye(e) ? e.toJS() : e : {} + } + + function we(e) { + var t, n; + if (ye(e)) return e; + if (e instanceof se.a.File) return e; + if (!Se(e)) return e; + if (l()(e)) return f()(n = W.a.Seq(e)).call(n, we).toList(); + if (ae()(d()(e))) { + var r, o = function (e) { + if (!ae()(d()(e))) return e; + var t, n = {}, r = "_**[]", o = {}, a = i()(d()(e).call(e)); + try { + for (a.s(); !(t = a.n()).done;) { + var s = t.value; + if (n[s[0]] || o[s[0]] && o[s[0]].containsMultiple) { + var u, c, l, p; + if (!o[s[0]]) o[s[0]] = { + containsMultiple: !0, + length: 1 + }, n[v()(l = v()(p = "".concat(s[0])).call(p, r)).call(l, o[s[0]].length)] = n[s[0]], delete n[s[0]]; + o[s[0]].length += 1, n[v()(u = v()(c = "".concat(s[0])).call(c, r)).call(u, o[s[0]].length)] = s[1] + } else n[s[0]] = s[1] + } + } catch (e) { + a.e(e) + } finally { + a.f() + } + return n + }(e); + return f()(r = W.a.OrderedMap(o)).call(r, we) + } + return f()(t = W.a.OrderedMap(e)).call(t, we) + } + + function xe(e) { + return l()(e) ? e : [e] + } + + function Ee(e) { + return "function" == typeof e + } + + function Se(e) { + return !!e && "object" === u()(e) + } + + function Ce(e) { + return "function" == typeof e + } + + function Ae(e) { + return l()(e) + } + + var ke = Z.a; + + function Oe(e, t) { + var n; + return S()(n = x()(e)).call(n, (function (n, r) { + return n[r] = t(e[r], r), n + }), {}) + } + + function je(e, t) { + var n; + return S()(n = x()(e)).call(n, (function (n, r) { + var o = t(e[r], r); + return o && "object" === u()(o) && A()(n, o), n + }), {}) + } + + function Te(e) { + return function (t) { + t.dispatch, t.getState; + return function (t) { + return function (n) { + return "function" == typeof n ? n(e()) : t(n) + } + } + } + } + + function Ie(e) { + var t, n = e.keySeq(); + return n.contains(ge) ? ge : O()(t = _()(n).call(n, (function (e) { + return "2" === (e + "")[0] + }))).call(t).first() + } + + function Pe(e, t) { + if (!W.a.Iterable.isIterable(e)) return W.a.List(); + var n = e.getIn(l()(t) ? t : [t]); + return W.a.List.isList(n) ? n : W.a.List() + } + + function Ne(e) { + var t, + n = [/filename\*=[^']+'\w*'"([^"]+)";?/i, /filename\*=[^']+'\w*'([^;]+);?/i, /filename="([^;]*);?"/i, /filename=([^;]*);?/i]; + if (P()(n).call(n, (function (n) { + return null !== (t = n.exec(e)) + })), null !== t && t.length > 1) try { + return decodeURIComponent(t[1]) + } catch (e) { + console.error(e) + } + return null + } + + function Me(e) { + return t = e.replace(/\.[^./]*$/, ""), Y()($()(t)); + var t + } + + function Re(e, t, n, r, a) { + if (!t) return []; + var i = [], s = t.get("nullable"), c = t.get("required"), p = t.get("maximum"), h = t.get("minimum"), + d = t.get("type"), m = t.get("format"), g = t.get("maxLength"), b = t.get("minLength"), + w = t.get("uniqueItems"), x = t.get("maxItems"), E = t.get("minItems"), S = t.get("pattern"), + C = n || c; + if (s && null === e || !d || !(C || "array" === d || !(!C && !(null != e)))) return []; + var A = "string" === d && e, k = "array" === d && l()(e) && e.length, + O = "array" === d && W.a.List.isList(e) && e.count(), + j = [A, k, O, "array" === d && "string" == typeof e && e, "file" === d && e instanceof se.a.File, "boolean" === d && (e || !1 === e), "number" === d && (e || 0 === e), "integer" === d && (e || 0 === e), "object" === d && "object" === u()(e) && null !== e, "object" === d && "string" == typeof e && e], + T = P()(j).call(j, (function (e) { + return !!e + })); + if (C && !T && !r) return i.push("Required field is not provided"), i; + if ("object" === d && (null === a || "application/json" === a)) { + var I, N = e; + if ("string" == typeof e) try { + N = JSON.parse(e) + } catch (e) { + return i.push("Parameter string value must be valid JSON"), i + } + if (t && t.has("required") && Ce(c.isList) && c.isList() && y()(c).call(c, (function (e) { + void 0 === N[e] && i.push({propKey: e, error: "Required property not found"}) + })), t && t.has("properties")) y()(I = t.get("properties")).call(I, (function (e, t) { + var n = Re(N[t], e, !1, r, a); + i.push.apply(i, o()(f()(n).call(n, (function (e) { + return {propKey: t, error: e} + })))) + })) + } + if (S) { + var M = function (e, t) { + if (!new RegExp(t).test(e)) return "Value must follow pattern " + t + }(e, S); + M && i.push(M) + } + if (E && "array" === d) { + var R = function (e, t) { + var n; + if (!e && t >= 1 || e && e.length < t) return v()(n = "Array must contain at least ".concat(t, " item")).call(n, 1 === t ? "" : "s") + }(e, E); + R && i.push(R) + } + if (x && "array" === d) { + var D = function (e, t) { + var n; + if (e && e.length > t) return v()(n = "Array must not contain more then ".concat(t, " item")).call(n, 1 === t ? "" : "s") + }(e, x); + D && i.push({needRemove: !0, error: D}) + } + if (w && "array" === d) { + var L = function (e, t) { + if (e && ("true" === t || !0 === t)) { + var n = Object(V.fromJS)(e), r = n.toSet(); + if (e.length > r.size) { + var o = Object(V.Set)(); + if (y()(n).call(n, (function (e, t) { + _()(n).call(n, (function (t) { + return Ce(t.equals) ? t.equals(e) : t === e + })).size > 1 && (o = o.add(t)) + })), 0 !== o.size) return f()(o).call(o, (function (e) { + return {index: e, error: "No duplicates allowed."} + })).toArray() + } + } + }(e, w); + L && i.push.apply(i, o()(L)) + } + if (g || 0 === g) { + var B = function (e, t) { + var n; + if (e.length > t) return v()(n = "Value must be no longer than ".concat(t, " character")).call(n, 1 !== t ? "s" : "") + }(e, g); + B && i.push(B) + } + if (b) { + var F = function (e, t) { + var n; + if (e.length < t) return v()(n = "Value must be at least ".concat(t, " character")).call(n, 1 !== t ? "s" : "") + }(e, b); + F && i.push(F) + } + if (p || 0 === p) { + var U = function (e, t) { + if (e > t) return "Value must be less than ".concat(t) + }(e, p); + U && i.push(U) + } + if (h || 0 === h) { + var q = function (e, t) { + if (e < t) return "Value must be greater than ".concat(t) + }(e, h); + q && i.push(q) + } + if ("string" === d) { + var z; + if (!(z = "date-time" === m ? function (e) { + if (isNaN(Date.parse(e))) return "Value must be a DateTime" + }(e) : "uuid" === m ? function (e) { + if (e = e.toString().toLowerCase(), !/^[{(]?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}[)}]?$/.test(e)) return "Value must be a Guid" + }(e) : function (e) { + if (e && "string" != typeof e) return "Value must be a string" + }(e))) return i; + i.push(z) + } else if ("boolean" === d) { + var H = function (e) { + if ("true" !== e && "false" !== e && !0 !== e && !1 !== e) return "Value must be a boolean" + }(e); + if (!H) return i; + i.push(H) + } else if ("number" === d) { + var J = function (e) { + if (!/^-?\d+(\.?\d+)?$/.test(e)) return "Value must be a number" + }(e); + if (!J) return i; + i.push(J) + } else if ("integer" === d) { + var $ = function (e) { + if (!/^-?\d+$/.test(e)) return "Value must be an integer" + }(e); + if (!$) return i; + i.push($) + } else if ("array" === d) { + if (!k && !O) return i; + e && y()(e).call(e, (function (e, n) { + var s = Re(e, t.get("items"), !1, r, a); + i.push.apply(i, o()(f()(s).call(s, (function (e) { + return {index: n, error: e} + })))) + })) + } else if ("file" === d) { + var K = function (e) { + if (e && !(e instanceof se.a.File)) return "Value must be a file" + }(e); + if (!K) return i; + i.push(K) + } + return i + } + + var De = function (e, t) { + var n = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {}, r = n.isOAS3, + o = void 0 !== r && r, a = n.bypassRequiredCheck, i = void 0 !== a && a, s = e.get("required"), + u = Object(le.a)(e, {isOAS3: o}), c = u.schema, l = u.parameterContentMediaType; + return Re(t, c, s, i, l) + }, Le = function (e, t, n) { + if (e && (!e.xml || !e.xml.name)) { + if (e.xml = e.xml || {}, !e.$$ref) return e.type || e.items || e.properties || e.additionalProperties ? '\n\x3c!-- XML example cannot be generated; root element name is undefined --\x3e' : null; + var r = e.$$ref.match(/\S*\/(\S+)$/); + e.xml.name = r[1] + } + return Object(ie.memoizedCreateXMLExample)(e, t, n) + }, Be = [{when: /json/, shouldStringifyTypes: ["string"]}], Fe = ["object"], Ue = function (e, t, n, r) { + var a = Object(ie.memoizedSampleFromSchema)(e, t, r), i = u()(a), + s = S()(Be).call(Be, (function (e, t) { + var r; + return t.when.test(n) ? v()(r = []).call(r, o()(e), o()(t.shouldStringifyTypes)) : e + }), Fe); + return te()(s, (function (e) { + return e === i + })) ? M()(a, null, 2) : a + }, qe = function (e, t, n, r) { + var o, a = Ue(e, t, n, r); + try { + "\n" === (o = ve.a.safeDump(ve.a.safeLoad(a), {lineWidth: -1}))[o.length - 1] && (o = T()(o).call(o, 0, o.length - 1)) + } catch (e) { + return console.error(e), "error: could not generate yaml example" + } + return o.replace(/\t/g, " ") + }, ze = function (e) { + var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : "", + n = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {}, + r = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : void 0; + return e && Ce(e.toJS) && (e = e.toJS()), r && Ce(r.toJS) && (r = r.toJS()), /xml/.test(t) ? Le(e, n, r) : /(yaml|yml)/.test(t) ? qe(e, n, t, r) : Ue(e, n, t, r) + }, Ve = function () { + var e = {}, t = se.a.location.search; + if (!t) return {}; + if ("" != t) { + var n = t.substr(1).split("&"); + for (var r in n) n.hasOwnProperty(r) && (r = n[r].split("="), e[decodeURIComponent(r[0])] = r[1] && decodeURIComponent(r[1]) || "") + } + return e + }, We = function (t) { + return (t instanceof e ? t : e.from(t.toString(), "utf-8")).toString("base64") + }, He = { + operationsSorter: { + alpha: function (e, t) { + return e.get("path").localeCompare(t.get("path")) + }, method: function (e, t) { + return e.get("method").localeCompare(t.get("method")) + } + }, tagsSorter: { + alpha: function (e, t) { + return e.localeCompare(t) + } + } + }, Je = function (e) { + var t = []; + for (var n in e) { + var r = e[n]; + void 0 !== r && "" !== r && t.push([n, "=", encodeURIComponent(r).replace(/%20/g, "+")].join("")) + } + return t.join("&") + }, $e = function (e, t, n) { + return !!Q()(n, (function (n) { + return re()(e[n], t[n]) + })) + }; + + function Ke(e) { + return "string" != typeof e || "" === e ? "" : Object(H.sanitizeUrl)(e) + } + + function Ye(e) { + return !(!e || D()(e).call(e, "localhost") >= 0 || D()(e).call(e, "127.0.0.1") >= 0 || "none" === e) + } + + function Ge(e) { + if (!W.a.OrderedMap.isOrderedMap(e)) return null; + if (!e.size) return null; + var t = B()(e).call(e, (function (e, t) { + return U()(t).call(t, "2") && x()(e.get("content") || {}).length > 0 + })), n = e.get("default") || W.a.OrderedMap(), + r = (n.get("content") || W.a.OrderedMap()).keySeq().toJS().length ? n : null; + return t || r + } + + var Ze = function (e) { + return "string" == typeof e || e instanceof String ? z()(e).call(e).replace(/\s/g, "%20") : "" + }, Xe = function (e) { + return ce()(Ze(e).replace(/%20/g, "_")) + }, Qe = function (e) { + return _()(e).call(e, (function (e, t) { + return /^x-/.test(t) + })) + }, et = function (e) { + return _()(e).call(e, (function (e, t) { + return /^pattern|maxLength|minLength|maximum|minimum/.test(t) + })) + }; + + function tt(e, t) { + var n, r = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : function () { + return !0 + }; + if ("object" !== u()(e) || l()(e) || null === e || !t) return e; + var o = A()({}, e); + return y()(n = x()(o)).call(n, (function (e) { + e === t && r(o[e], e) ? delete o[e] : o[e] = tt(o[e], t, r) + })), o + } + + function nt(e) { + if ("string" == typeof e) return e; + if (e && e.toJS && (e = e.toJS()), "object" === u()(e) && null !== e) try { + return M()(e, null, 2) + } catch (t) { + return String(e) + } + return null == e ? "" : e.toString() + } + + function rt(e) { + return "number" == typeof e ? e.toString() : e + } + + function ot(e) { + var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {}, n = t.returnAll, + r = void 0 !== n && n, o = t.allowHashes, a = void 0 === o || o; + if (!W.a.Map.isMap(e)) throw new Error("paramToIdentifier: received a non-Im.Map parameter as input"); + var i, s, u, c = e.get("name"), l = e.get("in"), p = []; + e && e.hashCode && l && c && a && p.push(v()(i = v()(s = "".concat(l, ".")).call(s, c, ".hash-")).call(i, e.hashCode())); + l && c && p.push(v()(u = "".concat(l, ".")).call(u, c)); + return p.push(c), r ? p : p[0] || "" + } + + function at(e, t) { + var n, r = ot(e, {returnAll: !0}); + return _()(n = f()(r).call(r, (function (e) { + return t[e] + }))).call(n, (function (e) { + return void 0 !== e + }))[0] + } + + function it() { + return ut(fe()(32).toString("base64")) + } + + function st(e) { + return ut(de()("sha256").update(e).digest("base64")) + } + + function ut(e) { + return e.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "") + } + + var ct = function (e) { + return !e || !(!ye(e) || !e.isEmpty()) + } + }).call(this, n(76).Buffer) + }, function (e, t) { + e.exports = function (e, t) { + if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function") + }, e.exports.default = e.exports, e.exports.__esModule = !0 + }, function (e, t, n) { + var r = n(243); + + function o(e, t) { + for (var n = 0; n < t.length; n++) { + var o = t[n]; + o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), r(e, o.key, o) + } + } + + e.exports = function (e, t, n) { + return t && o(e.prototype, t), n && o(e, n), e + }, e.exports.default = e.exports, e.exports.__esModule = !0 + }, function (e, t, n) { + var r = n(921), o = n(924); + e.exports = function (e, t) { + if ("function" != typeof t && null !== t) throw new TypeError("Super expression must either be null or a function"); + e.prototype = r(t && t.prototype, {constructor: {value: e, writable: !0, configurable: !0}}), t && o(e, t) + }, e.exports.default = e.exports, e.exports.__esModule = !0 + }, function (e, t, n) { + var r = n(469), o = n(209), a = n(935), i = n(936); + e.exports = function (e) { + var t = a(); + return function () { + var n, a = o(e); + if (t) { + var s = o(this).constructor; + n = r(a, arguments, s) + } else n = a.apply(this, arguments); + return i(this, n) + } + }, e.exports.default = e.exports, e.exports.__esModule = !0 + }, function (e, t) { + e.exports = function (e) { + if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + return e + }, e.exports.default = e.exports, e.exports.__esModule = !0 + }, function (e, t, n) { + e.exports = n(1014)() + }, function (e, t, n) { + e.exports = n(583) + }, function (e, t, n) { + e.exports = n(604) + }, function (e, t, n) { + e.exports = n(671) + }, function (e, t, n) { + var r = n(635), o = n(388), a = n(185), i = n(644); + e.exports = function (e) { + return r(e) || o(e) || a(e) || i() + }, e.exports.default = e.exports, e.exports.__esModule = !0 + }, function (e, t, n) { + var r = n(396), o = n(645), a = n(185), i = n(399); + e.exports = function (e, t) { + return r(e) || o(e, t) || a(e, t) || i() + }, e.exports.default = e.exports, e.exports.__esModule = !0 + }, function (e, t, n) { + e.exports = n(586) + }, function (e, t, n) { + e.exports = n(400) + }, function (e, t, n) { + var r = n(177), o = n(575); + + function a(t) { + return "function" == typeof r && "symbol" == typeof o ? (e.exports = a = function (e) { + return typeof e + }, e.exports.default = e.exports, e.exports.__esModule = !0) : (e.exports = a = function (e) { + return e && "function" == typeof r && e.constructor === r && e !== r.prototype ? "symbol" : typeof e + }, e.exports.default = e.exports, e.exports.__esModule = !0), a(t) + } + + e.exports = a, e.exports.default = e.exports, e.exports.__esModule = !0 + }, function (e, t, n) { + "use strict"; + + function r(e, t) { + return e === t + } + + function o(e, t, n) { + if (null === t || null === n || t.length !== n.length) return !1; + for (var r = t.length, o = 0; o < r; o++) if (!e(t[o], n[o])) return !1; + return !0 + } + + function a(e) { + var t = Array.isArray(e[0]) ? e[0] : e; + if (!t.every((function (e) { + return "function" == typeof e + }))) { + var n = t.map((function (e) { + return typeof e + })).join(", "); + throw new Error("Selector creators expect all input-selectors to be functions, instead received the following types: [" + n + "]") + } + return t + } + + n.d(t, "a", (function () { + return i + })); + var i = function (e) { + for (var t = arguments.length, n = Array(t > 1 ? t - 1 : 0), r = 1; r < t; r++) n[r - 1] = arguments[r]; + return function () { + for (var t = arguments.length, r = Array(t), o = 0; o < t; o++) r[o] = arguments[o]; + var i = 0, s = r.pop(), u = a(r), c = e.apply(void 0, [function () { + return i++, s.apply(null, arguments) + }].concat(n)), l = e((function () { + for (var e = [], t = u.length, n = 0; n < t; n++) e.push(u[n].apply(null, arguments)); + return c.apply(null, e) + })); + return l.resultFunc = s, l.dependencies = u, l.recomputations = function () { + return i + }, l.resetRecomputations = function () { + return i = 0 + }, l + } + }((function (e) { + var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : r, n = null, a = null; + return function () { + return o(t, n, arguments) || (a = e.apply(null, arguments)), n = arguments, a + } + })) + }, function (e, t, n) { + e.exports = n(606) + }, function (e, t, n) { + e.exports = n(599) + }, function (e, t, n) { + e.exports = n(601) + }, function (e, t, n) { + "use strict"; + var r = n(42), o = n(107).f, a = n(358), i = n(33), s = n(109), u = n(69), c = n(55), l = function (e) { + var t = function (t, n, r) { + if (this instanceof e) { + switch (arguments.length) { + case 0: + return new e; + case 1: + return new e(t); + case 2: + return new e(t, n) + } + return new e(t, n, r) + } + return e.apply(this, arguments) + }; + return t.prototype = e.prototype, t + }; + e.exports = function (e, t) { + var n, p, f, h, d, m, v, g, y = e.target, b = e.global, _ = e.stat, w = e.proto, + x = b ? r : _ ? r[y] : (r[y] || {}).prototype, E = b ? i : i[y] || (i[y] = {}), S = E.prototype; + for (f in t) n = !a(b ? f : y + (_ ? "." : "#") + f, e.forced) && x && c(x, f), d = E[f], n && (m = e.noTargetGet ? (g = o(x, f)) && g.value : x[f]), h = n && m ? m : t[f], n && typeof d == typeof h || (v = e.bind && n ? s(h, r) : e.wrap && n ? l(h) : w && "function" == typeof h ? s(Function.call, h) : h, (e.sham || h && h.sham || d && d.sham) && u(v, "sham", !0), E[f] = v, w && (c(i, p = y + "Prototype") || u(i, p, {}), i[p][f] = h, e.real && S && !S[f] && u(S, f, h))) + } + }, function (e, t, n) { + var r = n(449), o = n(450), a = n(878), i = n(451), s = n(883), u = n(885), c = n(890), l = n(243), p = n(3); + + function f(e, t) { + var n = r(e); + if (o) { + var s = o(e); + t && (s = a(s).call(s, (function (t) { + return i(e, t).enumerable + }))), n.push.apply(n, s) + } + return n + } + + e.exports = function (e) { + for (var t = 1; t < arguments.length; t++) { + var n, r = null != arguments[t] ? arguments[t] : {}; + if (t % 2) s(n = f(Object(r), !0)).call(n, (function (t) { + p(e, t, r[t]) + })); else if (u) c(e, u(r)); else { + var o; + s(o = f(Object(r))).call(o, (function (t) { + l(e, t, i(r, t)) + })) + } + } + return e + }, e.exports.default = e.exports, e.exports.__esModule = !0 + }, function (e, t, n) { + "use strict"; + e.exports = function (e, t, n, r, o, a, i, s) { + if (!e) { + var u; + if (void 0 === t) u = new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings."); else { + var c = [n, r, o, a, i, s], l = 0; + (u = new Error(t.replace(/%s/g, (function () { + return c[l++] + })))).name = "Invariant Violation" + } + throw u.framesToPop = 1, u + } + } + }, function (e, t, n) { + "use strict"; + t.a = function () { + var e = { + location: {}, history: {}, open: function () { + }, close: function () { + }, File: function () { + } + }; + if ("undefined" == typeof window) return e; + try { + e = window; + for (var t = 0, n = ["File", "Blob", "FormData"]; t < n.length; t++) { + var r = n[t]; + r in window && (e[r] = window[r]) + } + } catch (e) { + console.error(e) + } + return e + }() + }, function (e, t, n) { + "use strict"; + var r, o = n(1), a = "<>", i = function () { + invariant(!1, "ImmutablePropTypes type checking code is stripped in production.") + }; + i.isRequired = i; + var s = function () { + return i + }; + + function u(e) { + var t = typeof e; + return Array.isArray(e) ? "array" : e instanceof RegExp ? "object" : e instanceof o.Iterable ? "Immutable." + e.toSource().split(" ")[0] : t + } + + function c(e) { + function t(t, n, r, o, i, s) { + for (var u = arguments.length, c = Array(u > 6 ? u - 6 : 0), l = 6; l < u; l++) c[l - 6] = arguments[l]; + if (s = s || r, o = o || a, null != n[r]) return e.apply(void 0, [n, r, o, i, s].concat(c)); + var p = i; + return t ? new Error("Required " + p + " `" + s + "` was not specified in `" + o + "`.") : void 0 + } + + var n = t.bind(null, !1); + return n.isRequired = t.bind(null, !0), n + } + + function l(e, t) { + return n = "Iterable." + e, r = function (e) { + return o.Iterable.isIterable(e) && t(e) + }, c((function (e, t, o, a, i) { + var s = e[t]; + if (!r(s)) { + var c = u(s); + return new Error("Invalid " + a + " `" + i + "` of type `" + c + "` supplied to `" + o + "`, expected `" + n + "`.") + } + return null + })); + var n, r + } + + (r = { + listOf: s, + mapOf: s, + orderedMapOf: s, + setOf: s, + orderedSetOf: s, + stackOf: s, + iterableOf: s, + recordOf: s, + shape: s, + contains: s, + mapContains: s, + orderedMapContains: s, + list: i, + map: i, + orderedMap: i, + set: i, + orderedSet: i, + stack: i, + seq: i, + record: i, + iterable: i + }).iterable.indexed = l("Indexed", o.Iterable.isIndexed), r.iterable.keyed = l("Keyed", o.Iterable.isKeyed), e.exports = r + }, function (e, t, n) { + var r = n(919); + + function o() { + return e.exports = o = r || function (e) { + for (var t = 1; t < arguments.length; t++) { + var n = arguments[t]; + for (var r in n) Object.prototype.hasOwnProperty.call(n, r) && (e[r] = n[r]) + } + return e + }, e.exports.default = e.exports, e.exports.__esModule = !0, o.apply(this, arguments) + } + + e.exports = o, e.exports.default = e.exports, e.exports.__esModule = !0 + }, function (e, t, n) { + e.exports = n(595) + }, function (e, t, n) { + "use strict"; + e.exports = function (e) { + for (var t = arguments.length - 1, n = "Minified React error #" + e + "; visit http://facebook.github.io/react/docs/error-decoder.html?invariant=" + e, r = 0; r < t; r++) n += "&args[]=" + encodeURIComponent(arguments[r + 1]); + n += " for the full message or use the non-minified dev environment for full errors and additional helpful warnings."; + var o = new Error(n); + throw o.name = "Invariant Violation", o.framesToPop = 1, o + } + }, function (e, t, n) { + e.exports = n(588) + }, function (e, t) { + e.exports = {} + }, function (e, t, n) { + "use strict"; + var r = n(82); + e.exports = r + }, function (e, t, n) { + "use strict"; + n.r(t), n.d(t, "isOAS3", (function () { + return c + })), n.d(t, "isSwagger2", (function () { + return l + })), n.d(t, "OAS3ComponentWrapFactory", (function () { + return p + })); + var r = n(29), o = n.n(r), a = n(174), i = n.n(a), s = n(0), u = n.n(s); + + function c(e) { + var t = e.get("openapi"); + return "string" == typeof t && (i()(t).call(t, "3.0.") && t.length > 4) + } + + function l(e) { + var t = e.get("swagger"); + return "string" == typeof t && i()(t).call(t, "2.0") + } + + function p(e) { + return function (t, n) { + return function (r) { + return n && n.specSelectors && n.specSelectors.specJson ? c(n.specSelectors.specJson()) ? u.a.createElement(e, o()({}, r, n, {Ori: t})) : u.a.createElement(t, r) : (console.warn("OAS3 wrapper: couldn't get spec"), null) + } + } + } + }, function (e, t, n) { + e.exports = n(660) + }, function (e, t) { + e.exports = function (e) { + try { + return !!e() + } catch (e) { + return !0 + } + } + }, function (e, t, n) { + e.exports = n(664) + }, function (e, t, n) { + var r = n(42), o = n(229), a = n(55), i = n(181), s = n(231), u = n(359), c = o("wks"), l = r.Symbol, + p = u ? l : l && l.withoutSetter || i; + e.exports = function (e) { + return a(c, e) && (s || "string" == typeof c[e]) || (s && a(l, e) ? c[e] = l[e] : c[e] = p("Symbol." + e)), c[e] + } + }, function (e, t, n) { + "use strict"; + var r = Object.getOwnPropertySymbols, o = Object.prototype.hasOwnProperty, + a = Object.prototype.propertyIsEnumerable; + + function i(e) { + if (null == e) throw new TypeError("Object.assign cannot be called with null or undefined"); + return Object(e) + } + + e.exports = function () { + try { + if (!Object.assign) return !1; + var e = new String("abc"); + if (e[5] = "de", "5" === Object.getOwnPropertyNames(e)[0]) return !1; + for (var t = {}, n = 0; n < 10; n++) t["_" + String.fromCharCode(n)] = n; + if ("0123456789" !== Object.getOwnPropertyNames(t).map((function (e) { + return t[e] + })).join("")) return !1; + var r = {}; + return "abcdefghijklmnopqrst".split("").forEach((function (e) { + r[e] = e + })), "abcdefghijklmnopqrst" === Object.keys(Object.assign({}, r)).join("") + } catch (e) { + return !1 + } + }() ? Object.assign : function (e, t) { + for (var n, s, u = i(e), c = 1; c < arguments.length; c++) { + for (var l in n = Object(arguments[c])) o.call(n, l) && (u[l] = n[l]); + if (r) { + s = r(n); + for (var p = 0; p < s.length; p++) a.call(n, s[p]) && (u[s[p]] = n[s[p]]) + } + } + return u + } + }, function (e, t, n) { + e.exports = n(907) + }, function (e, t, n) { + (function (t) { + var n = function (e) { + return e && e.Math == Math && e + }; + e.exports = n("object" == typeof globalThis && globalThis) || n("object" == typeof window && window) || n("object" == typeof self && self) || n("object" == typeof t && t) || function () { + return this + }() || Function("return this")() + }).call(this, n(54)) + }, function (e, t, n) { + var r = n(33); + e.exports = function (e) { + return r[e + "Prototype"] + } + }, function (e, t, n) { + "use strict"; + var r = n(31), o = n(139), a = n(470), i = (n(26), o.ID_ATTRIBUTE_NAME), s = a, + u = "__reactInternalInstance$" + Math.random().toString(36).slice(2); + + function c(e, t) { + return 1 === e.nodeType && e.getAttribute(i) === String(t) || 8 === e.nodeType && e.nodeValue === " react-text: " + t + " " || 8 === e.nodeType && e.nodeValue === " react-empty: " + t + " " + } + + function l(e) { + for (var t; t = e._renderedComponent;) e = t; + return e + } + + function p(e, t) { + var n = l(e); + n._hostNode = t, t[u] = n + } + + function f(e, t) { + if (!(e._flags & s.hasCachedChildNodes)) { + var n = e._renderedChildren, o = t.firstChild; + e:for (var a in n) if (n.hasOwnProperty(a)) { + var i = n[a], u = l(i)._domID; + if (0 !== u) { + for (; null !== o; o = o.nextSibling) if (c(o, u)) { + p(i, o); + continue e + } + r("32", u) + } + } + e._flags |= s.hasCachedChildNodes + } + } + + function h(e) { + if (e[u]) return e[u]; + for (var t, n, r = []; !e[u];) { + if (r.push(e), !e.parentNode) return null; + e = e.parentNode + } + for (; e && (n = e[u]); e = r.pop()) t = n, r.length && f(n, e); + return t + } + + var d = { + getClosestInstanceFromNode: h, getInstanceFromNode: function (e) { + var t = h(e); + return null != t && t._hostNode === e ? t : null + }, getNodeFromInstance: function (e) { + if (void 0 === e._hostNode && r("33"), e._hostNode) return e._hostNode; + for (var t = []; !e._hostNode;) t.push(e), e._hostParent || r("34"), e = e._hostParent; + for (; t.length; e = t.pop()) f(e, e._hostNode); + return e._hostNode + }, precacheChildNodes: f, precacheNode: p, uncacheNode: function (e) { + var t = e._hostNode; + t && (delete t[u], e._hostNode = null) + } + }; + e.exports = d + }, function (e, t) { + e.exports = function (e) { + return "object" == typeof e ? null !== e : "function" == typeof e + } + }, function (e, t, n) { + var r = n(196); + e.exports = function (e, t, n) { + var o = null == e ? void 0 : r(e, t); + return void 0 === o ? n : o + } + }, function (e, t, n) { + "use strict"; + n.r(t), n.d(t, "UPDATE_SPEC", (function () { + return te + })), n.d(t, "UPDATE_URL", (function () { + return ne + })), n.d(t, "UPDATE_JSON", (function () { + return re + })), n.d(t, "UPDATE_PARAM", (function () { + return oe + })), n.d(t, "UPDATE_EMPTY_PARAM_INCLUSION", (function () { + return ae + })), n.d(t, "VALIDATE_PARAMS", (function () { + return ie + })), n.d(t, "SET_RESPONSE", (function () { + return se + })), n.d(t, "SET_REQUEST", (function () { + return ue + })), n.d(t, "SET_MUTATED_REQUEST", (function () { + return ce + })), n.d(t, "LOG_REQUEST", (function () { + return le + })), n.d(t, "CLEAR_RESPONSE", (function () { + return pe + })), n.d(t, "CLEAR_REQUEST", (function () { + return fe + })), n.d(t, "CLEAR_VALIDATE_PARAMS", (function () { + return he + })), n.d(t, "UPDATE_OPERATION_META_VALUE", (function () { + return de + })), n.d(t, "UPDATE_RESOLVED", (function () { + return me + })), n.d(t, "UPDATE_RESOLVED_SUBTREE", (function () { + return ve + })), n.d(t, "SET_SCHEME", (function () { + return ge + })), n.d(t, "updateSpec", (function () { + return ye + })), n.d(t, "updateResolved", (function () { + return be + })), n.d(t, "updateUrl", (function () { + return _e + })), n.d(t, "updateJsonSpec", (function () { + return we + })), n.d(t, "parseToJson", (function () { + return xe + })), n.d(t, "resolveSpec", (function () { + return Se + })), n.d(t, "requestResolvedSubtree", (function () { + return ke + })), n.d(t, "changeParam", (function () { + return Oe + })), n.d(t, "changeParamByIdentity", (function () { + return je + })), n.d(t, "updateResolvedSubtree", (function () { + return Te + })), n.d(t, "invalidateResolvedSubtreeCache", (function () { + return Ie + })), n.d(t, "validateParams", (function () { + return Pe + })), n.d(t, "updateEmptyParamInclusion", (function () { + return Ne + })), n.d(t, "clearValidateParams", (function () { + return Me + })), n.d(t, "changeConsumesValue", (function () { + return Re + })), n.d(t, "changeProducesValue", (function () { + return De + })), n.d(t, "setResponse", (function () { + return Le + })), n.d(t, "setRequest", (function () { + return Be + })), n.d(t, "setMutatedRequest", (function () { + return Fe + })), n.d(t, "logRequest", (function () { + return Ue + })), n.d(t, "executeRequest", (function () { + return qe + })), n.d(t, "execute", (function () { + return ze + })), n.d(t, "clearResponse", (function () { + return Ve + })), n.d(t, "clearRequest", (function () { + return We + })), n.d(t, "setScheme", (function () { + return He + })); + var r = n(25), o = n.n(r), a = n(56), i = n.n(a), s = n(78), u = n.n(s), c = n(19), l = n.n(c), p = n(41), + f = n.n(p), h = n(13), d = n.n(h), m = n(4), v = n.n(m), g = n(345), y = n.n(g), b = n(21), _ = n.n(b), + w = n(104), x = n.n(w), E = n(67), S = n.n(E), C = n(12), A = n.n(C), k = n(213), O = n.n(k), j = n(14), + T = n.n(j), I = n(18), P = n.n(I), N = n(2), M = n.n(N), R = n(17), D = n.n(R), L = n(22), B = n.n(L), + F = n(346), U = n.n(F), q = n(77), z = n.n(q), V = n(1), W = n(97), H = n.n(W), J = n(143), $ = n.n(J), + K = n(214), Y = n.n(K), G = n(520), Z = n.n(G), X = n(347), Q = n.n(X), ee = n(5), te = "spec_update_spec", + ne = "spec_update_url", re = "spec_update_json", oe = "spec_update_param", + ae = "spec_update_empty_param_inclusion", ie = "spec_validate_param", se = "spec_set_response", + ue = "spec_set_request", ce = "spec_set_mutated_request", le = "spec_log_request", + pe = "spec_clear_response", fe = "spec_clear_request", he = "spec_clear_validate_param", + de = "spec_update_operation_meta_value", me = "spec_update_resolved", ve = "spec_update_resolved_subtree", + ge = "set_scheme"; + + function ye(e) { + var t, n = (t = e, Y()(t) ? t : "").replace(/\t/g, " "); + if ("string" == typeof e) return {type: te, payload: n} + } + + function be(e) { + return {type: me, payload: e} + } + + function _e(e) { + return {type: ne, payload: e} + } + + function we(e) { + return {type: re, payload: e} + } + + var xe = function (e) { + return function (t) { + var n = t.specActions, r = t.specSelectors, o = t.errActions, a = r.specStr, i = null; + try { + e = e || a(), o.clear({source: "parser"}), i = z.a.safeLoad(e) + } catch (e) { + return console.error(e), o.newSpecErr({ + source: "parser", + level: "error", + message: e.reason, + line: e.mark && e.mark.line ? e.mark.line + 1 : void 0 + }) + } + return i && "object" === l()(i) ? n.updateJsonSpec(i) : {} + } + }, Ee = !1, Se = function (e, t) { + return function (n) { + var r = n.specActions, o = n.specSelectors, a = n.errActions, i = n.fn, s = i.fetch, u = i.resolve, + c = i.AST, l = void 0 === c ? {} : c, p = n.getConfigs; + Ee || (console.warn("specActions.resolveSpec is deprecated since v3.10.0 and will be removed in v4.0.0; use requestResolvedSubtree instead!"), Ee = !0); + var f = p(), h = f.modelPropertyMacro, m = f.parameterMacro, g = f.requestInterceptor, + b = f.responseInterceptor; + void 0 === e && (e = o.specJson()), void 0 === t && (t = o.url()); + var _ = l.getLineNumberForPath ? l.getLineNumberForPath : function () { + }, w = o.specStr(); + return u({ + fetch: s, + spec: e, + baseDoc: t, + modelPropertyMacro: h, + parameterMacro: m, + requestInterceptor: g, + responseInterceptor: b + }).then((function (e) { + var t = e.spec, n = e.errors; + if (a.clear({type: "thrown"}), d()(n) && n.length > 0) { + var o = v()(n).call(n, (function (e) { + return console.error(e), e.line = e.fullPath ? _(w, e.fullPath) : null, e.path = e.fullPath ? e.fullPath.join(".") : null, e.level = "error", e.type = "thrown", e.source = "resolver", y()(e, "message", { + enumerable: !0, + value: e.message + }), e + })); + a.newThrownErrBatch(o) + } + return r.updateResolved(t) + })) + } + }, Ce = [], Ae = Z()(u()(f.a.mark((function e() { + var t, n, r, o, a, i, s, c, l, p, h, m, g, b, w, E, C, k; + return f.a.wrap((function (e) { + for (; ;) switch (e.prev = e.next) { + case 0: + if (t = Ce.system) { + e.next = 4; + break + } + return console.error("debResolveSubtrees: don't have a system to operate on, aborting."), e.abrupt("return"); + case 4: + if (n = t.errActions, r = t.errSelectors, o = t.fn, a = o.resolveSubtree, i = o.fetch, s = o.AST, c = void 0 === s ? {} : s, l = t.specSelectors, p = t.specActions, a) { + e.next = 8; + break + } + return console.error("Error: Swagger-Client did not provide a `resolveSubtree` method, doing nothing."), e.abrupt("return"); + case 8: + return h = c.getLineNumberForPath ? c.getLineNumberForPath : function () { + }, m = l.specStr(), g = t.getConfigs(), b = g.modelPropertyMacro, w = g.parameterMacro, E = g.requestInterceptor, C = g.responseInterceptor, e.prev = 11, e.next = 14, _()(Ce).call(Ce, function () { + var e = u()(f.a.mark((function e(t, o) { + var s, c, p, g, _, k, j, T, I; + return f.a.wrap((function (e) { + for (; ;) switch (e.prev = e.next) { + case 0: + return e.next = 2, t; + case 2: + return s = e.sent, c = s.resultMap, p = s.specWithCurrentSubtrees, e.next = 7, a(p, o, { + baseDoc: l.url(), + modelPropertyMacro: b, + parameterMacro: w, + requestInterceptor: E, + responseInterceptor: C + }); + case 7: + if (g = e.sent, _ = g.errors, k = g.spec, r.allErrors().size && n.clearBy((function (e) { + var t; + return "thrown" !== e.get("type") || "resolver" !== e.get("source") || !x()(t = e.get("fullPath")).call(t, (function (e, t) { + return e === o[t] || void 0 === o[t] + })) + })), d()(_) && _.length > 0 && (j = v()(_).call(_, (function (e) { + return e.line = e.fullPath ? h(m, e.fullPath) : null, e.path = e.fullPath ? e.fullPath.join(".") : null, e.level = "error", e.type = "thrown", e.source = "resolver", y()(e, "message", { + enumerable: !0, + value: e.message + }), e + })), n.newThrownErrBatch(j)), !k || !l.isOAS3() || "components" !== o[0] || "securitySchemes" !== o[1]) { + e.next = 15; + break + } + return e.next = 15, S.a.all(v()(T = A()(I = O()(k)).call(I, (function (e) { + return "openIdConnect" === e.type + }))).call(T, function () { + var e = u()(f.a.mark((function e(t) { + var n, r; + return f.a.wrap((function (e) { + for (; ;) switch (e.prev = e.next) { + case 0: + return n = { + url: t.openIdConnectUrl, + requestInterceptor: E, + responseInterceptor: C + }, e.prev = 1, e.next = 4, i(n); + case 4: + (r = e.sent) instanceof Error || r.status >= 400 ? console.error(r.statusText + " " + n.url) : t.openIdConnectData = JSON.parse(r.text), e.next = 11; + break; + case 8: + e.prev = 8, e.t0 = e.catch(1), console.error(e.t0); + case 11: + case"end": + return e.stop() + } + }), e, null, [[1, 8]]) + }))); + return function (t) { + return e.apply(this, arguments) + } + }())); + case 15: + return Q()(c, o, k), Q()(p, o, k), e.abrupt("return", { + resultMap: c, + specWithCurrentSubtrees: p + }); + case 18: + case"end": + return e.stop() + } + }), e) + }))); + return function (t, n) { + return e.apply(this, arguments) + } + }(), S.a.resolve({ + resultMap: (l.specResolvedSubtree([]) || Object(V.Map)()).toJS(), + specWithCurrentSubtrees: l.specJson().toJS() + })); + case 14: + k = e.sent, delete Ce.system, Ce = [], e.next = 22; + break; + case 19: + e.prev = 19, e.t0 = e.catch(11), console.error(e.t0); + case 22: + p.updateResolvedSubtree([], k.resultMap); + case 23: + case"end": + return e.stop() + } + }), e, null, [[11, 19]]) + }))), 35), ke = function (e) { + return function (t) { + var n; + T()(n = v()(Ce).call(Ce, (function (e) { + return e.join("@@") + }))).call(n, e.join("@@")) > -1 || (Ce.push(e), Ce.system = t, Ae()) + } + }; + + function Oe(e, t, n, r, o) { + return {type: oe, payload: {path: e, value: r, paramName: t, paramIn: n, isXml: o}} + } + + function je(e, t, n, r) { + return {type: oe, payload: {path: e, param: t, value: n, isXml: r}} + } + + var Te = function (e, t) { + return {type: ve, payload: {path: e, value: t}} + }, Ie = function () { + return {type: ve, payload: {path: [], value: Object(V.Map)()}} + }, Pe = function (e, t) { + return {type: ie, payload: {pathMethod: e, isOAS3: t}} + }, Ne = function (e, t, n, r) { + return {type: ae, payload: {pathMethod: e, paramName: t, paramIn: n, includeEmptyValue: r}} + }; + + function Me(e) { + return {type: he, payload: {pathMethod: e}} + } + + function Re(e, t) { + return {type: de, payload: {path: e, value: t, key: "consumes_value"}} + } + + function De(e, t) { + return {type: de, payload: {path: e, value: t, key: "produces_value"}} + } + + var Le = function (e, t, n) { + return {payload: {path: e, method: t, res: n}, type: se} + }, Be = function (e, t, n) { + return {payload: {path: e, method: t, req: n}, type: ue} + }, Fe = function (e, t, n) { + return {payload: {path: e, method: t, req: n}, type: ce} + }, Ue = function (e) { + return {payload: e, type: le} + }, qe = function (e) { + return function (t) { + var n, r, o = t.fn, a = t.specActions, i = t.specSelectors, s = t.getConfigs, c = t.oas3Selectors, + l = e.pathName, p = e.method, h = e.operation, m = s(), g = m.requestInterceptor, + y = m.responseInterceptor, b = h.toJS(); + h && h.get("parameters") && P()(n = A()(r = h.get("parameters")).call(r, (function (e) { + return e && !0 === e.get("allowEmptyValue") + }))).call(n, (function (t) { + if (i.parameterInclusionSettingFor([l, p], t.get("name"), t.get("in"))) { + e.parameters = e.parameters || {}; + var n = Object(ee.C)(t, e.parameters); + (!n || n && 0 === n.size) && (e.parameters[t.get( + + )] = "") + } + })); + if (e.contextUrl = H()(i.url()).toString(), b && b.operationId ? e.operationId = b.operationId : b && l && p && (e.operationId = o.opId(b, l, p)), i.isOAS3()) { + var _, w = M()(_ = "".concat(l, ":")).call(_, p); + e.server = c.selectedServer(w) || c.selectedServer(); + var x = c.serverVariables({server: e.server, namespace: w}).toJS(), + E = c.serverVariables({server: e.server}).toJS(); + e.serverVariables = D()(x).length ? x : E, e.requestContentType = c.requestContentType(l, p), e.responseContentType = c.responseContentType(l, p) || "*/*"; + var S = c.requestBodyValue(l, p), C = c.requestBodyInclusionSetting(l, p); + if (Object(ee.t)(S)) e.requestBody = JSON.parse(S); else if (S && S.toJS) { + var k; + e.requestBody = A()(k = v()(S).call(S, (function (e) { + return V.Map.isMap(e) ? e.get("value") : e + }))).call(k, (function (e, t) { + return (d()(e) ? 0 !== e.length : !Object(ee.q)(e)) || C.get(t) + })).toJS() + } else e.requestBody = S + } + var O = B()({}, e); + O = o.buildRequest(O), a.setRequest(e.pathName, e.method, O); + var j = function () { + var t = u()(f.a.mark((function t(n) { + var r, o; + return f.a.wrap((function (t) { + for (; ;) switch (t.prev = t.next) { + case 0: + return t.next = 2, g.apply(undefined, [n]); + case 2: + return r = t.sent, o = B()({}, r), a.setMutatedRequest(e.pathName, e.method, o), t.abrupt("return", r); + case 6: + case"end": + return t.stop() + } + }), t) + }))); + return function (e) { + return t.apply(this, arguments) + } + }(); + e.requestInterceptor = j, e.responseInterceptor = y; + var T = U()(); + return o.execute(e).then((function (t) { + t.duration = U()() - T, a.setResponse(e.pathName, e.method, t) + })).catch((function (t) { + "Failed to fetch" === t.message && (t.name = "", t.message = '**Failed to fetch.** \n**Possible Reasons:** \n - CORS \n - Network Failure \n - URL scheme must be "http" or "https" for CORS request.'), a.setResponse(e.pathName, e.method, { + error: !0, + err: $()(t) + }) + })) + } + }, ze = function () { + var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, t = e.path, n = e.method, + r = i()(e, ["path", "method"]); + return function (e) { + var a = e.fn.fetch, i = e.specSelectors, s = e.specActions, u = i.specJsonWithResolvedSubtrees().toJS(), + c = i.operationScheme(t, n), l = i.contentTypeValues([t, n]).toJS(), p = l.requestContentType, + f = l.responseContentType, h = /xml/i.test(p), d = i.parameterValues([t, n], h).toJS(); + return s.executeRequest(o()(o()({}, r), {}, { + fetch: a, + spec: u, + pathName: t, + method: n, + parameters: d, + requestContentType: p, + scheme: c, + responseContentType: f + })) + } + }; + + function Ve(e, t) { + return {type: pe, payload: {path: e, method: t}} + } + + function We(e, t) { + return {type: fe, payload: {path: e, method: t}} + } + + function He(e, t, n) { + return {type: ge, payload: {scheme: e, path: t, method: n}} + } + }, function (e, t, n) { + var r = n(33), o = n(55), a = n(238), i = n(70).f; + e.exports = function (e) { + var t = r.Symbol || (r.Symbol = {}); + o(t, e) || i(t, e, {value: a.f(e)}) + } + }, function (e, t, n) { + "use strict"; + var r = n(164), + o = ["kind", "resolve", "construct", "instanceOf", "predicate", "represent", "defaultStyle", "styleAliases"], + a = ["scalar", "sequence", "mapping"]; + e.exports = function (e, t) { + var n, i; + if (t = t || {}, Object.keys(t).forEach((function (t) { + if (-1 === o.indexOf(t)) throw new r('Unknown option "' + t + '" is met in definition of "' + e + '" YAML type.') + })), this.tag = e, this.kind = t.kind || null, this.resolve = t.resolve || function () { + return !0 + }, this.construct = t.construct || function (e) { + return e + }, this.instanceOf = t.instanceOf || null, this.predicate = t.predicate || null, this.represent = t.represent || null, this.defaultStyle = t.defaultStyle || null, this.styleAliases = (n = t.styleAliases || null, i = {}, null !== n && Object.keys(n).forEach((function (e) { + n[e].forEach((function (t) { + i[String(t)] = e + })) + })), i), -1 === a.indexOf(this.kind)) throw new r('Unknown kind "' + this.kind + '" is specified for "' + e + '" YAML type.') + } + }, function (e, t, n) { + var r = n(37); + e.exports = !r((function () { + return 7 != Object.defineProperty({}, 1, { + get: function () { + return 7 + } + })[1] + })) + }, function (e, t, n) { + var r = n(177), o = n(647), a = n(245), i = n(397), s = n(185); + e.exports = function (e, t) { + var n; + if (void 0 === r || null == o(e)) { + if (a(e) || (n = s(e)) || t && e && "number" == typeof e.length) { + n && (e = n); + var u = 0, c = function () { + }; + return { + s: c, n: function () { + return u >= e.length ? {done: !0} : {done: !1, value: e[u++]} + }, e: function (e) { + throw e + }, f: c + } + } + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.") + } + var l, p = !0, f = !1; + return { + s: function () { + n = i(e) + }, n: function () { + var e = n.next(); + return p = e.done, e + }, e: function (e) { + f = !0, l = e + }, f: function () { + try { + p || null == n.return || n.return() + } finally { + if (f) throw l + } + } + } + }, e.exports.default = e.exports, e.exports.__esModule = !0 + }, function (e, t, n) { + var r = n(45); + e.exports = function (e) { + if (!r(e)) throw TypeError(String(e) + " is not an object"); + return e + } + }, function (e, t) { + var n = Array.isArray; + e.exports = n + }, function (e, t) { + var n; + n = function () { + return this + }(); + try { + n = n || new Function("return this")() + } catch (e) { + "object" == typeof window && (n = window) + } + e.exports = n + }, function (e, t) { + var n = {}.hasOwnProperty; + e.exports = function (e, t) { + return n.call(e, t) + } + }, function (e, t, n) { + var r = n(450), o = n(452), a = n(895); + e.exports = function (e, t) { + if (null == e) return {}; + var n, i, s = a(e, t); + if (r) { + var u = r(e); + for (i = 0; i < u.length; i++) n = u[i], o(t).call(t, n) >= 0 || Object.prototype.propertyIsEnumerable.call(e, n) && (s[n] = e[n]) + } + return s + }, e.exports.default = e.exports, e.exports.__esModule = !0 + }, function (e, t, n) { + "use strict"; + n.r(t), n.d(t, "UPDATE_SELECTED_SERVER", (function () { + return r + })), n.d(t, "UPDATE_REQUEST_BODY_VALUE", (function () { + return o + })), n.d(t, "UPDATE_REQUEST_BODY_VALUE_RETAIN_FLAG", (function () { + return a + })), n.d(t, "UPDATE_REQUEST_BODY_INCLUSION", (function () { + return i + })), n.d(t, "UPDATE_ACTIVE_EXAMPLES_MEMBER", (function () { + return s + })), n.d(t, "UPDATE_REQUEST_CONTENT_TYPE", (function () { + return u + })), n.d(t, "UPDATE_RESPONSE_CONTENT_TYPE", (function () { + return c + })), n.d(t, "UPDATE_SERVER_VARIABLE_VALUE", (function () { + return l + })), n.d(t, "SET_REQUEST_BODY_VALIDATE_ERROR", (function () { + return p + })), n.d(t, "CLEAR_REQUEST_BODY_VALIDATE_ERROR", (function () { + return f + })), n.d(t, "CLEAR_REQUEST_BODY_VALUE", (function () { + return h + })), n.d(t, "setSelectedServer", (function () { + return d + })), n.d(t, "setRequestBodyValue", (function () { + return m + })), n.d(t, "setRetainRequestBodyValueFlag", (function () { + return v + })), n.d(t, "setRequestBodyInclusion", (function () { + return g + })), n.d(t, "setActiveExamplesMember", (function () { + return y + })), n.d(t, "setRequestContentType", (function () { + return b + })), n.d(t, "setResponseContentType", (function () { + return _ + })), n.d(t, "setServerVariableValue", (function () { + return w + })), n.d(t, "setRequestBodyValidateError", (function () { + return x + })), n.d(t, "clearRequestBodyValidateError", (function () { + return E + })), n.d(t, "initRequestBodyValidateError", (function () { + return S + })), n.d(t, "clearRequestBodyValue", (function () { + return C + })); + var r = "oas3_set_servers", o = "oas3_set_request_body_value", a = "oas3_set_request_body_retain_flag", + i = "oas3_set_request_body_inclusion", s = "oas3_set_active_examples_member", + u = "oas3_set_request_content_type", c = "oas3_set_response_content_type", + l = "oas3_set_server_variable_value", p = "oas3_set_request_body_validate_error", + f = "oas3_clear_request_body_validate_error", h = "oas3_clear_request_body_value"; + + function d(e, t) { + return {type: r, payload: {selectedServerUrl: e, namespace: t}} + } + + function m(e) { + var t = e.value, n = e.pathMethod; + return {type: o, payload: {value: t, pathMethod: n}} + } + + var v = function (e) { + var t = e.value, n = e.pathMethod; + return {type: a, payload: {value: t, pathMethod: n}} + }; + + function g(e) { + var t = e.value, n = e.pathMethod, r = e.name; + return {type: i, payload: {value: t, pathMethod: n, name: r}} + } + + function y(e) { + var t = e.name, n = e.pathMethod, r = e.contextType, o = e.contextName; + return {type: s, payload: {name: t, pathMethod: n, contextType: r, contextName: o}} + } + + function b(e) { + var t = e.value, n = e.pathMethod; + return {type: u, payload: {value: t, pathMethod: n}} + } + + function _(e) { + var t = e.value, n = e.path, r = e.method; + return {type: c, payload: {value: t, path: n, method: r}} + } + + function w(e) { + var t = e.server, n = e.namespace, r = e.key, o = e.val; + return {type: l, payload: {server: t, namespace: n, key: r, val: o}} + } + + var x = function (e) { + var t = e.path, n = e.method, r = e.validationErrors; + return {type: p, payload: {path: t, method: n, validationErrors: r}} + }, E = function (e) { + var t = e.path, n = e.method; + return {type: f, payload: {path: t, method: n}} + }, S = function (e) { + var t = e.pathMethod; + return {type: f, payload: {path: t[0], method: t[1]}} + }, C = function (e) { + var t = e.pathMethod; + return {type: h, payload: {pathMethod: t}} + } + }, function (e, t, n) { + "use strict"; + var r = !("undefined" == typeof window || !window.document || !window.document.createElement), o = { + canUseDOM: r, + canUseWorkers: "undefined" != typeof Worker, + canUseEventListeners: r && !(!window.addEventListener && !window.attachEvent), + canUseViewport: r && !!window.screen, + isInWorker: !r + }; + e.exports = o + }, function (e, t) { + e.exports = function (e) { + var t = typeof e; + return null != e && ("object" == t || "function" == t) + } + }, function (e, t, n) { + "use strict"; + n.d(t, "b", (function () { + return b + })), n.d(t, "e", (function () { + return _ + })), n.d(t, "c", (function () { + return x + })), n.d(t, "a", (function () { + return E + })), n.d(t, "d", (function () { + return S + })); + var r = n(51), o = n.n(r), a = n(18), i = n.n(a), s = n(36), u = n.n(s), c = n(2), l = n.n(c), p = n(19), + f = n.n(p), h = n(59), d = n.n(h), m = n(352), v = n.n(m), g = function (e) { + return String.prototype.toLowerCase.call(e) + }, y = function (e) { + return e.replace(/[^\w]/gi, "_") + }; + + function b(e) { + var t = e.openapi; + return !!t && v()(t, "3") + } + + function _(e, t) { + var n = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : "", + r = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : {}, + o = r.v2OperationIdCompatibilityMode; + if (!e || "object" !== f()(e)) return null; + var a = (e.operationId || "").replace(/\s/g, ""); + return a.length ? y(e.operationId) : w(t, n, {v2OperationIdCompatibilityMode: o}) + } + + function w(e, t) { + var n, r = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {}, + o = r.v2OperationIdCompatibilityMode; + if (o) { + var a, i, + s = l()(a = "".concat(t.toLowerCase(), "_")).call(a, e).replace(/[\s!@#$%^&*()_+=[{\]};:<>|./?,\\'""-]/g, "_"); + return (s = s || l()(i = "".concat(e.substring(1), "_")).call(i, t)).replace(/((_){2,})/g, "_").replace(/^(_)*/g, "").replace(/([_])*$/g, "") + } + return l()(n = "".concat(g(t))).call(n, y(e)) + } + + function x(e, t) { + var n; + return l()(n = "".concat(g(t), "-")).call(n, e) + } + + function E(e, t) { + return e && e.paths ? function (e, t) { + return function (e, t, n) { + if (!e || "object" !== f()(e) || !e.paths || "object" !== f()(e.paths)) return null; + var r = e.paths; + for (var o in r) for (var a in r[o]) if ("PARAMETERS" !== a.toUpperCase()) { + var i = r[o][a]; + if (i && "object" === f()(i)) { + var s = {spec: e, pathName: o, method: a.toUpperCase(), operation: i}, u = t(s); + if (n && u) return s + } + } + return + }(e, t, !0) || null + }(e, (function (e) { + var n, r = e.pathName, o = e.method, a = e.operation; + if (!a || "object" !== f()(a)) return !1; + var i = a.operationId, s = _(a, r, o), c = x(r, o); + return u()(n = [s, c, i]).call(n, (function (e) { + return e && e === t + })) + })) : null + } + + function S(e) { + var t = e.spec, n = t.paths, r = {}; + if (!n || t.$$normalized) return e; + for (var a in n) { + var s = n[a]; + if (d()(s)) { + var c = s.parameters, p = function (e) { + var n = s[e]; + if (!d()(n)) return "continue"; + var p = _(n, a, e); + if (p) { + r[p] ? r[p].push(n) : r[p] = [n]; + var f = r[p]; + if (f.length > 1) i()(f).call(f, (function (e, t) { + var n; + e.__originalOperationId = e.__originalOperationId || e.operationId, e.operationId = l()(n = "".concat(p)).call(n, t + 1) + })); else if (void 0 !== n.operationId) { + var h = f[0]; + h.__originalOperationId = h.__originalOperationId || n.operationId, h.operationId = p + } + } + if ("parameters" !== e) { + var m = [], v = {}; + for (var g in t) "produces" !== g && "consumes" !== g && "security" !== g || (v[g] = t[g], m.push(v)); + if (c && (v.parameters = c, m.push(v)), m.length) { + var y, b = o()(m); + try { + for (b.s(); !(y = b.n()).done;) { + var w = y.value; + for (var x in w) if (n[x]) { + if ("parameters" === x) { + var E, S = o()(w[x]); + try { + var C = function () { + var e, t = E.value; + u()(e = n[x]).call(e, (function (e) { + return e.name && e.name === t.name || e.$ref && e.$ref === t.$ref || e.$$ref && e.$$ref === t.$$ref || e === t + })) || n[x].push(t) + }; + for (S.s(); !(E = S.n()).done;) C() + } catch (e) { + S.e(e) + } finally { + S.f() + } + } + } else n[x] = w[x] + } + } catch (e) { + b.e(e) + } finally { + b.f() + } + } + } + }; + for (var f in s) p(f) + } + } + return t.$$normalized = !0, e + } + }, function (e, t, n) { + "use strict"; + n.r(t), n.d(t, "NEW_THROWN_ERR", (function () { + return a + })), n.d(t, "NEW_THROWN_ERR_BATCH", (function () { + return i + })), n.d(t, "NEW_SPEC_ERR", (function () { + return s + })), n.d(t, "NEW_SPEC_ERR_BATCH", (function () { + return u + })), n.d(t, "NEW_AUTH_ERR", (function () { + return c + })), n.d(t, "CLEAR", (function () { + return l + })), n.d(t, "CLEAR_BY", (function () { + return p + })), n.d(t, "newThrownErr", (function () { + return f + })), n.d(t, "newThrownErrBatch", (function () { + return h + })), n.d(t, "newSpecErr", (function () { + return d + })), n.d(t, "newSpecErrBatch", (function () { + return m + })), n.d(t, "newAuthErr", (function () { + return v + })), n.d(t, "clear", (function () { + return g + })), n.d(t, "clearBy", (function () { + return y + })); + var r = n(143), o = n.n(r), a = "err_new_thrown_err", i = "err_new_thrown_err_batch", s = "err_new_spec_err", + u = "err_new_spec_err_batch", c = "err_new_auth_err", l = "err_clear", p = "err_clear_by"; + + function f(e) { + return {type: a, payload: o()(e)} + } + + function h(e) { + return {type: i, payload: e} + } + + function d(e) { + return {type: s, payload: e} + } + + function m(e) { + return {type: u, payload: e} + } + + function v(e) { + return {type: c, payload: e} + } + + function g() { + var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}; + return {type: l, payload: e} + } + + function y() { + var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : function () { + return !0 + }; + return {type: p, payload: e} + } + }, function (e, t) { + "function" == typeof Object.create ? e.exports = function (e, t) { + e.super_ = t, e.prototype = Object.create(t.prototype, { + constructor: { + value: e, + enumerable: !1, + writable: !0, + configurable: !0 + } + }) + } : e.exports = function (e, t) { + e.super_ = t; + var n = function () { + }; + n.prototype = t.prototype, e.prototype = new n, e.prototype.constructor = e + } + }, function (e, t, n) { + var r = n(76), o = r.Buffer; + + function a(e, t) { + for (var n in e) t[n] = e[n] + } + + function i(e, t, n) { + return o(e, t, n) + } + + o.from && o.alloc && o.allocUnsafe && o.allocUnsafeSlow ? e.exports = r : (a(r, t), t.Buffer = i), a(o, i), i.from = function (e, t, n) { + if ("number" == typeof e) throw new TypeError("Argument must not be a number"); + return o(e, t, n) + }, i.alloc = function (e, t, n) { + if ("number" != typeof e) throw new TypeError("Argument must be a number"); + var r = o(e); + return void 0 !== t ? "string" == typeof n ? r.fill(t, n) : r.fill(t) : r.fill(0), r + }, i.allocUnsafe = function (e) { + if ("number" != typeof e) throw new TypeError("Argument must be a number"); + return o(e) + }, i.allocUnsafeSlow = function (e) { + if ("number" != typeof e) throw new TypeError("Argument must be a number"); + return r.SlowBuffer(e) + } + }, function (e, t, n) { + var r; + !function () { + "use strict"; + var n = {}.hasOwnProperty; + + function o() { + for (var e = [], t = 0; t < arguments.length; t++) { + var r = arguments[t]; + if (r) { + var a = typeof r; + if ("string" === a || "number" === a) e.push(r); else if (Array.isArray(r) && r.length) { + var i = o.apply(null, r); + i && e.push(i) + } else if ("object" === a) for (var s in r) n.call(r, s) && r[s] && e.push(s) + } + } + return e.join(" ") + } + + e.exports ? (o.default = o, e.exports = o) : void 0 === (r = function () { + return o + }.apply(t, [])) || (e.exports = r) + }() + }, function (e, t, n) { + var r = n(114), o = n(59); + e.exports = function (e) { + if (!o(e)) return !1; + var t = r(e); + return "[object Function]" == t || "[object GeneratorFunction]" == t || "[object AsyncFunction]" == t || "[object Proxy]" == t + } + }, function (e, t, n) { + e.exports = n(674) + }, function (e, t, n) { + e.exports = n(909) + }, function (e, t, n) { + var r = n(179), o = n(128); + e.exports = function (e) { + return r(o(e)) + } + }, function (e, t, n) { + var r = n(50), o = n(70), a = n(108); + e.exports = r ? function (e, t, n) { + return o.f(e, t, a(1, n)) + } : function (e, t, n) { + return e[t] = n, e + } + }, function (e, t, n) { + var r = n(50), o = n(357), a = n(52), i = n(180), s = Object.defineProperty; + t.f = r ? s : function (e, t, n) { + if (a(e), t = i(t, !0), a(n), o) try { + return s(e, t, n) + } catch (e) { + } + if ("get" in n || "set" in n) throw TypeError("Accessors not supported"); + return "value" in n && (e[t] = n.value), e + } + }, function (e, t, n) { + var r = n(128); + e.exports = function (e) { + return Object(r(e)) + } + }, function (e, t, n) { + var r = n(33), o = n(42), a = function (e) { + return "function" == typeof e ? e : void 0 + }; + e.exports = function (e, t) { + return arguments.length < 2 ? a(r[e]) || a(o[e]) : r[e] && r[e][t] || o[e] && o[e][t] + } + }, function (e, t, n) { + n(158); + var r = n(579), o = n(42), a = n(89), i = n(69), s = n(112), u = n(39)("toStringTag"); + for (var c in r) { + var l = o[c], p = l && l.prototype; + p && a(p) !== u && i(p, u, c), s[c] = s.Array + } + }, function (e, t, n) { + var r = n(406), o = "object" == typeof self && self && self.Object === Object && self, + a = r || o || Function("return this")(); + e.exports = a + }, function (e, t, n) { + "use strict"; + e.exports = {debugTool: null} + }, function (e, t, n) { + "use strict"; + (function (e) { + var r = n(591), o = n(592), a = n(372); + + function i() { + return u.TYPED_ARRAY_SUPPORT ? 2147483647 : 1073741823 + } + + function s(e, t) { + if (i() < t) throw new RangeError("Invalid typed array length"); + return u.TYPED_ARRAY_SUPPORT ? (e = new Uint8Array(t)).__proto__ = u.prototype : (null === e && (e = new u(t)), e.length = t), e + } + + function u(e, t, n) { + if (!(u.TYPED_ARRAY_SUPPORT || this instanceof u)) return new u(e, t, n); + if ("number" == typeof e) { + if ("string" == typeof t) throw new Error("If encoding is specified then the first argument must be a string"); + return p(this, e) + } + return c(this, e, t, n) + } + + function c(e, t, n, r) { + if ("number" == typeof t) throw new TypeError('"value" argument must not be a number'); + return "undefined" != typeof ArrayBuffer && t instanceof ArrayBuffer ? function (e, t, n, r) { + if (t.byteLength, n < 0 || t.byteLength < n) throw new RangeError("'offset' is out of bounds"); + if (t.byteLength < n + (r || 0)) throw new RangeError("'length' is out of bounds"); + t = void 0 === n && void 0 === r ? new Uint8Array(t) : void 0 === r ? new Uint8Array(t, n) : new Uint8Array(t, n, r); + u.TYPED_ARRAY_SUPPORT ? (e = t).__proto__ = u.prototype : e = f(e, t); + return e + }(e, t, n, r) : "string" == typeof t ? function (e, t, n) { + "string" == typeof n && "" !== n || (n = "utf8"); + if (!u.isEncoding(n)) throw new TypeError('"encoding" must be a valid string encoding'); + var r = 0 | d(t, n), o = (e = s(e, r)).write(t, n); + o !== r && (e = e.slice(0, o)); + return e + }(e, t, n) : function (e, t) { + if (u.isBuffer(t)) { + var n = 0 | h(t.length); + return 0 === (e = s(e, n)).length || t.copy(e, 0, 0, n), e + } + if (t) { + if ("undefined" != typeof ArrayBuffer && t.buffer instanceof ArrayBuffer || "length" in t) return "number" != typeof t.length || (r = t.length) != r ? s(e, 0) : f(e, t); + if ("Buffer" === t.type && a(t.data)) return f(e, t.data) + } + var r; + throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.") + }(e, t) + } + + function l(e) { + if ("number" != typeof e) throw new TypeError('"size" argument must be a number'); + if (e < 0) throw new RangeError('"size" argument must not be negative') + } + + function p(e, t) { + if (l(t), e = s(e, t < 0 ? 0 : 0 | h(t)), !u.TYPED_ARRAY_SUPPORT) for (var n = 0; n < t; ++n) e[n] = 0; + return e + } + + function f(e, t) { + var n = t.length < 0 ? 0 : 0 | h(t.length); + e = s(e, n); + for (var r = 0; r < n; r += 1) e[r] = 255 & t[r]; + return e + } + + function h(e) { + if (e >= i()) throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x" + i().toString(16) + " bytes"); + return 0 | e + } + + function d(e, t) { + if (u.isBuffer(e)) return e.length; + if ("undefined" != typeof ArrayBuffer && "function" == typeof ArrayBuffer.isView && (ArrayBuffer.isView(e) || e instanceof ArrayBuffer)) return e.byteLength; + "string" != typeof e && (e = "" + e); + var n = e.length; + if (0 === n) return 0; + for (var r = !1; ;) switch (t) { + case"ascii": + case"latin1": + case"binary": + return n; + case"utf8": + case"utf-8": + case void 0: + return q(e).length; + case"ucs2": + case"ucs-2": + case"utf16le": + case"utf-16le": + return 2 * n; + case"hex": + return n >>> 1; + case"base64": + return z(e).length; + default: + if (r) return q(e).length; + t = ("" + t).toLowerCase(), r = !0 + } + } + + function m(e, t, n) { + var r = !1; + if ((void 0 === t || t < 0) && (t = 0), t > this.length) return ""; + if ((void 0 === n || n > this.length) && (n = this.length), n <= 0) return ""; + if ((n >>>= 0) <= (t >>>= 0)) return ""; + for (e || (e = "utf8"); ;) switch (e) { + case"hex": + return T(this, t, n); + case"utf8": + case"utf-8": + return A(this, t, n); + case"ascii": + return O(this, t, n); + case"latin1": + case"binary": + return j(this, t, n); + case"base64": + return C(this, t, n); + case"ucs2": + case"ucs-2": + case"utf16le": + case"utf-16le": + return I(this, t, n); + default: + if (r) throw new TypeError("Unknown encoding: " + e); + e = (e + "").toLowerCase(), r = !0 + } + } + + function v(e, t, n) { + var r = e[t]; + e[t] = e[n], e[n] = r + } + + function g(e, t, n, r, o) { + if (0 === e.length) return -1; + if ("string" == typeof n ? (r = n, n = 0) : n > 2147483647 ? n = 2147483647 : n < -2147483648 && (n = -2147483648), n = +n, isNaN(n) && (n = o ? 0 : e.length - 1), n < 0 && (n = e.length + n), n >= e.length) { + if (o) return -1; + n = e.length - 1 + } else if (n < 0) { + if (!o) return -1; + n = 0 + } + if ("string" == typeof t && (t = u.from(t, r)), u.isBuffer(t)) return 0 === t.length ? -1 : y(e, t, n, r, o); + if ("number" == typeof t) return t &= 255, u.TYPED_ARRAY_SUPPORT && "function" == typeof Uint8Array.prototype.indexOf ? o ? Uint8Array.prototype.indexOf.call(e, t, n) : Uint8Array.prototype.lastIndexOf.call(e, t, n) : y(e, [t], n, r, o); + throw new TypeError("val must be string, number or Buffer") + } + + function y(e, t, n, r, o) { + var a, i = 1, s = e.length, u = t.length; + if (void 0 !== r && ("ucs2" === (r = String(r).toLowerCase()) || "ucs-2" === r || "utf16le" === r || "utf-16le" === r)) { + if (e.length < 2 || t.length < 2) return -1; + i = 2, s /= 2, u /= 2, n /= 2 + } + + function c(e, t) { + return 1 === i ? e[t] : e.readUInt16BE(t * i) + } + + if (o) { + var l = -1; + for (a = n; a < s; a++) if (c(e, a) === c(t, -1 === l ? 0 : a - l)) { + if (-1 === l && (l = a), a - l + 1 === u) return l * i + } else -1 !== l && (a -= a - l), l = -1 + } else for (n + u > s && (n = s - u), a = n; a >= 0; a--) { + for (var p = !0, f = 0; f < u; f++) if (c(e, a + f) !== c(t, f)) { + p = !1; + break + } + if (p) return a + } + return -1 + } + + function b(e, t, n, r) { + n = Number(n) || 0; + var o = e.length - n; + r ? (r = Number(r)) > o && (r = o) : r = o; + var a = t.length; + if (a % 2 != 0) throw new TypeError("Invalid hex string"); + r > a / 2 && (r = a / 2); + for (var i = 0; i < r; ++i) { + var s = parseInt(t.substr(2 * i, 2), 16); + if (isNaN(s)) return i; + e[n + i] = s + } + return i + } + + function _(e, t, n, r) { + return V(q(t, e.length - n), e, n, r) + } + + function w(e, t, n, r) { + return V(function (e) { + for (var t = [], n = 0; n < e.length; ++n) t.push(255 & e.charCodeAt(n)); + return t + }(t), e, n, r) + } + + function x(e, t, n, r) { + return w(e, t, n, r) + } + + function E(e, t, n, r) { + return V(z(t), e, n, r) + } + + function S(e, t, n, r) { + return V(function (e, t) { + for (var n, r, o, a = [], i = 0; i < e.length && !((t -= 2) < 0); ++i) r = (n = e.charCodeAt(i)) >> 8, o = n % 256, a.push(o), a.push(r); + return a + }(t, e.length - n), e, n, r) + } + + function C(e, t, n) { + return 0 === t && n === e.length ? r.fromByteArray(e) : r.fromByteArray(e.slice(t, n)) + } + + function A(e, t, n) { + n = Math.min(e.length, n); + for (var r = [], o = t; o < n;) { + var a, i, s, u, c = e[o], l = null, p = c > 239 ? 4 : c > 223 ? 3 : c > 191 ? 2 : 1; + if (o + p <= n) switch (p) { + case 1: + c < 128 && (l = c); + break; + case 2: + 128 == (192 & (a = e[o + 1])) && (u = (31 & c) << 6 | 63 & a) > 127 && (l = u); + break; + case 3: + a = e[o + 1], i = e[o + 2], 128 == (192 & a) && 128 == (192 & i) && (u = (15 & c) << 12 | (63 & a) << 6 | 63 & i) > 2047 && (u < 55296 || u > 57343) && (l = u); + break; + case 4: + a = e[o + 1], i = e[o + 2], s = e[o + 3], 128 == (192 & a) && 128 == (192 & i) && 128 == (192 & s) && (u = (15 & c) << 18 | (63 & a) << 12 | (63 & i) << 6 | 63 & s) > 65535 && u < 1114112 && (l = u) + } + null === l ? (l = 65533, p = 1) : l > 65535 && (l -= 65536, r.push(l >>> 10 & 1023 | 55296), l = 56320 | 1023 & l), r.push(l), o += p + } + return function (e) { + var t = e.length; + if (t <= k) return String.fromCharCode.apply(String, e); + var n = "", r = 0; + for (; r < t;) n += String.fromCharCode.apply(String, e.slice(r, r += k)); + return n + }(r) + } + + t.Buffer = u, t.SlowBuffer = function (e) { + +e != e && (e = 0); + return u.alloc(+e) + }, t.INSPECT_MAX_BYTES = 50, u.TYPED_ARRAY_SUPPORT = void 0 !== e.TYPED_ARRAY_SUPPORT ? e.TYPED_ARRAY_SUPPORT : function () { + try { + var e = new Uint8Array(1); + return e.__proto__ = { + __proto__: Uint8Array.prototype, foo: function () { + return 42 + } + }, 42 === e.foo() && "function" == typeof e.subarray && 0 === e.subarray(1, 1).byteLength + } catch (e) { + return !1 + } + }(), t.kMaxLength = i(), u.poolSize = 8192, u._augment = function (e) { + return e.__proto__ = u.prototype, e + }, u.from = function (e, t, n) { + return c(null, e, t, n) + }, u.TYPED_ARRAY_SUPPORT && (u.prototype.__proto__ = Uint8Array.prototype, u.__proto__ = Uint8Array, "undefined" != typeof Symbol && Symbol.species && u[Symbol.species] === u && Object.defineProperty(u, Symbol.species, { + value: null, + configurable: !0 + })), u.alloc = function (e, t, n) { + return function (e, t, n, r) { + return l(t), t <= 0 ? s(e, t) : void 0 !== n ? "string" == typeof r ? s(e, t).fill(n, r) : s(e, t).fill(n) : s(e, t) + }(null, e, t, n) + }, u.allocUnsafe = function (e) { + return p(null, e) + }, u.allocUnsafeSlow = function (e) { + return p(null, e) + }, u.isBuffer = function (e) { + return !(null == e || !e._isBuffer) + }, u.compare = function (e, t) { + if (!u.isBuffer(e) || !u.isBuffer(t)) throw new TypeError("Arguments must be Buffers"); + if (e === t) return 0; + for (var n = e.length, r = t.length, o = 0, a = Math.min(n, r); o < a; ++o) if (e[o] !== t[o]) { + n = e[o], r = t[o]; + break + } + return n < r ? -1 : r < n ? 1 : 0 + }, u.isEncoding = function (e) { + switch (String(e).toLowerCase()) { + case"hex": + case"utf8": + case"utf-8": + case"ascii": + case"latin1": + case"binary": + case"base64": + case"ucs2": + case"ucs-2": + case"utf16le": + case"utf-16le": + return !0; + default: + return !1 + } + }, u.concat = function (e, t) { + if (!a(e)) throw new TypeError('"list" argument must be an Array of Buffers'); + if (0 === e.length) return u.alloc(0); + var n; + if (void 0 === t) for (t = 0, n = 0; n < e.length; ++n) t += e[n].length; + var r = u.allocUnsafe(t), o = 0; + for (n = 0; n < e.length; ++n) { + var i = e[n]; + if (!u.isBuffer(i)) throw new TypeError('"list" argument must be an Array of Buffers'); + i.copy(r, o), o += i.length + } + return r + }, u.byteLength = d, u.prototype._isBuffer = !0, u.prototype.swap16 = function () { + var e = this.length; + if (e % 2 != 0) throw new RangeError("Buffer size must be a multiple of 16-bits"); + for (var t = 0; t < e; t += 2) v(this, t, t + 1); + return this + }, u.prototype.swap32 = function () { + var e = this.length; + if (e % 4 != 0) throw new RangeError("Buffer size must be a multiple of 32-bits"); + for (var t = 0; t < e; t += 4) v(this, t, t + 3), v(this, t + 1, t + 2); + return this + }, u.prototype.swap64 = function () { + var e = this.length; + if (e % 8 != 0) throw new RangeError("Buffer size must be a multiple of 64-bits"); + for (var t = 0; t < e; t += 8) v(this, t, t + 7), v(this, t + 1, t + 6), v(this, t + 2, t + 5), v(this, t + 3, t + 4); + return this + }, u.prototype.toString = function () { + var e = 0 | this.length; + return 0 === e ? "" : 0 === arguments.length ? A(this, 0, e) : m.apply(this, arguments) + }, u.prototype.equals = function (e) { + if (!u.isBuffer(e)) throw new TypeError("Argument must be a Buffer"); + return this === e || 0 === u.compare(this, e) + }, u.prototype.inspect = function () { + var e = "", n = t.INSPECT_MAX_BYTES; + return this.length > 0 && (e = this.toString("hex", 0, n).match(/.{2}/g).join(" "), this.length > n && (e += " ... ")), "" + }, u.prototype.compare = function (e, t, n, r, o) { + if (!u.isBuffer(e)) throw new TypeError("Argument must be a Buffer"); + if (void 0 === t && (t = 0), void 0 === n && (n = e ? e.length : 0), void 0 === r && (r = 0), void 0 === o && (o = this.length), t < 0 || n > e.length || r < 0 || o > this.length) throw new RangeError("out of range index"); + if (r >= o && t >= n) return 0; + if (r >= o) return -1; + if (t >= n) return 1; + if (this === e) return 0; + for (var a = (o >>>= 0) - (r >>>= 0), i = (n >>>= 0) - (t >>>= 0), s = Math.min(a, i), c = this.slice(r, o), l = e.slice(t, n), p = 0; p < s; ++p) if (c[p] !== l[p]) { + a = c[p], i = l[p]; + break + } + return a < i ? -1 : i < a ? 1 : 0 + }, u.prototype.includes = function (e, t, n) { + return -1 !== this.indexOf(e, t, n) + }, u.prototype.indexOf = function (e, t, n) { + return g(this, e, t, n, !0) + }, u.prototype.lastIndexOf = function (e, t, n) { + return g(this, e, t, n, !1) + }, u.prototype.write = function (e, t, n, r) { + if (void 0 === t) r = "utf8", n = this.length, t = 0; else if (void 0 === n && "string" == typeof t) r = t, n = this.length, t = 0; else { + if (!isFinite(t)) throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported"); + t |= 0, isFinite(n) ? (n |= 0, void 0 === r && (r = "utf8")) : (r = n, n = void 0) + } + var o = this.length - t; + if ((void 0 === n || n > o) && (n = o), e.length > 0 && (n < 0 || t < 0) || t > this.length) throw new RangeError("Attempt to write outside buffer bounds"); + r || (r = "utf8"); + for (var a = !1; ;) switch (r) { + case"hex": + return b(this, e, t, n); + case"utf8": + case"utf-8": + return _(this, e, t, n); + case"ascii": + return w(this, e, t, n); + case"latin1": + case"binary": + return x(this, e, t, n); + case"base64": + return E(this, e, t, n); + case"ucs2": + case"ucs-2": + case"utf16le": + case"utf-16le": + return S(this, e, t, n); + default: + if (a) throw new TypeError("Unknown encoding: " + r); + r = ("" + r).toLowerCase(), a = !0 + } + }, u.prototype.toJSON = function () { + return {type: "Buffer", data: Array.prototype.slice.call(this._arr || this, 0)} + }; + var k = 4096; + + function O(e, t, n) { + var r = ""; + n = Math.min(e.length, n); + for (var o = t; o < n; ++o) r += String.fromCharCode(127 & e[o]); + return r + } + + function j(e, t, n) { + var r = ""; + n = Math.min(e.length, n); + for (var o = t; o < n; ++o) r += String.fromCharCode(e[o]); + return r + } + + function T(e, t, n) { + var r = e.length; + (!t || t < 0) && (t = 0), (!n || n < 0 || n > r) && (n = r); + for (var o = "", a = t; a < n; ++a) o += U(e[a]); + return o + } + + function I(e, t, n) { + for (var r = e.slice(t, n), o = "", a = 0; a < r.length; a += 2) o += String.fromCharCode(r[a] + 256 * r[a + 1]); + return o + } + + function P(e, t, n) { + if (e % 1 != 0 || e < 0) throw new RangeError("offset is not uint"); + if (e + t > n) throw new RangeError("Trying to access beyond buffer length") + } + + function N(e, t, n, r, o, a) { + if (!u.isBuffer(e)) throw new TypeError('"buffer" argument must be a Buffer instance'); + if (t > o || t < a) throw new RangeError('"value" argument is out of bounds'); + if (n + r > e.length) throw new RangeError("Index out of range") + } + + function M(e, t, n, r) { + t < 0 && (t = 65535 + t + 1); + for (var o = 0, a = Math.min(e.length - n, 2); o < a; ++o) e[n + o] = (t & 255 << 8 * (r ? o : 1 - o)) >>> 8 * (r ? o : 1 - o) + } + + function R(e, t, n, r) { + t < 0 && (t = 4294967295 + t + 1); + for (var o = 0, a = Math.min(e.length - n, 4); o < a; ++o) e[n + o] = t >>> 8 * (r ? o : 3 - o) & 255 + } + + function D(e, t, n, r, o, a) { + if (n + r > e.length) throw new RangeError("Index out of range"); + if (n < 0) throw new RangeError("Index out of range") + } + + function L(e, t, n, r, a) { + return a || D(e, 0, n, 4), o.write(e, t, n, r, 23, 4), n + 4 + } + + function B(e, t, n, r, a) { + return a || D(e, 0, n, 8), o.write(e, t, n, r, 52, 8), n + 8 + } + + u.prototype.slice = function (e, t) { + var n, r = this.length; + if ((e = ~~e) < 0 ? (e += r) < 0 && (e = 0) : e > r && (e = r), (t = void 0 === t ? r : ~~t) < 0 ? (t += r) < 0 && (t = 0) : t > r && (t = r), t < e && (t = e), u.TYPED_ARRAY_SUPPORT) (n = this.subarray(e, t)).__proto__ = u.prototype; else { + var o = t - e; + n = new u(o, void 0); + for (var a = 0; a < o; ++a) n[a] = this[a + e] + } + return n + }, u.prototype.readUIntLE = function (e, t, n) { + e |= 0, t |= 0, n || P(e, t, this.length); + for (var r = this[e], o = 1, a = 0; ++a < t && (o *= 256);) r += this[e + a] * o; + return r + }, u.prototype.readUIntBE = function (e, t, n) { + e |= 0, t |= 0, n || P(e, t, this.length); + for (var r = this[e + --t], o = 1; t > 0 && (o *= 256);) r += this[e + --t] * o; + return r + }, u.prototype.readUInt8 = function (e, t) { + return t || P(e, 1, this.length), this[e] + }, u.prototype.readUInt16LE = function (e, t) { + return t || P(e, 2, this.length), this[e] | this[e + 1] << 8 + }, u.prototype.readUInt16BE = function (e, t) { + return t || P(e, 2, this.length), this[e] << 8 | this[e + 1] + }, u.prototype.readUInt32LE = function (e, t) { + return t || P(e, 4, this.length), (this[e] | this[e + 1] << 8 | this[e + 2] << 16) + 16777216 * this[e + 3] + }, u.prototype.readUInt32BE = function (e, t) { + return t || P(e, 4, this.length), 16777216 * this[e] + (this[e + 1] << 16 | this[e + 2] << 8 | this[e + 3]) + }, u.prototype.readIntLE = function (e, t, n) { + e |= 0, t |= 0, n || P(e, t, this.length); + for (var r = this[e], o = 1, a = 0; ++a < t && (o *= 256);) r += this[e + a] * o; + return r >= (o *= 128) && (r -= Math.pow(2, 8 * t)), r + }, u.prototype.readIntBE = function (e, t, n) { + e |= 0, t |= 0, n || P(e, t, this.length); + for (var r = t, o = 1, a = this[e + --r]; r > 0 && (o *= 256);) a += this[e + --r] * o; + return a >= (o *= 128) && (a -= Math.pow(2, 8 * t)), a + }, u.prototype.readInt8 = function (e, t) { + return t || P(e, 1, this.length), 128 & this[e] ? -1 * (255 - this[e] + 1) : this[e] + }, u.prototype.readInt16LE = function (e, t) { + t || P(e, 2, this.length); + var n = this[e] | this[e + 1] << 8; + return 32768 & n ? 4294901760 | n : n + }, u.prototype.readInt16BE = function (e, t) { + t || P(e, 2, this.length); + var n = this[e + 1] | this[e] << 8; + return 32768 & n ? 4294901760 | n : n + }, u.prototype.readInt32LE = function (e, t) { + return t || P(e, 4, this.length), this[e] | this[e + 1] << 8 | this[e + 2] << 16 | this[e + 3] << 24 + }, u.prototype.readInt32BE = function (e, t) { + return t || P(e, 4, this.length), this[e] << 24 | this[e + 1] << 16 | this[e + 2] << 8 | this[e + 3] + }, u.prototype.readFloatLE = function (e, t) { + return t || P(e, 4, this.length), o.read(this, e, !0, 23, 4) + }, u.prototype.readFloatBE = function (e, t) { + return t || P(e, 4, this.length), o.read(this, e, !1, 23, 4) + }, u.prototype.readDoubleLE = function (e, t) { + return t || P(e, 8, this.length), o.read(this, e, !0, 52, 8) + }, u.prototype.readDoubleBE = function (e, t) { + return t || P(e, 8, this.length), o.read(this, e, !1, 52, 8) + }, u.prototype.writeUIntLE = function (e, t, n, r) { + (e = +e, t |= 0, n |= 0, r) || N(this, e, t, n, Math.pow(2, 8 * n) - 1, 0); + var o = 1, a = 0; + for (this[t] = 255 & e; ++a < n && (o *= 256);) this[t + a] = e / o & 255; + return t + n + }, u.prototype.writeUIntBE = function (e, t, n, r) { + (e = +e, t |= 0, n |= 0, r) || N(this, e, t, n, Math.pow(2, 8 * n) - 1, 0); + var o = n - 1, a = 1; + for (this[t + o] = 255 & e; --o >= 0 && (a *= 256);) this[t + o] = e / a & 255; + return t + n + }, u.prototype.writeUInt8 = function (e, t, n) { + return e = +e, t |= 0, n || N(this, e, t, 1, 255, 0), u.TYPED_ARRAY_SUPPORT || (e = Math.floor(e)), this[t] = 255 & e, t + 1 + }, u.prototype.writeUInt16LE = function (e, t, n) { + return e = +e, t |= 0, n || N(this, e, t, 2, 65535, 0), u.TYPED_ARRAY_SUPPORT ? (this[t] = 255 & e, this[t + 1] = e >>> 8) : M(this, e, t, !0), t + 2 + }, u.prototype.writeUInt16BE = function (e, t, n) { + return e = +e, t |= 0, n || N(this, e, t, 2, 65535, 0), u.TYPED_ARRAY_SUPPORT ? (this[t] = e >>> 8, this[t + 1] = 255 & e) : M(this, e, t, !1), t + 2 + }, u.prototype.writeUInt32LE = function (e, t, n) { + return e = +e, t |= 0, n || N(this, e, t, 4, 4294967295, 0), u.TYPED_ARRAY_SUPPORT ? (this[t + 3] = e >>> 24, this[t + 2] = e >>> 16, this[t + 1] = e >>> 8, this[t] = 255 & e) : R(this, e, t, !0), t + 4 + }, u.prototype.writeUInt32BE = function (e, t, n) { + return e = +e, t |= 0, n || N(this, e, t, 4, 4294967295, 0), u.TYPED_ARRAY_SUPPORT ? (this[t] = e >>> 24, this[t + 1] = e >>> 16, this[t + 2] = e >>> 8, this[t + 3] = 255 & e) : R(this, e, t, !1), t + 4 + }, u.prototype.writeIntLE = function (e, t, n, r) { + if (e = +e, t |= 0, !r) { + var o = Math.pow(2, 8 * n - 1); + N(this, e, t, n, o - 1, -o) + } + var a = 0, i = 1, s = 0; + for (this[t] = 255 & e; ++a < n && (i *= 256);) e < 0 && 0 === s && 0 !== this[t + a - 1] && (s = 1), this[t + a] = (e / i >> 0) - s & 255; + return t + n + }, u.prototype.writeIntBE = function (e, t, n, r) { + if (e = +e, t |= 0, !r) { + var o = Math.pow(2, 8 * n - 1); + N(this, e, t, n, o - 1, -o) + } + var a = n - 1, i = 1, s = 0; + for (this[t + a] = 255 & e; --a >= 0 && (i *= 256);) e < 0 && 0 === s && 0 !== this[t + a + 1] && (s = 1), this[t + a] = (e / i >> 0) - s & 255; + return t + n + }, u.prototype.writeInt8 = function (e, t, n) { + return e = +e, t |= 0, n || N(this, e, t, 1, 127, -128), u.TYPED_ARRAY_SUPPORT || (e = Math.floor(e)), e < 0 && (e = 255 + e + 1), this[t] = 255 & e, t + 1 + }, u.prototype.writeInt16LE = function (e, t, n) { + return e = +e, t |= 0, n || N(this, e, t, 2, 32767, -32768), u.TYPED_ARRAY_SUPPORT ? (this[t] = 255 & e, this[t + 1] = e >>> 8) : M(this, e, t, !0), t + 2 + }, u.prototype.writeInt16BE = function (e, t, n) { + return e = +e, t |= 0, n || N(this, e, t, 2, 32767, -32768), u.TYPED_ARRAY_SUPPORT ? (this[t] = e >>> 8, this[t + 1] = 255 & e) : M(this, e, t, !1), t + 2 + }, u.prototype.writeInt32LE = function (e, t, n) { + return e = +e, t |= 0, n || N(this, e, t, 4, 2147483647, -2147483648), u.TYPED_ARRAY_SUPPORT ? (this[t] = 255 & e, this[t + 1] = e >>> 8, this[t + 2] = e >>> 16, this[t + 3] = e >>> 24) : R(this, e, t, !0), t + 4 + }, u.prototype.writeInt32BE = function (e, t, n) { + return e = +e, t |= 0, n || N(this, e, t, 4, 2147483647, -2147483648), e < 0 && (e = 4294967295 + e + 1), u.TYPED_ARRAY_SUPPORT ? (this[t] = e >>> 24, this[t + 1] = e >>> 16, this[t + 2] = e >>> 8, this[t + 3] = 255 & e) : R(this, e, t, !1), t + 4 + }, u.prototype.writeFloatLE = function (e, t, n) { + return L(this, e, t, !0, n) + }, u.prototype.writeFloatBE = function (e, t, n) { + return L(this, e, t, !1, n) + }, u.prototype.writeDoubleLE = function (e, t, n) { + return B(this, e, t, !0, n) + }, u.prototype.writeDoubleBE = function (e, t, n) { + return B(this, e, t, !1, n) + }, u.prototype.copy = function (e, t, n, r) { + if (n || (n = 0), r || 0 === r || (r = this.length), t >= e.length && (t = e.length), t || (t = 0), r > 0 && r < n && (r = n), r === n) return 0; + if (0 === e.length || 0 === this.length) return 0; + if (t < 0) throw new RangeError("targetStart out of bounds"); + if (n < 0 || n >= this.length) throw new RangeError("sourceStart out of bounds"); + if (r < 0) throw new RangeError("sourceEnd out of bounds"); + r > this.length && (r = this.length), e.length - t < r - n && (r = e.length - t + n); + var o, a = r - n; + if (this === e && n < t && t < r) for (o = a - 1; o >= 0; --o) e[o + t] = this[o + n]; else if (a < 1e3 || !u.TYPED_ARRAY_SUPPORT) for (o = 0; o < a; ++o) e[o + t] = this[o + n]; else Uint8Array.prototype.set.call(e, this.subarray(n, n + a), t); + return a + }, u.prototype.fill = function (e, t, n, r) { + if ("string" == typeof e) { + if ("string" == typeof t ? (r = t, t = 0, n = this.length) : "string" == typeof n && (r = n, n = this.length), 1 === e.length) { + var o = e.charCodeAt(0); + o < 256 && (e = o) + } + if (void 0 !== r && "string" != typeof r) throw new TypeError("encoding must be a string"); + if ("string" == typeof r && !u.isEncoding(r)) throw new TypeError("Unknown encoding: " + r) + } else "number" == typeof e && (e &= 255); + if (t < 0 || this.length < t || this.length < n) throw new RangeError("Out of range index"); + if (n <= t) return this; + var a; + if (t >>>= 0, n = void 0 === n ? this.length : n >>> 0, e || (e = 0), "number" == typeof e) for (a = t; a < n; ++a) this[a] = e; else { + var i = u.isBuffer(e) ? e : q(new u(e, r).toString()), s = i.length; + for (a = 0; a < n - t; ++a) this[a + t] = i[a % s] + } + return this + }; + var F = /[^+\/0-9A-Za-z-_]/g; + + function U(e) { + return e < 16 ? "0" + e.toString(16) : e.toString(16) + } + + function q(e, t) { + var n; + t = t || 1 / 0; + for (var r = e.length, o = null, a = [], i = 0; i < r; ++i) { + if ((n = e.charCodeAt(i)) > 55295 && n < 57344) { + if (!o) { + if (n > 56319) { + (t -= 3) > -1 && a.push(239, 191, 189); + continue + } + if (i + 1 === r) { + (t -= 3) > -1 && a.push(239, 191, 189); + continue + } + o = n; + continue + } + if (n < 56320) { + (t -= 3) > -1 && a.push(239, 191, 189), o = n; + continue + } + n = 65536 + (o - 55296 << 10 | n - 56320) + } else o && (t -= 3) > -1 && a.push(239, 191, 189); + if (o = null, n < 128) { + if ((t -= 1) < 0) break; + a.push(n) + } else if (n < 2048) { + if ((t -= 2) < 0) break; + a.push(n >> 6 | 192, 63 & n | 128) + } else if (n < 65536) { + if ((t -= 3) < 0) break; + a.push(n >> 12 | 224, n >> 6 & 63 | 128, 63 & n | 128) + } else { + if (!(n < 1114112)) throw new Error("Invalid code point"); + if ((t -= 4) < 0) break; + a.push(n >> 18 | 240, n >> 12 & 63 | 128, n >> 6 & 63 | 128, 63 & n | 128) + } + } + return a + } + + function z(e) { + return r.toByteArray(function (e) { + if ((e = function (e) { + return e.trim ? e.trim() : e.replace(/^\s+|\s+$/g, "") + }(e).replace(F, "")).length < 2) return ""; + for (; e.length % 4 != 0;) e += "="; + return e + }(e)) + } + + function V(e, t, n, r) { + for (var o = 0; o < r && !(o + n >= t.length || o >= e.length); ++o) t[o + n] = e[o]; + return o + } + }).call(this, n(54)) + }, function (e, t, n) { + "use strict"; + var r = n(849); + e.exports = r + }, function (e, t, n) { + var r = n(896); + + function o(e, t, n, o, a, i, s) { + try { + var u = e[i](s), c = u.value + } catch (e) { + return void n(e) + } + u.done ? t(c) : r.resolve(c).then(o, a) + } + + e.exports = function (e) { + return function () { + var t = this, n = arguments; + return new r((function (r, a) { + var i = e.apply(t, n); + + function s(e) { + o(i, r, a, s, u, "next", e) + } + + function u(e) { + o(i, r, a, s, u, "throw", e) + } + + s(void 0) + })) + } + }, e.exports.default = e.exports, e.exports.__esModule = !0 + }, function (e, t) { + e.exports = function (e) { + if ("function" != typeof e) throw TypeError(String(e) + " is not a function"); + return e + } + }, function (e, t, n) { + var r = n(150), o = Math.min; + e.exports = function (e) { + return e > 0 ? o(r(e), 9007199254740991) : 0 + } + }, function (e, t, n) { + var r, o, a, i = n(363), s = n(42), u = n(45), c = n(69), l = n(55), p = n(230), f = n(184), h = n(156), + d = s.WeakMap; + if (i) { + var m = p.state || (p.state = new d), v = m.get, g = m.has, y = m.set; + r = function (e, t) { + return t.facade = e, y.call(m, e, t), t + }, o = function (e) { + return v.call(m, e) || {} + }, a = function (e) { + return g.call(m, e) + } + } else { + var b = f("state"); + h[b] = !0, r = function (e, t) { + return t.facade = e, c(e, b, t), t + }, o = function (e) { + return l(e, b) ? e[b] : {} + }, a = function (e) { + return l(e, b) + } + } + e.exports = { + set: r, get: o, has: a, enforce: function (e) { + return a(e) ? o(e) : r(e, {}) + }, getterFor: function (e) { + return function (t) { + var n; + if (!u(t) || (n = o(t)).type !== e) throw TypeError("Incompatible receiver, " + e + " required"); + return n + } + } + } + }, function (e, t, n) { + "use strict"; + + function r(e) { + return function () { + return e + } + } + + var o = function () { + }; + o.thatReturns = r, o.thatReturnsFalse = r(!1), o.thatReturnsTrue = r(!0), o.thatReturnsNull = r(null), o.thatReturnsThis = function () { + return this + }, o.thatReturnsArgument = function (e) { + return e + }, e.exports = o + }, function (e, t, n) { + "use strict"; + var r = n(31), o = n(40), a = n(474), i = n(124), s = n(475), u = n(140), c = n(203), l = n(26), p = [], f = 0, + h = a.getPooled(), d = !1, m = null; + + function v() { + x.ReactReconcileTransaction && m || r("123") + } + + var g = [{ + initialize: function () { + this.dirtyComponentsLength = p.length + }, close: function () { + this.dirtyComponentsLength !== p.length ? (p.splice(0, this.dirtyComponentsLength), w()) : p.length = 0 + } + }, { + initialize: function () { + this.callbackQueue.reset() + }, close: function () { + this.callbackQueue.notifyAll() + } + }]; + + function y() { + this.reinitializeTransaction(), this.dirtyComponentsLength = null, this.callbackQueue = a.getPooled(), this.reconcileTransaction = x.ReactReconcileTransaction.getPooled(!0) + } + + function b(e, t) { + return e._mountOrder - t._mountOrder + } + + function _(e) { + var t = e.dirtyComponentsLength; + t !== p.length && r("124", t, p.length), p.sort(b), f++; + for (var n = 0; n < t; n++) { + var o, a = p[n], i = a._pendingCallbacks; + if (a._pendingCallbacks = null, s.logTopLevelRenders) { + var c = a; + a._currentElement.type.isReactTopLevelWrapper && (c = a._renderedComponent), o = "React update: " + c.getName(), console.time(o) + } + if (u.performUpdateIfNecessary(a, e.reconcileTransaction, f), o && console.timeEnd(o), i) for (var l = 0; l < i.length; l++) e.callbackQueue.enqueue(i[l], a.getPublicInstance()) + } + } + + o(y.prototype, c, { + getTransactionWrappers: function () { + return g + }, destructor: function () { + this.dirtyComponentsLength = null, a.release(this.callbackQueue), this.callbackQueue = null, x.ReactReconcileTransaction.release(this.reconcileTransaction), this.reconcileTransaction = null + }, perform: function (e, t, n) { + return c.perform.call(this, this.reconcileTransaction.perform, this.reconcileTransaction, e, t, n) + } + }), i.addPoolingTo(y); + var w = function () { + for (; p.length || d;) { + if (p.length) { + var e = y.getPooled(); + e.perform(_, null, e), y.release(e) + } + if (d) { + d = !1; + var t = h; + h = a.getPooled(), t.notifyAll(), a.release(t) + } + } + }; + var x = { + ReactReconcileTransaction: null, batchedUpdates: function (e, t, n, r, o, a) { + return v(), m.batchedUpdates(e, t, n, r, o, a) + }, enqueueUpdate: function e(t) { + v(), m.isBatchingUpdates ? (p.push(t), null == t._updateBatchNumber && (t._updateBatchNumber = f + 1)) : m.batchedUpdates(e, t) + }, flushBatchedUpdates: w, injection: { + injectReconcileTransaction: function (e) { + e || r("126"), x.ReactReconcileTransaction = e + }, injectBatchingStrategy: function (e) { + e || r("127"), "function" != typeof e.batchedUpdates && r("128"), "boolean" != typeof e.isBatchingUpdates && r("129"), m = e + } + }, asap: function (e, t) { + l(m.isBatchingUpdates, "ReactUpdates.asap: Can't enqueue an asap callback in a context whereupdates are not being batched."), h.enqueue(e, t), d = !0 + } + }; + e.exports = x + }, function (e, t, n) { + "use strict"; + (function (t) { + function n(e) { + return e instanceof t || e instanceof Date || e instanceof RegExp + } + + function r(e) { + if (e instanceof t) { + var n = t.alloc ? t.alloc(e.length) : new t(e.length); + return e.copy(n), n + } + if (e instanceof Date) return new Date(e.getTime()); + if (e instanceof RegExp) return new RegExp(e); + throw new Error("Unexpected situation") + } + + function o(e) { + var t = []; + return e.forEach((function (e, a) { + "object" == typeof e && null !== e ? Array.isArray(e) ? t[a] = o(e) : n(e) ? t[a] = r(e) : t[a] = i({}, e) : t[a] = e + })), t + } + + function a(e, t) { + return "__proto__" === t ? void 0 : e[t] + } + + var i = e.exports = function () { + if (arguments.length < 1 || "object" != typeof arguments[0]) return !1; + if (arguments.length < 2) return arguments[0]; + var e, t, s = arguments[0], u = Array.prototype.slice.call(arguments, 1); + return u.forEach((function (u) { + "object" != typeof u || null === u || Array.isArray(u) || Object.keys(u).forEach((function (c) { + return t = a(s, c), (e = a(u, c)) === s ? void 0 : "object" != typeof e || null === e ? void (s[c] = e) : Array.isArray(e) ? void (s[c] = o(e)) : n(e) ? void (s[c] = r(e)) : "object" != typeof t || null === t || Array.isArray(t) ? void (s[c] = i({}, e)) : void (s[c] = i(t, e)) + })) + })), s + } + }).call(this, n(76).Buffer) + }, function (e, t, n) { + e.exports = n(649) + }, function (e, t, n) { + "use strict"; + var r = n(1076), o = n(1077); + + function a() { + this.protocol = null, this.slashes = null, this.auth = null, this.host = null, this.port = null, this.hostname = null, this.hash = null, this.search = null, this.query = null, this.pathname = null, this.path = null, this.href = null + } + + t.parse = b, t.resolve = function (e, t) { + return b(e, !1, !0).resolve(t) + }, t.resolveObject = function (e, t) { + return e ? b(e, !1, !0).resolveObject(t) : t + }, t.format = function (e) { + o.isString(e) && (e = b(e)); + return e instanceof a ? e.format() : a.prototype.format.call(e) + }, t.Url = a; + var i = /^([a-z0-9.+-]+:)/i, s = /:[0-9]*$/, u = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/, + c = ["{", "}", "|", "\\", "^", "`"].concat(["<", ">", '"', "`", " ", "\r", "\n", "\t"]), + l = ["'"].concat(c), p = ["%", "/", "?", ";", "#"].concat(l), f = ["/", "?", "#"], + h = /^[+a-z0-9A-Z_-]{0,63}$/, d = /^([+a-z0-9A-Z_-]{0,63})(.*)$/, m = {javascript: !0, "javascript:": !0}, + v = {javascript: !0, "javascript:": !0}, g = { + http: !0, + https: !0, + ftp: !0, + gopher: !0, + file: !0, + "http:": !0, + "https:": !0, + "ftp:": !0, + "gopher:": !0, + "file:": !0 + }, y = n(1078); + + function b(e, t, n) { + if (e && o.isObject(e) && e instanceof a) return e; + var r = new a; + return r.parse(e, t, n), r + } + + a.prototype.parse = function (e, t, n) { + if (!o.isString(e)) throw new TypeError("Parameter 'url' must be a string, not " + typeof e); + var a = e.indexOf("?"), s = -1 !== a && a < e.indexOf("#") ? "?" : "#", c = e.split(s); + c[0] = c[0].replace(/\\/g, "/"); + var b = e = c.join(s); + if (b = b.trim(), !n && 1 === e.split("#").length) { + var _ = u.exec(b); + if (_) return this.path = b, this.href = b, this.pathname = _[1], _[2] ? (this.search = _[2], this.query = t ? y.parse(this.search.substr(1)) : this.search.substr(1)) : t && (this.search = "", this.query = {}), this + } + var w = i.exec(b); + if (w) { + var x = (w = w[0]).toLowerCase(); + this.protocol = x, b = b.substr(w.length) + } + if (n || w || b.match(/^\/\/[^@\/]+@[^@\/]+/)) { + var E = "//" === b.substr(0, 2); + !E || w && v[w] || (b = b.substr(2), this.slashes = !0) + } + if (!v[w] && (E || w && !g[w])) { + for (var S, C, A = -1, k = 0; k < f.length; k++) { + -1 !== (O = b.indexOf(f[k])) && (-1 === A || O < A) && (A = O) + } + -1 !== (C = -1 === A ? b.lastIndexOf("@") : b.lastIndexOf("@", A)) && (S = b.slice(0, C), b = b.slice(C + 1), this.auth = decodeURIComponent(S)), A = -1; + for (k = 0; k < p.length; k++) { + var O; + -1 !== (O = b.indexOf(p[k])) && (-1 === A || O < A) && (A = O) + } + -1 === A && (A = b.length), this.host = b.slice(0, A), b = b.slice(A), this.parseHost(), this.hostname = this.hostname || ""; + var j = "[" === this.hostname[0] && "]" === this.hostname[this.hostname.length - 1]; + if (!j) for (var T = this.hostname.split(/\./), I = (k = 0, T.length); k < I; k++) { + var P = T[k]; + if (P && !P.match(h)) { + for (var N = "", M = 0, R = P.length; M < R; M++) P.charCodeAt(M) > 127 ? N += "x" : N += P[M]; + if (!N.match(h)) { + var D = T.slice(0, k), L = T.slice(k + 1), B = P.match(d); + B && (D.push(B[1]), L.unshift(B[2])), L.length && (b = "/" + L.join(".") + b), this.hostname = D.join("."); + break + } + } + } + this.hostname.length > 255 ? this.hostname = "" : this.hostname = this.hostname.toLowerCase(), j || (this.hostname = r.toASCII(this.hostname)); + var F = this.port ? ":" + this.port : "", U = this.hostname || ""; + this.host = U + F, this.href += this.host, j && (this.hostname = this.hostname.substr(1, this.hostname.length - 2), "/" !== b[0] && (b = "/" + b)) + } + if (!m[x]) for (k = 0, I = l.length; k < I; k++) { + var q = l[k]; + if (-1 !== b.indexOf(q)) { + var z = encodeURIComponent(q); + z === q && (z = escape(q)), b = b.split(q).join(z) + } + } + var V = b.indexOf("#"); + -1 !== V && (this.hash = b.substr(V), b = b.slice(0, V)); + var W = b.indexOf("?"); + if (-1 !== W ? (this.search = b.substr(W), this.query = b.substr(W + 1), t && (this.query = y.parse(this.query)), b = b.slice(0, W)) : t && (this.search = "", this.query = {}), b && (this.pathname = b), g[x] && this.hostname && !this.pathname && (this.pathname = "/"), this.pathname || this.search) { + F = this.pathname || ""; + var H = this.search || ""; + this.path = F + H + } + return this.href = this.format(), this + }, a.prototype.format = function () { + var e = this.auth || ""; + e && (e = (e = encodeURIComponent(e)).replace(/%3A/i, ":"), e += "@"); + var t = this.protocol || "", n = this.pathname || "", r = this.hash || "", a = !1, i = ""; + this.host ? a = e + this.host : this.hostname && (a = e + (-1 === this.hostname.indexOf(":") ? this.hostname : "[" + this.hostname + "]"), this.port && (a += ":" + this.port)), this.query && o.isObject(this.query) && Object.keys(this.query).length && (i = y.stringify(this.query)); + var s = this.search || i && "?" + i || ""; + return t && ":" !== t.substr(-1) && (t += ":"), this.slashes || (!t || g[t]) && !1 !== a ? (a = "//" + (a || ""), n && "/" !== n.charAt(0) && (n = "/" + n)) : a || (a = ""), r && "#" !== r.charAt(0) && (r = "#" + r), s && "?" !== s.charAt(0) && (s = "?" + s), t + a + (n = n.replace(/[?#]/g, (function (e) { + return encodeURIComponent(e) + }))) + (s = s.replace("#", "%23")) + r + }, a.prototype.resolve = function (e) { + return this.resolveObject(b(e, !1, !0)).format() + }, a.prototype.resolveObject = function (e) { + if (o.isString(e)) { + var t = new a; + t.parse(e, !1, !0), e = t + } + for (var n = new a, r = Object.keys(this), i = 0; i < r.length; i++) { + var s = r[i]; + n[s] = this[s] + } + if (n.hash = e.hash, "" === e.href) return n.href = n.format(), n; + if (e.slashes && !e.protocol) { + for (var u = Object.keys(e), c = 0; c < u.length; c++) { + var l = u[c]; + "protocol" !== l && (n[l] = e[l]) + } + return g[n.protocol] && n.hostname && !n.pathname && (n.path = n.pathname = "/"), n.href = n.format(), n + } + if (e.protocol && e.protocol !== n.protocol) { + if (!g[e.protocol]) { + for (var p = Object.keys(e), f = 0; f < p.length; f++) { + var h = p[f]; + n[h] = e[h] + } + return n.href = n.format(), n + } + if (n.protocol = e.protocol, e.host || v[e.protocol]) n.pathname = e.pathname; else { + for (var d = (e.pathname || "").split("/"); d.length && !(e.host = d.shift());) ; + e.host || (e.host = ""), e.hostname || (e.hostname = ""), "" !== d[0] && d.unshift(""), d.length < 2 && d.unshift(""), n.pathname = d.join("/") + } + if (n.search = e.search, n.query = e.query, n.host = e.host || "", n.auth = e.auth, n.hostname = e.hostname || e.host, n.port = e.port, n.pathname || n.search) { + var m = n.pathname || "", y = n.search || ""; + n.path = m + y + } + return n.slashes = n.slashes || e.slashes, n.href = n.format(), n + } + var b = n.pathname && "/" === n.pathname.charAt(0), + _ = e.host || e.pathname && "/" === e.pathname.charAt(0), w = _ || b || n.host && e.pathname, x = w, + E = n.pathname && n.pathname.split("/") || [], + S = (d = e.pathname && e.pathname.split("/") || [], n.protocol && !g[n.protocol]); + if (S && (n.hostname = "", n.port = null, n.host && ("" === E[0] ? E[0] = n.host : E.unshift(n.host)), n.host = "", e.protocol && (e.hostname = null, e.port = null, e.host && ("" === d[0] ? d[0] = e.host : d.unshift(e.host)), e.host = null), w = w && ("" === d[0] || "" === E[0])), _) n.host = e.host || "" === e.host ? e.host : n.host, n.hostname = e.hostname || "" === e.hostname ? e.hostname : n.hostname, n.search = e.search, n.query = e.query, E = d; else if (d.length) E || (E = []), E.pop(), E = E.concat(d), n.search = e.search, n.query = e.query; else if (!o.isNullOrUndefined(e.search)) { + if (S) n.hostname = n.host = E.shift(), (j = !!(n.host && n.host.indexOf("@") > 0) && n.host.split("@")) && (n.auth = j.shift(), n.host = n.hostname = j.shift()); + return n.search = e.search, n.query = e.query, o.isNull(n.pathname) && o.isNull(n.search) || (n.path = (n.pathname ? n.pathname : "") + (n.search ? n.search : "")), n.href = n.format(), n + } + if (!E.length) return n.pathname = null, n.search ? n.path = "/" + n.search : n.path = null, n.href = n.format(), n; + for (var C = E.slice(-1)[0], A = (n.host || e.host || E.length > 1) && ("." === C || ".." === C) || "" === C, k = 0, O = E.length; O >= 0; O--) "." === (C = E[O]) ? E.splice(O, 1) : ".." === C ? (E.splice(O, 1), k++) : k && (E.splice(O, 1), k--); + if (!w && !x) for (; k--; k) E.unshift(".."); + !w || "" === E[0] || E[0] && "/" === E[0].charAt(0) || E.unshift(""), A && "/" !== E.join("/").substr(-1) && E.push(""); + var j, T = "" === E[0] || E[0] && "/" === E[0].charAt(0); + S && (n.hostname = n.host = T ? "" : E.length ? E.shift() : "", (j = !!(n.host && n.host.indexOf("@") > 0) && n.host.split("@")) && (n.auth = j.shift(), n.host = n.hostname = j.shift())); + return (w = w || n.host && E.length) && !T && E.unshift(""), E.length ? n.pathname = E.join("/") : (n.pathname = null, n.path = null), o.isNull(n.pathname) && o.isNull(n.search) || (n.path = (n.pathname ? n.pathname : "") + (n.search ? n.search : "")), n.auth = e.auth || n.auth, n.slashes = n.slashes || e.slashes, n.href = n.format(), n + }, a.prototype.parseHost = function () { + var e = this.host, t = s.exec(e); + t && (":" !== (t = t[0]) && (this.port = t.substr(1)), e = e.substr(0, e.length - t.length)), e && (this.hostname = e) + } + }, function (e, t, n) { + "use strict"; + n.r(t), n.d(t, "SHOW_AUTH_POPUP", (function () { + return h + })), n.d(t, "AUTHORIZE", (function () { + return d + })), n.d(t, "LOGOUT", (function () { + return m + })), n.d(t, "PRE_AUTHORIZE_OAUTH2", (function () { + return v + })), n.d(t, "AUTHORIZE_OAUTH2", (function () { + return g + })), n.d(t, "VALIDATE", (function () { + return y + })), n.d(t, "CONFIGURE_AUTH", (function () { + return b + })), n.d(t, "RESTORE_AUTHORIZATION", (function () { + return _ + })), n.d(t, "showDefinitions", (function () { + return w + })), n.d(t, "authorize", (function () { + return x + })), n.d(t, "authorizeWithPersistOption", (function () { + return E + })), n.d(t, "logout", (function () { + return S + })), n.d(t, "logoutWithPersistOption", (function () { + return C + })), n.d(t, "preAuthorizeImplicit", (function () { + return A + })), n.d(t, "authorizeOauth2", (function () { + return k + })), n.d(t, "authorizeOauth2WithPersistOption", (function () { + return O + })), n.d(t, "authorizePassword", (function () { + return j + })), n.d(t, "authorizeApplication", (function () { + return T + })), n.d(t, "authorizeAccessCodeWithFormParams", (function () { + return I + })), n.d(t, "authorizeAccessCodeWithBasicAuthentication", (function () { + return P + })), n.d(t, "authorizeRequest", (function () { + return N + })), n.d(t, "configureAuth", (function () { + return M + })), n.d(t, "restoreAuthorization", (function () { + return R + })), n.d(t, "persistAuthorizationIfNeeded", (function () { + return D + })); + var r = n(19), o = n.n(r), a = n(32), i = n.n(a), s = n(22), u = n.n(s), c = n(97), l = n.n(c), p = n(27), + f = n(5), h = "show_popup", d = "authorize", m = "logout", v = "pre_authorize_oauth2", + g = "authorize_oauth2", y = "validate", b = "configure_auth", _ = "restore_authorization"; + + function w(e) { + return {type: h, payload: e} + } + + function x(e) { + return {type: d, payload: e} + } + + var E = function (e) { + return function (t) { + var n = t.authActions; + n.authorize(e), n.persistAuthorizationIfNeeded() + } + }; + + function S(e) { + return {type: m, payload: e} + } + + var C = function (e) { + return function (t) { + var n = t.authActions; + n.logout(e), n.persistAuthorizationIfNeeded() + } + }, A = function (e) { + return function (t) { + var n = t.authActions, r = t.errActions, o = e.auth, a = e.token, s = e.isValid, u = o.schema, + c = o.name, l = u.get("flow"); + delete p.a.swaggerUIRedirectOauth2, "accessCode" === l || s || r.newAuthErr({ + authId: c, + source: "auth", + level: "warning", + message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server" + }), a.error ? r.newAuthErr({ + authId: c, + source: "auth", + level: "error", + message: i()(a) + }) : n.authorizeOauth2WithPersistOption({auth: o, token: a}) + } + }; + + function k(e) { + return {type: g, payload: e} + } + + var O = function (e) { + return function (t) { + var n = t.authActions; + n.authorizeOauth2(e), n.persistAuthorizationIfNeeded() + } + }, j = function (e) { + return function (t) { + var n = t.authActions, r = e.schema, o = e.name, a = e.username, i = e.password, s = e.passwordType, + c = e.clientId, l = e.clientSecret, + p = {grant_type: "password", scope: e.scopes.join(" "), username: a, password: i}, h = {}; + switch (s) { + case"request-body": + !function (e, t, n) { + t && u()(e, {client_id: t}); + n && u()(e, {client_secret: n}) + }(p, c, l); + break; + case"basic": + h.Authorization = "Basic " + Object(f.a)(c + ":" + l); + break; + default: + console.warn("Warning: invalid passwordType ".concat(s, " was passed, not including client id and secret")) + } + return n.authorizeRequest({ + body: Object(f.b)(p), + url: r.get("tokenUrl"), + name: o, + headers: h, + query: {}, + auth: e + }) + } + }; + var T = function (e) { + return function (t) { + var n = t.authActions, r = e.schema, o = e.scopes, a = e.name, i = e.clientId, s = e.clientSecret, + u = {Authorization: "Basic " + Object(f.a)(i + ":" + s)}, + c = {grant_type: "client_credentials", scope: o.join(" ")}; + return n.authorizeRequest({body: Object(f.b)(c), name: a, url: r.get("tokenUrl"), auth: e, headers: u}) + } + }, I = function (e) { + var t = e.auth, n = e.redirectUrl; + return function (e) { + var r = e.authActions, o = t.schema, a = t.name, i = t.clientId, s = t.clientSecret, u = t.codeVerifier, + c = { + grant_type: "authorization_code", + code: t.code, + client_id: i, + client_secret: s, + redirect_uri: n, + code_verifier: u + }; + return r.authorizeRequest({body: Object(f.b)(c), name: a, url: o.get("tokenUrl"), auth: t}) + } + }, P = function (e) { + var t = e.auth, n = e.redirectUrl; + return function (e) { + var r = e.authActions, o = t.schema, a = t.name, i = t.clientId, s = t.clientSecret, + u = {Authorization: "Basic " + Object(f.a)(i + ":" + s)}, + c = {grant_type: "authorization_code", code: t.code, client_id: i, redirect_uri: n}; + return r.authorizeRequest({body: Object(f.b)(c), name: a, url: o.get("tokenUrl"), auth: t, headers: u}) + } + }, N = function (e) { + return function (t) { + var n, r = t.fn, a = t.getConfigs, s = t.authActions, c = t.errActions, p = t.oas3Selectors, + f = t.specSelectors, h = t.authSelectors, d = e.body, m = e.query, v = void 0 === m ? {} : m, + g = e.headers, y = void 0 === g ? {} : g, b = e.name, _ = e.url, w = e.auth, + x = (h.getConfigs() || {}).additionalQueryStringParams; + if (f.isOAS3()) { + var E = p.serverEffectiveValue(p.selectedServer()); + n = l()(_, E, !0) + } else n = l()(_, f.url(), !0); + "object" === o()(x) && (n.query = u()({}, n.query, x)); + var S = n.toString(), C = u()({ + Accept: "application/json, text/plain, */*", + "Content-Type": "application/x-www-form-urlencoded", + "X-Requested-With": "XMLHttpRequest" + }, y); + r.fetch({ + url: S, + method: "post", + headers: C, + query: v, + body: d, + requestInterceptor: a().requestInterceptor, + responseInterceptor: a().responseInterceptor + }).then((function (e) { + var t = JSON.parse(e.data), n = t && (t.error || ""), r = t && (t.parseError || ""); + e.ok ? n || r ? c.newAuthErr({ + authId: b, + level: "error", + source: "auth", + message: i()(t) + }) : s.authorizeOauth2WithPersistOption({auth: w, token: t}) : c.newAuthErr({ + authId: b, + level: "error", + source: "auth", + message: e.statusText + }) + })).catch((function (e) { + var t = new Error(e).message; + if (e.response && e.response.data) { + var n = e.response.data; + try { + var r = "string" == typeof n ? JSON.parse(n) : n; + r.error && (t += ", error: ".concat(r.error)), r.error_description && (t += ", description: ".concat(r.error_description)) + } catch (e) { + } + } + c.newAuthErr({authId: b, level: "error", source: "auth", message: t}) + })) + } + }; + + function M(e) { + return {type: b, payload: e} + } + + function R(e) { + return {type: _, payload: e} + } + + var D = function () { + return function (e) { + var t = e.authSelectors; + if ((0, e.getConfigs)().persistAuthorization) { + var n = t.authorized(); + localStorage.setItem("authorized", i()(n.toJS())) + } + } + } + }, function (e, t, n) { + var r = n(1106); + e.exports = function (e) { + for (var t = 1; t < arguments.length; t++) { + var n = null != arguments[t] ? Object(arguments[t]) : {}, o = Object.keys(n); + "function" == typeof Object.getOwnPropertySymbols && (o = o.concat(Object.getOwnPropertySymbols(n).filter((function (e) { + return Object.getOwnPropertyDescriptor(n, e).enumerable + })))), o.forEach((function (t) { + r(e, t, n[t]) + })) + } + return e + } + }, function (e, t, n) { + var r = n(239), o = n(148), a = n(39)("toStringTag"), i = "Arguments" == o(function () { + return arguments + }()); + e.exports = r ? o : function (e) { + var t, n, r; + return void 0 === e ? "Undefined" : null === e ? "Null" : "string" == typeof (n = function (e, t) { + try { + return e[t] + } catch (e) { + } + }(t = Object(e), a)) ? n : i ? o(t) : "Object" == (r = o(t)) && "function" == typeof t.callee ? "Arguments" : r + } + }, function (e, t, n) { + var r = n(109), o = n(179), a = n(71), i = n(80), s = n(228), u = [].push, c = function (e) { + var t = 1 == e, n = 2 == e, c = 3 == e, l = 4 == e, p = 6 == e, f = 7 == e, h = 5 == e || p; + return function (d, m, v, g) { + for (var y, b, _ = a(d), w = o(_), x = r(m, v, 3), E = i(w.length), S = 0, C = g || s, A = t ? C(d, E) : n || f ? C(d, 0) : void 0; E > S; S++) if ((h || S in w) && (b = x(y = w[S], S, _), e)) if (t) A[S] = b; else if (b) switch (e) { + case 3: + return !0; + case 5: + return y; + case 6: + return S; + case 2: + u.call(A, y) + } else switch (e) { + case 4: + return !1; + case 7: + u.call(A, y) + } + return p ? -1 : c || l ? l : A + } + }; + e.exports = { + forEach: c(0), + map: c(1), + filter: c(2), + some: c(3), + every: c(4), + find: c(5), + findIndex: c(6), + filterOut: c(7) + } + }, function (e, t, n) { + "use strict"; + e.exports = {current: null} + }, function (e, t) { + e.exports = function (e) { + return null != e && "object" == typeof e + } + }, function (e, t) { + var n, r, o = e.exports = {}; + + function a() { + throw new Error("setTimeout has not been defined") + } + + function i() { + throw new Error("clearTimeout has not been defined") + } + + function s(e) { + if (n === setTimeout) return setTimeout(e, 0); + if ((n === a || !n) && setTimeout) return n = setTimeout, setTimeout(e, 0); + try { + return n(e, 0) + } catch (t) { + try { + return n.call(null, e, 0) + } catch (t) { + return n.call(this, e, 0) + } + } + } + + !function () { + try { + n = "function" == typeof setTimeout ? setTimeout : a + } catch (e) { + n = a + } + try { + r = "function" == typeof clearTimeout ? clearTimeout : i + } catch (e) { + r = i + } + }(); + var u, c = [], l = !1, p = -1; + + function f() { + l && u && (l = !1, u.length ? c = u.concat(c) : p = -1, c.length && h()) + } + + function h() { + if (!l) { + var e = s(f); + l = !0; + for (var t = c.length; t;) { + for (u = c, c = []; ++p < t;) u && u[p].run(); + p = -1, t = c.length + } + u = null, l = !1, function (e) { + if (r === clearTimeout) return clearTimeout(e); + if ((r === i || !r) && clearTimeout) return r = clearTimeout, clearTimeout(e); + try { + r(e) + } catch (t) { + try { + return r.call(null, e) + } catch (t) { + return r.call(this, e) + } + } + }(e) + } + } + + function d(e, t) { + this.fun = e, this.array = t + } + + function m() { + } + + o.nextTick = function (e) { + var t = new Array(arguments.length - 1); + if (arguments.length > 1) for (var n = 1; n < arguments.length; n++) t[n - 1] = arguments[n]; + c.push(new d(e, t)), 1 !== c.length || l || s(h) + }, d.prototype.run = function () { + this.fun.apply(null, this.array) + }, o.title = "browser", o.browser = !0, o.env = {}, o.argv = [], o.version = "", o.versions = {}, o.on = m, o.addListener = m, o.once = m, o.off = m, o.removeListener = m, o.removeAllListeners = m, o.emit = m, o.prependListener = m, o.prependOnceListener = m, o.listeners = function (e) { + return [] + }, o.binding = function (e) { + throw new Error("process.binding is not supported") + }, o.cwd = function () { + return "/" + }, o.chdir = function (e) { + throw new Error("process.chdir is not supported") + }, o.umask = function () { + return 0 + } + }, function (e, t, n) { + "use strict"; + var r = n(40), o = n(124), a = n(82), + i = (n(34), ["dispatchConfig", "_targetInst", "nativeEvent", "isDefaultPrevented", "isPropagationStopped", "_dispatchListeners", "_dispatchInstances"]), + s = { + type: null, + target: null, + currentTarget: a.thatReturnsNull, + eventPhase: null, + bubbles: null, + cancelable: null, + timeStamp: function (e) { + return e.timeStamp || Date.now() + }, + defaultPrevented: null, + isTrusted: null + }; + + function u(e, t, n, r) { + this.dispatchConfig = e, this._targetInst = t, this.nativeEvent = n; + var o = this.constructor.Interface; + for (var i in o) if (o.hasOwnProperty(i)) { + 0; + var s = o[i]; + s ? this[i] = s(n) : "target" === i ? this.target = r : this[i] = n[i] + } + var u = null != n.defaultPrevented ? n.defaultPrevented : !1 === n.returnValue; + return this.isDefaultPrevented = u ? a.thatReturnsTrue : a.thatReturnsFalse, this.isPropagationStopped = a.thatReturnsFalse, this + } + + r(u.prototype, { + preventDefault: function () { + this.defaultPrevented = !0; + var e = this.nativeEvent; + e && (e.preventDefault ? e.preventDefault() : "unknown" != typeof e.returnValue && (e.returnValue = !1), this.isDefaultPrevented = a.thatReturnsTrue) + }, stopPropagation: function () { + var e = this.nativeEvent; + e && (e.stopPropagation ? e.stopPropagation() : "unknown" != typeof e.cancelBubble && (e.cancelBubble = !0), this.isPropagationStopped = a.thatReturnsTrue) + }, persist: function () { + this.isPersistent = a.thatReturnsTrue + }, isPersistent: a.thatReturnsFalse, destructor: function () { + var e = this.constructor.Interface; + for (var t in e) this[t] = null; + for (var n = 0; n < i.length; n++) this[i[n]] = null + } + }), u.Interface = s, u.augmentClass = function (e, t) { + var n = this, a = function () { + }; + a.prototype = n.prototype; + var i = new a; + r(i, e.prototype), e.prototype = i, e.prototype.constructor = e, e.Interface = r({}, n.Interface, t), e.augmentClass = n.augmentClass, o.addPoolingTo(e, o.fourArgumentPooler) + }, o.addPoolingTo(u, o.fourArgumentPooler), e.exports = u + }, function (e, t, n) { + var r = n(405); + e.exports = function (e) { + return null == e ? "" : r(e) + } + }, function (e, t, n) { + "use strict"; + n.r(t), n.d(t, "lastError", (function () { + return M + })), n.d(t, "url", (function () { + return R + })), n.d(t, "specStr", (function () { + return D + })), n.d(t, "specSource", (function () { + return L + })), n.d(t, "specJson", (function () { + return B + })), n.d(t, "specResolved", (function () { + return F + })), n.d(t, "specResolvedSubtree", (function () { + return U + })), n.d(t, "specJsonWithResolvedSubtrees", (function () { + return z + })), n.d(t, "spec", (function () { + return V + })), n.d(t, "isOAS3", (function () { + return W + })), n.d(t, "info", (function () { + return H + })), n.d(t, "externalDocs", (function () { + return J + })), n.d(t, "version", (function () { + return $ + })), n.d(t, "semver", (function () { + return K + })), n.d(t, "paths", (function () { + return Y + })), n.d(t, "operations", (function () { + return G + })), n.d(t, "consumes", (function () { + return Z + })), n.d(t, "produces", (function () { + return X + })), n.d(t, "security", (function () { + return Q + })), n.d(t, "securityDefinitions", (function () { + return ee + })), n.d(t, "findDefinition", (function () { + return te + })), n.d(t, "definitions", (function () { + return ne + })), n.d(t, "basePath", (function () { + return re + })), n.d(t, "host", (function () { + return oe + })), n.d(t, "schemes", (function () { + return ae + })), n.d(t, "operationsWithRootInherited", (function () { + return ie + })), n.d(t, "tags", (function () { + return se + })), n.d(t, "tagDetails", (function () { + return ue + })), n.d(t, "operationsWithTags", (function () { + return ce + })), n.d(t, "taggedOperations", (function () { + return le + })), n.d(t, "responses", (function () { + return pe + })), n.d(t, "requests", (function () { + return fe + })), n.d(t, "mutatedRequests", (function () { + return he + })), n.d(t, "responseFor", (function () { + return de + })), n.d(t, "requestFor", (function () { + return me + })), n.d(t, "mutatedRequestFor", (function () { + return ve + })), n.d(t, "allowTryItOutFor", (function () { + return ge + })), n.d(t, "parameterWithMetaByIdentity", (function () { + return ye + })), n.d(t, "parameterInclusionSettingFor", (function () { + return be + })), n.d(t, "parameterWithMeta", (function () { + return _e + })), n.d(t, "operationWithMeta", (function () { + return we + })), n.d(t, "getParameter", (function () { + return xe + })), n.d(t, "hasHost", (function () { + return Ee + })), n.d(t, "parameterValues", (function () { + return Se + })), n.d(t, "parametersIncludeIn", (function () { + return Ce + })), n.d(t, "parametersIncludeType", (function () { + return Ae + })), n.d(t, "contentTypeValues", (function () { + return ke + })), n.d(t, "currentProducesFor", (function () { + return Oe + })), n.d(t, "producesOptionsFor", (function () { + return je + })), n.d(t, "consumesOptionsFor", (function () { + return Te + })), n.d(t, "operationScheme", (function () { + return Ie + })), n.d(t, "canExecuteScheme", (function () { + return Pe + })), n.d(t, "validateBeforeExecute", (function () { + return Ne + })), n.d(t, "getOAS3RequiredRequestBodyContentType", (function () { + return Me + })), n.d(t, "isMediaTypeSchemaPropertiesEqual", (function () { + return Re + })); + var r = n(16), o = n.n(r), a = n(15), i = n.n(a), s = n(2), u = n.n(s), c = n(23), l = n.n(c), p = n(18), + f = n.n(p), h = n(14), d = n.n(h), m = n(4), v = n.n(m), g = n(12), y = n.n(g), b = n(66), _ = n.n(b), + w = n(21), x = n.n(w), E = n(211), S = n.n(E), C = n(36), A = n.n(C), k = n(13), O = n.n(k), j = n(20), + T = n(5), I = n(1), P = ["get", "put", "post", "delete", "options", "head", "patch", "trace"], + N = function (e) { + return e || Object(I.Map)() + }, M = Object(j.a)(N, (function (e) { + return e.get("lastError") + })), R = Object(j.a)(N, (function (e) { + return e.get("url") + })), D = Object(j.a)(N, (function (e) { + return e.get("spec") || "" + })), L = Object(j.a)(N, (function (e) { + return e.get("specSource") || "not-editor" + })), B = Object(j.a)(N, (function (e) { + return e.get("json", Object(I.Map)()) + })), F = Object(j.a)(N, (function (e) { + return e.get("resolved", Object(I.Map)()) + })), U = function (e, t) { + var n; + return e.getIn(u()(n = ["resolvedSubtrees"]).call(n, i()(t)), void 0) + }, q = function e(t, n) { + return I.Map.isMap(t) && I.Map.isMap(n) ? n.get("$$ref") ? n : Object(I.OrderedMap)().mergeWith(e, t, n) : n + }, z = Object(j.a)(N, (function (e) { + return Object(I.OrderedMap)().mergeWith(q, e.get("json"), e.get("resolvedSubtrees")) + })), V = function (e) { + return B(e) + }, W = Object(j.a)(V, (function () { + return !1 + })), H = Object(j.a)(V, (function (e) { + return De(e && e.get("info")) + })), J = Object(j.a)(V, (function (e) { + return De(e && e.get("externalDocs")) + })), $ = Object(j.a)(H, (function (e) { + return e && e.get("version") + })), K = Object(j.a)($, (function (e) { + var t; + return l()(t = /v?([0-9]*)\.([0-9]*)\.([0-9]*)/i.exec(e)).call(t, 1) + })), Y = Object(j.a)(z, (function (e) { + return e.get("paths") + })), G = Object(j.a)(Y, (function (e) { + if (!e || e.size < 1) return Object(I.List)(); + var t = Object(I.List)(); + return e && f()(e) ? (f()(e).call(e, (function (e, n) { + if (!e || !f()(e)) return {}; + f()(e).call(e, (function (e, r) { + var o; + d()(P).call(P, r) < 0 || (t = t.push(Object(I.fromJS)({ + path: n, + method: r, + operation: e, + id: u()(o = "".concat(r, "-")).call(o, n) + }))) + })) + })), t) : Object(I.List)() + })), Z = Object(j.a)(V, (function (e) { + return Object(I.Set)(e.get("consumes")) + })), X = Object(j.a)(V, (function (e) { + return Object(I.Set)(e.get("produces")) + })), Q = Object(j.a)(V, (function (e) { + return e.get("security", Object(I.List)()) + })), ee = Object(j.a)(V, (function (e) { + return e.get("securityDefinitions") + })), te = function (e, t) { + var n = e.getIn(["resolvedSubtrees", "definitions", t], null), + r = e.getIn(["json", "definitions", t], null); + return n || r || null + }, ne = Object(j.a)(V, (function (e) { + var t = e.get("definitions"); + return I.Map.isMap(t) ? t : Object(I.Map)() + })), re = Object(j.a)(V, (function (e) { + return e.get("basePath") + })), oe = Object(j.a)(V, (function (e) { + return e.get("host") + })), ae = Object(j.a)(V, (function (e) { + return e.get("schemes", Object(I.Map)()) + })), ie = Object(j.a)(G, Z, X, (function (e, t, n) { + return v()(e).call(e, (function (e) { + return e.update("operation", (function (e) { + if (e) { + if (!I.Map.isMap(e)) return; + return e.withMutations((function (e) { + return e.get("consumes") || e.update("consumes", (function (e) { + return Object(I.Set)(e).merge(t) + })), e.get("produces") || e.update("produces", (function (e) { + return Object(I.Set)(e).merge(n) + })), e + })) + } + return Object(I.Map)() + })) + })) + })), se = Object(j.a)(V, (function (e) { + var t = e.get("tags", Object(I.List)()); + return I.List.isList(t) ? y()(t).call(t, (function (e) { + return I.Map.isMap(e) + })) : Object(I.List)() + })), ue = function (e, t) { + var n, r = se(e) || Object(I.List)(); + return _()(n = y()(r).call(r, I.Map.isMap)).call(n, (function (e) { + return e.get("name") === t + }), Object(I.Map)()) + }, ce = Object(j.a)(ie, se, (function (e, t) { + return x()(e).call(e, (function (e, t) { + var n = Object(I.Set)(t.getIn(["operation", "tags"])); + return n.count() < 1 ? e.update("default", Object(I.List)(), (function (e) { + return e.push(t) + })) : x()(n).call(n, (function (e, n) { + return e.update(n, Object(I.List)(), (function (e) { + return e.push(t) + })) + }), e) + }), x()(t).call(t, (function (e, t) { + return e.set(t.get("name"), Object(I.List)()) + }), Object(I.OrderedMap)())) + })), le = function (e) { + return function (t) { + var n, r = (0, t.getConfigs)(), o = r.tagsSorter, a = r.operationsSorter; + return v()(n = ce(e).sortBy((function (e, t) { + return t + }), (function (e, t) { + var n = "function" == typeof o ? o : T.I.tagsSorter[o]; + return n ? n(e, t) : null + }))).call(n, (function (t, n) { + var r = "function" == typeof a ? a : T.I.operationsSorter[a], o = r ? S()(t).call(t, r) : t; + return Object(I.Map)({tagDetails: ue(e, n), operations: o}) + })) + } + }, pe = Object(j.a)(N, (function (e) { + return e.get("responses", Object(I.Map)()) + })), fe = Object(j.a)(N, (function (e) { + return e.get("requests", Object(I.Map)()) + })), he = Object(j.a)(N, (function (e) { + return e.get("mutatedRequests", Object(I.Map)()) + })), de = function (e, t, n) { + return pe(e).getIn([t, n], null) + }, me = function (e, t, n) { + return fe(e).getIn([t, n], null) + }, ve = function (e, t, n) { + return he(e).getIn([t, n], null) + }, ge = function () { + return !0 + }, ye = function (e, t, n) { + var r, o, a = z(e).getIn(u()(r = ["paths"]).call(r, i()(t), ["parameters"]), Object(I.OrderedMap)()), + s = e.getIn(u()(o = ["meta", "paths"]).call(o, i()(t), ["parameters"]), Object(I.OrderedMap)()), + c = v()(a).call(a, (function (e) { + var t, r, o, a = s.get(u()(t = "".concat(n.get("in"), ".")).call(t, n.get("name"))), + i = s.get(u()(r = u()(o = "".concat(n.get("in"), ".")).call(o, n.get("name"), ".hash-")).call(r, n.hashCode())); + // console.log(n.get("name")); + return Object(I.OrderedMap)().merge(e, a, i) + })); + return _()(c).call(c, (function (e) { + // console.log(e.get("name")); + // console.log(n.get("name")); + return e.get("in") === n.get("in") && e.get("name") === n.get("name") + }), Object(I.OrderedMap)()) + }, be = function (e, t, n, r) { + var o, a, s = u()(o = "".concat(r, ".")).call(o, n); + return e.getIn(u()(a = ["meta", "paths"]).call(a, i()(t), ["parameter_inclusions", s]), !1) + }, _e = function (e, t, n, r) { + var o, a = z(e).getIn(u()(o = ["paths"]).call(o, i()(t), ["parameters"]), Object(I.OrderedMap)()), + s = _()(a).call(a, (function (e) { + return e.get("in") === r && e.get("name") === n + }), Object(I.OrderedMap)()); + return ye(e, t, s) + }, we = function (e, t, n) { + var r, o = z(e).getIn(["paths", t, n], Object(I.OrderedMap)()), + a = e.getIn(["meta", "paths", t, n], Object(I.OrderedMap)()), + i = v()(r = o.get("parameters", Object(I.List)())).call(r, (function (r) { + return ye(e, [t, n], r) + })); + return Object(I.OrderedMap)().merge(o, a).set("parameters", i) + }; + + function xe(e, t, n, r) { + var o; + t = t || []; + var a = e.getIn(u()(o = ["meta", "paths"]).call(o, i()(t), ["parameters"]), Object(I.fromJS)([])); + return _()(a).call(a, (function (e) { + return I.Map.isMap(e) && e.get("name") === n && e.get("in") === r + })) || Object(I.Map)() + } + + var Ee = Object(j.a)(V, (function (e) { + var t = e.get("host"); + return "string" == typeof t && t.length > 0 && "/" !== t[0] + })); + + function Se(e, t, n) { + var r; + t = t || []; + var o = we.apply(void 0, u()(r = [e]).call(r, i()(t))).get("parameters", Object(I.List)()); + return x()(o).call(o, (function (e, t) { + var r = n && "body" === t.get("in") ? t.get("value_xml") : t.get("value"); + return e.set(Object(T.B)(t, {allowHashes: !1}), r) + }), Object(I.fromJS)({})) + } + + function Ce(e) { + var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : ""; + if (I.List.isList(e)) return A()(e).call(e, (function (e) { + return I.Map.isMap(e) && e.get("in") === t + })) + } + + function Ae(e) { + var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : ""; + if (I.List.isList(e)) return A()(e).call(e, (function (e) { + return I.Map.isMap(e) && e.get("type") === t + })) + } + + function ke(e, t) { + var n, r; + t = t || []; + var o = z(e).getIn(u()(n = ["paths"]).call(n, i()(t)), Object(I.fromJS)({})), + a = e.getIn(u()(r = ["meta", "paths"]).call(r, i()(t)), Object(I.fromJS)({})), s = Oe(e, t), + c = o.get("parameters") || new I.List, + l = a.get("consumes_value") ? a.get("consumes_value") : Ae(c, "file") ? "multipart/form-data" : Ae(c, "formData") ? "application/x-www-form-urlencoded" : void 0; + return Object(I.fromJS)({requestContentType: l, responseContentType: s}) + } + + function Oe(e, t) { + var n, r; + t = t || []; + var o = z(e).getIn(u()(n = ["paths"]).call(n, i()(t)), null); + if (null !== o) { + var a = e.getIn(u()(r = ["meta", "paths"]).call(r, i()(t), ["produces_value"]), null), + s = o.getIn(["produces", 0], null); + return a || s || "application/json" + } + } + + function je(e, t) { + var n; + t = t || []; + var r = z(e), a = r.getIn(u()(n = ["paths"]).call(n, i()(t)), null); + if (null !== a) { + var s = t, c = o()(s, 1)[0], l = a.get("produces", null), p = r.getIn(["paths", c, "produces"], null), + f = r.getIn(["produces"], null); + return l || p || f + } + } + + function Te(e, t) { + var n; + t = t || []; + var r = z(e), a = r.getIn(u()(n = ["paths"]).call(n, i()(t)), null); + if (null !== a) { + var s = t, c = o()(s, 1)[0], l = a.get("consumes", null), p = r.getIn(["paths", c, "consumes"], null), + f = r.getIn(["consumes"], null); + return l || p || f + } + } + + var Ie = function (e, t, n) { + var r = e.get("url").match(/^([a-z][a-z0-9+\-.]*):/), o = O()(r) ? r[1] : null; + return e.getIn(["scheme", t, n]) || e.getIn(["scheme", "_defaultScheme"]) || o || "" + }, Pe = function (e, t, n) { + var r; + return d()(r = ["http", "https"]).call(r, Ie(e, t, n)) > -1 + }, Ne = function (e, t) { + var n; + t = t || []; + var r = e.getIn(u()(n = ["meta", "paths"]).call(n, i()(t), ["parameters"]), Object(I.fromJS)([])), o = !0; + return f()(r).call(r, (function (e) { + var t = e.get("errors"); + t && t.count() && (o = !1) + })), o + }, Me = function (e, t) { + var n, r, o = {requestBody: !1, requestContentType: {}}, + a = e.getIn(u()(n = ["resolvedSubtrees", "paths"]).call(n, i()(t), ["requestBody"]), Object(I.fromJS)([])); + return a.size < 1 || (a.getIn(["required"]) && (o.requestBody = a.getIn(["required"])), f()(r = a.getIn(["content"]).entrySeq()).call(r, (function (e) { + var t = e[0]; + if (e[1].getIn(["schema", "required"])) { + var n = e[1].getIn(["schema", "required"]).toJS(); + o.requestContentType[t] = n + } + }))), o + }, Re = function (e, t, n, r) { + var o; + if ((n || r) && n === r) return !0; + var a = e.getIn(u()(o = ["resolvedSubtrees", "paths"]).call(o, i()(t), ["requestBody", "content"]), Object(I.fromJS)([])); + if (a.size < 2 || !n || !r) return !1; + var s = a.getIn([n, "schema", "properties"], Object(I.fromJS)([])), + c = a.getIn([r, "schema", "properties"], Object(I.fromJS)([])); + return !!s.equals(c) + }; + + function De(e) { + return I.Map.isMap(e) ? e : new I.Map + } + }, function (e, t, n) { + "use strict"; + (function (t) { + var r = n(916), o = n(917), a = /^[A-Za-z][A-Za-z0-9+-.]*:[\\/]+/, + i = /^([a-z][a-z0-9.+-]*:)?([\\/]{1,})?([\S\s]*)/i, + s = new RegExp("^[\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFF]+"); + + function u(e) { + return (e || "").toString().replace(s, "") + } + + var c = [["#", "hash"], ["?", "query"], function (e) { + return e.replace("\\", "/") + }, ["/", "pathname"], ["@", "auth", 1], [NaN, "host", void 0, 1, 1], [/:(\d+)$/, "port", void 0, 1], [NaN, "hostname", void 0, 1, 1]], + l = {hash: 1, query: 1}; + + function p(e) { + var n, + r = ("undefined" != typeof window ? window : void 0 !== t ? t : "undefined" != typeof self ? self : {}).location || {}, + o = {}, i = typeof (e = e || r); + if ("blob:" === e.protocol) o = new h(unescape(e.pathname), {}); else if ("string" === i) for (n in o = new h(e, {}), l) delete o[n]; else if ("object" === i) { + for (n in e) n in l || (o[n] = e[n]); + void 0 === o.slashes && (o.slashes = a.test(e.href)) + } + return o + } + + function f(e) { + e = u(e); + var t = i.exec(e); + return { + protocol: t[1] ? t[1].toLowerCase() : "", + slashes: !!(t[2] && t[2].length >= 2), + rest: t[2] && 1 === t[2].length ? "/" + t[3] : t[3] + } + } + + function h(e, t, n) { + if (e = u(e), !(this instanceof h)) return new h(e, t, n); + var a, i, s, l, d, m, v = c.slice(), g = typeof t, y = this, b = 0; + for ("object" !== g && "string" !== g && (n = t, t = null), n && "function" != typeof n && (n = o.parse), t = p(t), a = !(i = f(e || "")).protocol && !i.slashes, y.slashes = i.slashes || a && t.slashes, y.protocol = i.protocol || t.protocol || "", e = i.rest, i.slashes || (v[3] = [/(.*)/, "pathname"]); b < v.length; b++) "function" != typeof (l = v[b]) ? (s = l[0], m = l[1], s != s ? y[m] = e : "string" == typeof s ? ~(d = e.indexOf(s)) && ("number" == typeof l[2] ? (y[m] = e.slice(0, d), e = e.slice(d + l[2])) : (y[m] = e.slice(d), e = e.slice(0, d))) : (d = s.exec(e)) && (y[m] = d[1], e = e.slice(0, d.index)), y[m] = y[m] || a && l[3] && t[m] || "", l[4] && (y[m] = y[m].toLowerCase())) : e = l(e); + n && (y.query = n(y.query)), a && t.slashes && "/" !== y.pathname.charAt(0) && ("" !== y.pathname || "" !== t.pathname) && (y.pathname = function (e, t) { + if ("" === e) return t; + for (var n = (t || "/").split("/").slice(0, -1).concat(e.split("/")), r = n.length, o = n[r - 1], a = !1, i = 0; r--;) "." === n[r] ? n.splice(r, 1) : ".." === n[r] ? (n.splice(r, 1), i++) : i && (0 === r && (a = !0), n.splice(r, 1), i--); + return a && n.unshift(""), "." !== o && ".." !== o || n.push(""), n.join("/") + }(y.pathname, t.pathname)), "/" !== y.pathname.charAt(0) && y.hostname && (y.pathname = "/" + y.pathname), r(y.port, y.protocol) || (y.host = y.hostname, y.port = ""), y.username = y.password = "", y.auth && (l = y.auth.split(":"), y.username = l[0] || "", y.password = l[1] || ""), y.origin = y.protocol && y.host && "file:" !== y.protocol ? y.protocol + "//" + y.host : "null", y.href = y.toString() + } + + h.prototype = { + set: function (e, t, n) { + var a = this; + switch (e) { + case"query": + "string" == typeof t && t.length && (t = (n || o.parse)(t)), a[e] = t; + break; + case"port": + a[e] = t, r(t, a.protocol) ? t && (a.host = a.hostname + ":" + t) : (a.host = a.hostname, a[e] = ""); + break; + case"hostname": + a[e] = t, a.port && (t += ":" + a.port), a.host = t; + break; + case"host": + a[e] = t, /:\d+$/.test(t) ? (t = t.split(":"), a.port = t.pop(), a.hostname = t.join(":")) : (a.hostname = t, a.port = ""); + break; + case"protocol": + a.protocol = t.toLowerCase(), a.slashes = !n; + break; + case"pathname": + case"hash": + if (t) { + var i = "pathname" === e ? "/" : "#"; + a[e] = t.charAt(0) !== i ? i + t : t + } else a[e] = t; + break; + default: + a[e] = t + } + for (var s = 0; s < c.length; s++) { + var u = c[s]; + u[4] && (a[u[1]] = a[u[1]].toLowerCase()) + } + return a.origin = a.protocol && a.host && "file:" !== a.protocol ? a.protocol + "//" + a.host : "null", a.href = a.toString(), a + }, toString: function (e) { + e && "function" == typeof e || (e = o.stringify); + var t, n = this, r = n.protocol; + r && ":" !== r.charAt(r.length - 1) && (r += ":"); + var a = r + (n.slashes ? "//" : ""); + return n.username && (a += n.username, n.password && (a += ":" + n.password), a += "@"), a += n.host + n.pathname, (t = "object" == typeof n.query ? e(n.query) : n.query) && (a += "?" !== t.charAt(0) ? "?" + t : t), n.hash && (a += n.hash), a + } + }, h.extractProtocol = f, h.location = p, h.trimLeft = u, h.qs = o, e.exports = h + }).call(this, n(54)) + }, function (e, t, n) { + e.exports = n(1084) + }, function (e, t) { + e.exports = !0 + }, function (e, t, n) { + var r = n(239), o = n(70).f, a = n(69), i = n(55), s = n(553), u = n(39)("toStringTag"); + e.exports = function (e, t, n, c) { + if (e) { + var l = n ? e : e.prototype; + i(l, u) || o(l, u, {configurable: !0, value: t}), c && !r && a(l, "toString", s) + } + } + }, function (e, t, n) { + "use strict"; + var r = n(366).charAt, o = n(81), a = n(240), i = "String Iterator", s = o.set, u = o.getterFor(i); + a(String, "String", (function (e) { + s(this, {type: i, string: String(e), index: 0}) + }), (function () { + var e, t = u(this), n = t.string, o = t.index; + return o >= n.length ? {value: void 0, done: !0} : (e = r(n, o), t.index += e.length, {value: e, done: !1}) + })) + }, function (e, t, n) { + "use strict"; + e.exports = function (e) { + if ("function" != typeof e) throw new TypeError(e + " is not a function"); + return e + } + }, function (e, t, n) { + e.exports = n(682) + }, function (e, t, n) { + e.exports = n(870) + }, function (e, t, n) { + "use strict"; + n.r(t), n.d(t, "UPDATE_LAYOUT", (function () { + return o + })), n.d(t, "UPDATE_FILTER", (function () { + return a + })), n.d(t, "UPDATE_MODE", (function () { + return i + })), n.d(t, "SHOW", (function () { + return s + })), n.d(t, "updateLayout", (function () { + return u + })), n.d(t, "updateFilter", (function () { + return c + })), n.d(t, "show", (function () { + return l + })), n.d(t, "changeMode", (function () { + return p + })); + var r = n(5), o = "layout_update_layout", a = "layout_update_filter", i = "layout_update_mode", + s = "layout_show"; + + function u(e) { + return {type: o, payload: e} + } + + function c(e) { + return {type: a, payload: e} + } + + function l(e) { + var t = !(arguments.length > 1 && void 0 !== arguments[1]) || arguments[1]; + return e = Object(r.w)(e), {type: s, payload: {thing: e, shown: t}} + } + + function p(e) { + var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : ""; + return e = Object(r.w)(e), {type: i, payload: {thing: e, mode: t}} + } + }, function (e, t, n) { + var r = n(420), o = n(162), a = n(192), i = n(53), s = n(117), u = n(193), c = n(161), l = n(251), + p = Object.prototype.hasOwnProperty; + e.exports = function (e) { + if (null == e) return !0; + if (s(e) && (i(e) || "string" == typeof e || "function" == typeof e.splice || u(e) || l(e) || a(e))) return !e.length; + var t = o(e); + if ("[object Map]" == t || "[object Set]" == t) return !e.size; + if (c(e)) return !r(e).length; + for (var n in e) if (p.call(e, n)) return !1; + return !0 + } + }, function (e, t, n) { + var r = n(50), o = n(178), a = n(108), i = n(68), s = n(180), u = n(55), c = n(357), + l = Object.getOwnPropertyDescriptor; + t.f = r ? l : function (e, t) { + if (e = i(e), t = s(t, !0), c) try { + return l(e, t) + } catch (e) { + } + if (u(e, t)) return a(!o.f.call(e, t), e[t]) + } + }, function (e, t) { + e.exports = function (e, t) { + return {enumerable: !(1 & e), configurable: !(2 & e), writable: !(4 & e), value: t} + } + }, function (e, t, n) { + var r = n(79); + e.exports = function (e, t, n) { + if (r(e), void 0 === t) return e; + switch (n) { + case 0: + return function () { + return e.call(t) + }; + case 1: + return function (n) { + return e.call(t, n) + }; + case 2: + return function (n, r) { + return e.call(t, n, r) + }; + case 3: + return function (n, r, o) { + return e.call(t, n, r, o) + } + } + return function () { + return e.apply(t, arguments) + } + } + }, function (e, t, n) { + var r, o = n(52), a = n(232), i = n(235), s = n(156), u = n(362), c = n(227), l = n(184), p = l("IE_PROTO"), + f = function () { + }, h = function (e) { + return "