张洋洋
2025-01-10 a28eb2cb2abdd3f27075ca8468cf1a2bbf7de3cf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
package com.se.simu.controller;
 
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.se.simu.config.PropertiesConfig;
import com.se.simu.domain.dto.GeDb;
import com.se.simu.domain.dto.GeLayer;
import com.se.simu.domain.po.DataPo;
import com.se.simu.domain.po.SimuPo;
import com.se.simu.domain.vo.*;
import com.se.simu.service.*;
import com.se.simu.utils.CsvToSQLiteUtils;
import com.se.simu.utils.ShpToolUtils;
import com.se.simu.utils.ZarrUtils;
import com.se.simu.utils.ZipUtils;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
 
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.*;
 
@Api(tags = "仿真管理")
@Slf4j
@RestController
@RequestMapping("/simu")
@SuppressWarnings("ALL")
public class SimuController extends BaseController {
    @Resource
    UwService uwService;
 
    @Resource
    GedbService gedbService;
 
    @Resource
    SimuService simuService;
 
    @Resource
    SimuFilesService simuFilesService;
 
    @Resource
    PropertiesConfig config;
 
    @Value("${simu-app.filePath}")
    private String uploadedFolder;
 
 
    @Resource
    ResultService resultService;
 
    private final List<String> FLOOD_TYPE = new ArrayList<>(Arrays.asList("沙袋", "防水板"));
 
    @ApiOperation(value = "创建")
    @PostMapping(value = "/create", produces = "application/json; charset=UTF-8")
    public R<Object> create(@RequestBody @ApiParam("创建仿真视图类") CreateSimuVo vo) {
        try {
            if (null == vo.getTotal() || vo.getTotal() < 1 || vo.getTotal() > 1000) {
                return fail("降雨量不能为空,且取值在1~1000之间");
            }
            if (null == vo.getDuration() || vo.getDuration() < 1 || vo.getDuration() > 10080) {
                return fail("仿真时长不能为空,且取值在1~10080之间");
            }
            if (null == vo.getMinx() || null == vo.getMiny() || null == vo.getMaxx() || null == vo.getMaxy()) {
                return fail("选择范围不能为空", false);
            }
            if (null == vo.getPid() || vo.getPid() < 0) {
                vo.setPid(0);
            }
            if (null == vo.getNum() || vo.getNum() < 1) {
                vo.setNum(simuService.getMaxId() + 1);
            }
            if (null == vo.getPid() || vo.getPid() < 0) {
                vo.setPid(0);
            }
            if (null == vo.getStartTime()) {
                vo.setStartTime(new Date());
            }
            if (vo.getPid() > 0) {
                SimuPo pp = simuService.getSimuByPid(vo.getPid());
                if (null == pp) {
                    return fail("pid不存在");
                }
                if (null == vo.getFloodStart() || vo.getFloodStart() < 1 || vo.getFloodStart() > vo.getDuration() * 60) {
                    return fail("防汛开始时间不能为空,且取值在1~" + (vo.getDuration() * 60) + "之间");
                }
                if (null == vo.getFloodEnd() || vo.getFloodEnd() < vo.getFloodStart() || vo.getFloodEnd() > vo.getDuration() * 60) {
                    return fail("防汛结束时间不能为空,且取值在" + vo.getFloodStart() + "~" + (vo.getDuration() * 60) + "之间");
                }
                if (null == vo.getFloodHeight() || vo.getFloodHeight() < 1 || vo.getFloodHeight() > 2000) {
                    return fail("防汛高度不能为空,且取值在1~2000之间");
                }
                if (!FLOOD_TYPE.contains(vo.getFloodType())) {
                    return fail("防汛类型不能为空,且只能是沙袋和防水板");
                }
                if (null == vo.getFloodMinx() || null == vo.getFloodMiny() || null == vo.getFloodMaxx() || null == vo.getFloodMaxy()) {
                    return fail("防汛范围不能为空", false);
                }
            }
 
            boolean flag = simuService.create(vo);
 
            return success(flag, flag ? "成功" : "失败");
        } catch (Exception ex) {
            return fail(ex, null);
        }
    }
 
