diff --git a/car_fmw/src/Control.kt b/car_fmw/src/Control.kt index b98a6ca5dcf..57c4ecd3610 100644 --- a/car_fmw/src/Control.kt +++ b/car_fmw/src/Control.kt @@ -71,11 +71,13 @@ object Control { val angles = request.angles val size = angles.size val attempts = request.attempts - val distances = IntArray(size) - for (i in 0..(size - 1)) { + + var i = 0 + while (i < size) { distances[i] = sonarMeasure(request.smoothing, attempts[i], angles[i], request.windowSize) + i++ } val response = SonarResponse.BuilderSonarResponse(distances).build() @@ -84,13 +86,15 @@ object Control { private fun sonarMeasure(smoothing: SonarRequest.Smoothing, attempts: Int, angle: Int, windowSize: Int): Int { val data = IntArray(attempts) - - for (i in 0..(attempts - 1)) { + var i = 0 + while (i < attempts) { data[i] = Sonar.getSmoothDistance(angle, windowSize) if (smoothing.id == SonarRequest.Smoothing.NONE.id && data[i] != -1) { return data[i] } + + i++ } return when (smoothing.id) { diff --git a/car_fmw/src/ProtoRW.kt b/car_fmw/src/ProtoRW.kt index 7894d2c213a..edf7fff34bc 100644 --- a/car_fmw/src/ProtoRW.kt +++ b/car_fmw/src/ProtoRW.kt @@ -21,7 +21,7 @@ object Reader { fun readSonar(): SonarRequest { val stream = getInputStream() - return SonarRequest.BuilderSonarRequest(IntArray(0), IntArray(0), 0, SonarRequest.Smoothing.NONE, 0).parseFrom(stream).build() + return SonarRequest.BuilderSonarRequest(IntArray(0), IntArray(0), 0, SonarRequest.Smoothing.NONE).parseFrom(stream).build() } private fun getInputStream(): CodedInputStream { diff --git a/car_srv/kotlinSrv/build.gradle b/car_srv/kotlinSrv/build.gradle index 6865180f631..e106539166e 100644 --- a/car_srv/kotlinSrv/build.gradle +++ b/car_srv/kotlinSrv/build.gradle @@ -17,11 +17,13 @@ repositories { } apply plugin: "kotlin2js" +apply plugin: 'kotlin' sourceSets { main.kotlin.srcDirs += 'src' main.kotlin.srcDirs += '../../proto/compiler/build/sources' main.kotlin.srcDirs += '../../proto/protofiles_sources/out' + main.java.srcDirs += 'src/main/kotlin' } task copyKotlinLib(type: Copy) { @@ -38,4 +40,5 @@ compileKotlin2Js.kotlinOptions.outputPrefix = "${projectDir}/kotlinJsRequiredFil dependencies { compile "org.jetbrains.kotlin:kotlin-js-library:$kotlin_version" + compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" } diff --git a/car_srv/kotlinSrv/src/control/car/ControllerToUsb.kt b/car_srv/kotlinSrv/src/control/car/ControllerToUsb.kt index 634cc9ae352..25dad70f2db 100644 --- a/car_srv/kotlinSrv/src/control/car/ControllerToUsb.kt +++ b/car_srv/kotlinSrv/src/control/car/ControllerToUsb.kt @@ -8,7 +8,7 @@ import mcTransport class ControllerToUsb : Controller { override fun executeRoute(route: RouteRequest, callback: (ByteArray) -> Unit) { - println("Execute Route:") + println("Execute route:") mcTransport.setCallBack { bytes -> callback.invoke(bytes) @@ -18,7 +18,7 @@ class ControllerToUsb : Controller { } override fun executeMetricRoute(request: RouteMetricRequest, callback: (ByteArray) -> Unit) { - println("Execute Route:") + println("Execute metric route:") mcTransport.setCallBack { bytes -> callback.invoke(bytes) diff --git a/kotstd/include/IntArray.kt b/kotstd/include/IntArray.kt index 89856aa1ea2..09767b162b9 100644 --- a/kotstd/include/IntArray.kt +++ b/kotstd/include/IntArray.kt @@ -120,8 +120,10 @@ operator fun IntArray.plus(elements: IntArray): IntArray { fun IntArray.max(from: Int = 0): Int { var result = from - for (i in (from + 1)..(size - 1)) { + var i = from + while (i < size - 1) { result = if (get(i) > get(result)) i else result + i++ } return get(result) @@ -129,8 +131,10 @@ fun IntArray.max(from: Int = 0): Int { fun IntArray.min(from: Int = 0): Int { var result = from - for (i in 1..(size - 1)) { + var i = from + while (i < size - 1) { result = if (this.get(i) < this.get(result)) i else result + i++ } return this.get(result) @@ -138,8 +142,10 @@ fun IntArray.min(from: Int = 0): Int { fun IntArray.sum(): Int { var result = 0 - for (i in 0..(size - 1)) { + var i = 0 + while (i < size - 1) { result += this.get(i) + i++ } return result @@ -147,8 +153,10 @@ fun IntArray.sum(): Int { fun IntArray.sort(): IntArray { val result = this.clone() - for (i in 0..(size - 1)) { + var i = 0 + while (i < size - 1) { result[i] = this.max(i) + i++ } return result @@ -159,3 +167,29 @@ fun IntArray.mean(): Int = fun IntArray.median(): Int = this.sort()[this.size / 2] + +fun IntArray.filter(predicate: (Int) -> Boolean): IntArray { + var resultSize = 0 + var i = 0 + while (i < size - 1) { + if (predicate(get(i))) { + resultSize++ + } + + i++ + } + + val result = IntArray(resultSize) + var j = 0 + i = 0 + while (i < size - 1) { + if (predicate(get(i))) { + result[j] = get(i) + j++ + } + + i++ + } + + return result +} diff --git a/proto/protofiles_sources/server_car/sonar.proto b/proto/protofiles_sources/server_car/sonar.proto index 6dfaee77d33..f94d31ba849 100644 --- a/proto/protofiles_sources/server_car/sonar.proto +++ b/proto/protofiles_sources/server_car/sonar.proto @@ -3,9 +3,8 @@ syntax = "proto3"; message SonarRequest { repeated int32 angles = 1; repeated int32 attempts = 2; - int32 threshold = 3; + int32 windowSize = 3; Smoothing smoothing = 4; - int32 windowSize = 5; enum Smoothing { NONE = 0; diff --git a/server/.idea/libraries/Gradle__io_netty_netty_all_4_1_2_Final.xml b/server/.idea/libraries/Gradle__io_netty_netty_all_4_1_2_Final.xml deleted file mode 100644 index 9f66e77ee92..00000000000 --- a/server/.idea/libraries/Gradle__io_netty_netty_all_4_1_2_Final.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/server/build.gradle b/server/build.gradle index 6faf3fde5fd..6d7f77128c1 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -51,6 +51,9 @@ jar { dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" compile "io.netty:netty-all:4.1.2.Final" + compile group: 'org.asynchttpclient', name: 'async-http-client', version: '2.0.0-RC9' + compile files ("../proto/compiler/build/protokot-runtime.jar") } diff --git a/server/src/main/java/DebugClInterface.kt b/server/src/main/java/DebugClInterface.kt index 8b11685e694..333a7581eb6 100644 --- a/server/src/main/java/DebugClInterface.kt +++ b/server/src/main/java/DebugClInterface.kt @@ -5,6 +5,7 @@ import car.client.Client import io.netty.buffer.Unpooled import io.netty.handler.codec.http.* import objects.Car +import objects.Environment import java.util.concurrent.Exchanger object DebugClInterface { @@ -14,7 +15,6 @@ object DebugClInterface { private val routeRegex = Regex("route [0-9]{1,10}") private val sonarRegex = Regex("sonar [0-9]{1,10}") - private val environment = objects.Environment.instance private val helpString = "available commands:\n" + "cars - get list of connected cars\n" + "route [car_id] - setting a route for car with car id.\n" + @@ -50,8 +50,8 @@ object DebugClInterface { val commandType = readString.split(" ")[0].toLowerCase() when (commandType) { "cars" -> { - synchronized(environment, { - println(environment.map.values) + synchronized(Environment, { + println(Environment.map.values) }) } "route" -> executeRouteCommand(readString) @@ -81,7 +81,7 @@ object DebugClInterface { } else 1 if (algorithmImpl == null) { - algorithmImpl = RoomBypassingAlgorithm(environment.map.values.last(), exchanger) + algorithmImpl = RoomBypassingAlgorithm(Environment.map.values.last(), exchanger) } while (count > 0) { count-- @@ -106,8 +106,8 @@ object DebugClInterface { return } val car: Car? = - synchronized(environment, { - environment.map[id] + synchronized(Environment, { + Environment.map[id] }) if (car == null) { println("car with id=$id not found") @@ -154,10 +154,9 @@ object DebugClInterface { println(helpString) return } - val car: Car? = - synchronized(environment, { - environment.map[id] - }) + val car: Car? = synchronized(Environment, { + Environment.map[id] + }) if (car == null) { println("car with id=$id not found") return @@ -169,8 +168,8 @@ object DebugClInterface { try { Client.sendRequest(request, car.host, car.port, mapOf(Pair("angles", requestMessage.angles))) } catch (e: InactiveCarException) { - synchronized(environment, { - environment.map.remove(id) + synchronized(Environment, { + Environment.map.remove(id) }) } } @@ -183,7 +182,7 @@ object DebugClInterface { when (command) { "reset" -> return null "done" -> { - val sonarBuilder = SonarRequest.BuilderSonarRequest(angles.toIntArray(), IntArray(angles.size, {1}), 0, SonarRequest.Smoothing.NONE) + val sonarBuilder = SonarRequest.BuilderSonarRequest(angles.toIntArray(), IntArray(angles.size, { 1 }), 0, SonarRequest.Smoothing.NONE) return sonarBuilder.build() } else -> { @@ -207,7 +206,7 @@ object DebugClInterface { } private fun executeRefreshLocationCommand() { - val cars = synchronized(environment, { environment.map.values }) + val cars = synchronized(Environment, { Environment.map.values }) val inactiveCars = mutableListOf() for (car in cars) { val request = getDefaultHttpRequest(car.host, getLocationUrl, ByteArray(0)) @@ -218,9 +217,9 @@ object DebugClInterface { } println("ref loc done") } - synchronized(environment, { + synchronized(Environment, { for (id in inactiveCars) { - environment.map.remove(id) + Environment.map.remove(id) } }) } @@ -241,8 +240,8 @@ object DebugClInterface { return } val car: Car? = - synchronized(environment, { - environment.map[id] + synchronized(Environment, { + Environment.map[id] }) if (car == null) { println("car with id=$id not found") @@ -255,8 +254,8 @@ object DebugClInterface { try { Client.sendRequest(request, car.host, car.port, mapOf(Pair("uid", id))) } catch (e: InactiveCarException) { - synchronized(environment, { - environment.map.remove(id) + synchronized(Environment, { + Environment.map.remove(id) }) } } @@ -295,7 +294,6 @@ object DebugClInterface { } } - private fun getDefaultHttpRequest(host: String, url: String, bytes: ByteArray): DefaultFullHttpRequest { val request = DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, url, Unpooled.copiedBuffer(bytes)) request.headers().set(HttpHeaderNames.HOST, host) diff --git a/server/src/main/java/RoomScanner/CarController.kt b/server/src/main/java/RoomScanner/CarController.kt index 4b552e7baf6..b075b0e6a94 100644 --- a/server/src/main/java/RoomScanner/CarController.kt +++ b/server/src/main/java/RoomScanner/CarController.kt @@ -1,5 +1,11 @@ package RoomScanner +import CodedInputStream +import CodedOutputStream +import RouteMetricRequest +import SonarRequest +import SonarResponse +import car.client.CarClient import objects.Car class CarController(var car: Car) { @@ -30,21 +36,38 @@ class CarController(var car: Car) { val direction = if (rotateAngle > 0) Direction.RIGHT else Direction.LEFT drive(direction, rotateAngle.toInt()) - angle = rotateAngle + angle = target } private fun drive(direction: Direction, distance: Int) { - when (direction) { - Direction.BACKWARD -> {} - Direction.FORWARD -> {} - Direction.LEFT -> {} - Direction.RIGHT -> {} + val request = RouteMetricRequest.BuilderRouteMetricRequest(intArrayOf(distance), intArrayOf(direction.id)).build() + val data = serialize(request.getSizeNoTag(), { i -> request.writeTo(i) }) + CarClient.sendRequest(car, CarClient.Request.ROUTE_METRIC, data).get() + } + + fun scan(angles: IntArray): List> { + val request = SonarRequest.BuilderSonarRequest(angles, IntArray(angles.size, { 5 }), 0, SonarRequest.Smoothing.MEDIAN).build() + val data = serialize(request.getSizeNoTag(), { i -> request.writeTo(i) }) + val response = CarClient.sendRequest(car, CarClient.Request.SONAR, data).get().responseBodyAsBytes + + val distances = SonarResponse.BuilderSonarResponse(IntArray(0)).parseFrom(CodedInputStream(response)).build().distances + + return distances.mapIndexed { i: Int, distance: Int -> convertToPoint(angles[i].toDouble(), distance.toDouble()) } + } + + fun convertToPoint(angle: Double, distance: Double): Pair { + if (distance <= 0) { + return Pair(0.0, 0.0) } + + val realAngle = Math.toRadians(angle + this.angle) + return Pair(Math.cos(realAngle) * distance + position.first, Math.sin(realAngle) * distance + position.second) } - fun scan(angles: IntArray): MutableList> { - throw UnsupportedOperationException() + inline fun serialize(size: Int, writeTo: (CodedOutputStream) -> Unit): ByteArray { + val bytes = ByteArray(size) + writeTo(CodedOutputStream(bytes)) + + return bytes } - - -} \ No newline at end of file +} diff --git a/server/src/main/java/RoomScanner/RoomScanner.kt b/server/src/main/java/RoomScanner/RoomScanner.kt index 78ecebbbd0a..c0e9abcaa91 100644 --- a/server/src/main/java/RoomScanner/RoomScanner.kt +++ b/server/src/main/java/RoomScanner/RoomScanner.kt @@ -1,9 +1,9 @@ package RoomScanner -class RoomScanner(val controller: CarController) { +class RoomScanner(val controller: CarController): Thread() { private val points = mutableListOf>() - fun run() { + override fun run() { while (true) { scan() println("[${points.joinToString { "[${it.first}, ${it.second}]" }}}]") @@ -12,16 +12,16 @@ class RoomScanner(val controller: CarController) { fun scan() { val horizon = IntArray(180 / 5, { it * 5 }) + val iterationPoints = mutableListOf>() controller.rotateOn(0.0) - val iterationPoints = controller.scan(horizon) - + iterationPoints.addAll(controller.scan(horizon)) controller.rotateOn(180.0) iterationPoints.addAll(controller.scan(horizon)) points.addAll(iterationPoints) - val target = iterationPoints.maxBy { distance(controller.position, it) } + val target = iterationPoints.filter { it.first > 0 && it.second > 0 }.maxBy { distance(controller.position, it) } target ?: return controller.moveTo(target) diff --git a/server/src/main/java/ServerMain.kt b/server/src/main/java/ServerMain.kt index f978aeb3a87..fe819113d36 100644 --- a/server/src/main/java/ServerMain.kt +++ b/server/src/main/java/ServerMain.kt @@ -1,5 +1,8 @@ +import RoomScanner.CarController +import RoomScanner.RoomScanner import car.Dropper import car.client.Client +import objects.Environment val carServerPort: Int = 7925 val webServerPort: Int = 7926 @@ -11,7 +14,7 @@ val debugMemoryUrl = "/debug/memory" val sonarUrl = "/sonar" fun main(args: Array) { - + var roomScanner: RoomScanner? = null val carServer = car.server.Server.getCarServerThread(carServerPort) val webServer = web.server.Server.getWebServerThread(webServerPort) val carsDestroy = Dropper.getCarsDestroyThread() @@ -19,6 +22,13 @@ fun main(args: Array) { carsDestroy.start() webServer.start() + if (args.contains("--scan")) { + Environment.onCarConnect { car -> + roomScanner = RoomScanner(CarController(car)) + roomScanner!!.start() + } + } + //CL user interface DebugClInterface.run() @@ -26,4 +36,6 @@ fun main(args: Array) { carServer.interrupt() webServer.interrupt() Client.shutDownClient() + + roomScanner?.interrupt() } diff --git a/server/src/main/java/algorithm/AbstractAlgorithm.kt b/server/src/main/java/algorithm/AbstractAlgorithm.kt index 1a185eee47b..bdd4ad1aba3 100644 --- a/server/src/main/java/algorithm/AbstractAlgorithm.kt +++ b/server/src/main/java/algorithm/AbstractAlgorithm.kt @@ -9,7 +9,6 @@ import io.netty.buffer.Unpooled import io.netty.handler.codec.http.* import objects.Car import setRouteMetricUrl -import setRouteUrl import sonarUrl import java.util.* import java.util.concurrent.Exchanger @@ -44,7 +43,7 @@ abstract class AbstractAlgorithm(val thisCar: Car, val exchanger: Exchanger { - return prevSonarDistances - } - private fun getAngles(): IntArray { return requiredAngles } diff --git a/server/src/main/java/algorithm/RoomModel.kt b/server/src/main/java/algorithm/RoomModel.kt index 79295132abe..9dc013653a0 100644 --- a/server/src/main/java/algorithm/RoomModel.kt +++ b/server/src/main/java/algorithm/RoomModel.kt @@ -24,7 +24,7 @@ object RoomModel { fun getUpdate(): Waypoints { val algorithm = DebugClInterface.algorithmImpl - if (algorithm == null || !(algorithm is RoomBypassingAlgorithm)) { + if (algorithm == null || algorithm !is RoomBypassingAlgorithm) { val emptyArr = IntArray(0) return Waypoints.BuilderWaypoints(emptyArr, emptyArr, emptyArr, emptyArr, false).build() diff --git a/server/src/main/java/car/Dropper.kt b/server/src/main/java/car/Dropper.kt index 1e522e80b0d..fa6bd19b2e8 100644 --- a/server/src/main/java/car/Dropper.kt +++ b/server/src/main/java/car/Dropper.kt @@ -20,16 +20,15 @@ object Dropper { return { var stopped = false while (!stopped) { - val environment = Environment.instance - synchronized(environment, { + synchronized(Environment, { val currentTime = System.currentTimeMillis() val keysToRemove = mutableListOf() - for ((key, value) in environment.map) { + for ((key, value) in Environment.map) { if ((value.lastAction + timeDeltaToDrop) < currentTime) { keysToRemove.add(key) } } - dropInactiveCar(keysToRemove, environment) + dropInactiveCar(keysToRemove, Environment) }) try { Thread.sleep(60000) diff --git a/server/src/main/java/car/client/CarClient.kt b/server/src/main/java/car/client/CarClient.kt new file mode 100644 index 00000000000..150219e1118 --- /dev/null +++ b/server/src/main/java/car/client/CarClient.kt @@ -0,0 +1,19 @@ +package car.client + +import objects.Car +import org.asynchttpclient.ListenableFuture +import org.asynchttpclient.Response + +object CarClient { + enum class Request(val url: String) { + CONNECT("connect"), + GET_LOCATION("getLocation"), + ROUTE("route"), + ROUTE_METRIC("routeMetric"), + SONAR("sonar"), + DEBUG_MEMORY("debug/memory"); + } + + fun sendRequest(car: Car, request: Request, data: ByteArray): ListenableFuture + = Client.makeRequest("http://${car.host}:${car.port}/${request.url}", data) +} diff --git a/server/src/main/java/car/client/Client.kt b/server/src/main/java/car/client/Client.kt index 53ee3d1d478..430c6d75c17 100644 --- a/server/src/main/java/car/client/Client.kt +++ b/server/src/main/java/car/client/Client.kt @@ -6,21 +6,16 @@ import io.netty.channel.nio.NioEventLoopGroup import io.netty.channel.socket.nio.NioSocketChannel import io.netty.handler.codec.http.HttpRequest import io.netty.util.AttributeKey +import org.asynchttpclient.DefaultAsyncHttpClient +import org.asynchttpclient.ListenableFuture +import org.asynchttpclient.Response import java.net.ConnectException +import java.rmi.UnexpectedException object Client { - - val group: NioEventLoopGroup = NioEventLoopGroup() - val bootstrap: Bootstrap = makeBootstrap() - - private fun makeBootstrap(): Bootstrap { - val b = Bootstrap() - b.group(group).channel(NioSocketChannel().javaClass).handler(ClientInitializer()) - .attr(AttributeKey.newInstance("url"), "") - .attr(AttributeKey.newInstance("uid"), 0) - .attr(AttributeKey.newInstance("angles"), IntArray(0)) - return b - } + val group = NioEventLoopGroup() + val bootstrap = makeBootstrap() + val client = DefaultAsyncHttpClient() fun shutDownClient() { group.shutdownGracefully() @@ -41,4 +36,16 @@ object Client { throw InactiveCarException() } } + + fun makeRequest(request: String, data: ByteArray): ListenableFuture = + client.preparePost(request).setBody(data).execute() ?: throw UnexpectedException(request) + + private fun makeBootstrap(): Bootstrap { + val b = Bootstrap() + b.group(group).channel(NioSocketChannel().javaClass).handler(ClientInitializer()) + .attr(AttributeKey.newInstance("url"), "") + .attr(AttributeKey.newInstance("uid"), 0) + .attr(AttributeKey.newInstance("angles"), IntArray(0)) + return b + } } \ No newline at end of file diff --git a/server/src/main/java/car/client/ClientHandler.kt b/server/src/main/java/car/client/ClientHandler.kt index 083c45c7922..61c7e4171f2 100644 --- a/server/src/main/java/car/client/ClientHandler.kt +++ b/server/src/main/java/car/client/ClientHandler.kt @@ -19,9 +19,7 @@ import java.util.* import java.util.concurrent.TimeUnit import java.util.concurrent.TimeoutException -class ClientHandler : SimpleChannelInboundHandler { - - constructor() +class ClientHandler : SimpleChannelInboundHandler() { var contentBytes: ByteArray = ByteArray(0) @@ -64,11 +62,10 @@ class ClientHandler : SimpleChannelInboundHandler { } private fun handlerGetLocationResponse(message: LocationResponse, carUid: Int) { - val environment = Environment.instance if (message.code == 0) { val data = message.locationResponseData - synchronized(environment, { - val car = environment.map[carUid] + synchronized(Environment, { + val car = Environment.map[carUid] if (car != null) { car.x = data.x car.y = data.y @@ -106,4 +103,4 @@ class ClientHandler : SimpleChannelInboundHandler { contentsBytes.readBytes(contentBytes) } } -} \ No newline at end of file +} diff --git a/server/src/main/java/car/server/Handler.kt b/server/src/main/java/car/server/Handler.kt index ef03555e326..d418e94210d 100644 --- a/server/src/main/java/car/server/Handler.kt +++ b/server/src/main/java/car/server/Handler.kt @@ -13,13 +13,10 @@ import io.netty.handler.codec.http.* import objects.Environment class Handler : SimpleChannelInboundHandler() { - var url: String = "" var contentBytes: ByteArray = ByteArray(0) override fun channelReadComplete(ctx: ChannelHandlerContext) { - - val environment = Environment.instance var success = true var answer = ByteArray(0) when (url) { @@ -27,7 +24,7 @@ class Handler : SimpleChannelInboundHandler() { val data = ConnectionRequest.BuilderConnectionRequest(IntArray(0), 0).build() data.mergeFrom(CodedInputStream(contentBytes)) val ipStr = data.ipValues.map { elem -> elem.toString() }.reduce { elem1, elem2 -> elem1 + "." + elem2 } - val uid = environment.connectCar(ipStr, data.port) + val uid = Environment.connectCar(ipStr, data.port) val responseObject = ConnectionResponse.BuilderConnectionResponse(uid, 0).build() answer = ByteArray(responseObject.getSizeNoTag()) responseObject.writeTo(CodedOutputStream(answer)) diff --git a/server/src/main/java/objects/Environment.kt b/server/src/main/java/objects/Environment.kt index 96c4857a8a3..a12b6b4b752 100644 --- a/server/src/main/java/objects/Environment.kt +++ b/server/src/main/java/objects/Environment.kt @@ -1,22 +1,21 @@ package objects -class Environment private constructor() { - - val map: MutableMap +object Environment { private var uid = 0 - - companion object { - val instance = Environment() - } - - init { - map = mutableMapOf() - } + private val onConnect = mutableListOf<(Car) -> Unit>() + val map = mutableMapOf() @Synchronized fun connectCar(host: String, port: Int): Int { uid++ - map.put(uid, Car(uid, host, port)) + val car = Car(uid, host, port) + onConnect.forEach { it(car) } + map.put(uid, car) return uid } + + @Synchronized + fun onCarConnect(callback: (Car) -> Unit) { + onConnect.add(callback) + } } diff --git a/server/src/main/java/utils.kt b/server/src/main/java/utils.kt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/server/src/main/java/web/server/Handler.kt b/server/src/main/java/web/server/Handler.kt index fd989d37b0b..433fcfa8c80 100644 --- a/server/src/main/java/web/server/Handler.kt +++ b/server/src/main/java/web/server/Handler.kt @@ -1,14 +1,17 @@ package web.server +import CodedInputStream +import CodedOutputStream +import DirectionRequest +import GenericResponse +import ModeChange +import Result +import algorithm.RoomModel import io.netty.buffer.Unpooled import io.netty.channel.ChannelHandlerContext import io.netty.channel.SimpleChannelInboundHandler import io.netty.handler.codec.http.* import io.netty.util.CharsetUtil -import GenericResponse -import CodedOutputStream -import CodedInputStream -import algorithm.RoomModel import java.util.* class Handler : SimpleChannelInboundHandler() { @@ -41,9 +44,9 @@ class Handler : SimpleChannelInboundHandler() { Unpooled.copiedBuffer(Base64.getEncoder().encodeToString(outs.buffer), CharsetUtil.UTF_8) ) response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes()) - response.headers().add("Access-Control-Allow-Origin", "*"); - response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS"); - response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length"); + response.headers().add("Access-Control-Allow-Origin", "*") + response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS") + response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length") ctx.writeAndFlush(response).addListener(io.netty.channel.ChannelFutureListener.CLOSE) } Constants.getWaypointsURL -> { @@ -61,9 +64,9 @@ class Handler : SimpleChannelInboundHandler() { Unpooled.copiedBuffer(Base64.getEncoder().encodeToString(outs.buffer), CharsetUtil.UTF_8) ) response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes()) - response.headers().add("Access-Control-Allow-Origin", "*"); - response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS"); - response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length"); + response.headers().add("Access-Control-Allow-Origin", "*") + response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS") + response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length") ctx.writeAndFlush(response).addListener(io.netty.channel.ChannelFutureListener.CLOSE) } Constants.directionOrderURL -> { @@ -92,9 +95,9 @@ class Handler : SimpleChannelInboundHandler() { Unpooled.copiedBuffer(Base64.getEncoder().encodeToString(outs.buffer), CharsetUtil.UTF_8) ) response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes()) - response.headers().add("Access-Control-Allow-Origin", "*"); - response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS"); - response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length"); + response.headers().add("Access-Control-Allow-Origin", "*") + response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS") + response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length") ctx.writeAndFlush(response).addListener(io.netty.channel.ChannelFutureListener.CLOSE) } Constants.getDebug -> { @@ -108,9 +111,9 @@ class Handler : SimpleChannelInboundHandler() { Unpooled.copiedBuffer(Base64.getEncoder().encodeToString(outs.buffer), CharsetUtil.UTF_8) ) response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes()) - response.headers().add("Access-Control-Allow-Origin", "*"); - response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS"); - response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length"); + response.headers().add("Access-Control-Allow-Origin", "*") + response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS") + response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length") ctx.writeAndFlush(response).addListener(io.netty.channel.ChannelFutureListener.CLOSE) } }