diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/ObjectRegistry.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/ObjectRegistry.kt index 378672b1..eb64bb28 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/ObjectRegistry.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/ObjectRegistry.kt @@ -18,7 +18,7 @@ import ru.dbotthepony.kstarbound.util.PathStack import java.util.* import kotlin.reflect.KClass -inline fun ObjectRegistry(name: String, noinline key: (T) -> String, noinline intKey: ((T) -> Int)? = null): ObjectRegistry { +inline fun ObjectRegistry(name: String, noinline key: ((T) -> String)? = null, noinline intKey: ((T) -> Int)? = null): ObjectRegistry { return ObjectRegistry(T::class, name, key, intKey) } @@ -48,7 +48,7 @@ class RegistryObject(val value: T, private val json: JsonObject, val fi } } -class ObjectRegistry(val clazz: KClass, val name: String, val key: (T) -> String, val intKey: ((T) -> Int)? = null) { +class ObjectRegistry(val clazz: KClass, val name: String, val key: ((T) -> String)? = null, val intKey: ((T) -> Int)? = null) { private val objects = Object2ObjectOpenHashMap>() private val intObjects = Int2ObjectOpenHashMap>() @@ -160,17 +160,19 @@ class ObjectRegistry(val clazz: KClass, val name: String, val key: ( return pathStack(file.computeDirectory()) { val elem = gson.fromJson(file.reader(), JsonObject::class.java) val value = gson.fromJson(JsonTreeReader(elem), clazz.java) - add(RegistryObject(value, elem, file, gson, pathStack)) + add(RegistryObject(value, elem, file, gson, pathStack), this.key?.invoke(value) ?: throw UnsupportedOperationException("No key mapper")) } } fun add(value: T, json: JsonObject, file: IStarboundFile, gson: Gson, pathStack: PathStack): Boolean { - return add(RegistryObject(value, json, file, gson, pathStack)) + return add(RegistryObject(value, json, file, gson, pathStack), this.key?.invoke(value) ?: throw UnsupportedOperationException("No key mapper")) } - private fun add(value: RegistryObject): Boolean { - val key = this.key.invoke(value.value) + fun add(value: T, json: JsonObject, file: IStarboundFile, gson: Gson, pathStack: PathStack, key: String): Boolean { + return add(RegistryObject(value, json, file, gson, pathStack), key) + } + private fun add(value: RegistryObject, key: String): Boolean { val existing = objects.put(key, value) if (existing != null) { @@ -184,7 +186,7 @@ class ObjectRegistry(val clazz: KClass, val name: String, val key: ( val intExisting = intObjects.put(intKey, value) if (intExisting != null) { - LOGGER.warn("Registry $name already has object with ID $intKey (new $key, old ${this.key.invoke(intExisting.value)})! Overwriting. (old originated from ${intExisting.file}, new originate from ${value.file}).") + LOGGER.warn("Registry $name already has object with ID $intKey (new $key, old ${ objects.entries.firstOrNull { it.value === intExisting }?.key })! Overwriting. (old originated from ${intExisting.file}, new originate from ${value.file}).") } return existing != null || intExisting != null diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt index defc3b65..d690156a 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt @@ -1,5 +1,6 @@ package ru.dbotthepony.kstarbound +import com.google.common.cache.CacheBuilder import com.google.common.collect.Interner import com.google.common.collect.Interners import com.google.gson.* @@ -7,6 +8,7 @@ import com.google.gson.internal.bind.JsonTreeReader import it.unimi.dsi.fastutil.objects.Object2ObjectFunction import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap import org.apache.logging.log4j.LogManager +import org.lwjgl.stb.STBImage import ru.dbotthepony.kstarbound.api.ISBFileLocator import ru.dbotthepony.kstarbound.api.IStarboundFile import ru.dbotthepony.kstarbound.api.NonExistingFile @@ -63,20 +65,23 @@ import ru.dbotthepony.kstarbound.util.PathStack import ru.dbotthepony.kstarbound.util.SBPattern import ru.dbotthepony.kstarbound.util.WriteOnce import ru.dbotthepony.kstarbound.util.traverseJsonPath +import ru.dbotthepony.kvector.vector.nint.Vector2i import java.io.* import java.text.DateFormat +import java.time.Duration import java.util.* import java.util.function.BiConsumer import java.util.function.BinaryOperator import java.util.function.Function import java.util.function.Supplier import java.util.stream.Collector +import kotlin.NoSuchElementException import kotlin.collections.ArrayList class Starbound : ISBFileLocator { private val logger = LogManager.getLogger() - val pathStack = PathStack(Starbound.STRINGS) + val pathStack = PathStack(STRINGS) private val _tiles = ObjectRegistry("tiles", TileDefinition::materialName, TileDefinition::materialId) val tiles = _tiles.view @@ -108,6 +113,12 @@ class Starbound : ISBFileLocator { private val _techs = ObjectRegistry("techs", TechDefinition::name) val techs = _techs.view + private val _jsonFunctions = ObjectRegistry("json functions") + val jsonFunctions = _jsonFunctions.view + + private val _json2Functions = ObjectRegistry("json 2functions") + val json2Functions = _json2Functions.view + val gson: Gson = with(GsonBuilder()) { serializeNulls() setDateFormat(DateFormat.LONG) @@ -115,7 +126,12 @@ class Starbound : ISBFileLocator { setPrettyPrinting() registerTypeAdapter(InternedStringAdapter(STRINGS)) - registerTypeAdapter(InternedJsonElementAdapter(STRINGS)) + + InternedJsonElementAdapter(STRINGS).also { + registerTypeAdapter(it) + registerTypeAdapter(it.arrays) + registerTypeAdapter(it.objects) + } registerTypeAdapter(Nothing::class.java, NothingAdapter) @@ -160,6 +176,7 @@ class Starbound : ISBFileLocator { registerTypeAdapter(JsonFunction.CONSTRAINT_ADAPTER) registerTypeAdapter(JsonFunction.INTERPOLATION_ADAPTER) registerTypeAdapter(JsonFunction.Companion) + registerTypeAdapterFactory(Json2Function.Companion) // Общее registerTypeAdapterFactory(ThingDescription.Factory(STRINGS)) @@ -193,6 +210,12 @@ class Starbound : ISBFileLocator { val atlasRegistry = AtlasConfiguration.Registry(this, pathStack, gson) + private val imageCache = CacheBuilder.newBuilder() + .concurrencyLevel(8) + .softValues() + .expireAfterAccess(Duration.ofMinutes(10)) + .build() + fun item(name: String): ItemDescriptor { return ItemDescriptor(items[name] ?: return ItemDescriptor.EMPTY) } @@ -271,11 +294,42 @@ class Starbound : ISBFileLocator { } val read = file.readToString() - it.load(read, chunkName = file.computeFullPath()) + it.load(read, chunkName = "@" + file.computeFullPath()) it.call() } - fun expose(state: LuaState) { + fun imageData(path: String): ImageData { + return imageCache.get(path) { + val file = locate(path) + + if (!file.exists) { + throw FileNotFoundException("No such file $file") + } + + if (!file.isFile) { + throw IllegalStateException("File $file is a directory") + } + + val getWidth = intArrayOf(0) + val getHeight = intArrayOf(0) + val components = intArrayOf(0) + + val data = STBImage.stbi_load_from_memory( + file.readDirect(), + getWidth, getHeight, + components, 0 + ) ?: throw IllegalArgumentException("File $file is not an image or it is corrupted") + + ImageData(data, getWidth[0], getHeight[0], components[0]) + } + } + + fun imageSize(path: String): Vector2i { + val image = imageData(path) + return Vector2i(image.width, image.height) + } + + fun pushLuaAPI(state: LuaState) { state.pushWeak(this) { args -> luaRequire(args.lua, args) 0 @@ -286,18 +340,62 @@ class Starbound : ISBFileLocator { state.pushTable() state.storeGlobal("root") state.loadGlobal("root") - val root = state.stackTop - state.push("assetJson") - state.pushWeak(this) {args -> + state.setTableFunction("assetJson", this) {args -> args.lua.push(loadJsonAsset(args.getString())) 1 } - state.setTableValue(root) + state.setTableFunction("makeCurrentVersionedJson", this) {args -> + TODO("makeCurrentVersionedJson") + } + + state.setTableFunction("loadVersionedJson", this) {args -> + TODO("loadVersionedJson") + } + + state.setTableFunction("evalFunction", this) {args -> + val name = args.getString() + val fn = jsonFunctions[name] ?: throw NoSuchElementException("No such function $name") + args.push(fn.value.evaluate(args.getDouble())) + 1 + } + + state.setTableFunction("evalFunction2", this) {args -> + val name = args.getString() + val fn = json2Functions[name] ?: throw NoSuchElementException("No such 2function $name") + args.push(fn.value.evaluate(args.getDouble(), args.getDouble())) + 1 + } + + state.setTableFunction("imageSize", this) {args -> + val (width, height) = imageSize(args.getString()) + + with(args.lua) { + pushTable(hashSize = 2) + val table = stackTop + + setTableValue("width", width) + setTableValue("height", height) + + setTableValue("x", width) + setTableValue("y", height) + + push(1) + push(width) + setTableValue(table) + + push(2) + push(height) + setTableValue(table) + } + + 1 + } + state.pop() - state.load(polyfill, "starbound.jar!/scripts/polyfill.lua") + state.load(polyfill, "@starbound.jar!/scripts/polyfill.lua") state.call() } @@ -488,7 +586,9 @@ class Starbound : ISBFileLocator { callback(false, false, "Finished building file index in ${System.currentTimeMillis() - time}ms".also(logger::info)) - loadStage(callback, this::loadItemDefinitions, "item definitions") + loadStage(callback, { loadItemDefinitions(it, ext2files) }, "item definitions") + loadStage(callback, { loadJsonFunctions(it, ext2files["functions"] ?: listOf()) }, "json functions") + loadStage(callback, { loadJson2Functions(it, ext2files["2functions"] ?: listOf()) }, "json 2functions") loadStage(callback, _tiles, ext2files["material"] ?: listOf()) loadStage(callback, _tileModifiers, ext2files["matmod"] ?: listOf()) @@ -539,26 +639,28 @@ class Starbound : ISBFileLocator { } } - private fun loadItemDefinitions(callback: (String) -> Unit) { - val files = linkedMapOf( - ".item" to ItemPrototype::class.java, - ".currency" to CurrencyItemPrototype::class.java, - ".liqitem" to LiquidItemPrototype::class.java, - ".matitem" to MaterialItemPrototype::class.java, - ".flashlight" to FlashlightPrototype::class.java, - ".harvestingtool" to HarvestingToolPrototype::class.java, - ".head" to HeadArmorItemPrototype::class.java, - ".chest" to ChestArmorItemPrototype::class.java, - ".legs" to LegsArmorItemPrototype::class.java, - ".back" to BackArmorItemPrototype::class.java, + private fun loadItemDefinitions(callback: (String) -> Unit, files: Map>) { + val fileMap = mapOf( + "item" to ItemPrototype::class.java, + "currency" to CurrencyItemPrototype::class.java, + "liqitem" to LiquidItemPrototype::class.java, + "matitem" to MaterialItemPrototype::class.java, + "flashlight" to FlashlightPrototype::class.java, + "harvestingtool" to HarvestingToolPrototype::class.java, + "head" to HeadArmorItemPrototype::class.java, + "chest" to ChestArmorItemPrototype::class.java, + "legs" to LegsArmorItemPrototype::class.java, + "back" to BackArmorItemPrototype::class.java, ) - for (fs in fileSystems) { - for (listedFile in fs.explore().filter { it.isFile }.filter { f -> files.keys.any { f.name.endsWith(it) } }) { + for ((ext, clazz) in fileMap) { + val fileList = files[ext] ?: continue + + for (listedFile in fileList) { try { callback("Loading $listedFile") val json = gson.fromJson(listedFile.reader(), JsonObject::class.java) - val def: ItemPrototype = pathStack(listedFile.computeDirectory()) { gson.fromJson(JsonTreeReader(json), files.entries.first { listedFile.name.endsWith(it.key) }.value) } + val def: ItemPrototype = pathStack(listedFile.computeDirectory()) { gson.fromJson(JsonTreeReader(json), clazz) } _items.add(def, json, listedFile, gson, pathStack) } catch (err: Throwable) { logger.error("Loading item definition file $listedFile", err) @@ -571,6 +673,46 @@ class Starbound : ISBFileLocator { } } + private fun loadJsonFunctions(callback: (String) -> Unit, files: Collection) { + for (listedFile in files) { + try { + callback("Loading $listedFile") + val json = gson.fromJson(listedFile.reader(), JsonObject::class.java) + + for ((k, v) in json.entrySet()) { + val fn = gson.fromJson(JsonTreeReader(v), JsonFunction::class.java) + _jsonFunctions.add(fn, json, listedFile, gson, pathStack, k) + } + } catch (err: Throwable) { + logger.error("Loading json function definition file $listedFile", err) + } + + if (terminateLoading) { + return + } + } + } + + private fun loadJson2Functions(callback: (String) -> Unit, files: Collection) { + for (listedFile in files) { + try { + callback("Loading $listedFile") + val json = gson.fromJson(listedFile.reader(), JsonObject::class.java) + + for ((k, v) in json.entrySet()) { + val fn = gson.fromJson(JsonTreeReader(v), Json2Function::class.java) + _json2Functions.add(fn, json, listedFile, gson, pathStack, k) + } + } catch (err: Throwable) { + logger.error("Loading json 2function definition file $listedFile", err) + } + + if (terminateLoading) { + return + } + } + } + companion object { /** * Глобальный [Interner] для [String] diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt index 14ea3e5a..1e10e705 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt @@ -175,7 +175,7 @@ class StarboundClient(val starbound: Starbound) : Closeable { input.installCallback(window) GLFW.glfwMakeContextCurrent(window) - gl = GLStateTracker(starbound) + gl = GLStateTracker(this) GLFW.glfwSetFramebufferSizeCallback(window) { _, w, h -> if (w == 0 || h == 0) { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLStateTracker.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLStateTracker.kt index 9cab5d68..7845e179 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLStateTracker.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLStateTracker.kt @@ -5,6 +5,7 @@ import org.lwjgl.opengl.GL import org.lwjgl.opengl.GL46.* import org.lwjgl.opengl.GLCapabilities import ru.dbotthepony.kstarbound.api.ISBFileLocator +import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.freetype.FreeType import ru.dbotthepony.kstarbound.client.freetype.InvalidArgumentException import ru.dbotthepony.kstarbound.client.gl.shader.GLPrograms @@ -116,7 +117,7 @@ private class TexturesTracker(maxValue: Int) : ReadWriteProperty GL_R + 2 -> GL_RG + 3 -> GL_RGB + 4 -> GL_RGBA + else -> throw IllegalArgumentException("Weird amount of channels in file: $numChannels") + } + + upload(bufferFormat, data.width, data.height, bufferFormat, GL_UNSIGNED_BYTE, data.data) + + return this + } + var isValid = true private set diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/JsonFunction.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/JsonFunction.kt index b9e2b00c..0508a039 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/JsonFunction.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/JsonFunction.kt @@ -1,66 +1,118 @@ package ru.dbotthepony.kstarbound.defs import com.google.common.collect.ImmutableList +import com.google.gson.Gson +import com.google.gson.JsonArray import com.google.gson.JsonSyntaxException import com.google.gson.TypeAdapter +import com.google.gson.TypeAdapterFactory +import com.google.gson.reflect.TypeToken import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonToken import com.google.gson.stream.JsonWriter +import ru.dbotthepony.kstarbound.io.json.InternedJsonElementAdapter import ru.dbotthepony.kstarbound.io.json.builder.EnumAdapter import ru.dbotthepony.kstarbound.io.json.builder.IStringSerializable import ru.dbotthepony.kstarbound.io.json.Vector2dTypeAdapter +import ru.dbotthepony.kvector.util.linearInterpolation import ru.dbotthepony.kvector.vector.ndouble.Vector2d -enum class JsonFunctionInterpolation(vararg aliases: String) : IStringSerializable { - LINEAR; +enum class JsonFunctionInterpolation { + LINEAR { + override fun interpolate(t: Double, a: Double, b: Double): Double { + return linearInterpolation(t, a, b) + } + }; - private val aliases: Array = Array(aliases.size) { aliases[it].uppercase() } - - override fun match(name: String): Boolean { - for (alias in aliases) - if (name == alias) - return true - - return name == this.name - } - - override fun write(out: JsonWriter) { - out.value(this.name) - } + abstract fun interpolate(t: Double, a: Double, b: Double): Double } -enum class JsonFunctionConstraint(vararg aliases: String) : IStringSerializable { - CLAMP; +enum class JsonFunctionConstraint { + CLAMP { + override fun process(x: Double, lower: Double, upper: Double): Double { + return x.coerceIn(lower, upper) + } + }; - private val aliases: Array = Array(aliases.size) { aliases[it].uppercase() } + abstract fun process(x: Double, lower: Double, upper: Double): Double +} - override fun match(name: String): Boolean { - for (alias in aliases) - if (name == alias) - return true - - return name == this.name +data class DoubleRange(val start: Double, val end: Double) : Comparable { + init { + require(start <= end) { "start <= end: $start <= $end" } } - override fun write(out: JsonWriter) { - out.value(this.name) + val length = end - start + + operator fun contains(value: Double): Boolean { + return value in start .. end + } + + fun determine(value: Double): Double { + if (value < start) { + return 0.0 + } else if (value > end) { + return 1.0 + } else { + return (value - start) / length + } + } + + override fun compareTo(other: Double): Int { + if (other < start) { + return 1 + } else if (other > end) { + return -1 + } else { + return 0 + } } } class JsonFunction( val interpolation: JsonFunctionInterpolation, val constraint: JsonFunctionConstraint, - val ranges: List + ranges: Collection ) { + val ranges: ImmutableList = ranges.stream().sorted { o1, o2 -> o1.x.compareTo(o2.x) }.collect(ImmutableList.toImmutableList()) + val lowerBound = this.ranges.first().x + val upperBound = this.ranges.last().x + + fun evaluate(input: Double): Double { + val x = constraint.process(input, lowerBound, upperBound) + + when (interpolation) { + JsonFunctionInterpolation.LINEAR -> { + if (x < ranges[0].x) { + return ranges[0].y + } + + for (i in 0 until ranges.size - 1) { + val a = ranges[i] + val b = ranges[i + 1] + + if (x in a.x .. b.x) { + return linearInterpolation((x - a.x) / (b.x - a.x), a.y, b.y) + } + } + + return ranges.last().y + } + } + } + companion object : TypeAdapter() { val CONSTRAINT_ADAPTER = EnumAdapter(JsonFunctionConstraint::class) val INTERPOLATION_ADAPTER = EnumAdapter(JsonFunctionInterpolation::class) - override fun write(out: JsonWriter, value: JsonFunction) { + override fun write(out: JsonWriter, value: JsonFunction?) { TODO("Not yet implemented") } - override fun read(reader: JsonReader): JsonFunction { + override fun read(reader: JsonReader): JsonFunction? { + if (reader.peek() == JsonToken.NULL) + return null + reader.beginArray() val interpolation = INTERPOLATION_ADAPTER.read(reader) ?: throw JsonSyntaxException("Missing interpolation") @@ -78,3 +130,196 @@ class JsonFunction( } } } + +class Json2Function( + val interpolation: JsonFunctionInterpolation, + val constraint: JsonFunctionConstraint, + xRanges: List, // значения [a, b, c, d] + yRanges: List, // значения [a, [b, c, d]] +) { + init { + require(xRanges.isNotEmpty()) { "X ranges are empty" } + require(yRanges.isNotEmpty()) { "Y ranges are empty" } + } + + val xRanges: ImmutableList = xRanges.stream().sorted { o1, o2 -> o1.edge.compareTo(o2.edge) }.collect(ImmutableList.toImmutableList()) + val yRanges: ImmutableList = yRanges.stream().sorted { o1, o2 -> o1.edge.compareTo(o2.edge) }.collect(ImmutableList.toImmutableList()) + + data class Ranges(val interpolation: JsonFunctionInterpolation, val edge: Double, val ranges: ImmutableList) { + val step = 1.0 / ranges.size.toDouble() + + fun map(value: Double): Double { + if (value <= ranges.first().start) { + return 0.0 + } else if (value >= ranges.last().end) { + return 1.0 + } + + var i = 0.0 + + for (range in ranges) { + if (value in range) { + return i + range.determine(value) * step + } else { + i += step + } + } + + return i + } + + fun unmap(t: Double): Double { + if (t <= 0.0) { + return ranges.first().start + } else if (t >= 1.0) { + return ranges.last().end + } + + val unmap = t / step + val range = ranges[unmap.toInt()] + return interpolation.interpolate(unmap % 1.0, range.start, range.end) + } + } + + fun evaluate(x: Double, y: Double): Double { + var xT = 0.0 + + if (xRanges.size == 1) { + xT = xRanges[0].map(x) + } else { + var hit = false + + for (i in 1 until xRanges.size) { + val a = xRanges[i - 1] + val b = xRanges[i] + + if (x in a.edge .. b.edge) { + xT = interpolation.interpolate((x - a.edge) / (b.edge - a.edge), a.map(x), b.map(x)) + hit = true + break + } + } + + if (!hit) { + xT = xRanges.last().map(x) + } + } + + if (yRanges.size == 1) { + return yRanges[0].unmap(xT) + } else { + for (i in 1 until yRanges.size) { + val a = yRanges[i - 1] + val b = yRanges[i] + + if (y in a.edge .. b.edge) { + return interpolation.interpolate((y - a.edge) / (b.edge - a.edge), a.unmap(xT), b.unmap(xT)) + } + } + + return yRanges.last().unmap(xT) + } + } + + companion object : TypeAdapterFactory { + override fun create(gson: Gson, type: TypeToken): TypeAdapter? { + if (type.rawType == Json2Function::class.java) { + return object : TypeAdapter() { + val elements = gson.getAdapter(JsonArray::class.java) + + override fun write(out: JsonWriter, value: Json2Function?) { + TODO("Not yet implemented") + } + + override fun read(reader: JsonReader): Json2Function? { + if (reader.peek() == JsonToken.NULL) + return null + + reader.beginArray() + + val interpolation = JsonFunction.INTERPOLATION_ADAPTER.read(reader) ?: throw JsonSyntaxException("Missing interpolation") + val constraint = JsonFunction.CONSTRAINT_ADAPTER.read(reader) ?: throw JsonSyntaxException("Missing constraint") + + val xRanges = ArrayList() + val yRanges = ArrayList() + + val elements = elements.read(reader) + + for ((i, row) in elements.withIndex()) { + if (row !is JsonArray) { + throw JsonSyntaxException("Invalid function ranges at row $i") + } + + if (row.size() < 2) { + throw JsonSyntaxException("Row at $i should have at least 2 elements") + } + + val edge = row[0].asDouble + + if (row[1] is JsonArray) { + val ySource = row[1].asJsonArray + + if (ySource.size() < 2) { + throw JsonSyntaxException("Y ranges at row $i should have at least 2 elements") + } + + val ranges = ImmutableList.Builder() + var prev = ySource[0].asDouble + + for (elem in 1 until ySource.size()) { + val v = ySource[elem].asDouble + ranges.add(DoubleRange(prev, v)) + prev = v + } + + yRanges.add(Ranges(interpolation, edge, ranges.build())) + } else { + if (row.size() < 3) { + throw JsonSyntaxException("Row at $i should have at least 3 elements") + } + + val ranges = ImmutableList.Builder() + var prev = row[1].asDouble + + for (elem in 2 until row.size()) { + val v = row[elem].asDouble + ranges.add(DoubleRange(prev, v)) + prev = v + } + + xRanges.add(Ranges(interpolation, edge, ranges.build())) + } + } + + reader.endArray() + + if (xRanges.isEmpty()) { + throw JsonSyntaxException("No X ranges") + } + + if (yRanges.isEmpty()) { + throw JsonSyntaxException("No Y ranges") + } + + val size = xRanges.first().ranges.size + var broken = xRanges.firstOrNull { it.ranges.size != size } + + if (broken != null) { + throw JsonSyntaxException("One or more of X ranges are having different size (found ${broken.ranges.size}, expected $size)") + } + + broken = yRanges.firstOrNull { it.ranges.size != size } + + if (broken != null) { + throw JsonSyntaxException("One or more of Y ranges are having different size (found ${broken.ranges.size}, expected $size)") + } + + return Json2Function(interpolation, constraint, xRanges, yRanges) + } + } as TypeAdapter + } + + return null + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/io/ImageData.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/io/ImageData.kt new file mode 100644 index 00000000..91ea81f8 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/io/ImageData.kt @@ -0,0 +1,54 @@ +package ru.dbotthepony.kstarbound.io + +import org.lwjgl.stb.STBImage +import org.lwjgl.system.MemoryUtil.memAddress +import ru.dbotthepony.kvector.vector.ndouble.Vector2d +import ru.dbotthepony.kvector.vector.nint.Vector2i +import java.lang.ref.Cleaner +import java.nio.ByteBuffer + +private val cleaner = Cleaner.create { Thread(it, "STB Image Cleaner") } + +class ImageData(val data: ByteBuffer, val width: Int, val height: Int, val amountOfChannels: Int) { + init { + val address = memAddress(data) + cleaner.register(data) { STBImage.nstbi_image_free(address) } + + check(width >= 0) { "Invalid width $width" } + check(height >= 0) { "Invalid height $height" } + check(amountOfChannels in 1 .. 4) { "Unknown number of channels $amountOfChannels" } + } + + operator fun get(x: Int, y: Int): Int { + require(x in 0 until width) { "X out of bounds: $x" } + require(y in 0 until height) { "Y out of bounds: $y" } + + val offset = y * width * amountOfChannels + x * amountOfChannels + + when (amountOfChannels) { + 4 -> return data[offset].toInt() or + data[offset + 1].toInt().shl(8) or + data[offset + 2].toInt().shl(16) or + data[offset + 3].toInt().shl(24) + + 3 -> return data[offset].toInt() or + data[offset + 1].toInt().shl(8) or + data[offset + 2].toInt().shl(16) + + 2 -> return data[offset].toInt() or + data[offset + 1].toInt().shl(8) + + 1 -> return data[offset].toInt() + + else -> throw IllegalStateException() + } + } + + fun worldSpaces(pos: Vector2d, spaceScan: Double, flip: Boolean): List { + when (amountOfChannels) { + 3 -> TODO() + 4 -> TODO() + else -> throw IllegalStateException("Can not check world space taken by image with $amountOfChannels color channels") + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/io/json/InternedJsonElementAdapter.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/io/json/InternedJsonElementAdapter.kt index 5dcd1f02..3529a7dc 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/io/json/InternedJsonElementAdapter.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/io/json/InternedJsonElementAdapter.kt @@ -24,24 +24,46 @@ class InternedJsonElementAdapter(val stringInterner: Interner) : TypeAda JsonToken.NUMBER -> JsonPrimitive(LazilyParsedNumber(`in`.nextString())) JsonToken.BOOLEAN -> if (`in`.nextBoolean()) TRUE else FALSE JsonToken.NULL -> JsonNull.INSTANCE - JsonToken.BEGIN_ARRAY -> { - val output = JsonArray() - `in`.beginArray() - while (`in`.hasNext()) { output.add(read(`in`)) } - `in`.endArray() - output - } - JsonToken.BEGIN_OBJECT -> { - val output = JsonObject() - `in`.beginObject() - while (`in`.hasNext()) { output.add(stringInterner.intern(`in`.nextName()), read(`in`)) } - `in`.endObject() - output - } + JsonToken.BEGIN_ARRAY -> arrays.read(`in`) + JsonToken.BEGIN_OBJECT -> objects.read(`in`) else -> throw IllegalArgumentException(p.toString()) } } + val objects = object : TypeAdapter() { + override fun write(out: JsonWriter, value: JsonObject?) { + return TypeAdapters.JSON_ELEMENT.write(out, value) + } + + override fun read(`in`: JsonReader): JsonObject? { + if (`in`.peek() == JsonToken.NULL) + return null + + val output = JsonObject() + `in`.beginObject() + while (`in`.hasNext()) { output.add(stringInterner.intern(`in`.nextName()), this@InternedJsonElementAdapter.read(`in`)) } + `in`.endObject() + return output + } + } + + val arrays = object : TypeAdapter() { + override fun write(out: JsonWriter, value: JsonArray?) { + return TypeAdapters.JSON_ELEMENT.write(out, value) + } + + override fun read(`in`: JsonReader): JsonArray? { + if (`in`.peek() == JsonToken.NULL) + return null + + val output = JsonArray() + `in`.beginArray() + while (`in`.hasNext()) { output.add(this@InternedJsonElementAdapter.read(`in`)) } + `in`.endArray() + return output + } + } + companion object { val TRUE = JsonPrimitive(true) val FALSE = JsonPrimitive(false) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaState.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaState.kt index 472c0aa2..6464e3f7 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaState.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaState.kt @@ -526,6 +526,15 @@ class LuaState private constructor(private val pointer: Pointer, val stringInter if (position > this.top) return null return this.getBoolOrNil(position) } + + fun push() = this@LuaState.push() + fun push(value: Int) = this@LuaState.push(value) + fun push(value: Long) = this@LuaState.push(value) + fun push(value: Double) = this@LuaState.push(value) + fun push(value: Float) = this@LuaState.push(value) + fun push(value: Boolean) = this@LuaState.push(value) + fun push(value: String?) = this@LuaState.push(value) + fun push(value: JsonElement?) = this@LuaState.push(value) } /** diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Scripts.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Scripts.kt index f2389141..83b2d666 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Scripts.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Scripts.kt @@ -13,7 +13,7 @@ private val messageHandlerLua by lazy { loadInternalScript("message_handler") } private val configLua by lazy { loadInternalScript("config") } fun LuaState.exposeConfig(config: JsonElement) { - load(configLua, "starbound.jar!/scripts/config.lua") + load(configLua, "@starbound.jar!/scripts/config.lua") call() loadGlobal("config") @@ -30,7 +30,7 @@ fun LuaState.exposeConfig(config: JsonElement) { class MessageHandler(val lua: LuaState) { init { - lua.load(messageHandlerLua, "starbound.jar!/scripts/message_handler.lua") + lua.load(messageHandlerLua, "@starbound.jar!/scripts/message_handler.lua") lua.call() lua.loadGlobal("message") diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/player/Avatar.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/player/Avatar.kt index 2cb933c2..a4e7bb50 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/player/Avatar.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/player/Avatar.kt @@ -196,14 +196,14 @@ class Avatar(val starbound: Starbound, val uniqueId: UUID) { * Triggers an immediate cleanup of the player's inventory, removing item stacks with 0 quantity. May rarely be required in special cases of making several sequential modifications to the player's inventory within a single tick. */ fun cleanupItems() { - + TODO() } /** * Adds the specified item to the player's inventory. */ fun giveItem(descriptor: ItemDescriptor) { - + TODO() } /** @@ -297,7 +297,7 @@ class Avatar(val starbound: Starbound, val uniqueId: UUID) { } } - fun expose(lua: LuaState) { + fun pushLuaAPI(lua: LuaState) { lua.load(playerLua) lua.pushTable() diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/player/QuestInstance.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/player/QuestInstance.kt index 432a2a52..165a91ac 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/player/QuestInstance.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/player/QuestInstance.kt @@ -120,8 +120,8 @@ class QuestInstance( lua.pop() - avatar.starbound.expose(lua) - avatar.expose(lua) + avatar.starbound.pushLuaAPI(lua) + avatar.pushLuaAPI(lua) lua.exposeConfig(template.scriptConfig) } @@ -170,7 +170,7 @@ class QuestInstance( } try { - lua.load(script.readToString(), template.script.fullPath) + lua.load(script.readToString(), "@" + template.script.fullPath) } catch(err: Throwable) { LOGGER.error("Error loading Lua code for quest ${descriptor.questId}", err) return false diff --git a/src/test/java/ru/dbotthepony/kstarbound/test/Json2FunctionsTest.java b/src/test/java/ru/dbotthepony/kstarbound/test/Json2FunctionsTest.java new file mode 100644 index 00000000..27eb3a85 --- /dev/null +++ b/src/test/java/ru/dbotthepony/kstarbound/test/Json2FunctionsTest.java @@ -0,0 +1,1457 @@ +package ru.dbotthepony.kstarbound.test; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import ru.dbotthepony.kstarbound.Starbound; +import ru.dbotthepony.kstarbound.defs.Json2Function; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public final class Json2FunctionsTest { + private final double[] test2FunctionData = { + 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 5.000000, + 0.000000, 0.000000, 10.000000, + 0.000000, 0.000000, 15.000000, + 0.000000, 0.000000, 20.000000, + 0.000000, 0.000000, 25.000000, + 0.000000, 0.000000, 30.000000, + 5.000000, 5.000000, 0.000000, + 4.750000, 5.000000, 5.000000, + 4.500000, 5.000000, 10.000000, + 4.250000, 5.000000, 15.000000, + 4.000000, 5.000000, 20.000000, + 3.750000, 5.000000, 25.000000, + 3.500000, 5.000000, 30.000000, + 10.000000, 10.000000, 0.000000, + 9.500000, 10.000000, 5.000000, + 9.000000, 10.000000, 10.000000, + 8.500000, 10.000000, 15.000000, + 8.000000, 10.000000, 20.000000, + 7.500000, 10.000000, 25.000000, + 7.000000, 10.000000, 30.000000, + 15.000000, 15.000000, 0.000000, + 14.250000, 15.000000, 5.000000, + 13.500000, 15.000000, 10.000000, + 12.750000, 15.000000, 15.000000, + 12.000000, 15.000000, 20.000000, + 11.250000, 15.000000, 25.000000, + 10.500000, 15.000000, 30.000000, + 20.000000, 20.000000, 0.000000, + 19.000000, 20.000000, 5.000000, + 18.000000, 20.000000, 10.000000, + 17.000000, 20.000000, 15.000000, + 16.000000, 20.000000, 20.000000, + 15.000000, 20.000000, 25.000000, + 14.000000, 20.000000, 30.000000, + 25.000000, 25.000000, 0.000000, + 23.750000, 25.000000, 5.000000, + 22.500000, 25.000000, 10.000000, + 21.250000, 25.000000, 15.000000, + 20.000000, 25.000000, 20.000000, + 18.750000, 25.000000, 25.000000, + 17.500000, 25.000000, 30.000000, + 30.000000, 30.000000, 0.000000, + 28.500000, 30.000000, 5.000000, + 27.000000, 30.000000, 10.000000, + 25.500000, 30.000000, 15.000000, + 24.000000, 30.000000, 20.000000, + 22.500000, 30.000000, 25.000000, + 21.000000, 30.000000, 30.000000, + 35.000000, 35.000000, 0.000000, + 33.250000, 35.000000, 5.000000, + 31.500000, 35.000000, 10.000000, + 29.750000, 35.000000, 15.000000, + 28.000000, 35.000000, 20.000000, + 26.250000, 35.000000, 25.000000, + 24.500000, 35.000000, 30.000000, + 40.000000, 40.000000, 0.000000, + 38.000000, 40.000000, 5.000000, + 36.000000, 40.000000, 10.000000, + 34.000000, 40.000000, 15.000000, + 32.000000, 40.000000, 20.000000, + 30.000000, 40.000000, 25.000000, + 28.000000, 40.000000, 30.000000, + 45.000000, 45.000000, 0.000000, + 42.750000, 45.000000, 5.000000, + 40.500000, 45.000000, 10.000000, + 38.250000, 45.000000, 15.000000, + 36.000000, 45.000000, 20.000000, + 33.750000, 45.000000, 25.000000, + 31.500000, 45.000000, 30.000000, + 50.000000, 50.000000, 0.000000, + 47.500000, 50.000000, 5.000000, + 45.000000, 50.000000, 10.000000, + 42.500000, 50.000000, 15.000000, + 40.000000, 50.000000, 20.000000, + 37.500000, 50.000000, 25.000000, + 35.000000, 50.000000, 30.000000, + 55.000000, 55.000000, 0.000000, + 52.250000, 55.000000, 5.000000, + 49.500000, 55.000000, 10.000000, + 46.750000, 55.000000, 15.000000, + 44.000000, 55.000000, 20.000000, + 41.250000, 55.000000, 25.000000, + 38.500000, 55.000000, 30.000000, + 60.000000, 60.000000, 0.000000, + 57.000000, 60.000000, 5.000000, + 54.000000, 60.000000, 10.000000, + 51.000000, 60.000000, 15.000000, + 48.000000, 60.000000, 20.000000, + 45.000000, 60.000000, 25.000000, + 42.000000, 60.000000, 30.000000, + 65.000000, 65.000000, 0.000000, + 61.750000, 65.000000, 5.000000, + 58.500000, 65.000000, 10.000000, + 55.250000, 65.000000, 15.000000, + 52.000000, 65.000000, 20.000000, + 48.750000, 65.000000, 25.000000, + 45.500000, 65.000000, 30.000000, + 70.000000, 70.000000, 0.000000, + 66.500000, 70.000000, 5.000000, + 63.000000, 70.000000, 10.000000, + 59.500000, 70.000000, 15.000000, + 56.000000, 70.000000, 20.000000, + 52.500000, 70.000000, 25.000000, + 49.000000, 70.000000, 30.000000, + 75.000000, 75.000000, 0.000000, + 71.250000, 75.000000, 5.000000, + 67.500000, 75.000000, 10.000000, + 63.750000, 75.000000, 15.000000, + 60.000000, 75.000000, 20.000000, + 56.250000, 75.000000, 25.000000, + 52.500000, 75.000000, 30.000000, + 80.000000, 80.000000, 0.000000, + 76.000000, 80.000000, 5.000000, + 72.000000, 80.000000, 10.000000, + 68.000000, 80.000000, 15.000000, + 64.000000, 80.000000, 20.000000, + 60.000000, 80.000000, 25.000000, + 56.000000, 80.000000, 30.000000, + 85.000000, 85.000000, 0.000000, + 80.750000, 85.000000, 5.000000, + 76.500000, 85.000000, 10.000000, + 72.250000, 85.000000, 15.000000, + 68.000000, 85.000000, 20.000000, + 63.750000, 85.000000, 25.000000, + 59.500000, 85.000000, 30.000000, + 90.000000, 90.000000, 0.000000, + 85.500000, 90.000000, 5.000000, + 81.000000, 90.000000, 10.000000, + 76.500000, 90.000000, 15.000000, + 72.000000, 90.000000, 20.000000, + 67.500000, 90.000000, 25.000000, + 63.000000, 90.000000, 30.000000, + 95.000000, 95.000000, 0.000000, + 90.250000, 95.000000, 5.000000, + 85.500000, 95.000000, 10.000000, + 80.750000, 95.000000, 15.000000, + 76.000000, 95.000000, 20.000000, + 71.250000, 95.000000, 25.000000, + 66.500000, 95.000000, 30.000000, + 100.000000, 100.000000, 0.000000, + 95.000000, 100.000000, 5.000000, + 90.000000, 100.000000, 10.000000, + 85.000000, 100.000000, 15.000000, + 80.000000, 100.000000, 20.000000, + 75.000000, 100.000000, 25.000000, + 70.000000, 100.000000, 30.000000, + 105.000000, 105.000000, 0.000000, + 99.750000, 105.000000, 5.000000, + 94.500000, 105.000000, 10.000000, + 89.250000, 105.000000, 15.000000, + 84.000000, 105.000000, 20.000000, + 78.750000, 105.000000, 25.000000, + 73.500000, 105.000000, 30.000000, + 110.000000, 110.000000, 0.000000, + 104.500000, 110.000000, 5.000000, + 99.000000, 110.000000, 10.000000, + 93.500000, 110.000000, 15.000000, + 88.000000, 110.000000, 20.000000, + 82.500000, 110.000000, 25.000000, + 77.000000, 110.000000, 30.000000, + 115.000000, 115.000000, 0.000000, + 109.250000, 115.000000, 5.000000, + 103.500000, 115.000000, 10.000000, + 97.750000, 115.000000, 15.000000, + 92.000000, 115.000000, 20.000000, + 86.250000, 115.000000, 25.000000, + 80.500000, 115.000000, 30.000000, + 120.000000, 120.000000, 0.000000, + 114.000000, 120.000000, 5.000000, + 108.000000, 120.000000, 10.000000, + 102.000000, 120.000000, 15.000000, + 96.000000, 120.000000, 20.000000, + 90.000000, 120.000000, 25.000000, + 84.000000, 120.000000, 30.000000, + 125.000000, 125.000000, 0.000000, + 118.750000, 125.000000, 5.000000, + 112.500000, 125.000000, 10.000000, + 106.250000, 125.000000, 15.000000, + 100.000000, 125.000000, 20.000000, + 93.750000, 125.000000, 25.000000, + 87.500000, 125.000000, 30.000000, + 130.000000, 130.000000, 0.000000, + 123.500000, 130.000000, 5.000000, + 117.000000, 130.000000, 10.000000, + 110.500000, 130.000000, 15.000000, + 104.000000, 130.000000, 20.000000, + 97.500000, 130.000000, 25.000000, + 91.000000, 130.000000, 30.000000, + 135.000000, 135.000000, 0.000000, + 128.250000, 135.000000, 5.000000, + 121.500000, 135.000000, 10.000000, + 114.750000, 135.000000, 15.000000, + 108.000000, 135.000000, 20.000000, + 101.250000, 135.000000, 25.000000, + 94.500000, 135.000000, 30.000000, + 140.000000, 140.000000, 0.000000, + 133.000000, 140.000000, 5.000000, + 126.000000, 140.000000, 10.000000, + 119.000000, 140.000000, 15.000000, + 112.000000, 140.000000, 20.000000, + 105.000000, 140.000000, 25.000000, + 98.000000, 140.000000, 30.000000, + 145.000000, 145.000000, 0.000000, + 137.750000, 145.000000, 5.000000, + 130.500000, 145.000000, 10.000000, + 123.250000, 145.000000, 15.000000, + 116.000000, 145.000000, 20.000000, + 108.750000, 145.000000, 25.000000, + 101.500000, 145.000000, 30.000000, + 150.000000, 150.000000, 0.000000, + 142.500000, 150.000000, 5.000000, + 135.000000, 150.000000, 10.000000, + 127.500000, 150.000000, 15.000000, + 120.000000, 150.000000, 20.000000, + 112.500000, 150.000000, 25.000000, + 105.000000, 150.000000, 30.000000, + 155.000000, 155.000000, 0.000000, + 147.250000, 155.000000, 5.000000, + 139.500000, 155.000000, 10.000000, + 131.750000, 155.000000, 15.000000, + 124.000000, 155.000000, 20.000000, + 116.250000, 155.000000, 25.000000, + 108.500000, 155.000000, 30.000000, + 160.000000, 160.000000, 0.000000, + 152.000000, 160.000000, 5.000000, + 144.000000, 160.000000, 10.000000, + 136.000000, 160.000000, 15.000000, + 128.000000, 160.000000, 20.000000, + 120.000000, 160.000000, 25.000000, + 112.000000, 160.000000, 30.000000, + 165.000000, 165.000000, 0.000000, + 156.750000, 165.000000, 5.000000, + 148.500000, 165.000000, 10.000000, + 140.250000, 165.000000, 15.000000, + 132.000000, 165.000000, 20.000000, + 123.750000, 165.000000, 25.000000, + 115.500000, 165.000000, 30.000000, + 170.000000, 170.000000, 0.000000, + 161.500000, 170.000000, 5.000000, + 153.000000, 170.000000, 10.000000, + 144.500000, 170.000000, 15.000000, + 136.000000, 170.000000, 20.000000, + 127.500000, 170.000000, 25.000000, + 119.000000, 170.000000, 30.000000, + 175.000000, 175.000000, 0.000000, + 166.250000, 175.000000, 5.000000, + 157.500000, 175.000000, 10.000000, + 148.750000, 175.000000, 15.000000, + 140.000000, 175.000000, 20.000000, + 131.250000, 175.000000, 25.000000, + 122.500000, 175.000000, 30.000000, + 180.000000, 180.000000, 0.000000, + 171.000000, 180.000000, 5.000000, + 162.000000, 180.000000, 10.000000, + 153.000000, 180.000000, 15.000000, + 144.000000, 180.000000, 20.000000, + 135.000000, 180.000000, 25.000000, + 126.000000, 180.000000, 30.000000, + 185.000000, 185.000000, 0.000000, + 175.750000, 185.000000, 5.000000, + 166.500000, 185.000000, 10.000000, + 157.250000, 185.000000, 15.000000, + 148.000000, 185.000000, 20.000000, + 138.750000, 185.000000, 25.000000, + 129.500000, 185.000000, 30.000000, + 190.000000, 190.000000, 0.000000, + 180.500000, 190.000000, 5.000000, + 171.000000, 190.000000, 10.000000, + 161.500000, 190.000000, 15.000000, + 152.000000, 190.000000, 20.000000, + 142.500000, 190.000000, 25.000000, + 133.000000, 190.000000, 30.000000, + 195.000000, 195.000000, 0.000000, + 185.250000, 195.000000, 5.000000, + 175.500000, 195.000000, 10.000000, + 165.750000, 195.000000, 15.000000, + 156.000000, 195.000000, 20.000000, + 146.250000, 195.000000, 25.000000, + 136.500000, 195.000000, 30.000000, + 200.000000, 200.000000, 0.000000, + 190.000000, 200.000000, 5.000000, + 180.000000, 200.000000, 10.000000, + 170.000000, 200.000000, 15.000000, + 160.000000, 200.000000, 20.000000, + 150.000000, 200.000000, 25.000000, + 140.000000, 200.000000, 30.000000, + 205.000000, 205.000000, 0.000000, + 194.750000, 205.000000, 5.000000, + 184.500000, 205.000000, 10.000000, + 174.250000, 205.000000, 15.000000, + 164.000000, 205.000000, 20.000000, + 153.750000, 205.000000, 25.000000, + 143.500000, 205.000000, 30.000000, + 210.000000, 210.000000, 0.000000, + 199.500000, 210.000000, 5.000000, + 189.000000, 210.000000, 10.000000, + 178.500000, 210.000000, 15.000000, + 168.000000, 210.000000, 20.000000, + 157.500000, 210.000000, 25.000000, + 147.000000, 210.000000, 30.000000, + 215.000000, 215.000000, 0.000000, + 204.250000, 215.000000, 5.000000, + 193.500000, 215.000000, 10.000000, + 182.750000, 215.000000, 15.000000, + 172.000000, 215.000000, 20.000000, + 161.250000, 215.000000, 25.000000, + 150.500000, 215.000000, 30.000000, + 220.000000, 220.000000, 0.000000, + 209.000000, 220.000000, 5.000000, + 198.000000, 220.000000, 10.000000, + 187.000000, 220.000000, 15.000000, + 176.000000, 220.000000, 20.000000, + 165.000000, 220.000000, 25.000000, + 154.000000, 220.000000, 30.000000, + 225.000000, 225.000000, 0.000000, + 213.750000, 225.000000, 5.000000, + 202.500000, 225.000000, 10.000000, + 191.250000, 225.000000, 15.000000, + 180.000000, 225.000000, 20.000000, + 168.750000, 225.000000, 25.000000, + 157.500000, 225.000000, 30.000000, + 230.000000, 230.000000, 0.000000, + 218.500000, 230.000000, 5.000000, + 207.000000, 230.000000, 10.000000, + 195.500000, 230.000000, 15.000000, + 184.000000, 230.000000, 20.000000, + 172.500000, 230.000000, 25.000000, + 161.000000, 230.000000, 30.000000, + 235.000000, 235.000000, 0.000000, + 223.250000, 235.000000, 5.000000, + 211.500000, 235.000000, 10.000000, + 199.750000, 235.000000, 15.000000, + 188.000000, 235.000000, 20.000000, + 176.250000, 235.000000, 25.000000, + 164.500000, 235.000000, 30.000000, + 240.000000, 240.000000, 0.000000, + 228.000000, 240.000000, 5.000000, + 216.000000, 240.000000, 10.000000, + 204.000000, 240.000000, 15.000000, + 192.000000, 240.000000, 20.000000, + 180.000000, 240.000000, 25.000000, + 168.000000, 240.000000, 30.000000, + 245.000000, 245.000000, 0.000000, + 232.750000, 245.000000, 5.000000, + 220.500000, 245.000000, 10.000000, + 208.250000, 245.000000, 15.000000, + 196.000000, 245.000000, 20.000000, + 183.750000, 245.000000, 25.000000, + 171.500000, 245.000000, 30.000000, + 250.000000, 250.000000, 0.000000, + 237.500000, 250.000000, 5.000000, + 225.000000, 250.000000, 10.000000, + 212.500000, 250.000000, 15.000000, + 200.000000, 250.000000, 20.000000, + 187.500000, 250.000000, 25.000000, + 175.000000, 250.000000, 30.000000, + 255.000000, 255.000000, 0.000000, + 242.250000, 255.000000, 5.000000, + 229.500000, 255.000000, 10.000000, + 216.750000, 255.000000, 15.000000, + 204.000000, 255.000000, 20.000000, + 191.250000, 255.000000, 25.000000, + 178.500000, 255.000000, 30.000000, + 260.000000, 260.000000, 0.000000, + 247.000000, 260.000000, 5.000000, + 234.000000, 260.000000, 10.000000, + 221.000000, 260.000000, 15.000000, + 208.000000, 260.000000, 20.000000, + 195.000000, 260.000000, 25.000000, + 182.000000, 260.000000, 30.000000, + 265.000000, 265.000000, 0.000000, + 251.750000, 265.000000, 5.000000, + 238.500000, 265.000000, 10.000000, + 225.250000, 265.000000, 15.000000, + 212.000000, 265.000000, 20.000000, + 198.750000, 265.000000, 25.000000, + 185.500000, 265.000000, 30.000000, + 270.000000, 270.000000, 0.000000, + 256.500000, 270.000000, 5.000000, + 243.000000, 270.000000, 10.000000, + 229.500000, 270.000000, 15.000000, + 216.000000, 270.000000, 20.000000, + 202.500000, 270.000000, 25.000000, + 189.000000, 270.000000, 30.000000, + 275.000000, 275.000000, 0.000000, + 261.250000, 275.000000, 5.000000, + 247.500000, 275.000000, 10.000000, + 233.750000, 275.000000, 15.000000, + 220.000000, 275.000000, 20.000000, + 206.250000, 275.000000, 25.000000, + 192.500000, 275.000000, 30.000000, + 280.000000, 280.000000, 0.000000, + 266.000000, 280.000000, 5.000000, + 252.000000, 280.000000, 10.000000, + 238.000000, 280.000000, 15.000000, + 224.000000, 280.000000, 20.000000, + 210.000000, 280.000000, 25.000000, + 196.000000, 280.000000, 30.000000, + 285.000000, 285.000000, 0.000000, + 270.750000, 285.000000, 5.000000, + 256.500000, 285.000000, 10.000000, + 242.250000, 285.000000, 15.000000, + 228.000000, 285.000000, 20.000000, + 213.750000, 285.000000, 25.000000, + 199.500000, 285.000000, 30.000000, + 290.000000, 290.000000, 0.000000, + 275.500000, 290.000000, 5.000000, + 261.000000, 290.000000, 10.000000, + 246.500000, 290.000000, 15.000000, + 232.000000, 290.000000, 20.000000, + 217.500000, 290.000000, 25.000000, + 203.000000, 290.000000, 30.000000, + 295.000000, 295.000000, 0.000000, + 280.250000, 295.000000, 5.000000, + 265.500000, 295.000000, 10.000000, + 250.750000, 295.000000, 15.000000, + 236.000000, 295.000000, 20.000000, + 221.250000, 295.000000, 25.000000, + 206.500000, 295.000000, 30.000000, + 300.000000, 300.000000, 0.000000, + 285.000000, 300.000000, 5.000000, + 270.000000, 300.000000, 10.000000, + 255.000000, 300.000000, 15.000000, + 240.000000, 300.000000, 20.000000, + 225.000000, 300.000000, 25.000000, + 210.000000, 300.000000, 30.000000, + 305.000000, 305.000000, 0.000000, + 289.750000, 305.000000, 5.000000, + 274.500000, 305.000000, 10.000000, + 259.250000, 305.000000, 15.000000, + 244.000000, 305.000000, 20.000000, + 228.750000, 305.000000, 25.000000, + 213.500000, 305.000000, 30.000000, + 310.000000, 310.000000, 0.000000, + 294.500000, 310.000000, 5.000000, + 279.000000, 310.000000, 10.000000, + 263.500000, 310.000000, 15.000000, + 248.000000, 310.000000, 20.000000, + 232.500000, 310.000000, 25.000000, + 217.000000, 310.000000, 30.000000, + 315.000000, 315.000000, 0.000000, + 299.250000, 315.000000, 5.000000, + 283.500000, 315.000000, 10.000000, + 267.750000, 315.000000, 15.000000, + 252.000000, 315.000000, 20.000000, + 236.250000, 315.000000, 25.000000, + 220.500000, 315.000000, 30.000000, + 320.000000, 320.000000, 0.000000, + 304.000000, 320.000000, 5.000000, + 288.000000, 320.000000, 10.000000, + 272.000000, 320.000000, 15.000000, + 256.000000, 320.000000, 20.000000, + 240.000000, 320.000000, 25.000000, + 224.000000, 320.000000, 30.000000, + 325.000000, 325.000000, 0.000000, + 308.750000, 325.000000, 5.000000, + 292.500000, 325.000000, 10.000000, + 276.250000, 325.000000, 15.000000, + 260.000000, 325.000000, 20.000000, + 243.750000, 325.000000, 25.000000, + 227.500000, 325.000000, 30.000000, + 330.000000, 330.000000, 0.000000, + 313.500000, 330.000000, 5.000000, + 297.000000, 330.000000, 10.000000, + 280.500000, 330.000000, 15.000000, + 264.000000, 330.000000, 20.000000, + 247.500000, 330.000000, 25.000000, + 231.000000, 330.000000, 30.000000, + 335.000000, 335.000000, 0.000000, + 318.250000, 335.000000, 5.000000, + 301.500000, 335.000000, 10.000000, + 284.750000, 335.000000, 15.000000, + 268.000000, 335.000000, 20.000000, + 251.250000, 335.000000, 25.000000, + 234.500000, 335.000000, 30.000000, + 340.000000, 340.000000, 0.000000, + 323.000000, 340.000000, 5.000000, + 306.000000, 340.000000, 10.000000, + 289.000000, 340.000000, 15.000000, + 272.000000, 340.000000, 20.000000, + 255.000000, 340.000000, 25.000000, + 238.000000, 340.000000, 30.000000, + 345.000000, 345.000000, 0.000000, + 327.750000, 345.000000, 5.000000, + 310.500000, 345.000000, 10.000000, + 293.250000, 345.000000, 15.000000, + 276.000000, 345.000000, 20.000000, + 258.750000, 345.000000, 25.000000, + 241.500000, 345.000000, 30.000000, + 350.000000, 350.000000, 0.000000, + 332.500000, 350.000000, 5.000000, + 315.000000, 350.000000, 10.000000, + 297.500000, 350.000000, 15.000000, + 280.000000, 350.000000, 20.000000, + 262.500000, 350.000000, 25.000000, + 245.000000, 350.000000, 30.000000, + 355.000000, 355.000000, 0.000000, + 337.250000, 355.000000, 5.000000, + 319.500000, 355.000000, 10.000000, + 301.750000, 355.000000, 15.000000, + 284.000000, 355.000000, 20.000000, + 266.250000, 355.000000, 25.000000, + 248.500000, 355.000000, 30.000000, + 360.000000, 360.000000, 0.000000, + 342.000000, 360.000000, 5.000000, + 324.000000, 360.000000, 10.000000, + 306.000000, 360.000000, 15.000000, + 288.000000, 360.000000, 20.000000, + 270.000000, 360.000000, 25.000000, + 252.000000, 360.000000, 30.000000, + 365.000000, 365.000000, 0.000000, + 346.750000, 365.000000, 5.000000, + 328.500000, 365.000000, 10.000000, + 310.250000, 365.000000, 15.000000, + 292.000000, 365.000000, 20.000000, + 273.750000, 365.000000, 25.000000, + 255.500000, 365.000000, 30.000000, + 370.000000, 370.000000, 0.000000, + 351.500000, 370.000000, 5.000000, + 333.000000, 370.000000, 10.000000, + 314.500000, 370.000000, 15.000000, + 296.000000, 370.000000, 20.000000, + 277.500000, 370.000000, 25.000000, + 259.000000, 370.000000, 30.000000, + 375.000000, 375.000000, 0.000000, + 356.250000, 375.000000, 5.000000, + 337.500000, 375.000000, 10.000000, + 318.750000, 375.000000, 15.000000, + 300.000000, 375.000000, 20.000000, + 281.250000, 375.000000, 25.000000, + 262.500000, 375.000000, 30.000000, + 380.000000, 380.000000, 0.000000, + 361.000000, 380.000000, 5.000000, + 342.000000, 380.000000, 10.000000, + 323.000000, 380.000000, 15.000000, + 304.000000, 380.000000, 20.000000, + 285.000000, 380.000000, 25.000000, + 266.000000, 380.000000, 30.000000, + 385.000000, 385.000000, 0.000000, + 365.750000, 385.000000, 5.000000, + 346.500000, 385.000000, 10.000000, + 327.250000, 385.000000, 15.000000, + 308.000000, 385.000000, 20.000000, + 288.750000, 385.000000, 25.000000, + 269.500000, 385.000000, 30.000000, + 390.000000, 390.000000, 0.000000, + 370.500000, 390.000000, 5.000000, + 351.000000, 390.000000, 10.000000, + 331.500000, 390.000000, 15.000000, + 312.000000, 390.000000, 20.000000, + 292.500000, 390.000000, 25.000000, + 273.000000, 390.000000, 30.000000, + 395.000000, 395.000000, 0.000000, + 375.250000, 395.000000, 5.000000, + 355.500000, 395.000000, 10.000000, + 335.750000, 395.000000, 15.000000, + 316.000000, 395.000000, 20.000000, + 296.250000, 395.000000, 25.000000, + 276.500000, 395.000000, 30.000000, + 400.000000, 400.000000, 0.000000, + 380.000000, 400.000000, 5.000000, + 360.000000, 400.000000, 10.000000, + 340.000000, 400.000000, 15.000000, + 320.000000, 400.000000, 20.000000, + 300.000000, 400.000000, 25.000000, + 280.000000, 400.000000, 30.000000, + 405.000000, 405.000000, 0.000000, + 384.750000, 405.000000, 5.000000, + 364.500000, 405.000000, 10.000000, + 344.250000, 405.000000, 15.000000, + 324.000000, 405.000000, 20.000000, + 303.750000, 405.000000, 25.000000, + 283.500000, 405.000000, 30.000000, + 410.000000, 410.000000, 0.000000, + 389.500000, 410.000000, 5.000000, + 369.000000, 410.000000, 10.000000, + 348.500000, 410.000000, 15.000000, + 328.000000, 410.000000, 20.000000, + 307.500000, 410.000000, 25.000000, + 287.000000, 410.000000, 30.000000, + 415.000000, 415.000000, 0.000000, + 394.250000, 415.000000, 5.000000, + 373.500000, 415.000000, 10.000000, + 352.750000, 415.000000, 15.000000, + 332.000000, 415.000000, 20.000000, + 311.250000, 415.000000, 25.000000, + 290.500000, 415.000000, 30.000000, + 420.000000, 420.000000, 0.000000, + 399.000000, 420.000000, 5.000000, + 378.000000, 420.000000, 10.000000, + 357.000000, 420.000000, 15.000000, + 336.000000, 420.000000, 20.000000, + 315.000000, 420.000000, 25.000000, + 294.000000, 420.000000, 30.000000, + 425.000000, 425.000000, 0.000000, + 403.750000, 425.000000, 5.000000, + 382.500000, 425.000000, 10.000000, + 361.250000, 425.000000, 15.000000, + 340.000000, 425.000000, 20.000000, + 318.750000, 425.000000, 25.000000, + 297.500000, 425.000000, 30.000000, + 430.000000, 430.000000, 0.000000, + 408.500000, 430.000000, 5.000000, + 387.000000, 430.000000, 10.000000, + 365.500000, 430.000000, 15.000000, + 344.000000, 430.000000, 20.000000, + 322.500000, 430.000000, 25.000000, + 301.000000, 430.000000, 30.000000, + 435.000000, 435.000000, 0.000000, + 413.250000, 435.000000, 5.000000, + 391.500000, 435.000000, 10.000000, + 369.750000, 435.000000, 15.000000, + 348.000000, 435.000000, 20.000000, + 326.250000, 435.000000, 25.000000, + 304.500000, 435.000000, 30.000000, + 440.000000, 440.000000, 0.000000, + 418.000000, 440.000000, 5.000000, + 396.000000, 440.000000, 10.000000, + 374.000000, 440.000000, 15.000000, + 352.000000, 440.000000, 20.000000, + 330.000000, 440.000000, 25.000000, + 308.000000, 440.000000, 30.000000, + 445.000000, 445.000000, 0.000000, + 422.750000, 445.000000, 5.000000, + 400.500000, 445.000000, 10.000000, + 378.250000, 445.000000, 15.000000, + 356.000000, 445.000000, 20.000000, + 333.750000, 445.000000, 25.000000, + 311.500000, 445.000000, 30.000000, + 450.000000, 450.000000, 0.000000, + 427.500000, 450.000000, 5.000000, + 405.000000, 450.000000, 10.000000, + 382.500000, 450.000000, 15.000000, + 360.000000, 450.000000, 20.000000, + 337.500000, 450.000000, 25.000000, + 315.000000, 450.000000, 30.000000, + 455.000000, 455.000000, 0.000000, + 432.250000, 455.000000, 5.000000, + 409.500000, 455.000000, 10.000000, + 386.750000, 455.000000, 15.000000, + 364.000000, 455.000000, 20.000000, + 341.250000, 455.000000, 25.000000, + 318.500000, 455.000000, 30.000000, + 460.000000, 460.000000, 0.000000, + 437.000000, 460.000000, 5.000000, + 414.000000, 460.000000, 10.000000, + 391.000000, 460.000000, 15.000000, + 368.000000, 460.000000, 20.000000, + 345.000000, 460.000000, 25.000000, + 322.000000, 460.000000, 30.000000, + 465.000000, 465.000000, 0.000000, + 441.750000, 465.000000, 5.000000, + 418.500000, 465.000000, 10.000000, + 395.250000, 465.000000, 15.000000, + 372.000000, 465.000000, 20.000000, + 348.750000, 465.000000, 25.000000, + 325.500000, 465.000000, 30.000000, + 470.000000, 470.000000, 0.000000, + 446.500000, 470.000000, 5.000000, + 423.000000, 470.000000, 10.000000, + 399.500000, 470.000000, 15.000000, + 376.000000, 470.000000, 20.000000, + 352.500000, 470.000000, 25.000000, + 329.000000, 470.000000, 30.000000, + 475.000000, 475.000000, 0.000000, + 451.250000, 475.000000, 5.000000, + 427.500000, 475.000000, 10.000000, + 403.750000, 475.000000, 15.000000, + 380.000000, 475.000000, 20.000000, + 356.250000, 475.000000, 25.000000, + 332.500000, 475.000000, 30.000000, + 480.000000, 480.000000, 0.000000, + 456.000000, 480.000000, 5.000000, + 432.000000, 480.000000, 10.000000, + 408.000000, 480.000000, 15.000000, + 384.000000, 480.000000, 20.000000, + 360.000000, 480.000000, 25.000000, + 336.000000, 480.000000, 30.000000, + 485.000000, 485.000000, 0.000000, + 460.750000, 485.000000, 5.000000, + 436.500000, 485.000000, 10.000000, + 412.250000, 485.000000, 15.000000, + 388.000000, 485.000000, 20.000000, + 363.750000, 485.000000, 25.000000, + 339.500000, 485.000000, 30.000000, + 490.000000, 490.000000, 0.000000, + 465.500000, 490.000000, 5.000000, + 441.000000, 490.000000, 10.000000, + 416.500000, 490.000000, 15.000000, + 392.000000, 490.000000, 20.000000, + 367.500000, 490.000000, 25.000000, + 343.000000, 490.000000, 30.000000, + 495.000000, 495.000000, 0.000000, + 470.250000, 495.000000, 5.000000, + 445.500000, 495.000000, 10.000000, + 420.750000, 495.000000, 15.000000, + 396.000000, 495.000000, 20.000000, + 371.250000, 495.000000, 25.000000, + 346.500000, 495.000000, 30.000000, + 500.000000, 500.000000, 0.000000, + 475.000000, 500.000000, 5.000000, + 450.000000, 500.000000, 10.000000, + 425.000000, 500.000000, 15.000000, + 400.000000, 500.000000, 20.000000, + 375.000000, 500.000000, 25.000000, + 350.000000, 500.000000, 30.000000, + 505.000000, 505.000000, 0.000000, + 479.750000, 505.000000, 5.000000, + 454.500000, 505.000000, 10.000000, + 429.250000, 505.000000, 15.000000, + 404.000000, 505.000000, 20.000000, + 378.750000, 505.000000, 25.000000, + 353.500000, 505.000000, 30.000000, + 510.000000, 510.000000, 0.000000, + 484.500000, 510.000000, 5.000000, + 459.000000, 510.000000, 10.000000, + 433.500000, 510.000000, 15.000000, + 408.000000, 510.000000, 20.000000, + 382.500000, 510.000000, 25.000000, + 357.000000, 510.000000, 30.000000, + 515.000000, 515.000000, 0.000000, + 489.250000, 515.000000, 5.000000, + 463.500000, 515.000000, 10.000000, + 437.750000, 515.000000, 15.000000, + 412.000000, 515.000000, 20.000000, + 386.250000, 515.000000, 25.000000, + 360.500000, 515.000000, 30.000000, + 520.000000, 520.000000, 0.000000, + 494.000000, 520.000000, 5.000000, + 468.000000, 520.000000, 10.000000, + 442.000000, 520.000000, 15.000000, + 416.000000, 520.000000, 20.000000, + 390.000000, 520.000000, 25.000000, + 364.000000, 520.000000, 30.000000, + 525.000000, 525.000000, 0.000000, + 498.750000, 525.000000, 5.000000, + 472.500000, 525.000000, 10.000000, + 446.250000, 525.000000, 15.000000, + 420.000000, 525.000000, 20.000000, + 393.750000, 525.000000, 25.000000, + 367.500000, 525.000000, 30.000000, + 530.000000, 530.000000, 0.000000, + 503.500000, 530.000000, 5.000000, + 477.000000, 530.000000, 10.000000, + 450.500000, 530.000000, 15.000000, + 424.000000, 530.000000, 20.000000, + 397.500000, 530.000000, 25.000000, + 371.000000, 530.000000, 30.000000, + 535.000000, 535.000000, 0.000000, + 508.250000, 535.000000, 5.000000, + 481.500000, 535.000000, 10.000000, + 454.750000, 535.000000, 15.000000, + 428.000000, 535.000000, 20.000000, + 401.250000, 535.000000, 25.000000, + 374.500000, 535.000000, 30.000000, + 540.000000, 540.000000, 0.000000, + 513.000000, 540.000000, 5.000000, + 486.000000, 540.000000, 10.000000, + 459.000000, 540.000000, 15.000000, + 432.000000, 540.000000, 20.000000, + 405.000000, 540.000000, 25.000000, + 378.000000, 540.000000, 30.000000, + 545.000000, 545.000000, 0.000000, + 517.750000, 545.000000, 5.000000, + 490.500000, 545.000000, 10.000000, + 463.250000, 545.000000, 15.000000, + 436.000000, 545.000000, 20.000000, + 408.750000, 545.000000, 25.000000, + 381.500000, 545.000000, 30.000000, + 550.000000, 550.000000, 0.000000, + 522.500000, 550.000000, 5.000000, + 495.000000, 550.000000, 10.000000, + 467.500000, 550.000000, 15.000000, + 440.000000, 550.000000, 20.000000, + 412.500000, 550.000000, 25.000000, + 385.000000, 550.000000, 30.000000, + 555.000000, 555.000000, 0.000000, + 527.250000, 555.000000, 5.000000, + 499.500000, 555.000000, 10.000000, + 471.750000, 555.000000, 15.000000, + 444.000000, 555.000000, 20.000000, + 416.250000, 555.000000, 25.000000, + 388.500000, 555.000000, 30.000000, + 560.000000, 560.000000, 0.000000, + 532.000000, 560.000000, 5.000000, + 504.000000, 560.000000, 10.000000, + 476.000000, 560.000000, 15.000000, + 448.000000, 560.000000, 20.000000, + 420.000000, 560.000000, 25.000000, + 392.000000, 560.000000, 30.000000, + 565.000000, 565.000000, 0.000000, + 536.750000, 565.000000, 5.000000, + 508.500000, 565.000000, 10.000000, + 480.250000, 565.000000, 15.000000, + 452.000000, 565.000000, 20.000000, + 423.750000, 565.000000, 25.000000, + 395.500000, 565.000000, 30.000000, + 570.000000, 570.000000, 0.000000, + 541.500000, 570.000000, 5.000000, + 513.000000, 570.000000, 10.000000, + 484.500000, 570.000000, 15.000000, + 456.000000, 570.000000, 20.000000, + 427.500000, 570.000000, 25.000000, + 399.000000, 570.000000, 30.000000, + 575.000000, 575.000000, 0.000000, + 546.250000, 575.000000, 5.000000, + 517.500000, 575.000000, 10.000000, + 488.750000, 575.000000, 15.000000, + 460.000000, 575.000000, 20.000000, + 431.250000, 575.000000, 25.000000, + 402.500000, 575.000000, 30.000000, + 580.000000, 580.000000, 0.000000, + 551.000000, 580.000000, 5.000000, + 522.000000, 580.000000, 10.000000, + 493.000000, 580.000000, 15.000000, + 464.000000, 580.000000, 20.000000, + 435.000000, 580.000000, 25.000000, + 406.000000, 580.000000, 30.000000, + 585.000000, 585.000000, 0.000000, + 555.750000, 585.000000, 5.000000, + 526.500000, 585.000000, 10.000000, + 497.250000, 585.000000, 15.000000, + 468.000000, 585.000000, 20.000000, + 438.750000, 585.000000, 25.000000, + 409.500000, 585.000000, 30.000000, + 590.000000, 590.000000, 0.000000, + 560.500000, 590.000000, 5.000000, + 531.000000, 590.000000, 10.000000, + 501.500000, 590.000000, 15.000000, + 472.000000, 590.000000, 20.000000, + 442.500000, 590.000000, 25.000000, + 413.000000, 590.000000, 30.000000, + 595.000000, 595.000000, 0.000000, + 565.250000, 595.000000, 5.000000, + 535.500000, 595.000000, 10.000000, + 505.750000, 595.000000, 15.000000, + 476.000000, 595.000000, 20.000000, + 446.250000, 595.000000, 25.000000, + 416.500000, 595.000000, 30.000000, + 600.000000, 600.000000, 0.000000, + 570.000000, 600.000000, 5.000000, + 540.000000, 600.000000, 10.000000, + 510.000000, 600.000000, 15.000000, + 480.000000, 600.000000, 20.000000, + 450.000000, 600.000000, 25.000000, + 420.000000, 600.000000, 30.000000, + 605.000000, 605.000000, 0.000000, + 574.750000, 605.000000, 5.000000, + 544.500000, 605.000000, 10.000000, + 514.250000, 605.000000, 15.000000, + 484.000000, 605.000000, 20.000000, + 453.750000, 605.000000, 25.000000, + 423.500000, 605.000000, 30.000000, + 610.000000, 610.000000, 0.000000, + 579.500000, 610.000000, 5.000000, + 549.000000, 610.000000, 10.000000, + 518.500000, 610.000000, 15.000000, + 488.000000, 610.000000, 20.000000, + 457.500000, 610.000000, 25.000000, + 427.000000, 610.000000, 30.000000, + 615.000000, 615.000000, 0.000000, + 584.250000, 615.000000, 5.000000, + 553.500000, 615.000000, 10.000000, + 522.750000, 615.000000, 15.000000, + 492.000000, 615.000000, 20.000000, + 461.250000, 615.000000, 25.000000, + 430.500000, 615.000000, 30.000000, + 620.000000, 620.000000, 0.000000, + 589.000000, 620.000000, 5.000000, + 558.000000, 620.000000, 10.000000, + 527.000000, 620.000000, 15.000000, + 496.000000, 620.000000, 20.000000, + 465.000000, 620.000000, 25.000000, + 434.000000, 620.000000, 30.000000, + 625.000000, 625.000000, 0.000000, + 593.750000, 625.000000, 5.000000, + 562.500000, 625.000000, 10.000000, + 531.250000, 625.000000, 15.000000, + 500.000000, 625.000000, 20.000000, + 468.750000, 625.000000, 25.000000, + 437.500000, 625.000000, 30.000000, + 630.000000, 630.000000, 0.000000, + 598.500000, 630.000000, 5.000000, + 567.000000, 630.000000, 10.000000, + 535.500000, 630.000000, 15.000000, + 504.000000, 630.000000, 20.000000, + 472.500000, 630.000000, 25.000000, + 441.000000, 630.000000, 30.000000, + 635.000000, 635.000000, 0.000000, + 603.250000, 635.000000, 5.000000, + 571.500000, 635.000000, 10.000000, + 539.750000, 635.000000, 15.000000, + 508.000000, 635.000000, 20.000000, + 476.250000, 635.000000, 25.000000, + 444.500000, 635.000000, 30.000000, + 640.000000, 640.000000, 0.000000, + 608.000000, 640.000000, 5.000000, + 576.000000, 640.000000, 10.000000, + 544.000000, 640.000000, 15.000000, + 512.000000, 640.000000, 20.000000, + 480.000000, 640.000000, 25.000000, + 448.000000, 640.000000, 30.000000, + 645.000000, 645.000000, 0.000000, + 612.750000, 645.000000, 5.000000, + 580.500000, 645.000000, 10.000000, + 548.250000, 645.000000, 15.000000, + 516.000000, 645.000000, 20.000000, + 483.750000, 645.000000, 25.000000, + 451.500000, 645.000000, 30.000000, + 650.000000, 650.000000, 0.000000, + 617.500000, 650.000000, 5.000000, + 585.000000, 650.000000, 10.000000, + 552.500000, 650.000000, 15.000000, + 520.000000, 650.000000, 20.000000, + 487.500000, 650.000000, 25.000000, + 455.000000, 650.000000, 30.000000, + 655.000000, 655.000000, 0.000000, + 622.250000, 655.000000, 5.000000, + 589.500000, 655.000000, 10.000000, + 556.750000, 655.000000, 15.000000, + 524.000000, 655.000000, 20.000000, + 491.250000, 655.000000, 25.000000, + 458.500000, 655.000000, 30.000000, + 660.000000, 660.000000, 0.000000, + 627.000000, 660.000000, 5.000000, + 594.000000, 660.000000, 10.000000, + 561.000000, 660.000000, 15.000000, + 528.000000, 660.000000, 20.000000, + 495.000000, 660.000000, 25.000000, + 462.000000, 660.000000, 30.000000, + 665.000000, 665.000000, 0.000000, + 631.750000, 665.000000, 5.000000, + 598.500000, 665.000000, 10.000000, + 565.250000, 665.000000, 15.000000, + 532.000000, 665.000000, 20.000000, + 498.750000, 665.000000, 25.000000, + 465.500000, 665.000000, 30.000000, + 670.000000, 670.000000, 0.000000, + 636.500000, 670.000000, 5.000000, + 603.000000, 670.000000, 10.000000, + 569.500000, 670.000000, 15.000000, + 536.000000, 670.000000, 20.000000, + 502.500000, 670.000000, 25.000000, + 469.000000, 670.000000, 30.000000, + 675.000000, 675.000000, 0.000000, + 641.250000, 675.000000, 5.000000, + 607.500000, 675.000000, 10.000000, + 573.750000, 675.000000, 15.000000, + 540.000000, 675.000000, 20.000000, + 506.250000, 675.000000, 25.000000, + 472.500000, 675.000000, 30.000000, + 680.000000, 680.000000, 0.000000, + 646.000000, 680.000000, 5.000000, + 612.000000, 680.000000, 10.000000, + 578.000000, 680.000000, 15.000000, + 544.000000, 680.000000, 20.000000, + 510.000000, 680.000000, 25.000000, + 476.000000, 680.000000, 30.000000, + 685.000000, 685.000000, 0.000000, + 650.750000, 685.000000, 5.000000, + 616.500000, 685.000000, 10.000000, + 582.250000, 685.000000, 15.000000, + 548.000000, 685.000000, 20.000000, + 513.750000, 685.000000, 25.000000, + 479.500000, 685.000000, 30.000000, + 690.000000, 690.000000, 0.000000, + 655.500000, 690.000000, 5.000000, + 621.000000, 690.000000, 10.000000, + 586.500000, 690.000000, 15.000000, + 552.000000, 690.000000, 20.000000, + 517.500000, 690.000000, 25.000000, + 483.000000, 690.000000, 30.000000, + 695.000000, 695.000000, 0.000000, + 660.250000, 695.000000, 5.000000, + 625.500000, 695.000000, 10.000000, + 590.750000, 695.000000, 15.000000, + 556.000000, 695.000000, 20.000000, + 521.250000, 695.000000, 25.000000, + 486.500000, 695.000000, 30.000000, + 700.000000, 700.000000, 0.000000, + 665.000000, 700.000000, 5.000000, + 630.000000, 700.000000, 10.000000, + 595.000000, 700.000000, 15.000000, + 560.000000, 700.000000, 20.000000, + 525.000000, 700.000000, 25.000000, + 490.000000, 700.000000, 30.000000, + 705.000000, 705.000000, 0.000000, + 669.750000, 705.000000, 5.000000, + 634.500000, 705.000000, 10.000000, + 599.250000, 705.000000, 15.000000, + 564.000000, 705.000000, 20.000000, + 528.750000, 705.000000, 25.000000, + 493.500000, 705.000000, 30.000000, + 710.000000, 710.000000, 0.000000, + 674.500000, 710.000000, 5.000000, + 639.000000, 710.000000, 10.000000, + 603.500000, 710.000000, 15.000000, + 568.000000, 710.000000, 20.000000, + 532.500000, 710.000000, 25.000000, + 497.000000, 710.000000, 30.000000, + 715.000000, 715.000000, 0.000000, + 679.250000, 715.000000, 5.000000, + 643.500000, 715.000000, 10.000000, + 607.750000, 715.000000, 15.000000, + 572.000000, 715.000000, 20.000000, + 536.250000, 715.000000, 25.000000, + 500.500000, 715.000000, 30.000000, + 720.000000, 720.000000, 0.000000, + 684.000000, 720.000000, 5.000000, + 648.000000, 720.000000, 10.000000, + 612.000000, 720.000000, 15.000000, + 576.000000, 720.000000, 20.000000, + 540.000000, 720.000000, 25.000000, + 504.000000, 720.000000, 30.000000, + 725.000000, 725.000000, 0.000000, + 688.750000, 725.000000, 5.000000, + 652.500000, 725.000000, 10.000000, + 616.250000, 725.000000, 15.000000, + 580.000000, 725.000000, 20.000000, + 543.750000, 725.000000, 25.000000, + 507.500000, 725.000000, 30.000000, + 730.000000, 730.000000, 0.000000, + 693.500000, 730.000000, 5.000000, + 657.000000, 730.000000, 10.000000, + 620.500000, 730.000000, 15.000000, + 584.000000, 730.000000, 20.000000, + 547.500000, 730.000000, 25.000000, + 511.000000, 730.000000, 30.000000, + 735.000000, 735.000000, 0.000000, + 698.250000, 735.000000, 5.000000, + 661.500000, 735.000000, 10.000000, + 624.750000, 735.000000, 15.000000, + 588.000000, 735.000000, 20.000000, + 551.250000, 735.000000, 25.000000, + 514.500000, 735.000000, 30.000000, + 740.000000, 740.000000, 0.000000, + 703.000000, 740.000000, 5.000000, + 666.000000, 740.000000, 10.000000, + 629.000000, 740.000000, 15.000000, + 592.000000, 740.000000, 20.000000, + 555.000000, 740.000000, 25.000000, + 518.000000, 740.000000, 30.000000, + 745.000000, 745.000000, 0.000000, + 707.750000, 745.000000, 5.000000, + 670.500000, 745.000000, 10.000000, + 633.250000, 745.000000, 15.000000, + 596.000000, 745.000000, 20.000000, + 558.750000, 745.000000, 25.000000, + 521.500000, 745.000000, 30.000000, + 750.000000, 750.000000, 0.000000, + 712.500000, 750.000000, 5.000000, + 675.000000, 750.000000, 10.000000, + 637.500000, 750.000000, 15.000000, + 600.000000, 750.000000, 20.000000, + 562.500000, 750.000000, 25.000000, + 525.000000, 750.000000, 30.000000, + 755.000000, 755.000000, 0.000000, + 717.250000, 755.000000, 5.000000, + 679.500000, 755.000000, 10.000000, + 641.750000, 755.000000, 15.000000, + 604.000000, 755.000000, 20.000000, + 566.250000, 755.000000, 25.000000, + 528.500000, 755.000000, 30.000000, + 760.000000, 760.000000, 0.000000, + 722.000000, 760.000000, 5.000000, + 684.000000, 760.000000, 10.000000, + 646.000000, 760.000000, 15.000000, + 608.000000, 760.000000, 20.000000, + 570.000000, 760.000000, 25.000000, + 532.000000, 760.000000, 30.000000, + 765.000000, 765.000000, 0.000000, + 726.750000, 765.000000, 5.000000, + 688.500000, 765.000000, 10.000000, + 650.250000, 765.000000, 15.000000, + 612.000000, 765.000000, 20.000000, + 573.750000, 765.000000, 25.000000, + 535.500000, 765.000000, 30.000000, + 770.000000, 770.000000, 0.000000, + 731.500000, 770.000000, 5.000000, + 693.000000, 770.000000, 10.000000, + 654.500000, 770.000000, 15.000000, + 616.000000, 770.000000, 20.000000, + 577.500000, 770.000000, 25.000000, + 539.000000, 770.000000, 30.000000, + 775.000000, 775.000000, 0.000000, + 736.250000, 775.000000, 5.000000, + 697.500000, 775.000000, 10.000000, + 658.750000, 775.000000, 15.000000, + 620.000000, 775.000000, 20.000000, + 581.250000, 775.000000, 25.000000, + 542.500000, 775.000000, 30.000000, + 780.000000, 780.000000, 0.000000, + 741.000000, 780.000000, 5.000000, + 702.000000, 780.000000, 10.000000, + 663.000000, 780.000000, 15.000000, + 624.000000, 780.000000, 20.000000, + 585.000000, 780.000000, 25.000000, + 546.000000, 780.000000, 30.000000, + 785.000000, 785.000000, 0.000000, + 745.750000, 785.000000, 5.000000, + 706.500000, 785.000000, 10.000000, + 667.250000, 785.000000, 15.000000, + 628.000000, 785.000000, 20.000000, + 588.750000, 785.000000, 25.000000, + 549.500000, 785.000000, 30.000000, + 790.000000, 790.000000, 0.000000, + 750.500000, 790.000000, 5.000000, + 711.000000, 790.000000, 10.000000, + 671.500000, 790.000000, 15.000000, + 632.000000, 790.000000, 20.000000, + 592.500000, 790.000000, 25.000000, + 553.000000, 790.000000, 30.000000, + 795.000000, 795.000000, 0.000000, + 755.250000, 795.000000, 5.000000, + 715.500000, 795.000000, 10.000000, + 675.750000, 795.000000, 15.000000, + 636.000000, 795.000000, 20.000000, + 596.250000, 795.000000, 25.000000, + 556.500000, 795.000000, 30.000000, + 800.000000, 800.000000, 0.000000, + 760.000000, 800.000000, 5.000000, + 720.000000, 800.000000, 10.000000, + 680.000000, 800.000000, 15.000000, + 640.000000, 800.000000, 20.000000, + 600.000000, 800.000000, 25.000000, + 560.000000, 800.000000, 30.000000, + 805.000000, 805.000000, 0.000000, + 764.750000, 805.000000, 5.000000, + 724.500000, 805.000000, 10.000000, + 684.250000, 805.000000, 15.000000, + 644.000000, 805.000000, 20.000000, + 603.750000, 805.000000, 25.000000, + 563.500000, 805.000000, 30.000000, + 810.000000, 810.000000, 0.000000, + 769.500000, 810.000000, 5.000000, + 729.000000, 810.000000, 10.000000, + 688.500000, 810.000000, 15.000000, + 648.000000, 810.000000, 20.000000, + 607.500000, 810.000000, 25.000000, + 567.000000, 810.000000, 30.000000, + 815.000000, 815.000000, 0.000000, + 774.250000, 815.000000, 5.000000, + 733.500000, 815.000000, 10.000000, + 692.750000, 815.000000, 15.000000, + 652.000000, 815.000000, 20.000000, + 611.250000, 815.000000, 25.000000, + 570.500000, 815.000000, 30.000000, + 820.000000, 820.000000, 0.000000, + 779.000000, 820.000000, 5.000000, + 738.000000, 820.000000, 10.000000, + 697.000000, 820.000000, 15.000000, + 656.000000, 820.000000, 20.000000, + 615.000000, 820.000000, 25.000000, + 574.000000, 820.000000, 30.000000, + 825.000000, 825.000000, 0.000000, + 783.750000, 825.000000, 5.000000, + 742.500000, 825.000000, 10.000000, + 701.250000, 825.000000, 15.000000, + 660.000000, 825.000000, 20.000000, + 618.750000, 825.000000, 25.000000, + 577.500000, 825.000000, 30.000000, + 830.000000, 830.000000, 0.000000, + 788.500000, 830.000000, 5.000000, + 747.000000, 830.000000, 10.000000, + 705.500000, 830.000000, 15.000000, + 664.000000, 830.000000, 20.000000, + 622.500000, 830.000000, 25.000000, + 581.000000, 830.000000, 30.000000, + 835.000000, 835.000000, 0.000000, + 793.250000, 835.000000, 5.000000, + 751.500000, 835.000000, 10.000000, + 709.750000, 835.000000, 15.000000, + 668.000000, 835.000000, 20.000000, + 626.250000, 835.000000, 25.000000, + 584.500000, 835.000000, 30.000000, + 840.000000, 840.000000, 0.000000, + 798.000000, 840.000000, 5.000000, + 756.000000, 840.000000, 10.000000, + 714.000000, 840.000000, 15.000000, + 672.000000, 840.000000, 20.000000, + 630.000000, 840.000000, 25.000000, + 588.000000, 840.000000, 30.000000, + 845.000000, 845.000000, 0.000000, + 802.750000, 845.000000, 5.000000, + 760.500000, 845.000000, 10.000000, + 718.250000, 845.000000, 15.000000, + 676.000000, 845.000000, 20.000000, + 633.750000, 845.000000, 25.000000, + 591.500000, 845.000000, 30.000000, + 850.000000, 850.000000, 0.000000, + 807.500000, 850.000000, 5.000000, + 765.000000, 850.000000, 10.000000, + 722.500000, 850.000000, 15.000000, + 680.000000, 850.000000, 20.000000, + 637.500000, 850.000000, 25.000000, + 595.000000, 850.000000, 30.000000, + 855.000000, 855.000000, 0.000000, + 812.250000, 855.000000, 5.000000, + 769.500000, 855.000000, 10.000000, + 726.750000, 855.000000, 15.000000, + 684.000000, 855.000000, 20.000000, + 641.250000, 855.000000, 25.000000, + 598.500000, 855.000000, 30.000000, + 860.000000, 860.000000, 0.000000, + 817.000000, 860.000000, 5.000000, + 774.000000, 860.000000, 10.000000, + 731.000000, 860.000000, 15.000000, + 688.000000, 860.000000, 20.000000, + 645.000000, 860.000000, 25.000000, + 602.000000, 860.000000, 30.000000, + 865.000000, 865.000000, 0.000000, + 821.750000, 865.000000, 5.000000, + 778.500000, 865.000000, 10.000000, + 735.250000, 865.000000, 15.000000, + 692.000000, 865.000000, 20.000000, + 648.750000, 865.000000, 25.000000, + 605.500000, 865.000000, 30.000000, + 870.000000, 870.000000, 0.000000, + 826.500000, 870.000000, 5.000000, + 783.000000, 870.000000, 10.000000, + 739.500000, 870.000000, 15.000000, + 696.000000, 870.000000, 20.000000, + 652.500000, 870.000000, 25.000000, + 609.000000, 870.000000, 30.000000, + 875.000000, 875.000000, 0.000000, + 831.250000, 875.000000, 5.000000, + 787.500000, 875.000000, 10.000000, + 743.750000, 875.000000, 15.000000, + 700.000000, 875.000000, 20.000000, + 656.250000, 875.000000, 25.000000, + 612.500000, 875.000000, 30.000000, + 880.000000, 880.000000, 0.000000, + 836.000000, 880.000000, 5.000000, + 792.000000, 880.000000, 10.000000, + 748.000000, 880.000000, 15.000000, + 704.000000, 880.000000, 20.000000, + 660.000000, 880.000000, 25.000000, + 616.000000, 880.000000, 30.000000, + 885.000000, 885.000000, 0.000000, + 840.750000, 885.000000, 5.000000, + 796.500000, 885.000000, 10.000000, + 752.250000, 885.000000, 15.000000, + 708.000000, 885.000000, 20.000000, + 663.750000, 885.000000, 25.000000, + 619.500000, 885.000000, 30.000000, + 890.000000, 890.000000, 0.000000, + 845.500000, 890.000000, 5.000000, + 801.000000, 890.000000, 10.000000, + 756.500000, 890.000000, 15.000000, + 712.000000, 890.000000, 20.000000, + 667.500000, 890.000000, 25.000000, + 623.000000, 890.000000, 30.000000, + 895.000000, 895.000000, 0.000000, + 850.250000, 895.000000, 5.000000, + 805.500000, 895.000000, 10.000000, + 760.750000, 895.000000, 15.000000, + 716.000000, 895.000000, 20.000000, + 671.250000, 895.000000, 25.000000, + 626.500000, 895.000000, 30.000000, + 900.000000, 900.000000, 0.000000, + 855.000000, 900.000000, 5.000000, + 810.000000, 900.000000, 10.000000, + 765.000000, 900.000000, 15.000000, + 720.000000, 900.000000, 20.000000, + 675.000000, 900.000000, 25.000000, + 630.000000, 900.000000, 30.000000, + 905.000000, 905.000000, 0.000000, + 859.750000, 905.000000, 5.000000, + 814.500000, 905.000000, 10.000000, + 769.250000, 905.000000, 15.000000, + 724.000000, 905.000000, 20.000000, + 678.750000, 905.000000, 25.000000, + 633.500000, 905.000000, 30.000000, + 910.000000, 910.000000, 0.000000, + 864.500000, 910.000000, 5.000000, + 819.000000, 910.000000, 10.000000, + 773.500000, 910.000000, 15.000000, + 728.000000, 910.000000, 20.000000, + 682.500000, 910.000000, 25.000000, + 637.000000, 910.000000, 30.000000, + 915.000000, 915.000000, 0.000000, + 869.250000, 915.000000, 5.000000, + 823.500000, 915.000000, 10.000000, + 777.750000, 915.000000, 15.000000, + 732.000000, 915.000000, 20.000000, + 686.250000, 915.000000, 25.000000, + 640.500000, 915.000000, 30.000000, + 920.000000, 920.000000, 0.000000, + 874.000000, 920.000000, 5.000000, + 828.000000, 920.000000, 10.000000, + 782.000000, 920.000000, 15.000000, + 736.000000, 920.000000, 20.000000, + 690.000000, 920.000000, 25.000000, + 644.000000, 920.000000, 30.000000, + 925.000000, 925.000000, 0.000000, + 878.750000, 925.000000, 5.000000, + 832.500000, 925.000000, 10.000000, + 786.250000, 925.000000, 15.000000, + 740.000000, 925.000000, 20.000000, + 693.750000, 925.000000, 25.000000, + 647.500000, 925.000000, 30.000000, + 930.000000, 930.000000, 0.000000, + 883.500000, 930.000000, 5.000000, + 837.000000, 930.000000, 10.000000, + 790.500000, 930.000000, 15.000000, + 744.000000, 930.000000, 20.000000, + 697.500000, 930.000000, 25.000000, + 651.000000, 930.000000, 30.000000, + 935.000000, 935.000000, 0.000000, + 888.250000, 935.000000, 5.000000, + 841.500000, 935.000000, 10.000000, + 794.750000, 935.000000, 15.000000, + 748.000000, 935.000000, 20.000000, + 701.250000, 935.000000, 25.000000, + 654.500000, 935.000000, 30.000000, + 940.000000, 940.000000, 0.000000, + 893.000000, 940.000000, 5.000000, + 846.000000, 940.000000, 10.000000, + 799.000000, 940.000000, 15.000000, + 752.000000, 940.000000, 20.000000, + 705.000000, 940.000000, 25.000000, + 658.000000, 940.000000, 30.000000, + 945.000000, 945.000000, 0.000000, + 897.750000, 945.000000, 5.000000, + 850.500000, 945.000000, 10.000000, + 803.250000, 945.000000, 15.000000, + 756.000000, 945.000000, 20.000000, + 708.750000, 945.000000, 25.000000, + 661.500000, 945.000000, 30.000000, + 950.000000, 950.000000, 0.000000, + 902.500000, 950.000000, 5.000000, + 855.000000, 950.000000, 10.000000, + 807.500000, 950.000000, 15.000000, + 760.000000, 950.000000, 20.000000, + 712.500000, 950.000000, 25.000000, + 665.000000, 950.000000, 30.000000, + 955.000000, 955.000000, 0.000000, + 907.250000, 955.000000, 5.000000, + 859.500000, 955.000000, 10.000000, + 811.750000, 955.000000, 15.000000, + 764.000000, 955.000000, 20.000000, + 716.250000, 955.000000, 25.000000, + 668.500000, 955.000000, 30.000000, + 960.000000, 960.000000, 0.000000, + 912.000000, 960.000000, 5.000000, + 864.000000, 960.000000, 10.000000, + 816.000000, 960.000000, 15.000000, + 768.000000, 960.000000, 20.000000, + 720.000000, 960.000000, 25.000000, + 672.000000, 960.000000, 30.000000, + 965.000000, 965.000000, 0.000000, + 916.750000, 965.000000, 5.000000, + 868.500000, 965.000000, 10.000000, + 820.250000, 965.000000, 15.000000, + 772.000000, 965.000000, 20.000000, + 723.750000, 965.000000, 25.000000, + 675.500000, 965.000000, 30.000000, + 970.000000, 970.000000, 0.000000, + 921.500000, 970.000000, 5.000000, + 873.000000, 970.000000, 10.000000, + 824.500000, 970.000000, 15.000000, + 776.000000, 970.000000, 20.000000, + 727.500000, 970.000000, 25.000000, + 679.000000, 970.000000, 30.000000, + 975.000000, 975.000000, 0.000000, + 926.250000, 975.000000, 5.000000, + 877.500000, 975.000000, 10.000000, + 828.750000, 975.000000, 15.000000, + 780.000000, 975.000000, 20.000000, + 731.250000, 975.000000, 25.000000, + 682.500000, 975.000000, 30.000000, + 980.000000, 980.000000, 0.000000, + 931.000000, 980.000000, 5.000000, + 882.000000, 980.000000, 10.000000, + 833.000000, 980.000000, 15.000000, + 784.000000, 980.000000, 20.000000, + 735.000000, 980.000000, 25.000000, + 686.000000, 980.000000, 30.000000, + 985.000000, 985.000000, 0.000000, + 935.750000, 985.000000, 5.000000, + 886.500000, 985.000000, 10.000000, + 837.250000, 985.000000, 15.000000, + 788.000000, 985.000000, 20.000000, + 738.750000, 985.000000, 25.000000, + 689.500000, 985.000000, 30.000000, + 990.000000, 990.000000, 0.000000, + 940.500000, 990.000000, 5.000000, + 891.000000, 990.000000, 10.000000, + 841.500000, 990.000000, 15.000000, + 792.000000, 990.000000, 20.000000, + 742.500000, 990.000000, 25.000000, + 693.000000, 990.000000, 30.000000, + 995.000000, 995.000000, 0.000000, + 945.250000, 995.000000, 5.000000, + 895.500000, 995.000000, 10.000000, + 845.750000, 995.000000, 15.000000, + 796.000000, 995.000000, 20.000000, + 746.250000, 995.000000, 25.000000, + 696.500000, 995.000000, 30.000000, + 1000.000000, 1000.000000, 0.000000, + 950.000000, 1000.000000, 5.000000, + 900.000000, 1000.000000, 10.000000, + 850.000000, 1000.000000, 15.000000, + 800.000000, 1000.000000, 20.000000, + 750.000000, 1000.000000, 25.000000, + 700.000000, 1000.000000, 30.000000, + }; + + @Test + @DisplayName("Json 2function evaluation") + public void test() { + var sb = new Starbound(); + + var fnData = """ + ["linear", "clamp", [ + [0, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 1000 ], //damage + // ------------------------------------------------------------------------------------------------------ + [0, [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 1000 ] ], + [10, [0, 9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 900 ] ], + [20, [0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 800 ] ], + [30, [0, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 700 ] ], + [40, [0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 600 ] ], + [50, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 500 ] ], + [60, [0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 400 ] ], + [70, [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 300 ] ], + [80, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 200 ] ], + [90, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100 ] ], + [100, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] ] + ]] + """; + + var fn = sb.getGson().fromJson(fnData, Json2Function.class); + + for (int i = 0; i < test2FunctionData.length; i += 3) { + double result = test2FunctionData[i]; + double x = test2FunctionData[i + 1]; + double y = test2FunctionData[i + 2]; + double evaluated = (float) fn.evaluate(x, y); + + if (result != evaluated) { + throw new RuntimeException("Evaluation of function returned " + evaluated + " while " + result + " was expected for inputs " + x + ", " + y); + } + } + } +}