    @ApiOperation(value = "删除")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ids", value = "ID", dataType = "Integer", paramType = "query", allowMultiple = true, example = "0")
    })
    @GetMapping(value = "/del")
    public R<Object> del(@RequestParam List<Integer> ids) {
        try {
            if (ids == null || ids.isEmpty()) {
                return fail("日志ID不能为空", null);
            }
 
            int count = simuService.del(ids);
 
            return success(count);
        } catch (Exception ex) {
            return fail(ex, null);
        }
    }
 
    @ApiOperation(value = "获取")
    @GetMapping("/get")
    public R<Object> get(@ApiParam("仿真视图类") SimuVo vo) {
        try {
            if (null == vo) {
                vo = new SimuVo();
            }
            if (null == vo.getPageSize() || vo.getPageSize() < 1) {
                vo.setPageSize(10);
            }
            if (null == vo.getPageIndex() || vo.getPageIndex() < 1) {
                vo.setPageIndex(1);
            }
 
            IPage<SimuPo> paged = simuService.get(vo);
            if (null == paged) {
                return success(null, 0);
            }
 
            return success(paged.getRecords(), paged.getTotal());
        } catch (Exception ex) {
            return fail(ex, null);
        }
    }
 
    @ApiOperation(value = "降水范围校验")
    @GetMapping("/rangeVerify")
    public R<Object> rangeVerify(@RequestParam @ApiParam("最小X") double minx,
                                 @RequestParam @ApiParam("最小y") double miny,
                                 @RequestParam @ApiParam("最大X") double maxx,
                                 @RequestParam @ApiParam("最大y") double maxy) {
        try {
            DataPo data = new DataPo();
            data.setMinx(minx);
            data.setMiny(miny);
            data.setMaxx(maxx);
            data.setMaxy(maxy);
            data.setEpsg(4326);
 
            String token = gedbService.getToken();
            GeDb db = gedbService.connectGedb(token, data);
            List<GeLayer> layers = gedbService.getLayers(token, db);
            boolean result = gedbService.queryBboxCount(token, db, layers);
            log.info("result = " + result);
            return success(result);
 
            //  return success(gedbService.queryBboxCount(token, db, layers));
        } catch (Exception ex) {
            return fail(ex, false);
        }
    }
 
    /**
     * 文件创建模拟
     * <p>
     * "状态:
     * 0-创建仿真任务,
     * 1-连接GEDB库,
     * 2-下载空间数据,
     * 3-下载高程数据,
     * 4-生成降雨文件,
     * 5-生成配置文件,
     * 6-模拟内涝仿真,
     * 7-处理水位文件,
     * 8-处理排水文件,
     * 9-处理仿真结果,
     * 10-完成,-10-出错
     *
     * @param vo VO
     * @return {@link R}<{@link Object}>
     */
    @ApiOperation(value = "文件创建")
    @PostMapping(value = "/file_create", produces = "application/json; charset=UTF-8")
    public R<Object> fileCreate(@RequestBody @ApiParam("创建仿真视图类") CreateFilesSimuVo vo) throws IOException {
        // 获取上传文件路径
        String targetDir = uploadedFolder;
        log.info("上传文件路径:{}", targetDir);
        // 获取各个文件的地址
        String floodFile = vo.getFloodFile();
        log.info("范围文件地址:{}", floodFile);
        try {
            // 判断是否绘制区域
            if (!StringUtils.isEmpty(vo.getMaxx().toString()) && !Objects.isNull(vo.getMaxx())) {
                rangeVerify(vo.getMinx(), vo.getMaxx(), vo.getMiny(), vo.getMaxy());
                log.info("绘制区域范围验证通过!");
            } else
                // 判断地址不为空
                if (StringUtils.isEmpty(floodFile)) {
                    return fail("范围文件地址不能为空", false);
                } else {
                    // 获取文件的后缀名
                    String fileName = floodFile.substring(floodFile.lastIndexOf("."));
                    // 判断后缀名是否为.shp
                    if (!fileName.equalsIgnoreCase(".shp")) {
                        return fail("范围文件格式不正确", false);
                    } else {
                        // 1 读取shp文件,获取范围值
                        JSONObject jsonObject = ShpToolUtils.readShp(floodFile);
                        // 2 获取jsonObject中的范围值
                        Double minX = jsonObject.getDouble("minY");
                        Double maxX = jsonObject.getDouble("maxY");
                        Double minY = jsonObject.getDouble("minX");
                        Double maxY = jsonObject.getDouble("maxX");
                        // 3 判断范围值是否为空
                        // vo.setMinx(jsonObject.getDouble("minX"));
                        // vo.setMaxx(jsonObject.getDouble("maxX"));
                        // vo.setMiny(jsonObject.getDouble("minY"));
                        // vo.setMaxy(jsonObject.getDouble("maxY"));
                        vo.setMinx(jsonObject.getDouble("minY"));
                        vo.setMaxx(jsonObject.getDouble("maxY"));
                        vo.setMiny(jsonObject.getDouble("minX"));
                        vo.setMaxy(jsonObject.getDouble("maxX"));
                        rangeVerify(minX, maxX, minY, maxY);
                    }
                }
            // todo: 解析范围文件 根据不同的的格式文件进行不同的解析,获取需要计算的范围值
            //  上传格式:.shp/.tiff/.img/.geojson
            //  重新给vo赋值
        } catch (Exception e) {
            log.error("解析范围文件失败");
            if (null == vo.getMinx() || null == vo.getMiny() || null == vo.getMaxx() || null == vo.getMaxy()) {
                return fail("解析范围文件失败!选择范围不能为空,请重新选择文件!", false);
            }
        }
        JSONArray jsonArray = new JSONArray();
        String stationFile = vo.getStationFile();
        log.info("站点文件shp地址:{}", stationFile);
        try {
            // 判断地址不为空
            if (StringUtils.isEmpty(stationFile)) {
                return fail("站点文件shp地址不能为空", false);
            }
            // 1 读取shp文件,获取站点坐标值
            jsonArray = ShpToolUtils.readShpGetLocal(stationFile);
            System.out.println("jsonArray = " + jsonArray);
        } catch (Exception e) {
            log.error("解析站点文件shp失败");
        }
 
        String stationRainFile = vo.getStationRainFile();
        log.info("站点雨量CSV文件地址:{}", floodFile);
        JSONArray array = new JSONArray();
        // 创建表名 时间戳
        String tableName = "station_rain_" + System.currentTimeMillis();
        try {
            // 判断地址不为空
            if (StringUtils.isEmpty(stationRainFile)) {
                return fail("站点雨量CSV文件地址不能为空", false);
            }
            // 1 读取CSV 文件
            array = CsvToSQLiteUtils.readCsvSaveLocal(stationRainFile, tableName);
            // 获取仿真时间 duration
            Integer duration = CsvToSQLiteUtils.getDuration(tableName);
            log.info("仿真时间 duration = {}", duration);
            vo.setDuration(duration);
 
            // 获取降雨总量 total
            Double total = CsvToSQLiteUtils.getTotal(tableName);
            log.info("降雨总量 total = {}", total);
            vo.setTotal(total);
 
        } catch (Exception e) {
            log.error("解析站点雨量CSV文件失败");
        }
        // TODO: 2024/12/24 根据这些文件的地址,获取文件内容,创建仿真视图
        try {
            if (null == vo.getDuration() || vo.getDuration() < 1 || vo.getDuration() > 10080) {
                return fail("仿真时长不能为空,且取值在1~10080之间");
            }
            if (null == vo.getPid() || vo.getPid() < 0) {
                vo.setPid(0);
            }
            if (null == vo.getNum() || vo.getNum() < 1) {
                vo.setNum(simuService.getMaxId() + 1);
            }
            if (null == vo.getStartTime()) {
                vo.setStartTime(new Date());
            }
            // 防汛作业
            if (vo.getPid() > 0) {
                SimuPo pp = simuService.getSimuByPid(vo.getPid());
                if (null == pp) {
                    return fail("pid不存在");
                }
                if (null == vo.getFloodStart() || vo.getFloodStart() < 1 || vo.getFloodStart() > vo.getDuration() * 60) {
                    return fail("防汛开始时间不能为空,且取值在1~" + (vo.getDuration() * 60) + "之间");
                }
                if (null == vo.getFloodEnd() || vo.getFloodEnd() < vo.getFloodStart() || vo.getFloodEnd() > vo.getDuration() * 60) {
                    return fail("防汛结束时间不能为空,且取值在" + vo.getFloodStart() + "~" + (vo.getDuration() * 60) + "之间");
                }
                if (null == vo.getFloodHeight() || vo.getFloodHeight() < 1 || vo.getFloodHeight() > 2000) {
                    return fail("防汛高度不能为空,且取值在1~2000之间");
                }
                if (!FLOOD_TYPE.contains(vo.getFloodType())) {
                    return fail("防汛类型不能为空,且只能是沙袋和防水板");
                }
                if (null == vo.getFloodMinx() || null == vo.getFloodMiny() || null == vo.getFloodMaxx() || null == vo.getFloodMaxy()) {
                    return fail("防汛范围不能为空", false);
                }
            }
            //todo 组装cityjson
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("shp", jsonArray);
            jsonObject.put("csv", array);
            // 开始模拟计算
            boolean flag = simuFilesService.createByfiles(vo);
            return success(flag, flag ? "成功" : "失败");
        } catch (Exception ex) {
            return fail(ex, null);
        }
    }
 
    @ApiOperation(value = "tarr文件组装")
    @GetMapping(value = "/testZarr", produces = "application/json; charset=UTF-8")
    public R<Boolean> testZarr(@RequestParam("name") String tableName) throws IOException {
        List<String> list = CsvToSQLiteUtils.getNameList(tableName);
        String basePath="D:\\城市内涝\\sem\\雨量站点数据\\"+tableName+"\\rainfall\\";
        for (String src : list
        ) {
            File directories = new File(basePath);
            if (!directories.exists()) {
                directories.mkdirs();
                System.out.println("Directories created successfully.");
            } else {
                System.out.println("Directories already exist.");
            }
            List<StationRainVo> stationRainVos = CsvToSQLiteUtils.getList(tableName, src);
            ZarrUtils.saveZarrRainfall(basePath+src,stationRainVos);
            ZarrUtils.saveZarrTime(basePath+src,stationRainVos);
            ZipUtils.toZarr(basePath+src,basePath+src+".zip");
            System.out.println(src+"的zarr数据生成=====================");
        }
        return success(true);
    }
 
}