修改多线程安装

This commit is contained in:
squallzhjch 2023-10-27 14:18:38 +08:00
parent 459970d01b
commit 43523d09b4
8 changed files with 549 additions and 525 deletions

View File

@ -83,6 +83,7 @@
"name": "车道边界类型",
"zoomMin": 18,
"zoomMax": 20,
"isDependOnOtherTable": true,
"checkLinkId": false,
"filterData": true,
"catch": true,
@ -154,6 +155,7 @@
"code": 2092,
"name": "车道类型",
"catch": true,
"isDependOnOtherTable": true,
"zoomMin": 18,
"zoomMax": 20,
"transformer": [
@ -176,6 +178,7 @@
"name": "桥",
"catch": true,
"existSubCode": true,
"isDependOnOtherTable": true,
"zoomMin": 15,
"zoomMax": 20,
"transformer": [
@ -352,6 +355,7 @@
"code": 4001,
"name": "路口",
"zoomMin": 15,
"isDependOnOtherTable": true,
"zoomMax": 17,
"catch": true,
"transformer": [
@ -493,6 +497,7 @@
"code": 4009,
"name": "警示信息",
"catch": true,
"isDependOnOtherTable": true,
"zoomMin": 15,
"zoomMax": 20,
"transformer": [
@ -581,6 +586,7 @@
"code": 4601,
"name": "车信",
"catch": true,
"isDependOnOtherTable": true,
"zoomMin": 15,
"zoomMax": 17,
"transformer": [
@ -609,6 +615,7 @@
"code": 5001,
"name": "车道中心线",
"catch": false,
"isDependOnOtherTable": true,
"checkLinkId": false,
"zoomMin": 18,
"zoomMax": 20,

View File

@ -20,14 +20,12 @@ class ImportConfig {
@Expose
var checked: Boolean = true
val preProcess: ImportPreProcess = ImportPreProcess()
fun transformProperties(renderEntity: RenderEntity, realm: Realm): RenderEntity? {
fun transformProperties(renderEntity: RenderEntity, realm: Realm?): RenderEntity? {
preProcess.realm = realm
val transformList = tableMap[renderEntity.code.toString()]?.transformer
if (transformList.isNullOrEmpty()) {
Log.e("qj", "子表转换为空===${renderEntity.code}")
return renderEntity
}
Log.e("qj", "子表转换不为空===${renderEntity.code}")
for (transform in transformList) {
// 开始执行转换
val key: String = transform.k

View File

@ -22,8 +22,12 @@ import dagger.assisted.AssistedInject
import io.realm.Realm
import io.realm.RealmConfiguration
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.sync.Mutex
import org.spatialite.database.SQLiteDatabase
import java.io.BufferedReader
import java.io.File
@ -142,20 +146,20 @@ class ImportOMDBHelper @AssistedInject constructor(
* @param configFile 对应的配置文件
* */
suspend fun importOmdbZipFile(
omdbZipFile: File,
task: TaskBean,
scope: CoroutineScope
): Flow<String> =
omdbZipFile: File, task: TaskBean, scope: CoroutineScope
): Boolean {
val channel = Channel<List<RenderEntity>>(Channel.RENDEZVOUS)
flow {
installTaskid = task.id.toString()
currentInstallTaskFolder = File(Constant.USER_DATA_PATH + "/$installTaskid")
if (!currentInstallTaskFolder.exists()) currentInstallTaskFolder.mkdirs()
currentInstallTaskConfig =
RealmConfiguration.Builder().directory(currentInstallTaskFolder).name("OMQS.realm")
RealmConfiguration.Builder().directory(currentInstallTaskFolder)
.name("OMQS.realm")
.encryptionKey(Constant.PASSWORD)
// .allowQueriesOnUiThread(true)
.schemaVersion(2).build()
val unZipFolder = File(omdbZipFile.parentFile, "result")
if (unZipFolder.exists()) {
unZipFolder.deleteRecursively()
@ -167,13 +171,6 @@ class ImportOMDBHelper @AssistedInject constructor(
var tableNum = 0
var processIndex = 0
//单个表要素时间统计
// var tableImportTime = System.currentTimeMillis()
//总表要素统计时间
// var dataImportTime = System.currentTimeMillis()
// Realm.compactRealm(currentInstallTaskConfig)
for (importConfig in importConfigList) {
tableNum += importConfig.tableMap.size
}
@ -187,52 +184,99 @@ class ImportOMDBHelper @AssistedInject constructor(
// lineList[index] = GeometryTools.createGeometry(it.geometry) as LineString
// index++
}
val resHashMap: HashMap<String, RenderEntity> = HashMap() //define empty hashmap
val listDependOnEntry = mutableListOf<MutableMap.MutableEntry<String, TableInfo>>()
//需要关联查询的表
val listDependOnEntry =
mutableMapOf<MutableMap.MutableEntry<String, TableInfo>, ImportConfig>()
//协程池
val listJob = mutableListOf<Job>()
try {
for (importConfig in importConfigList) {
for ((index, currentEntry) in importConfig.tableMap.entries.withIndex()) {
if (currentEntry.value.isDependOnOtherTable) {
listDependOnEntry.add(currentEntry)
listDependOnEntry[currentEntry] = importConfig
continue
}
val job = scope.async {
importData(unZipFiles, currentEntry, task,importConfig)
val job = scope.launch(Dispatchers.IO) {
importData(
channel,
unZipFiles,
currentEntry,
task,
importConfig,
hashMap
)
}
listJob.add(job)
processIndex += 1
// 1个文件发送一次flow流
emit("${processIndex}/${tableNum}")
}
}
val channelJob = scope.launch(Dispatchers.IO) {
val iterator = channel.iterator()
while (iterator.hasNext()) {
val next = iterator.next()
val realm = Realm.getInstance(currentInstallTaskConfig)
realm.executeTransaction {
Log.e("jingo", "安装数据 Realm数据插入")
it.copyToRealm(next)
}
realm.close()
}
Log.e("qj", "安装结束")
}
listJob.joinAll()
channel.close()
channelJob.join()
Log.e("jingo", "channel close 等待结束")
for ((currentEntry, importConfig) in listDependOnEntry) {
importData(
channel,
unZipFiles,
currentEntry,
task,
importConfig,
hashMap,
false
)
}
Log.e("jingo", "安装结束")
} catch (e: Exception) {
Log.e("jingo", "安装报错 ${e.message}")
throw e
return false
}
emit("finish")
// }.collect() { list ->
// if (list == null) {
// realm.close()
// } else {
// realm.executeTransaction {
// it.copyToRealm(list)
// }
// }
return true
}
private suspend fun importData(
f: Channel<List<RenderEntity>>,
unZipFiles: List<File>,
currentEntry: MutableMap.MutableEntry<String, TableInfo>,
task: TaskBean,
importConfig:ImportConfig
importConfig: ImportConfig,
hashMap: HashMap<Long, HadLinkDvoBean>,
isEmit: Boolean = true
) {
val listRenderEntity = mutableListOf<RenderEntity>()
//下载数据统计
var dataIndex = 0
//数据库插入的统计
var insertIndex = 0
val resHashMap: HashMap<String, RenderEntity> = HashMap() //define empty hashmap
var listRenderEntity = mutableListOf<RenderEntity>()
//单个表要素统计
var elementIndex = 0
var realm = Realm.getInstance(currentInstallTaskConfig)
val currentConfig = currentEntry.value
try {
var realm: Realm? = null
if (!isEmit) {
realm = Realm.getInstance(currentInstallTaskConfig)
realm.beginTransaction()
}
val txtFile = unZipFiles.find {
it.name == currentConfig.table
}
@ -240,14 +284,13 @@ class ImportOMDBHelper @AssistedInject constructor(
val fileReader = FileReader(txtFile)
val bufferedReader = BufferedReader(fileReader)
var line: String? = bufferedReader.readLine()
realm.beginTransaction()
while (line != null) {
if (line == null || line.trim() == "") {
line = bufferedReader.readLine()
continue
}
elementIndex += 1
dataIndex += 1
val map = gson.fromJson<Map<String, Any>>(
line, object : TypeToken<Map<String, Any>>() {}.type
).toMutableMap()
@ -269,23 +312,17 @@ class ImportOMDBHelper @AssistedInject constructor(
// 在外层记录当前数据的linkPid
if (map.containsKey("linkPid")) {
renderEntity.linkPid =
map["linkPid"].toString().split(",")[0]
renderEntity.linkPid = map["linkPid"].toString().split(",")[0]
} else if (map.containsKey("linkList")) {
val linkList = map["linkList"].toString()
if (!linkList.isNullOrEmpty() && linkList != "null") {
val list: List<LinkList> = gson.fromJson(
linkList,
object : TypeToken<List<LinkList>>() {}.type
linkList, object : TypeToken<List<LinkList>>() {}.type
)
renderEntity.linkPid = list[0].linkPid
}
}
Log.e(
"jingo",
"安装数据 ${renderEntity.table} ${renderEntity.linkPid} ${elementIndex} ${insertIndex}"
)
renderEntity.geometry = map["geometry"].toString()
// Log.d("ImportOMDBHelper", "解析===1处理3D")
// 其他数据插入到Properties中
@ -315,8 +352,7 @@ class ImportOMDBHelper @AssistedInject constructor(
for ((key, value) in map) {
when (value) {
is String -> renderEntity.properties[key] = value
is Int -> renderEntity.properties[key] =
value.toInt().toString()
is Int -> renderEntity.properties[key] = value.toInt().toString()
is Double -> renderEntity.properties[key] =
value.toDouble().toString()
@ -342,8 +378,7 @@ class ImportOMDBHelper @AssistedInject constructor(
}
DataCodeEnum.OMDB_LANE_MARK_BOUNDARYTYPE.code.toInt() -> {
val boundaryType =
renderEntity.properties["boundaryType"]
val boundaryType = renderEntity.properties["boundaryType"]
if (boundaryType != null) {
when (boundaryType.toInt()) {
0, 1, 6, 8, 9 -> {
@ -356,8 +391,7 @@ class ImportOMDBHelper @AssistedInject constructor(
}
DataCodeEnum.OMDB_RDBOUND_BOUNDARYTYPE.code.toInt() -> {
val boundaryType =
renderEntity.properties["boundaryType"]
val boundaryType = renderEntity.properties["boundaryType"]
if (boundaryType != null) {
when (boundaryType.toInt()) {
0, 1, 3, 4, 5, 7, 9 -> {
@ -370,8 +404,7 @@ class ImportOMDBHelper @AssistedInject constructor(
}
DataCodeEnum.OMDB_OBJECT_STOPLOCATION.code.toInt() -> {
val locationType =
renderEntity.properties["locationType"]
val locationType = renderEntity.properties["locationType"]
if (locationType != null) {
when (locationType.toInt()) {
3, 4 -> {
@ -438,8 +471,7 @@ class ImportOMDBHelper @AssistedInject constructor(
if (!linkList.isNullOrEmpty() && linkList != "null") {
val list: List<LinkList> = gson.fromJson(
linkList,
object : TypeToken<List<LinkList>>() {}.type
linkList, object : TypeToken<List<LinkList>>() {}.type
)
m@ for (link in list) {
@ -477,8 +509,6 @@ class ImportOMDBHelper @AssistedInject constructor(
}*/
// Log.e("qj", "${renderEntity.name}==不包括任务linkPid")
}
// Log.d("ImportOMDBHelper", "解析===2任务路线匹配")
// Log.d("ImportOMDBHelper", "解析===1预处理")
if (currentConfig.catch) {
renderEntity.catchEnable = 1
@ -487,8 +517,7 @@ class ImportOMDBHelper @AssistedInject constructor(
}
// 对renderEntity做预处理后再保存
val resultEntity =
importConfig.transformProperties(renderEntity, realm)
val resultEntity = importConfig.transformProperties(renderEntity, realm)
if (resultEntity != null) {
//对code编码需要特殊处理 存在多个属性值时渲染优先级SA>PA,存在多个属性值时渲染优先级FRONTAGE>MAIN_SIDE_A CCESS
@ -506,16 +535,14 @@ class ImportOMDBHelper @AssistedInject constructor(
renderEntity.code =
DataCodeEnum.OMDB_LINK_ATTRIBUTE_PA.code
} else {
type =
renderEntity.properties["frontage"]
type = renderEntity.properties["frontage"]
if (type != null && type == "1") {
renderEntity.code =
DataCodeEnum.OMDB_LINK_ATTRIBUTE_FORNTAGE.code
renderEntity.zoomMin = 15
renderEntity.zoomMax = 17
} else {
type =
renderEntity.properties["mainSideAccess"]
type = renderEntity.properties["mainSideAccess"]
if (type != null && type == "1") {
renderEntity.code =
DataCodeEnum.OMDB_LINK_ATTRIBUTE_MAIN_SIDE_ACCESS.code
@ -546,8 +573,7 @@ class ImportOMDBHelper @AssistedInject constructor(
DataCodeEnum.OMDB_RAMP.code.toInt() -> {
/*匝道*/
val formWay =
renderEntity.properties["formOfWay"]
val formWay = renderEntity.properties["formOfWay"]
if (formWay != null) {
when (formWay.toInt()) {
93 -> renderEntity.code =
@ -576,8 +602,7 @@ class ImportOMDBHelper @AssistedInject constructor(
DataCodeEnum.OMDB_LINK_FORM1.code.toInt() -> {
/*道路形态1*/
val formWay =
renderEntity.properties["formOfWay"]
val formWay = renderEntity.properties["formOfWay"]
if (formWay != null) {
when (formWay.toInt()) {
35 -> renderEntity.code =
@ -594,8 +619,7 @@ class ImportOMDBHelper @AssistedInject constructor(
DataCodeEnum.OMDB_LINK_FORM2.code.toInt() -> {
/*道路形态2*/
val formWay =
renderEntity.properties["formOfWay"]
val formWay = renderEntity.properties["formOfWay"]
if (formWay != null) {
when (formWay.toInt()) {
10 -> renderEntity.code =
@ -642,11 +666,9 @@ class ImportOMDBHelper @AssistedInject constructor(
DataCodeEnum.OMDB_LANE_CONSTRUCTION.code.toInt() -> {
//特殊处理空数据,渲染原则使用
val startTime =
renderEntity.properties["startTime"]
val startTime = renderEntity.properties["startTime"]
if (startTime == null || startTime == "") {
renderEntity.properties["startTime"] =
"null"
renderEntity.properties["startTime"] = "null"
}
}
}
@ -656,20 +678,17 @@ class ImportOMDBHelper @AssistedInject constructor(
val formOfWay = renderEntity.properties["formOfWay"]
if (formOfWay != null && formOfWay.toInt() == 30) {
renderEntity.enable = 2
renderEntity.code =
DataCodeEnum.OMDB_NODE_FORM.code
renderEntity.code = DataCodeEnum.OMDB_NODE_FORM.code
} else {
line = bufferedReader.readLine()
continue
}
} else if (renderEntity.table == DataCodeEnum.OMDB_NODE_PA.name) {//特殊处理因为code相同使用表名判断
//过滤不需要渲染的要素
val attributeType =
renderEntity.properties["attributeType"]
val attributeType = renderEntity.properties["attributeType"]
if (attributeType != null && attributeType.toInt() == 30) {
renderEntity.enable = 2
renderEntity.code =
DataCodeEnum.OMDB_NODE_PA.code
renderEntity.code = DataCodeEnum.OMDB_NODE_PA.code
} else {
line = bufferedReader.readLine()
continue
@ -677,7 +696,6 @@ class ImportOMDBHelper @AssistedInject constructor(
}
}
++insertIndex
//移除该字段,减少数据量
if (renderEntity.properties.containsKey("geometry")) {
@ -694,8 +712,7 @@ class ImportOMDBHelper @AssistedInject constructor(
if (renderEntity.linkRelation == null) {
renderEntity.linkRelation = LinkRelation()
}
renderEntity.linkRelation!!.linkPid =
renderEntity.linkPid
renderEntity.linkRelation!!.linkPid = renderEntity.linkPid
renderEntity.linkRelation!!.sNodeId =
renderEntity.properties["snodePid"]
renderEntity.linkRelation!!.eNodeId =
@ -704,62 +721,83 @@ class ImportOMDBHelper @AssistedInject constructor(
renderEntity.propertiesDb = StrZipUtil.compress(
gson.toJson(renderEntity.properties).toString()
)
listRenderEntity.add(renderEntity)
}
if (listRenderEntity.size > 10000) {
if (listRenderEntity.size > 20000) {
Log.e(
"jingo", "10000刷新"
"jingo",
"安装数据 ${currentConfig.table} $elementIndex ${listRenderEntity.size}"
)
realm.copyToRealm(listRenderEntity)
realm.commitTransaction()
realm.close()
listRenderEntity.clear()
insertIndex = 0
if (isEmit) {
f.send(listRenderEntity)
delay(100)
} else {
realm!!.copyToRealm(listRenderEntity)
realm!!.commitTransaction()
realm!!.close()
realm = Realm.getInstance(currentInstallTaskConfig)
realm.beginTransaction()
}
listRenderEntity = mutableListOf()
//
}
line = bufferedReader.readLine()
}
bufferedReader.close()
}
realm.copyToRealm(listRenderEntity)
realm.commitTransaction()
realm.close()
listRenderEntity.clear()
}
// 获取指定数据表的列名
fun getColumns(db: SQLiteDatabase, tableName: String): List<String> {
val columns = mutableListOf<String>()
// 查询 sqlite_master 表获取指定数据表的元数据信息
val cursor = db.query(
"sqlite_master",
arrayOf("sql"),
"type='table' AND name=?",
arrayOf(tableName),
null,
null,
null
Log.e(
"jingo",
"安装数据 ${currentConfig.table} $elementIndex ${listRenderEntity.size}"
)
if (isEmit) {
f.send(listRenderEntity)
delay(100)
// 从元数据信息中解析出列名
if (cursor.moveToFirst()) {
val sql = cursor.getString(0)
val startIndex = sql.indexOf("(") + 1
val endIndex = sql.lastIndexOf(")")
val columnDefs = sql.substring(startIndex, endIndex).split(",")
for (columnDef in columnDefs) {
val columnName = columnDef.trim().split(" ")[0]
if (!columnName.startsWith("rowid", true)) { // 排除 rowid 列
columns.add(columnName)
} else {
bufferedReader.close()
realm!!.copyToRealm(listRenderEntity)
realm!!.commitTransaction()
}
}
if (!isEmit) {
realm!!.close()
}
cursor.close()
return columns
} catch (e: Exception) {
Log.e("jingo", "安装报错 ${currentConfig.table} ${elementIndex} ${e.message}")
throw e
}
Log.e("jingo", "安装完成 ${currentConfig.table}")
}
// // 获取指定数据表的列名
// fun getColumns(db: SQLiteDatabase, tableName: String): List<String> {
// val columns = mutableListOf<String>()
//
// // 查询 sqlite_master 表获取指定数据表的元数据信息
// val cursor = db.query(
// "sqlite_master",
// arrayOf("sql"),
// "type='table' AND name=?",
// arrayOf(tableName),
// null,
// null,
// null
// )
//
// // 从元数据信息中解析出列名
// if (cursor.moveToFirst()) {
// val sql = cursor.getString(0)
// val startIndex = sql.indexOf("(") + 1
// val endIndex = sql.lastIndexOf(")")
// val columnDefs = sql.substring(startIndex, endIndex).split(",")
// for (columnDef in columnDefs) {
// val columnName = columnDef.trim().split(" ")[0]
// if (!columnName.startsWith("rowid", true)) { // 排除 rowid 列
// columns.add(columnName)
// }
// }
// }
// cursor.close()
// return columns
// }
}

View File

@ -733,6 +733,7 @@ class ImportPreProcess {
* 生成车道中心线面宽度
* */
fun generateAddWidthLine(renderEntity: RenderEntity) {
var newTime = 0L
// 添加车道中心面渲染原则,根据车道宽度进行渲染
val angleReference = ReferenceEntity()
// angleReference.renderEntityId = renderEntity.id
@ -741,6 +742,7 @@ class ImportPreProcess {
angleReference.geometry =
GeometryTools.createGeometry(renderEntity.geometry).buffer(0.000035)
.toString()//GeometryTools.computeLine(0.000035,0.000035,renderEntity.geometry)
angleReference.properties["qi_table"] = renderEntity.table
angleReference.properties["widthProperties"] = "3"
angleReference.zoomMin = renderEntity.zoomMin
@ -753,6 +755,7 @@ class ImportPreProcess {
)
listResult.add(angleReference)
insertData(listResult)
}
@ -962,11 +965,8 @@ class ImportPreProcess {
private fun insertData(list: List<RealmModel>) {
realm?.let {
Log.e("qj", "子表插入==")
if (list != null && list.isNotEmpty()) {
Log.e("qj", "子表插入开始==")
it.copyToRealm(list)
Log.e("qj", "子表插入结束==")
}
}
}

View File

@ -155,9 +155,8 @@ class TaskDownloadScope(
fileNew
)
if (task != null) {
importOMDBHelper.importOmdbZipFile(importOMDBHelper.omdbFile, task, this).collect {
Log.e("jingo", "数据安装 $it")
if (it == "finish") {
if (importOMDBHelper.importOmdbZipFile(importOMDBHelper.omdbFile, task, this)) {
// if (it == "finish") {
change(FileDownloadStatus.DONE)
Log.e("jingo", "数据安装结束")
withContext(Dispatchers.Main) {
@ -167,9 +166,9 @@ class TaskDownloadScope(
}
}
} else {
change(FileDownloadStatus.IMPORTING, it)
}
change(FileDownloadStatus.IMPORTING, "anzhuang")
}
// }
}
} catch (e: Exception) {
Log.e("jingo", "数据安装失败 ${e.toString()}")

View File

@ -1,17 +1,12 @@
package com.navinfo.omqs.ui.fragment.personalcenter
import android.net.Uri
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.blankj.utilcode.util.FileIOUtils
import com.blankj.utilcode.util.UriUtils
import com.blankj.utilcode.util.ZipUtils
import com.google.gson.Gson
import com.navinfo.collect.library.data.entity.*
import com.navinfo.collect.library.data.entity.TaskBean
import com.navinfo.omqs.bean.ScProblemTypeBean
import com.navinfo.omqs.bean.ScRootCauseAnalysisBean
import com.navinfo.omqs.bean.ScWarningCodeBean
@ -24,7 +19,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.apache.commons.io.input.BOMInputStream
import java.io.*
import java.util.*
import javax.inject.Inject
@ -158,16 +152,12 @@ class PersonalCenterViewModel @Inject constructor(
viewModelScope.launch(Dispatchers.IO) {
Log.d("OMQSApplication", "开始导入数据")
if (task != null) {
importOMDBHelper.importOmdbZipFile(importOMDBHelper.omdbFile, task, this).collect {
Log.d("importOMDBData", it)
}
importOMDBHelper.importOmdbZipFile(importOMDBHelper.omdbFile, task, this)
} else {
val newTask = TaskBean()
newTask.id = -1
importOMDBHelper.importOmdbZipFile(importOMDBHelper.omdbFile, newTask, this)
.collect {
Log.d("importOMDBData", it)
}
}
Log.d("OMQSApplication", "导入数据完成")
}

View File

@ -1,20 +1,14 @@
package com.navinfo.omqs.util
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import com.navinfo.collect.library.data.entity.HadLinkDvoBean
import com.navinfo.collect.library.data.entity.NiLocation
import com.navinfo.collect.library.data.entity.RenderEntity
import com.navinfo.collect.library.data.entity.TaskBean
import com.navinfo.collect.library.enums.DataCodeEnum
import com.navinfo.collect.library.utils.FootAndDistance
import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.omqs.db.RealmOperateHelper
import io.realm.Realm
import org.oscim.core.GeoPoint
import java.time.LocalDate
import java.time.LocalDateTime
class NaviEngineNew(
private val realmOperateHelper: RealmOperateHelper,

View File

@ -49,7 +49,6 @@ class GeometryToolsKt {
}
}
}
println("YGeometry-time:" + (System.currentTimeMillis() - startTime))
}
/**
@ -93,7 +92,6 @@ class GeometryToolsKt {
}
}
}
println("XGeometry-time:" + (System.currentTimeMillis() - startTime))
}
fun getMasterPoint(wkt: String): String {