diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7d5d64d..6114ede 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,6 +11,7 @@ + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7d5d64d..6114ede 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,6 +11,7 @@ + diff --git a/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt index bd2c821..6ee3191 100644 --- a/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt @@ -44,6 +44,16 @@ suspend fun getTask(@Query("userName") userName: String): String /** + * 提交工单 + */ + @GET("/ems/rs/task/update") + suspend fun uploadTask( + @Query("userId") userId: String, + @Query("taskId") taskId: String, + @Query("state") state: String + ): String + + /** * 安装新标识器 */ @POST("/ems/marker/save-marker-photo.do") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7d5d64d..6114ede 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,6 +11,7 @@ + diff --git a/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt index bd2c821..6ee3191 100644 --- a/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt @@ -44,6 +44,16 @@ suspend fun getTask(@Query("userName") userName: String): String /** + * 提交工单 + */ + @GET("/ems/rs/task/update") + suspend fun uploadTask( + @Query("userId") userId: String, + @Query("taskId") taskId: String, + @Query("state") state: String + ): String + + /** * 安装新标识器 */ @POST("/ems/marker/save-marker-photo.do") diff --git a/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt index 9972efd..1549f93 100644 --- a/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt @@ -60,6 +60,13 @@ } /** + * 提交工单 + */ + suspend fun uploadTask(userId: String, taskId: String?, state: String): String { + return api.uploadTask(userId, taskId.toString(), state) + } + + /** * 安装新标识器 */ suspend fun installLabel( diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7d5d64d..6114ede 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,6 +11,7 @@ + diff --git a/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt index bd2c821..6ee3191 100644 --- a/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt @@ -44,6 +44,16 @@ suspend fun getTask(@Query("userName") userName: String): String /** + * 提交工单 + */ + @GET("/ems/rs/task/update") + suspend fun uploadTask( + @Query("userId") userId: String, + @Query("taskId") taskId: String, + @Query("state") state: String + ): String + + /** * 安装新标识器 */ @POST("/ems/marker/save-marker-photo.do") diff --git a/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt index 9972efd..1549f93 100644 --- a/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt @@ -60,6 +60,13 @@ } /** + * 提交工单 + */ + suspend fun uploadTask(userId: String, taskId: String?, state: String): String { + return api.uploadTask(userId, taskId.toString(), state) + } + + /** * 安装新标识器 */ suspend fun installLabel( diff --git a/app/src/main/java/com/casic/detector/utils/DataBaseManager.kt b/app/src/main/java/com/casic/detector/utils/DataBaseManager.kt index 581b66c..988d439 100644 --- a/app/src/main/java/com/casic/detector/utils/DataBaseManager.kt +++ b/app/src/main/java/com/casic/detector/utils/DataBaseManager.kt @@ -56,6 +56,10 @@ return count.toInt() } + fun clearTasks() { + taskBeanDao.deleteAll() + } + fun insertTaskInformation( scanner: String, desc: String, @@ -80,4 +84,26 @@ taskBeanDao.insert(task) } + + fun queryDistinctTask(): List { + val result = ArrayList() + taskBeanDao.loadAll().forEach { + result.add(it) + } + //根据TaskId去重 + return result.distinctBy { it.taskId } + } + + private fun queryTaskById(taskId: String): List { + return taskBeanDao.queryBuilder().where(TaskBeanDao.Properties.TaskId.eq(taskId)).list() + } + + fun deleteTaskById(taskId: String?) { + if (taskId.isNullOrBlank()) { + return + } + queryTaskById(taskId).forEach { + taskBeanDao.delete(it) + } + } } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7d5d64d..6114ede 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,6 +11,7 @@ + diff --git a/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt index bd2c821..6ee3191 100644 --- a/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt @@ -44,6 +44,16 @@ suspend fun getTask(@Query("userName") userName: String): String /** + * 提交工单 + */ + @GET("/ems/rs/task/update") + suspend fun uploadTask( + @Query("userId") userId: String, + @Query("taskId") taskId: String, + @Query("state") state: String + ): String + + /** * 安装新标识器 */ @POST("/ems/marker/save-marker-photo.do") diff --git a/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt index 9972efd..1549f93 100644 --- a/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt @@ -60,6 +60,13 @@ } /** + * 提交工单 + */ + suspend fun uploadTask(userId: String, taskId: String?, state: String): String { + return api.uploadTask(userId, taskId.toString(), state) + } + + /** * 安装新标识器 */ suspend fun installLabel( diff --git a/app/src/main/java/com/casic/detector/utils/DataBaseManager.kt b/app/src/main/java/com/casic/detector/utils/DataBaseManager.kt index 581b66c..988d439 100644 --- a/app/src/main/java/com/casic/detector/utils/DataBaseManager.kt +++ b/app/src/main/java/com/casic/detector/utils/DataBaseManager.kt @@ -56,6 +56,10 @@ return count.toInt() } + fun clearTasks() { + taskBeanDao.deleteAll() + } + fun insertTaskInformation( scanner: String, desc: String, @@ -80,4 +84,26 @@ taskBeanDao.insert(task) } + + fun queryDistinctTask(): List { + val result = ArrayList() + taskBeanDao.loadAll().forEach { + result.add(it) + } + //根据TaskId去重 + return result.distinctBy { it.taskId } + } + + private fun queryTaskById(taskId: String): List { + return taskBeanDao.queryBuilder().where(TaskBeanDao.Properties.TaskId.eq(taskId)).list() + } + + fun deleteTaskById(taskId: String?) { + if (taskId.isNullOrBlank()) { + return + } + queryTaskById(taskId).forEach { + taskBeanDao.delete(it) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/view/MainActivity.kt b/app/src/main/java/com/casic/detector/view/MainActivity.kt index 107deb7..eaead98 100644 --- a/app/src/main/java/com/casic/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/detector/view/MainActivity.kt @@ -9,6 +9,7 @@ import android.net.Uri import android.os.Build import android.os.Bundle +import android.os.PowerManager import android.provider.Settings import android.util.Log import android.view.KeyEvent @@ -25,6 +26,7 @@ import com.casic.detector.BuildConfig import com.casic.detector.R import com.casic.detector.bean.LabelBean +import com.casic.detector.bean.TaskBean import com.casic.detector.callback.ILocationListener import com.casic.detector.cluster.ClusterItem import com.casic.detector.cluster.ClusterOverlay @@ -45,6 +47,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.android.synthetic.main.activity_main.* import kotlinx.coroutines.CoroutineScope @@ -71,10 +74,21 @@ private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } private var latitude: Double = 0.0 private var longitude: Double = 0.0 + private val powerManager by lazy { getSystemService() } + private var wakeLock: PowerManager.WakeLock? = null + private var taskBean: TaskBean? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + + wakeLock = powerManager?.run { + newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this@MainActivity.localClassName).apply { + //1h不休眠 + acquire(60 * 60 * 1000L) + } + } + setupTopBarLayout() initMapConfig(savedInstanceState) initData() @@ -180,8 +194,6 @@ if (it.isSuccess) { //清空之前的数据 DataBaseManager.get.clearTaskLabels() - //清空图层 - aMap.clear() //下载最新的数据 val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") val downloadUrl = companyId.toString().appendDownloadUrl(FileType.EXCEL) @@ -208,6 +220,8 @@ } taskViewModel.taskResult.observe(this) { if (it.success == "true") { + //清空之前的数据 + DataBaseManager.get.clearTasks() AlertMessageDialog.Builder() .setContext(this) .setTitle("温馨提示") @@ -230,13 +244,9 @@ val count = DataBaseManager.get.countTaskById(messageModel.id.toString()) if (count == 0) { messageModel.taskDetailInfos.forEach { info -> - val desc = if (info.description == null) { - "" - } else { - info.description.toString() - } DataBaseManager.get.insertTaskInformation( - userName, desc, + userName, + messageModel.description, info.taskId.toString(), info.taskCode.toString(), info.markerId.toString(), @@ -397,7 +407,52 @@ //巡检 inspectionButton.setOnClickListener { + val task = DataBaseManager.get.queryDistinctTask() + if (task.isNotEmpty()) { + val arrayList = ArrayList() + task.forEachIndexed { index, taskBean -> + arrayList.add("任务${index + 1}:${taskBean.taskId},${taskBean.desc}") + } + BottomActionSheet.Builder() + .setContext(this) + .setItemTextColor(Color.BLUE) + .setActionItemTitle(arrayList) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + taskBean = task[position] + + AlertControlDialog.Builder() + .setContext(context) + .setTitle("提示") + .setMessage("请选择操作方式") + .setPositiveButton("执行工单") + .setNegativeButton("提交工单") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + uploadTask(taskBean?.taskId, "1") + } + + override fun onCancelClick() { + uploadTask(taskBean?.taskId, "2") + } + }).build().show() + } + }).build().show() + } else { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("温馨提示") + .setMessage("现有任务已完成,请点击右上角菜单按钮下载新工单!") + .setPositiveButton("知道了") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + + } + }).build().show() + } } //探测 @@ -406,6 +461,23 @@ } } + private fun uploadTask(taskId: String?, state: String) { + if (isNetworkConnected()) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.uploadTask(userId, taskId, state) + } else { + NoNetworkDialog.Builder() + .setContext(context) + .setOnDialogButtonClickListener(object : + NoNetworkDialog.OnDialogButtonClickListener { + override fun onButtonClick() { + val intent = Intent(Settings.ACTION_SETTINGS) + startActivity(intent) + } + }).build().show() + } + } + //更新数据 private fun updateTaskData() { AlertControlDialog.Builder() @@ -526,7 +598,7 @@ taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "获取巡检工单中,请稍后") + LoadState.Loading -> LoadingDialogHub.show(this, "提交工单中,请稍后") else -> LoadingDialogHub.dismiss() } } @@ -619,6 +691,7 @@ } override fun onDestroy() { + wakeLock?.release() super.onDestroy() mapView.onDestroy() } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7d5d64d..6114ede 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,6 +11,7 @@ + diff --git a/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt index bd2c821..6ee3191 100644 --- a/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/detector/retrofit/RetrofitService.kt @@ -44,6 +44,16 @@ suspend fun getTask(@Query("userName") userName: String): String /** + * 提交工单 + */ + @GET("/ems/rs/task/update") + suspend fun uploadTask( + @Query("userId") userId: String, + @Query("taskId") taskId: String, + @Query("state") state: String + ): String + + /** * 安装新标识器 */ @POST("/ems/marker/save-marker-photo.do") diff --git a/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt index 9972efd..1549f93 100644 --- a/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/detector/retrofit/RetrofitServiceManager.kt @@ -60,6 +60,13 @@ } /** + * 提交工单 + */ + suspend fun uploadTask(userId: String, taskId: String?, state: String): String { + return api.uploadTask(userId, taskId.toString(), state) + } + + /** * 安装新标识器 */ suspend fun installLabel( diff --git a/app/src/main/java/com/casic/detector/utils/DataBaseManager.kt b/app/src/main/java/com/casic/detector/utils/DataBaseManager.kt index 581b66c..988d439 100644 --- a/app/src/main/java/com/casic/detector/utils/DataBaseManager.kt +++ b/app/src/main/java/com/casic/detector/utils/DataBaseManager.kt @@ -56,6 +56,10 @@ return count.toInt() } + fun clearTasks() { + taskBeanDao.deleteAll() + } + fun insertTaskInformation( scanner: String, desc: String, @@ -80,4 +84,26 @@ taskBeanDao.insert(task) } + + fun queryDistinctTask(): List { + val result = ArrayList() + taskBeanDao.loadAll().forEach { + result.add(it) + } + //根据TaskId去重 + return result.distinctBy { it.taskId } + } + + private fun queryTaskById(taskId: String): List { + return taskBeanDao.queryBuilder().where(TaskBeanDao.Properties.TaskId.eq(taskId)).list() + } + + fun deleteTaskById(taskId: String?) { + if (taskId.isNullOrBlank()) { + return + } + queryTaskById(taskId).forEach { + taskBeanDao.delete(it) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/view/MainActivity.kt b/app/src/main/java/com/casic/detector/view/MainActivity.kt index 107deb7..eaead98 100644 --- a/app/src/main/java/com/casic/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/detector/view/MainActivity.kt @@ -9,6 +9,7 @@ import android.net.Uri import android.os.Build import android.os.Bundle +import android.os.PowerManager import android.provider.Settings import android.util.Log import android.view.KeyEvent @@ -25,6 +26,7 @@ import com.casic.detector.BuildConfig import com.casic.detector.R import com.casic.detector.bean.LabelBean +import com.casic.detector.bean.TaskBean import com.casic.detector.callback.ILocationListener import com.casic.detector.cluster.ClusterItem import com.casic.detector.cluster.ClusterOverlay @@ -45,6 +47,7 @@ import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog +import com.pengxh.kt.lite.widget.dialog.BottomActionSheet import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.android.synthetic.main.activity_main.* import kotlinx.coroutines.CoroutineScope @@ -71,10 +74,21 @@ private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } private var latitude: Double = 0.0 private var longitude: Double = 0.0 + private val powerManager by lazy { getSystemService() } + private var wakeLock: PowerManager.WakeLock? = null + private var taskBean: TaskBean? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + + wakeLock = powerManager?.run { + newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this@MainActivity.localClassName).apply { + //1h不休眠 + acquire(60 * 60 * 1000L) + } + } + setupTopBarLayout() initMapConfig(savedInstanceState) initData() @@ -180,8 +194,6 @@ if (it.isSuccess) { //清空之前的数据 DataBaseManager.get.clearTaskLabels() - //清空图层 - aMap.clear() //下载最新的数据 val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") val downloadUrl = companyId.toString().appendDownloadUrl(FileType.EXCEL) @@ -208,6 +220,8 @@ } taskViewModel.taskResult.observe(this) { if (it.success == "true") { + //清空之前的数据 + DataBaseManager.get.clearTasks() AlertMessageDialog.Builder() .setContext(this) .setTitle("温馨提示") @@ -230,13 +244,9 @@ val count = DataBaseManager.get.countTaskById(messageModel.id.toString()) if (count == 0) { messageModel.taskDetailInfos.forEach { info -> - val desc = if (info.description == null) { - "" - } else { - info.description.toString() - } DataBaseManager.get.insertTaskInformation( - userName, desc, + userName, + messageModel.description, info.taskId.toString(), info.taskCode.toString(), info.markerId.toString(), @@ -397,7 +407,52 @@ //巡检 inspectionButton.setOnClickListener { + val task = DataBaseManager.get.queryDistinctTask() + if (task.isNotEmpty()) { + val arrayList = ArrayList() + task.forEachIndexed { index, taskBean -> + arrayList.add("任务${index + 1}:${taskBean.taskId},${taskBean.desc}") + } + BottomActionSheet.Builder() + .setContext(this) + .setItemTextColor(Color.BLUE) + .setActionItemTitle(arrayList) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + taskBean = task[position] + + AlertControlDialog.Builder() + .setContext(context) + .setTitle("提示") + .setMessage("请选择操作方式") + .setPositiveButton("执行工单") + .setNegativeButton("提交工单") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + uploadTask(taskBean?.taskId, "1") + } + + override fun onCancelClick() { + uploadTask(taskBean?.taskId, "2") + } + }).build().show() + } + }).build().show() + } else { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("温馨提示") + .setMessage("现有任务已完成,请点击右上角菜单按钮下载新工单!") + .setPositiveButton("知道了") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + + } + }).build().show() + } } //探测 @@ -406,6 +461,23 @@ } } + private fun uploadTask(taskId: String?, state: String) { + if (isNetworkConnected()) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.uploadTask(userId, taskId, state) + } else { + NoNetworkDialog.Builder() + .setContext(context) + .setOnDialogButtonClickListener(object : + NoNetworkDialog.OnDialogButtonClickListener { + override fun onButtonClick() { + val intent = Intent(Settings.ACTION_SETTINGS) + startActivity(intent) + } + }).build().show() + } + } + //更新数据 private fun updateTaskData() { AlertControlDialog.Builder() @@ -526,7 +598,7 @@ taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "获取巡检工单中,请稍后") + LoadState.Loading -> LoadingDialogHub.show(this, "提交工单中,请稍后") else -> LoadingDialogHub.dismiss() } } @@ -619,6 +691,7 @@ } override fun onDestroy() { + wakeLock?.release() super.onDestroy() mapView.onDestroy() } diff --git a/app/src/main/java/com/casic/detector/vm/TaskViewModel.kt b/app/src/main/java/com/casic/detector/vm/TaskViewModel.kt index d80069e..845b2b8 100644 --- a/app/src/main/java/com/casic/detector/vm/TaskViewModel.kt +++ b/app/src/main/java/com/casic/detector/vm/TaskViewModel.kt @@ -9,11 +9,13 @@ import com.casic.detector.model.MarkerImageModel import com.casic.detector.model.TaskModel import com.casic.detector.retrofit.RetrofitServiceManager +import com.casic.detector.utils.DataBaseManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.vm.BaseViewModel +import com.pengxh.kt.lite.vm.LoadState class TaskViewModel : BaseViewModel() { private val gson by lazy { Gson() } @@ -127,4 +129,20 @@ }, { it.convertChinese().show(BaseApplication.get()) }) + + fun uploadTask(userId: String, taskId: String?, state: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.uploadTask(userId, taskId, state) + if (response.separateResponseState()) { + loadState.value = LoadState.Success + //删除本地数据库 + DataBaseManager.get.deleteTaskById(taskId) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + loadState.value = LoadState.Fail + it.convertChinese().show(BaseApplication.get()) + }) } \ No newline at end of file