copied emulator logic to main server, add parsing cl args, add JSAP lib
This commit is contained in:
@@ -46,12 +46,15 @@ jar {
|
||||
"Main-Class": "ServerMainKt")
|
||||
}
|
||||
|
||||
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||
compile group: 'org.asynchttpclient', name: 'async-http-client', version: '2.0.0-RC9'
|
||||
compile group: "com.martiansoftware", name: "jsap", version: "2.1"
|
||||
|
||||
compile files ("../proto/compiler/build/protokot-runtime.jar")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<room>
|
||||
<walls>
|
||||
<wall startX="200" startY="300" endX="-150" endY="300"/>
|
||||
<wall startX="-150" startY="300" endX="-150" endY="-45"/>
|
||||
<wall startX="-150" startY="-45" endX="200" endY="-45"/>
|
||||
<wall startX="200" startY="-45" endX="200" endY="300"/>
|
||||
</walls>
|
||||
</room>
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import com.martiansoftware.jsap.FlaggedOption
|
||||
import com.martiansoftware.jsap.JSAP
|
||||
import com.martiansoftware.jsap.StringParser
|
||||
import com.martiansoftware.jsap.Switch
|
||||
|
||||
fun setClOptions(clParser: JSAP) {
|
||||
val optEmulator = Switch("emulator", 'e', "emulator")
|
||||
val optUseRandom = Switch("random", 'r', "random")
|
||||
val optSeedForRandom = getOption("seed", JSAP.LONG_PARSER, "1111", 's', "seed")
|
||||
val optTestRoom = getOption("test room", JSAP.STRING_PARSER, "", null, "room")
|
||||
val optHelp = getOption("help", JSAP.BOOLEAN_PARSER, "false", null, "help")
|
||||
|
||||
clParser.registerParameter(optEmulator)
|
||||
clParser.registerParameter(optUseRandom)
|
||||
clParser.registerParameter(optSeedForRandom)
|
||||
clParser.registerParameter(optTestRoom)
|
||||
clParser.registerParameter(optHelp)
|
||||
}
|
||||
|
||||
fun getOption(name: String, parser: StringParser, default: String, shortFlag: Char?, longFlag: String, required: Boolean = false): FlaggedOption {
|
||||
val result = FlaggedOption(name)
|
||||
.setStringParser(parser)
|
||||
.setDefault(default)
|
||||
.setRequired(required)
|
||||
if (shortFlag != null) {
|
||||
result.setShortFlag(shortFlag)
|
||||
}
|
||||
if (!longFlag.equals("")) {
|
||||
result.setLongFlag(longFlag)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -1,11 +1,36 @@
|
||||
import roomScanner.CarController
|
||||
import roomScanner.RoomScanner
|
||||
import clInterface.DebugClInterface
|
||||
import com.martiansoftware.jsap.JSAP
|
||||
import net.car.Dropper
|
||||
import net.car.client.Client
|
||||
import objects.CarReal
|
||||
import objects.Environment
|
||||
import objects.emulator.CarEmulator
|
||||
import objects.emulator.EmulatedRoom
|
||||
import objects.emulator.Rng
|
||||
import roomScanner.CarController
|
||||
import roomScanner.RoomScanner
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
val clParser = JSAP()
|
||||
setClOptions(clParser)
|
||||
val argsConfig = clParser.parse(args)
|
||||
if (!argsConfig.success() || argsConfig.getBoolean("help")) {
|
||||
println(clParser.getHelp())
|
||||
return
|
||||
}
|
||||
if (argsConfig.getBoolean("emulator")) {
|
||||
val pathToRoomConfig = argsConfig.getString("test room")
|
||||
val randomSeed = argsConfig.getLong("seed")
|
||||
val useRandom = argsConfig.getBoolean("random")
|
||||
val carUid = 1
|
||||
val emulatedRoom = EmulatedRoom.EmulatedRoomFromFile(pathToRoomConfig)
|
||||
if (emulatedRoom == null) {
|
||||
println("error parsin room from file $pathToRoomConfig")
|
||||
return
|
||||
}
|
||||
Environment.map.put(carUid, CarEmulator(carUid, emulatedRoom, useRandom, Rng(randomSeed)))
|
||||
}
|
||||
var roomScanner: RoomScanner? = null
|
||||
val carServer = net.car.server.Server.createCarServerThread()
|
||||
val webServer = net.web.server.Server.createWebServerThread()
|
||||
@@ -16,8 +41,10 @@ fun main(args: Array<String>) {
|
||||
|
||||
if (args.contains("--scan")) {
|
||||
Environment.onCarConnect { car ->
|
||||
roomScanner = RoomScanner(CarController(car))
|
||||
roomScanner!!.start()
|
||||
if (car is CarReal) {
|
||||
roomScanner = RoomScanner(CarController(car))
|
||||
roomScanner!!.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,4 +56,5 @@ fun main(args: Array<String>) {
|
||||
Client.shutDownClient()
|
||||
|
||||
roomScanner?.interrupt()
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import SonarResponse
|
||||
import algorithm.geometry.Angle
|
||||
import algorithm.geometry.AngleData
|
||||
import objects.Car
|
||||
import objects.CarReal
|
||||
import roomScanner.CarController.Direction.*
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@@ -6,6 +6,7 @@ import DebugResponseMemoryStats
|
||||
import DebugResponseSonarStats
|
||||
import roomScanner.serialize
|
||||
import net.car.client.Client
|
||||
import objects.CarReal
|
||||
import objects.Environment
|
||||
import java.rmi.UnexpectedException
|
||||
|
||||
@@ -14,6 +15,9 @@ class DebugInformation : CommandExecutor {
|
||||
override fun execute(command: String) {
|
||||
val params = command.split(" ")
|
||||
val car = Environment.map[params[1].toInt()]!!
|
||||
if (!(car is CarReal)) {
|
||||
return
|
||||
}
|
||||
val type = DebugRequest.Type.fromIntToType(params[2].toInt())
|
||||
|
||||
val request = DebugRequest.BuilderDebugRequest(type).build()
|
||||
|
||||
@@ -5,6 +5,7 @@ import roomScanner.serialize
|
||||
import SonarExploreAngleRequest
|
||||
import SonarExploreAngleResponse
|
||||
import net.car.client.Client
|
||||
import objects.CarReal
|
||||
import objects.Environment
|
||||
|
||||
class Explore : CommandExecutor {
|
||||
@@ -12,6 +13,9 @@ class Explore : CommandExecutor {
|
||||
override fun execute(command: String) {
|
||||
val params = command.split(" ")
|
||||
val car = Environment.map[params[1].toInt()]!!
|
||||
if (!(car is CarReal)) {
|
||||
return
|
||||
}
|
||||
val angle = params[2].toInt()
|
||||
val window = params[3].toInt()
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import CodedOutputStream
|
||||
import RouteMetricRequest
|
||||
import net.car.client.Client
|
||||
import objects.Car
|
||||
import objects.CarReal
|
||||
import objects.Environment
|
||||
import java.net.ConnectException
|
||||
|
||||
@@ -39,7 +40,11 @@ class RouteMetric : CommandExecutor {
|
||||
val requestBytes = ByteArray(routeMessage.getSizeNoTag())
|
||||
routeMessage.writeTo(CodedOutputStream(requestBytes))
|
||||
try {
|
||||
car.carConnection.sendRequest(Client.Request.ROUTE_METRIC, requestBytes)
|
||||
routeMessage.distances.forEachIndexed { idx, distance ->
|
||||
val direction = roomScanner.CarController.Direction.values()
|
||||
.filter { it.id == routeMessage.directions[idx] }.first()
|
||||
car.moveCar(distance, direction).get()
|
||||
}
|
||||
} catch (e: ConnectException) {
|
||||
synchronized(Environment, {
|
||||
Environment.map.remove(id)
|
||||
|
||||
@@ -2,7 +2,6 @@ package clInterface.executor
|
||||
|
||||
import CodedOutputStream
|
||||
import SonarRequest
|
||||
import net.car.client.Client
|
||||
import objects.Car
|
||||
import objects.Environment
|
||||
import java.net.ConnectException
|
||||
@@ -35,7 +34,7 @@ class Sonar : CommandExecutor {
|
||||
val requestBytes = ByteArray(requestMessage.getSizeNoTag())
|
||||
requestMessage.writeTo(CodedOutputStream(requestBytes))
|
||||
try {
|
||||
car.carConnection.sendRequest(Client.Request.SONAR, requestBytes)
|
||||
car.scan(requestMessage.angles, requestMessage.attempts.first(), requestMessage.windowSize, requestMessage.smoothing)
|
||||
} catch (e: ConnectException) {
|
||||
synchronized(Environment, {
|
||||
Environment.map.remove(id)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.car
|
||||
|
||||
import net.car.client.Client
|
||||
import objects.CarReal
|
||||
import objects.Environment
|
||||
import java.net.ConnectException
|
||||
import kotlin.concurrent.thread
|
||||
@@ -34,6 +35,9 @@ object Dropper {
|
||||
for (key in environment.map.keys) {
|
||||
try {
|
||||
val carValue = environment.map[key] ?: continue
|
||||
if (!(carValue is CarReal)) {
|
||||
continue
|
||||
}
|
||||
carValue.carConnection.sendRequest(Client.Request.PING, ByteArray(0))
|
||||
} catch (e: ConnectException) {
|
||||
environment.map.remove(key)
|
||||
|
||||
@@ -1,44 +1,17 @@
|
||||
package objects
|
||||
|
||||
import CodedOutputStream
|
||||
import RouteMetricRequest
|
||||
import SonarRequest
|
||||
import net.car.client.Client
|
||||
import org.asynchttpclient.ListenableFuture
|
||||
import org.asynchttpclient.Response
|
||||
import roomScanner.CarController.Direction
|
||||
import roomScanner.serialize
|
||||
import roomScanner.CarController
|
||||
|
||||
class Car constructor(val uid: Int, host: String, port: Int) {
|
||||
|
||||
private val CHARGE_CORRECTION = 1.0//on full charge ok is 0.83 - 0.86
|
||||
abstract class Car(val uid: Int) {
|
||||
|
||||
var x = 0.0
|
||||
var y = 0.0
|
||||
var angle = 0.0
|
||||
val carConnection = CarConnection(host, port)
|
||||
|
||||
fun moveCar(distance: Int, direction: Direction): ListenableFuture<Response> {
|
||||
abstract fun moveCar(distance: Int, direction: CarController.Direction): ListenableFuture<Response>
|
||||
|
||||
val route = RouteMetricRequest.BuilderRouteMetricRequest(
|
||||
IntArray(1, { (distance * CHARGE_CORRECTION).toInt() }), IntArray(1, { direction.id }))
|
||||
val bytesRoute = ByteArray(route.getSizeNoTag())
|
||||
route.writeTo(CodedOutputStream(bytesRoute))
|
||||
return carConnection.sendRequest(Client.Request.ROUTE_METRIC, bytesRoute)
|
||||
}
|
||||
|
||||
fun scan(angles: IntArray, attempts: Int, windowSize: Int, smoothing: SonarRequest.Smoothing): ListenableFuture<Response> {
|
||||
val message = SonarRequest.BuilderSonarRequest(
|
||||
angles = angles,
|
||||
attempts = IntArray(angles.size, { attempts }),
|
||||
smoothing = smoothing,
|
||||
windowSize = windowSize)
|
||||
.build()
|
||||
val data = serialize(message.getSizeNoTag(), { message.writeTo(it) })
|
||||
return carConnection.sendRequest(Client.Request.SONAR, data)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "$uid ; x:$x; y:$y; target:$angle"
|
||||
}
|
||||
abstract fun scan(angles: IntArray, attempts: Int, windowSize: Int, smoothing: SonarRequest.Smoothing): ListenableFuture<Response>
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package objects
|
||||
|
||||
import CodedOutputStream
|
||||
import RouteMetricRequest
|
||||
import SonarRequest
|
||||
import net.car.client.Client
|
||||
import org.asynchttpclient.ListenableFuture
|
||||
import org.asynchttpclient.Response
|
||||
import roomScanner.CarController.Direction
|
||||
import roomScanner.serialize
|
||||
|
||||
class CarReal(uid: Int, host: String, port: Int) : Car(uid) {
|
||||
|
||||
private val CHARGE_CORRECTION = 1.0//on full charge ok is 0.83 - 0.86
|
||||
val carConnection = CarConnection(host, port)
|
||||
|
||||
override fun moveCar(distance: Int, direction: Direction): ListenableFuture<Response> {
|
||||
|
||||
val route = RouteMetricRequest.BuilderRouteMetricRequest(
|
||||
IntArray(1, { (distance * CHARGE_CORRECTION).toInt() }), IntArray(1, { direction.id }))
|
||||
val bytesRoute = ByteArray(route.getSizeNoTag())
|
||||
route.writeTo(CodedOutputStream(bytesRoute))
|
||||
return carConnection.sendRequest(Client.Request.ROUTE_METRIC, bytesRoute)
|
||||
}
|
||||
|
||||
override fun scan(angles: IntArray, attempts: Int, windowSize: Int, smoothing: SonarRequest.Smoothing): ListenableFuture<Response> {
|
||||
val message = SonarRequest.BuilderSonarRequest(
|
||||
angles = angles,
|
||||
attempts = IntArray(angles.size, { attempts }),
|
||||
smoothing = smoothing,
|
||||
windowSize = windowSize)
|
||||
.build()
|
||||
val data = serialize(message.getSizeNoTag(), { message.writeTo(it) })
|
||||
return carConnection.sendRequest(Client.Request.SONAR, data)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "$uid ; x:$x; y:$y; target:$angle"
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ object Environment {
|
||||
@Synchronized
|
||||
fun connectCar(host: String, port: Int): Int {
|
||||
uid++
|
||||
val car = Car(uid, host, port)
|
||||
val car = CarReal(uid, host, port)
|
||||
onConnect.forEach { it(car) }
|
||||
map.put(uid, car)
|
||||
return uid
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
package objects.emulator
|
||||
|
||||
import SonarRequest
|
||||
import SonarResponse
|
||||
import algorithm.geometry.Angle
|
||||
import algorithm.geometry.Line
|
||||
import algorithm.geometry.Vector
|
||||
import objects.Car
|
||||
import org.asynchttpclient.ListenableFuture
|
||||
import org.asynchttpclient.Response
|
||||
import roomScanner.CarController
|
||||
import roomScanner.CarController.Direction.*
|
||||
import roomScanner.serialize
|
||||
|
||||
class CarEmulator(uid: Int, val testRoom: EmulatedRoom, val useRandom: Boolean, val randomGenerator: Rng) : Car(uid) {
|
||||
|
||||
private var xReal = 0
|
||||
private var yReal = 0
|
||||
private var angleReal = Angle(0)
|
||||
|
||||
override fun moveCar(distance: Int, direction: CarController.Direction): ListenableFuture<Response> {
|
||||
val coef = if (useRandom) randomGenerator.nextInt(900, 1100).toDouble() / 1000.0 else 1.0
|
||||
val distanceWithRandom = (coef * distance).toInt()
|
||||
when (direction) {
|
||||
FORWARD -> {
|
||||
xReal += (Math.cos(angleReal.rads()) * distanceWithRandom).toInt()
|
||||
yReal += (Math.sin(angleReal.rads()) * distanceWithRandom).toInt()
|
||||
}
|
||||
BACKWARD -> {
|
||||
xReal -= (Math.cos(angleReal.rads()) * distanceWithRandom).toInt()
|
||||
yReal -= (Math.sin(angleReal.rads()) * distanceWithRandom).toInt()
|
||||
}
|
||||
LEFT -> angleReal += Angle(distanceWithRandom)
|
||||
RIGHT -> angleReal -= Angle(distanceWithRandom)
|
||||
}
|
||||
println("x=$xReal y=$yReal angle=${angleReal.degs()}")
|
||||
return ListenableFutureImpl(ByteArray(0))
|
||||
}
|
||||
|
||||
override fun scan(angles: IntArray, attempts: Int, windowSize: Int, smoothing: SonarRequest.Smoothing): ListenableFuture<Response> {
|
||||
|
||||
|
||||
val xSensor0 = xReal.toInt()
|
||||
val ySensor0 = yReal.toInt()
|
||||
val carAngle = angleReal
|
||||
|
||||
val distances = arrayListOf<Int>()
|
||||
angles.forEach { angle ->
|
||||
val angleFinal = getSensorAngle(angle, carAngle.degs())
|
||||
val xSensor1: Int
|
||||
val ySensor1: Double
|
||||
//tg can be equal to inf if angle = 90 or 270. it vertical line. x1 = x0, y1 = y0+-[any number. eg 1]
|
||||
when (angleFinal) {
|
||||
90 -> {
|
||||
xSensor1 = xSensor0
|
||||
ySensor1 = (ySensor0 + 1).toDouble()
|
||||
}
|
||||
270 -> {
|
||||
xSensor1 = xSensor0
|
||||
ySensor1 = (ySensor0 - 1).toDouble()
|
||||
}
|
||||
in (90..270) -> {
|
||||
xSensor1 = xSensor0 - 1
|
||||
ySensor1 = ySensor0 + (xSensor1 - xSensor0) * Math.tan(angleFinal * Math.PI / 180)
|
||||
}
|
||||
else -> {
|
||||
xSensor1 = xSensor0 + 1
|
||||
ySensor1 = ySensor0 + (xSensor1 - xSensor0) * Math.tan(angleFinal * Math.PI / 180)
|
||||
}
|
||||
}
|
||||
val sensorLine = Line(ySensor0 - ySensor1, xSensor1.toDouble() - xSensor0,
|
||||
xSensor0 * ySensor1 - ySensor0 * xSensor1)
|
||||
|
||||
val sensorVector = Vector(xSensor0.toDouble(), ySensor0.toDouble(), xSensor1.toDouble(), ySensor1)
|
||||
val distance = getDistance(xSensor0, ySensor0, sensorLine, sensorVector)
|
||||
if (distance == -1) {
|
||||
distances.add(distance)
|
||||
} else {
|
||||
val delta = if (useRandom) randomGenerator.nextInt(-2, 2) else 0//return one of -2 -1 0 1 or 2
|
||||
distances.add(distance + delta)
|
||||
}
|
||||
}
|
||||
|
||||
val responseMessage = SonarResponse.BuilderSonarResponse(distances.toIntArray()).build()
|
||||
val bytes = serialize(responseMessage.getSizeNoTag(), { responseMessage.writeTo(it) })
|
||||
|
||||
return ListenableFutureImpl(bytes)
|
||||
}
|
||||
|
||||
private fun getDistance(xSensor0: Int, ySensor0: Int, sensorLine: Line, sensorVector: Vector): Int {
|
||||
var result = Long.MAX_VALUE
|
||||
for (wall in testRoom.emulatedWalls) {
|
||||
val wallLine = wall.line
|
||||
val slope = sensorLine.A * wallLine.B - sensorLine.B * wallLine.A
|
||||
if (Math.abs(slope) < 0.01) {
|
||||
//line is parallel.
|
||||
continue
|
||||
}
|
||||
val xIntersection = (sensorLine.B * wallLine.C - wallLine.B * sensorLine.C) / slope
|
||||
val yIntersection = (sensorLine.C * wallLine.A - wallLine.C * sensorLine.A) / slope
|
||||
|
||||
//filters by direction and intersection position
|
||||
val intersectionVector = Vector(xSensor0.toDouble(), ySensor0.toDouble(), xIntersection, yIntersection)
|
||||
if (intersectionVector.scalarProduct(sensorVector) < 0) {
|
||||
continue
|
||||
}
|
||||
val wallVector1 = Vector(xIntersection, yIntersection, wall.xTo.toDouble(), wall.yTo.toDouble())
|
||||
val wallVector2 = Vector(xIntersection, yIntersection, wall.xFrom.toDouble(), wall.yFrom.toDouble())
|
||||
if (wallVector1.scalarProduct(wallVector2) > 0) {
|
||||
continue
|
||||
}
|
||||
val currentDistance = Math.round(Math.sqrt(Math.pow(xIntersection - xSensor0, 2.0)
|
||||
+ Math.pow(yIntersection - ySensor0, 2.0)))
|
||||
if (currentDistance < result) {
|
||||
result = currentDistance
|
||||
}
|
||||
}
|
||||
return result.toInt()
|
||||
}
|
||||
|
||||
|
||||
private fun getSensorAngle(requestAngle: Int, carAngle: Int): Int {
|
||||
var angleTmp = carAngle - requestAngle
|
||||
while (angleTmp < 0) {
|
||||
angleTmp += 360
|
||||
}
|
||||
return angleTmp % 360
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package objects.emulator
|
||||
|
||||
import org.w3c.dom.Node
|
||||
import java.io.File
|
||||
import javax.xml.parsers.DocumentBuilderFactory
|
||||
|
||||
class EmulatedRoom() {
|
||||
val emulatedWalls = arrayListOf<EmulatedWall>()
|
||||
|
||||
constructor(EmulatedWalls: Collection<EmulatedWall>) : this() {
|
||||
this.emulatedWalls.addAll(EmulatedWalls)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun EmulatedRoomFromFile(pathToFile: String): EmulatedRoom? {
|
||||
|
||||
val factory = DocumentBuilderFactory.newInstance()
|
||||
val builder = factory.newDocumentBuilder()
|
||||
val doc = builder.parse(File(pathToFile))
|
||||
val root = doc.getDocumentElement()
|
||||
val rootChild = root.childNodes
|
||||
var walls: Node? = null
|
||||
for (i in 0..rootChild.length - 1) {
|
||||
val node = rootChild.item(i)
|
||||
if (node.nodeType == Node.ELEMENT_NODE) {
|
||||
walls = node
|
||||
break
|
||||
}
|
||||
}
|
||||
walls ?: return null
|
||||
val wallsChild = walls.childNodes
|
||||
val result = EmulatedRoom()
|
||||
for (i in 0..wallsChild.length - 1) {
|
||||
val wall = wallsChild.item(i)
|
||||
if (wall.nodeType != Node.ELEMENT_NODE) {
|
||||
continue
|
||||
}
|
||||
val EmulatedWall = EmulatedWall.wallFromXml(wall) ?: return null
|
||||
result.emulatedWalls.add(EmulatedWall)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package objects.emulator
|
||||
|
||||
import algorithm.geometry.Line
|
||||
import org.w3c.dom.Node
|
||||
|
||||
class EmulatedWall constructor(val line: Line, val xFrom: Int, val xTo: Int, val yFrom: Int, val yTo: Int) {
|
||||
|
||||
companion object {
|
||||
fun wallFromXml(wall: Node): EmulatedWall? {
|
||||
val points = wall.attributes
|
||||
val startX: Int
|
||||
val endX: Int
|
||||
val endY: Int
|
||||
val startY: Int
|
||||
try {
|
||||
startX = points.getNamedItem("startX").nodeValue.toInt()
|
||||
startY = points.getNamedItem("startY").nodeValue.toInt()
|
||||
endX = points.getNamedItem("endX").nodeValue.toInt()
|
||||
endY = points.getNamedItem("endY").nodeValue.toInt()
|
||||
} catch (e: NumberFormatException) {
|
||||
return null
|
||||
}
|
||||
val line = Line((startY - endY).toDouble(), (endX - startX).toDouble(), (startX * endY - startY * endX).toDouble())
|
||||
return EmulatedWall(line, startX, endX, startY, endY)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package objects.emulator
|
||||
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.buffer.Unpooled
|
||||
import org.asynchttpclient.ListenableFuture
|
||||
import org.asynchttpclient.Response
|
||||
import org.asynchttpclient.netty.EagerResponseBodyPart
|
||||
import org.asynchttpclient.netty.NettyResponse
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.Executor
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class ListenableFutureImpl(bytes: ByteArray) : ListenableFuture<Response> {
|
||||
|
||||
val response = NettyResponse(null, null, listOf(EagerResponseBodyPart(Unpooled.copiedBuffer(bytes), true)))
|
||||
|
||||
override fun done() {
|
||||
|
||||
}
|
||||
|
||||
override fun cancel(p0: Boolean): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun touch() {
|
||||
}
|
||||
|
||||
override fun get(): Response {
|
||||
return response
|
||||
}
|
||||
|
||||
override fun get(p0: Long, p1: TimeUnit): Response {
|
||||
return response
|
||||
}
|
||||
|
||||
override fun addListener(listener: Runnable?, exec: Executor?): ListenableFuture<Response> {
|
||||
return this
|
||||
}
|
||||
|
||||
override fun abort(t: Throwable?) {
|
||||
}
|
||||
|
||||
override fun isDone(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun toCompletableFuture(): CompletableFuture<Response> {
|
||||
throw UnsupportedOperationException("not implemented")
|
||||
}
|
||||
|
||||
override fun isCancelled(): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package objects.emulator
|
||||
|
||||
class Rng(seed: Long) {
|
||||
var curState = seed
|
||||
val a = 1664525L
|
||||
val c = 1013904223L
|
||||
val mod = 2147483648L
|
||||
|
||||
fun abs(value: Long): Long {
|
||||
if (value < 0)
|
||||
return -value
|
||||
return value
|
||||
}
|
||||
|
||||
fun nextInt(): Int {
|
||||
val res = curState
|
||||
curState = abs(a * curState + c) % mod
|
||||
return (res % mod).toInt()
|
||||
}
|
||||
|
||||
fun nextInt(min_val: Int, max_val: Int): Int {
|
||||
val rand = nextInt()
|
||||
val size = max_val - min_val + 1
|
||||
val randInRange = rand % size
|
||||
val res = randInRange + min_val
|
||||
return res
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,9 @@ import RouteMetricRequest
|
||||
import SonarRequest
|
||||
import SonarResponse
|
||||
import net.car.client.Client
|
||||
import objects.Car
|
||||
import objects.CarReal
|
||||
|
||||
class CarController(var car: Car) {
|
||||
class CarController(var car: CarReal) {
|
||||
enum class Direction(val id: Int) {
|
||||
FORWARD(0),
|
||||
BACKWARD(1),
|
||||
|
||||
@@ -6,7 +6,7 @@ class RoomScanner(val controller: CarController) : Thread() {
|
||||
private val GHOST_LEVEL = 50
|
||||
|
||||
override fun run() {
|
||||
println("Car connected ${controller.car.carConnection.host}")
|
||||
println("CarReal connected ${controller.car.carConnection.host}")
|
||||
for (i in 1..100) {
|
||||
step()
|
||||
println(plot(points))
|
||||
|
||||
Reference in New Issue
Block a user