Browse Source

Merge commit '3e9244ab9e517a1b8a20990edb701ee93b4d1b8d' into feature/dos/statistics

feature/dos/statistics
lkd9125(이경도) 5 days ago
parent
commit
b05d7dbdb3
  1. 4
      http/server/common.http
  2. 37
      pav-server/src/main/java/com/palnet/biz/api/comn/coordinate/model/CompotentAuthorityItemRS.java
  3. 8
      pav-server/src/main/java/com/palnet/biz/api/comn/coordinate/model/CompotentAuthorityRQ.java
  4. 2
      pav-server/src/main/java/com/palnet/biz/api/comn/coordinate/model/CompotentAuthorityRS.java
  5. 88
      pav-server/src/main/java/com/palnet/biz/api/comn/coordinate/service/ComnCoordinateService.java
  6. 17
      pav-server/src/main/java/com/palnet/biz/api/external/model/DosCptAuthResult.java
  7. 57
      pav-server/src/main/java/com/palnet/biz/api/external/service/DronOneStopService.java
  8. 62
      pav-server/src/main/java/com/palnet/comn/utils/AirspaceUtils.java
  9. 1116
      pav-server/src/main/java/com/palnet/comn/utils/CoordUtils.java
  10. 42
      pav-server/src/test/java/com/palnet/biz/api/comn/coordinate/service/ComnCoordinateServiceTest.java
  11. 13
      pav-server/src/test/java/com/palnet/biz/api/external/service/DronOneStopServiceTest.java

4
http/server/common.http

@ -0,0 +1,4 @@
### 좌표 to 관할지역
GET {{appHost}}/api/comn/coordinate/comptent-authority
?lat=37.5666103&lon=126.978
Authorization: {{accessToken}}

37
pav-server/src/main/java/com/palnet/biz/api/comn/coordinate/model/CompotentAuthorityItemRS.java

@ -0,0 +1,37 @@
package com.palnet.biz.api.comn.coordinate.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.Instant;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CompotentAuthorityItemRS {
// 관할기관코드
private String cptAuthCode;
// 관할기관명
private String cptAuthNm;
// 관할기관연락처
private String cptAuthTp;
// 관할기관FAX
private String cptAuthFax;
// 비고
private String rm;
// 수정일자
private Instant updateDt;
// 생성일자
private Instant createDt;
}

8
pav-server/src/main/java/com/palnet/biz/api/comn/coordinate/model/CompotentAuthorityRQ.java

@ -1,12 +1,18 @@
package com.palnet.biz.api.comn.coordinate.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CompotentAuthorityRQ {
private Double lat;
private Double lon;
}

2
pav-server/src/main/java/com/palnet/biz/api/comn/coordinate/model/CompotentAuthorityRS.java

@ -13,6 +13,6 @@ public class CompotentAuthorityRS {
private String address;
private List<FltCptAuthBas> fltCptpAuthBasList;
private List<CompotentAuthorityItemRS> fltCptpAuthBasList;
}

88
pav-server/src/main/java/com/palnet/biz/api/comn/coordinate/service/ComnCoordinateService.java

