src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImpl.kt
@@ -1,29 +1,44 @@
package com.flightfeather.uav.lightshare.service.impl
import com.flightfeather.uav.common.utils.DateUtil
import com.flightfeather.uav.common.utils.ExcelUtil
import com.flightfeather.uav.common.utils.FileExchange
import com.flightfeather.uav.common.utils.GsonUtils
import com.flightfeather.uav.domain.entity.RealTimeData
import com.flightfeather.uav.domain.entity.*
import com.flightfeather.uav.domain.mapper.RealTimeDataGridMapper
import com.flightfeather.uav.domain.mapper.RealTimeDataMapper
import com.flightfeather.uav.lightshare.bean.BaseResponse
import com.flightfeather.uav.lightshare.bean.DataHead
import com.flightfeather.uav.lightshare.bean.DataImportResult
import com.flightfeather.uav.lightshare.bean.DataVo
import com.flightfeather.uav.domain.mapper.RealTimeDataUavMapper
import com.flightfeather.uav.domain.mapper.RealTimeDataVehicleMapper
import com.flightfeather.uav.lightshare.bean.*
import com.flightfeather.uav.lightshare.service.RealTimeDataService
import com.flightfeather.uav.model.epw.EPWDataPrep
import com.flightfeather.uav.repository.AirDataRepository
import com.flightfeather.uav.socket.bean.AirData
import com.flightfeather.uav.socket.eunm.UWDeviceType
import com.github.pagehelper.PageHelper
import org.apache.poi.xssf.streaming.SXSSFWorkbook
import org.springframework.stereotype.Service
import org.springframework.web.multipart.MultipartFile
import tk.mybatis.mapper.entity.Example
import java.io.ByteArrayInputStream
import java.io.FileInputStream
import java.io.InputStream
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.*
import javax.servlet.http.HttpServletResponse
import javax.swing.text.DateFormatter
@Service
class RealTimeDataServiceImpl(val realTimeDataMapper: RealTimeDataMapper) : RealTimeDataService {
class RealTimeDataServiceImpl(
    private val realTimeDataMapper: RealTimeDataMapper,
    private val airDataRepository: AirDataRepository,
    private val realTimeDataVehicleMapper: RealTimeDataVehicleMapper,
    private val realTimeDataUavMapper: RealTimeDataUavMapper,
    private val realTimeDataGridMapper: RealTimeDataGridMapper
) : RealTimeDataService {
    private var dateFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    private var dateFormatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
    private val fileExchange = FileExchange()
    override fun getSecondData(deviceCode: String?, startTime: String?, endTime: String?, page: Int?, perPage: Int?): BaseResponse<List<DataVo>> {
@@ -31,32 +46,70 @@
        val _page = page ?: 1
        val sTime = startTime?.let { dateFormatter.parse(it) }
        val eTime = endTime?.let { dateFormatter.parse(it) }
        val pageInfo = PageHelper.startPage<RealTimeData>(_page, _perPage)
//        var pageInfo = PageHelper.startPage<BaseRealTimeData>(_page, _perPage)
        var pageNum = 1
        var pages = 0
        val result = mutableListOf<DataVo>()
        realTimeDataMapper.selectByExample(Example(RealTimeData::class.java).apply {
            createCriteria().apply {
                deviceCode?.let { andEqualTo("deviceCode", it) }
                sTime?.let { andGreaterThanOrEqualTo("dataTime", it) }
                eTime?.let { andLessThanOrEqualTo("dataTime", it) }
        when (UWDeviceType.getType(deviceCode)) {
            UWDeviceType.VEHICLE -> {
                val pageInfo = PageHelper.startPage<RealTimeDataVehicle>(_page, _perPage)
                realTimeDataVehicleMapper.selectByExample(Example(RealTimeDataVehicle::class.java).apply {
                    getSecondDataExample(this, deviceCode, sTime, eTime)
                }).forEach { result.add(it.toDataVo()) }
                pageNum = pageInfo.pageNum
                pages = pageInfo.pages
            }
            orderBy("dataTime").apply {
                // 当请求接口不传递起始时间,默认获取最新的数据
                if (startTime == null && endTime == null) {
                    desc()
            UWDeviceType.UAV -> {
                val pageInfo = PageHelper.startPage<RealTimeDataUav>(_page, _perPage)
                realTimeDataUavMapper.selectByExample(Example(RealTimeDataUav::class.java).apply {
                    getSecondDataExample(this, deviceCode, sTime, eTime)
                }).forEach { result.add(it.toDataVo()) }
                pageNum = pageInfo.pageNum
                pages = pageInfo.pages
            }
            UWDeviceType.GRID -> {
                val pageInfo = PageHelper.startPage<RealTimeDataGrid>(_page, _perPage)
                realTimeDataGridMapper.selectByExample(Example(RealTimeDataGrid::class.java).apply {
                    getSecondDataExample(this, deviceCode, sTime, eTime)
                }).forEach { result.add(it.toDataVo()) }
                pageNum = pageInfo.pageNum
                pages = pageInfo.pages
            }
            else -> {
                // 从原始数据表中获取数据
                val pageInfo = PageHelper.startPage<RealTimeData>(_page, _perPage)
                realTimeDataMapper.selectByExample(Example(RealTimeData::class.java).apply {
                    getSecondDataExample(this, deviceCode, sTime, eTime)
                }).forEach {
                    if (it.longitude == null || it.latitude == null) {
                        return@forEach
                    }
                    result.add(it.toDataVo())
                }
                pageNum = pageInfo.pageNum
                pages = pageInfo.pages
            }
        }).forEach {
            result.add(DataVo(
                    dateFormatter.format(it.dataTime),
                    it.deviceCode,
                    GsonUtils.parserJsonToArrayBeans(it.factors, AirData::class.java),
                    it.longitude.toDouble(), it.latitude.toDouble()
            ))
        }
        if (startTime == null && endTime == null) {
            result.reverse()
        }
        return BaseResponse(true, head = DataHead(pageInfo.pageNum, pageInfo.pages), data = result)
        return BaseResponse(true, head = DataHead(pageNum, pages), data = result)
    }
    private fun getSecondDataExample(example: Example, deviceCode: String?, sTime: Date?, eTime: Date?) {
        example.createCriteria().apply {
            deviceCode?.let { andEqualTo("deviceCode", it) }
            sTime?.let { andGreaterThanOrEqualTo("dataTime", it) }
            eTime?.let { andLessThanOrEqualTo("dataTime", it) }
        }
        example.orderBy("dataTime").apply {
            // 当请求接口不传递起始时间,默认获取最新的数据
            if (sTime == null && eTime == null) {
                desc()
            }
        }
    }
    override fun getNextData(deviceCode: String, updateTime: String, page: Int?, perPage: Int?): BaseResponse<List<DataVo>> {
@@ -64,19 +117,36 @@
        val _page = page ?: 1
        val pageInfo = PageHelper.startPage<RealTimeData>(_page, _perPage)
        val result = mutableListOf<DataVo>()
        realTimeDataMapper.selectByExample(Example(RealTimeData::class.java).apply {
            createCriteria().andEqualTo("deviceCode", deviceCode)
                .andGreaterThan("dataTime", updateTime)
            orderBy("dataTime")
        }).forEach {
            result.add(DataVo(
                dateFormatter.format(it.dataTime),
                it.deviceCode,
                GsonUtils.parserJsonToArrayBeans(it.factors, AirData::class.java),
                it.longitude.toDouble(), it.latitude.toDouble()
            ))
        when (UWDeviceType.getType(deviceCode)) {
            UWDeviceType.VEHICLE -> {
                realTimeDataVehicleMapper.selectByExample(Example(RealTimeDataVehicle::class.java).apply {
                    getNextDataExample(this, deviceCode, updateTime)
                }).forEach { result.add(it.toDataVo()) }
            }
            UWDeviceType.UAV -> {
                realTimeDataUavMapper.selectByExample(Example(RealTimeDataUav::class.java).apply {
                    getNextDataExample(this, deviceCode, updateTime)
                }).forEach { result.add(it.toDataVo()) }
            }
            UWDeviceType.GRID -> {
                realTimeDataGridMapper.selectByExample(Example(RealTimeDataGrid::class.java).apply {
                    getNextDataExample(this, deviceCode, updateTime)
                }).forEach { result.add(it.toDataVo()) }
            }
            else -> {
                realTimeDataMapper.selectByExample(Example(RealTimeData::class.java).apply {
                    getNextDataExample(this, deviceCode, updateTime)
                }).forEach { result.add(it.toDataVo()) }
            }
        }
        return BaseResponse(true, head = DataHead(pageInfo.pageNum, pageInfo.pages), data = result)
    }
    private fun getNextDataExample(example: Example, deviceCode: String, updateTime: String) {
        example.createCriteria().andEqualTo("deviceCode", deviceCode)
            .andGreaterThan("dataTime", updateTime)
        example.orderBy("dataTime")
    }
    override fun importData(file: MultipartFile): BaseResponse<DataImportResult> {
@@ -86,4 +156,143 @@
        }
        return BaseResponse(true, data = DataImportResult(""))
    }
    override fun outToWorkbook(deviceCode: String, startTime: String, endTime: String): SXSSFWorkbook {
        val sTime = dateFormatter.parse(startTime)
        val eTime = dateFormatter.parse(endTime)
        var page = 1
        var totalPage = 1
        val pageSize = 10000
        val workbook = SXSSFWorkbook()
        var rowIndex = 0
        while (page <= totalPage) {
            val pageInfo = PageHelper.startPage<RealTimeData>(page, pageSize)
            val r = realTimeDataMapper.selectByExample(Example(RealTimeData::class.java).apply {
                createCriteria().andEqualTo("deviceCode", deviceCode)
                    .apply {
                        sTime?.let { andGreaterThanOrEqualTo("dataTime", it) }
                        eTime?.let { andLessThanOrEqualTo("dataTime", it) }
                    }
            })
            if (r.isNotEmpty()) {
                val heads = if (page == 1) {
                    println("[${DateUtil.instance.dateToString(Date(), DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS)}] totalPage: ${pageInfo.pages}")
                    getTableTitle(r[0])
                } else {
                    emptyList()
                }
                val contents = getTableContents(r)
                print("[${DateUtil.instance.dateToString(Date(), DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS)}] currentPage: ${pageInfo.pageNum}......")
                rowIndex = ExcelUtil.write(heads, contents, workbook, row = rowIndex)
                println("output done")
            }
            totalPage = pageInfo.pages
            page++
        }
        return workbook
    }
    override fun outToExcel(deviceCode: String, startTime: String, endTime: String, response: HttpServletResponse): HttpServletResponse {
        val workbook = outToWorkbook(deviceCode, startTime, endTime)
        val out = response.outputStream
        workbook.write(out)
        workbook.close()
        out.flush()
        out.close()
        return response
    }
    fun getTableTitle(d: RealTimeData): List<Array<String>> {
        return listOf(d.toRowTitle())
    }
    fun getTableContents(list: List<RealTimeData>): List<Array<Any>> {
        val contents = mutableListOf<Array<Any>>()
        list.forEach {
            contents.add(it.toRowContent())
        }
        return contents
    }
    private fun getOriginData(deviceCode: String?, startTime: String?, endTime: String?, page: Int?, perPage: Int?): BaseResponse<List<DataVo>> {
        val _perPage = perPage ?: 60
        val _page = page ?: 1
        val sTime = startTime?.let { dateFormatter.parse(it) }
        val eTime = endTime?.let { dateFormatter.parse(it) }
//        var pageInfo = PageHelper.startPage<BaseRealTimeData>(_page, _perPage)
        var pageNum = 1
        var pages = 0
        val result = mutableListOf<DataVo>()
        // 从原始数据表中获取数据
        val pageInfo = PageHelper.startPage<RealTimeData>(_page, _perPage)
        realTimeDataMapper.selectByExample(Example(RealTimeData::class.java).apply {
            getSecondDataExample(this, deviceCode, sTime, eTime)
        }).forEach {
            if (it.longitude == null || it.latitude == null) {
                return@forEach
            }
            result.add(it.toDataVo())
        }
        pageNum = pageInfo.pageNum
        pages = pageInfo.pages
        if (startTime == null && endTime == null) {
            result.reverse()
        }
        return BaseResponse(true, head = DataHead(pageNum, pages), data = result)
    }
    override fun dataPreprocessing(): BaseResponse<String> {
        val epwDataPrep = EPWDataPrep()
        var page = 1
        var total = -1
        var count = 0
        while (total == -1 || page <= total) {
            println("------start------")
            val res = getOriginData("0d0000000001", "2021-07-05 19:47:01", "2021-11-05 00:00:00", page, 50000)
            res.head?.let {
                total = it.totalPage
            }
            if (page == 1) {
                println("总页数:$total")
            }
            println("当前页数:$page")
            val dataList = res.data ?: emptyList()
            val result = epwDataPrep.mDataPrep2(dataList)
            count += airDataRepository.savePrepData2(result)
            page++
        }
        return BaseResponse(count > 0, data = "插入数据: ${count}条")
    }
    override fun averageData(): BaseResponse<String> {
        val epwDataPrep = EPWDataPrep()
        var page = 1
        var total = -1
        var count = 0
        while (total == -1 || page <= total) {
            println("------start------")
            val res = getOriginData("0d0000000001", "2021-07-05 19:47:01", "2021-11-05 00:00:00", page, 50000)
            res.head?.let {
                total = it.totalPage
            }
            if (page == 1) {
                println("总页数:$total")
            }
            println("当前页数:$page")
            res.data?.forEach {
            }
            page++
        }
        return BaseResponse(count > 0, data = "插入数据: ${count}条")
    }
}