@ -1,20 +1,17 @@
package com.palnet.biz.api.comn.coordinate.service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil;
import com.palnet.biz.api.comn.coordinate.model.*;
import com.palnet.biz.jpa.entity.ComAdmDistrictBas;
import com.palnet.biz.jpa.entity.FltCptAuthBas;
import com.palnet.biz.jpa.repository.com.ComAdmDistrictBasRepository;
import com.palnet.biz.jpa.repository.flt.FltCptAuthAdmDistrictRelRepository;
import com.palnet.biz.jpa.repository.flt.FltCptAuthAdminDistrictBasQueryRepository;
import com.palnet.comn.code.ErrorCode;
import com.palnet.comn.exception.CustomException;
import com.palnet.comn.utils.CoordUtils;
import com.palnet.comn.utils.DmsUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException;
@ -24,12 +21,13 @@ import org.locationtech.jts.geom.GeometryFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.palnet.biz.jpa.entity.FltCptAuthBas;
import com.palnet.biz.jpa.repository.flt.FltCptAuthAdminDistrictBasQueryRepository;
import com.palnet.comn.utils.CoordUtils;
import com.palnet.comn.utils.DmsUtils;
import lombok.RequiredArgsConstructor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@ -50,9 +48,9 @@ public class ComnCoordinateService {
Coordinate coord = new Coordinate(rq.getLat(), rq.getLon());
CoordUtils utils = CoordUtils.getInstance();
String dms = DmsUtils.convertDDtoDMS(coord);
JSONObject code = new JSONObject();
try {
code = utils.getPlace(coord);
@ -63,24 +61,74 @@ public class ComnCoordinateService {
String[] scope = {"ctprvn", "sig", "emd", "li"};
final String cd = (String) code.get("CD");
Set<FltCptAuthBas> fltCptAuthBas = new HashSet<>();
Set<CompotentAuthorityItemRS> fltCptAuthBas = new HashSet<>();
for (String s : scope) {
String cdParam = CoordUtils.getInstance().addAdmCd(cd, s);
List<FltCptAuthBas> authList = fltCptAuthAdminDistrictBasQueryRepository.getFltCptAuthBas(cdParam);
fltCptAuthBas.addAll(new HashSet<>(authList));
List<CompotentAuthorityItemRS> itemList = authList.stream().map(item -> CompotentAuthorityItemRS.builder()
.cptAuthCode(item.getCptAuthCode())
.cptAuthNm(item.getCptAuthNm())
.cptAuthTp(item.getCptAuthTp())
.cptAuthFax(item.getCptAuthFax())
.rm(item.getRm())
.updateDt(item.getUpdateDt())
.createDt(item.getCreateDt())
.build()).collect(Collectors.toList());
fltCptAuthBas.addAll(new HashSet<>(itemList));
}
CompotentAuthorityRS result = new CompotentAuthorityRS();
result.setFltCptpAuthBasList(new ArrayList<>(fltCptAuthBas));
result.setDMS(dms);
result.setAddress(code.get("address").toString());
return result;
}
public List<CompotentAuthorityItemRS> getCompetentAuthority(List<CompotentAuthorityRQ> rq) {
CoordUtils utils = CoordUtils.getInstance();
List<Coordinate> coords = rq.stream().map(r -> new Coordinate(r.getLat(), r.getLon())).collect(Collectors.toList());
List<JSONObject> codeList = utils.getPlace(coords);
String[] scope = {"ctprvn", "sig", "emd", "li"};
Set<CompotentAuthorityItemRS> list = new HashSet<>();
for (JSONObject code : codeList) {
final String cd = (String) code.get("CD");
for (String s : scope) {
String cdParam = CoordUtils.getInstance().addAdmCd(cd, s);
List<FltCptAuthBas> authList = fltCptAuthAdminDistrictBasQueryRepository.getFltCptAuthBas(cdParam);
List<CompotentAuthorityItemRS> itemList = authList.stream().map(item -> CompotentAuthorityItemRS.builder()
.cptAuthCode(item.getCptAuthCode())
.cptAuthNm(item.getCptAuthNm())
.cptAuthTp(item.getCptAuthTp())
.cptAuthFax(item.getCptAuthFax())
.rm(item.getRm())
.updateDt(item.getUpdateDt())
.createDt(item.getCreateDt())
.build()).collect(Collectors.toList());
list.addAll(new HashSet<>(itemList));
}
}
log.debug("list : {}", list);
return new ArrayList<>(list);
}
public SearchAddressCoordinateRS getCoordinateByAddress(SearchAddressCoordinateRQ rq) {
String address = rq.getAddress();

17
pav-server/src/main/java/com/palnet/biz/api/external/model/DosCptAuthResult.java vendored

@ -0,0 +1,17 @@
package com.palnet.biz.api.external.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DosCptAuthResult {
private List<String> cptCode;
private List<String> controlCptCode;
}

57
pav-server/src/main/java/com/palnet/biz/api/external/service/DronOneStopService.java vendored

@ -1,11 +1,11 @@
package com.palnet.biz.api.external.service;
import com.palnet.biz.api.bas.dos.model.LimitZoneType;
import com.palnet.biz.api.comn.coordinate.model.CompotentAuthorityItemRS;
import com.palnet.biz.api.comn.coordinate.model.CompotentAuthorityRQ;
import com.palnet.biz.api.comn.coordinate.service.ComnCoordinateService;
import com.palnet.biz.api.comn.share.ShareService;
import com.palnet.biz.api.external.model.ApprovalCd;
import com.palnet.biz.api.external.model.DosApprovalResult;
import com.palnet.biz.api.external.model.DosPlanRq;
import com.palnet.biz.api.external.model.DosPlanRs;
import com.palnet.biz.api.external.model.*;
import com.palnet.biz.jpa.entity.*;
import com.palnet.biz.jpa.entity.type.ReviewedType;
import com.palnet.biz.jpa.repository.dos.*;
@ -26,6 +26,7 @@ import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@ -41,6 +42,8 @@ public class DronOneStopService {
private final DosFltPlanPilotRepository dosFltPlanPilotRepository;
private final ShareService shareService;
private final AreaUtils areaUtils;
private final ComnCoordinateService comnCoordinateService;
private final List<String> PASS_PURPOSES = List.of("수색구조", "인명구조", "시설정검");
public DosPlanRs saveDosPlan(DosPlanRq rq) {
@ -130,6 +133,7 @@ public class DronOneStopService {
// 검토결과 - approvalCd가 비대상일 경우 검토불필요 그외 대기
ReviewedType reviewedType = saveApprovalCd == ApprovalCd.UNTARGETED_AREA ? ReviewedType.UNNECESSARY : ReviewedType.WAIT;
DosCptAuthResult cptAuth = this.getCptAuth(centerCoordinate, area.getRadius());
// area save
DosFltPlanArea dosFltPlanAreaInsert = DosFltPlanArea.builder()
.planSno(saveDosFltPlanBas.getPlanSno())
@ -144,6 +148,8 @@ public class DronOneStopService {
.limitZone(approvalResult.getLimitZone())
.reviewedType(reviewedType)
.reqElev(reqElev)
.cptCd(cptAuth.getCptCode())
.innerCptCd(cptAuth.getControlCptCode())
.updateDt(Instant.now())
.createDt(Instant.now())
.build();
@ -352,4 +358,47 @@ public class DronOneStopService {
return distance;
}
public DosCptAuthResult getCptAuth(Coordinate centerCoordinate, Double radius) {
List<Coordinate> targetCoordinate = areaUtils.createCircle(centerCoordinate, radius);
List<CompotentAuthorityRQ> rq = targetCoordinate.stream().map(coordinate -> CompotentAuthorityRQ.builder()
.lat(coordinate.y)
.lon(coordinate.x)
.build()).collect(Collectors.toList());
List<CompotentAuthorityItemRS> competentAuthority = comnCoordinateService.getCompetentAuthority(rq);
DosCptAuthResult result = new DosCptAuthResult();
if (competentAuthority != null && !competentAuthority.isEmpty()) {
List<String> cptCode = competentAuthority.stream().map(CompotentAuthorityItemRS::getCptAuthCode).distinct().collect(Collectors.toList());
result.setCptCode(cptCode);
}
// TODO 관제권 체크 후 결과 반환
// 관제권 airspaces
Map<AirspaceUtils.AirspaceType, String> airspaceParamMap = Map.of(
AirspaceUtils.AirspaceType.C_CONTROL_GIMPO, "F0002", // 김포항공관리사무소(안전운항과)
AirspaceUtils.AirspaceType.C_CONTROL_ULSAN, "C0001" // 울산공항출장소
// AirspaceUtils.AirspaceType.C_CONTROL_JEJU, "F0008", // 제주지방항공청(안전운항과)
);
List<String> controlCptCode = new ArrayList<>();
AirspaceUtils airspaceUtils = AirspaceUtils.getInstance();
Geometry targetGeometry = airspaceUtils.createGeometryByCoordinate(targetCoordinate);
for (AirspaceUtils.AirspaceType airspaceType : airspaceParamMap.keySet()) {
List<AirspaceUtils.FeatureInfo> airspaces = airspaceUtils.getAirspaces(airspaceType);
if (airspaces == null || airspaces.isEmpty()) {
continue;
}
String innerCptCode = airspaceParamMap.get(airspaceType);
for (AirspaceUtils.FeatureInfo airspace : airspaces) {
if (airspace.getGeometry().intersects(targetGeometry)) {
controlCptCode.add(innerCptCode);
break;
}
}
}
if (!controlCptCode.isEmpty()) {
result.setControlCptCode(controlCptCode);
}
return result;
}
}

62
pav-server/src/main/java/com/palnet/comn/utils/AirspaceUtils.java

@ -33,10 +33,8 @@ public class AirspaceUtils {
private final String CLASS_PATH = "air" + File.separator + "airspace";
private final GeometryFactory geometryFactory = new GeometryFactory();
// private List<FeatureInfo> airspaces;
private Map<AirspaceType, List<FeatureInfo>> airspaceMap;
private AirspaceUtils() {
// 초기화
log.info("===== AirspaceUtils init =====");
@ -77,7 +75,6 @@ public class AirspaceUtils {
});
}
// 공역 중복 검사
public boolean isDuplicatedAirspaceElev(FeatureInfo target) {
@ -238,68 +235,13 @@ public class AirspaceUtils {
// get geometry
public List<FeatureInfo> getAirspaces(AirspaceType airspaceType) {
return this.airspaceMap.get(airspaceType.name());
return this.airspaceMap.get(airspaceType);
}
/*
// 파일에서 공역 데이터 가져와서 geometry로 변환 - 초기화.
private void loadResourceAirspace() {
Map<String, List<FeatureInfo>> featureInfoMap = new HashMap<>();
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = null;
try {
resources = resolver.getResources("classpath:" + CLASS_PATH + "/*-elev.json");
} catch (IOException e) {
log.warn("airspaces load error : {}", e.getMessage());
}
if (resources == null) {
log.info("airspace resources is null");
return;
}
for (Resource resource : resources) {
log.info(">>> resource name : {}", resource.getFilename());
try (InputStream is = resource.getInputStream()) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject) jsonParser.parse(reader);
List<FeatureInfo> fis = this.convertGeoJsonToGeometry(jsonObject);
String airspaceType = AirspaceType.ETC.name();
if (resource.getFilename().contains("gimpo-airport-2d-elev.json")) {
airspaceType = AirspaceType.GIMPO.name();
}
List<FeatureInfo> featureInfos = featureInfoMap.get(airspaceType);
if (featureInfos == null) {
featureInfos = new ArrayList<>();
}
featureInfos.addAll(fis);
featureInfoMap.put(airspaceType, featureInfos);
} catch (Exception e) {
log.warn("airspace resource read error : {}", e.getMessage());
}
}
for (Map.Entry<String, List<FeatureInfo>> entry : featureInfoMap.entrySet()) {
log.info(">>> key : {}, size : {}", entry.getKey(), entry.getValue().size());
}
this.airspaceMap = featureInfoMap;
}
*/
// 파일에서 공역 데이터 가져와서 geometry로 변환 - 초기화.
private void loadResourceAirspace() {
// D_NO_FLY_ZONE, // 비행금지구역
// D_RESTRICTED_FLIGHT_AREA, // 비행제한구역
// D_CONTROL_AIRPORT, // 관제권(공항)
// D_CONTROL_MILITARY_CIVILIAN, // 관제권(군사/민간)
// D_LIGHT_AIRCRAFT, // 경량항공기이착륙장
// D_ULTRA_LIGHT_AIRCRAFT, // 초경량비행장치공역
Map<AirspaceType, String> resourceInfo = Map.of(
AirspaceType.D_NO_FLY_ZONE, "default_airspace/_prohibitedArea.json",
AirspaceType.D_RESTRICTED_FLIGHT_AREA, "default_airspace/_restrictedArea.json",

1116
pav-server/src/main/java/com/palnet/comn/utils/CoordUtils.java

File diff suppressed because it is too large Load Diff

42
pav-server/src/test/java/com/palnet/biz/api/comn/coordinate/service/ComnCoordinateServiceTest.java

@ -0,0 +1,42 @@
package com.palnet.biz.api.comn.coordinate.service;
import com.palnet.biz.api.comn.coordinate.model.CompotentAuthorityItemRS;
import com.palnet.biz.api.comn.coordinate.model.CompotentAuthorityRQ;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Profile;
import org.springframework.test.context.ActiveProfiles;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@Slf4j
@ActiveProfiles("local")@Profile("local")
@SpringBootTest
class ComnCoordinateServiceTest {
@Autowired
private ComnCoordinateService comnCoordinateService;
@Test
void getCompotentAuthority() {
// given
List<CompotentAuthorityRQ> rq = List.of(
CompotentAuthorityRQ.builder().lat(37.566).lon(126.978).build(),
CompotentAuthorityRQ.builder().lat(37.567).lon(126.978).build(),
CompotentAuthorityRQ.builder().lat(37.567).lon(126.979).build(),
CompotentAuthorityRQ.builder().lat(37.566).lon(126.979).build(),
CompotentAuthorityRQ.builder().lat(37.566).lon(126.978).build()
);
// when
List<CompotentAuthorityItemRS> result = comnCoordinateService.getCompetentAuthority(rq);
// then
log.debug("result: {}", result);
}
}

13
pav-server/src/test/java/com/palnet/biz/api/external/service/DronOneStopServiceTest.java vendored

@ -1,6 +1,7 @@
package com.palnet.biz.api.external.service;
import com.palnet.biz.api.external.model.DosApprovalResult;
import com.palnet.biz.api.external.model.DosCptAuthResult;
import com.palnet.biz.jpa.entity.DosFltPlanArea;
import com.palnet.biz.jpa.entity.DosFltPlanResult;
import com.palnet.biz.jpa.repository.dos.DosFltPlanAreaRepository;
@ -127,9 +128,15 @@ class DronOneStopServiceTest {
}
}
// CPT 코드 업데이트 - 전체
@Test
void test() {
DosApprovalResult approvalResult= dronOneStopService.getApprovalResult(500.0, 492.0, new Coordinate(126.83916033495814, 37.56642984745274));
log.info("{}", approvalResult);
void updateAllCptCode() {
List<DosFltPlanArea> all = dosFltPlanAreaRepository.findAll();
all.forEach(area -> {
DosCptAuthResult result = dronOneStopService.getCptAuth(new Coordinate(area.getLon(), area.getLat()), area.getBufferZone());
result.setCptCode(result.getCptCode());
result.setControlCptCode(result.getControlCptCode());
});
dosFltPlanAreaRepository.saveAll(all);
}
}
Loading…
Cancel
Save