diff --git a/src/main/java/com/haemil/backend/prepare/controller/PrepareController.java b/src/main/java/com/haemil/backend/prepare/controller/PrepareController.java index 5c5298f..d0df348 100644 --- a/src/main/java/com/haemil/backend/prepare/controller/PrepareController.java +++ b/src/main/java/com/haemil/backend/prepare/controller/PrepareController.java @@ -5,7 +5,10 @@ import com.haemil.backend.global.config.BaseException; import com.haemil.backend.global.config.BaseResponse; import com.haemil.backend.global.config.ResponseStatus; +import com.haemil.backend.prepare.dto.PrePareInfoDto; import com.haemil.backend.prepare.dto.PrepareDto; +import com.haemil.backend.prepare.dto.PrepareNeedInfoDto; +import com.haemil.backend.prepare.dto.PrepareWeatherDto; import com.haemil.backend.prepare.service.PrepareService; import com.haemil.backend.weather.controller.AirController; import com.haemil.backend.weather.controller.LivingController; @@ -22,6 +25,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; @Slf4j @RestController @@ -34,44 +38,73 @@ public class PrepareController { private final AirController airController; private final ObjectMapper objectMapper; // ObjectMapper 주입 + private PrepareDto fetchDataAndProcess() throws BaseException { + ResponseEntity weatherResponse = weatherController.sendGetRequest(); + List todayTemps = weatherController.currentTimeData; + + ResponseEntity airResponse = airController.sendGetRequest(); + List todayAirs = airController.infoList; + + ResponseEntity livingResponse = livingController.sendGetRequest(); + List todayLivings = livingController.infoList; + + Map temps = weatherController.transformedData; // 최고 최저 온도 + + PrepareDto prepareDto = new PrepareDto(todayTemps, todayAirs, temps, todayLivings); + prepareService.filterWeatherData(todayTemps, prepareDto); + prepareService.filterAirData(todayAirs, prepareDto); + + return prepareDto; + } + @GetMapping("/send") public ResponseEntity sendGetRequest() { try { - // Call /weather/send to get weather data - ResponseEntity weatherResponse = weatherController.sendGetRequest(); - List todayTemps = weatherController.currentTimeData; + PrepareDto prepareDto = fetchDataAndProcess(); - // Call /air/send to get air data - ResponseEntity airResponse = airController.sendGetRequest(); - List todayAirs = airController.infoList; - - ResponseEntity livingResponse = livingController.sendGetRequest(); - List todayLivings = livingController.infoList; + List prepareDtoList = new ArrayList<>(); + prepareDtoList.add(prepareDto); - List temps = weatherController.tmnAndTmxData; -// log.info("minmax = {}", temps.get(0)); + List resultString = prepareService.ParsingJson(prepareDtoList); +// log.info("prePare_result = {}", resultString); // 외출 적합도 결과 log - PrepareDto prepareDto = new PrepareDto(todayTemps, todayAirs, temps, todayLivings); - prepareService.filterWeatherData(todayTemps, prepareDto); -// log.info("tmp = {}", prepareDto.getTmp()); + return new BaseResponse<>(resultString).convert(); + } catch(BaseException e) { + return new BaseResponse<>(e.getStatus()).convert(); + } + } - prepareService.filterAirData(todayAirs, prepareDto); + @GetMapping("/weather") + public ResponseEntity sendWeatherInfo() { + try { + PrepareDto prepareDto = fetchDataAndProcess(); List prepareDtoList = new ArrayList<>(); prepareDtoList.add(prepareDto); - String resultString = prepareService.ParsingJson(prepareDtoList); - log.info("prePare_result = {}", resultString); + List resultString = prepareService.ParsingWeather(prepareDtoList); +// log.info("prePare_weather_result = {}", resultString); // 외출 - 날씨 관련 정보 - Object jsonResult = objectMapper.readValue(resultString, Object.class); - String prettyJsonString = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonResult); + return new BaseResponse<>(resultString).convert(); + } catch(BaseException e) { + return new BaseResponse<>(e.getStatus()).convert(); + } + } - return new BaseResponse<>(prettyJsonString).convert(); + @GetMapping("/need") + public ResponseEntity sendNeedInfo() { + try { + PrepareDto prepareDto = fetchDataAndProcess(); + + List prepareDtoList = new ArrayList<>(); + prepareDtoList.add(prepareDto); + + List resultString = prepareService.ParsingNeed(prepareDtoList); +// log.info("prePare_need_result = {}", resultString); // 외출 물품 정보 + + return new BaseResponse<>(resultString).convert(); } catch(BaseException e) { return new BaseResponse<>(e.getStatus()).convert(); - } catch (JsonProcessingException e) { - return new BaseResponse<>(ResponseStatus.CANNOT_CONVERT_JSON).convert(); } } } - diff --git a/src/main/java/com/haemil/backend/prepare/dto/PrePareInfoDto.java b/src/main/java/com/haemil/backend/prepare/dto/PrePareInfoDto.java index fb3dc16..960a5bf 100644 --- a/src/main/java/com/haemil/backend/prepare/dto/PrePareInfoDto.java +++ b/src/main/java/com/haemil/backend/prepare/dto/PrePareInfoDto.java @@ -3,10 +3,10 @@ @Data public class PrePareInfoDto { - private String mask; // 미세먼지 농도 값에 따른 마스크 착용 -> 옵션 ) 자율, 권고, 필수 + private String pm10value; // 가장 최근꺼로 오늘꺼 미세먼지 수치 private String clothes; // 기온별 옷차림 -> 옵션 ) ex. "민소매, 반팔, 반바지, 원피스" - private boolean umbrella; // 강수량에 따른 우선 여부 private String feel_like; // 체감 온도 + private String uv; // 자외선 + private String result; // 외출 적합도 문장 -> 옵션 ) ex. "외출하기 좋은 날이네요" private int percent; // 외출 적합도 퍼센트 - private String result; // 외출 적합도 문장 -> 옵션 ) ex. "외출하기 좋은 날이네요"ㅇ } diff --git a/src/main/java/com/haemil/backend/prepare/dto/PrepareDto.java b/src/main/java/com/haemil/backend/prepare/dto/PrepareDto.java index 0df59d6..e6bc74e 100644 --- a/src/main/java/com/haemil/backend/prepare/dto/PrepareDto.java +++ b/src/main/java/com/haemil/backend/prepare/dto/PrepareDto.java @@ -8,6 +8,7 @@ import org.springframework.stereotype.Component; import java.util.List; +import java.util.Map; @Data @Component @@ -26,25 +27,28 @@ public class PrepareDto { private String pcp; // 1시간 강수량 private String reh; // 습도 private String sky; // 하늘 상태 + private String wsd; // 풍속(m/s) // 대기질 private String pm10grade; // 가장 최근꺼로 오늘꺼 미세먼지 등급 + private String pm10value; // 가장 최근꺼로 오늘꺼 미세먼지 수치 private String pm25grade; // 가장 최근꺼로 오늘꺼 초미세먼지 등급 + private String pm25value; // 가장 최근꺼로 오늘꺼 미세먼지 수치 // living private String feelLike; // 체감 온도 private String uv; // 자외선 - // 기본 생성자 public PrepareDto() { } - // 필요한 데이터를 주입받는 생성자 - public PrepareDto(List todayTemps, List todayAirs, List temps, List livings) { + public PrepareDto(List todayTemps, List todayAirs, Map temps, List livings) { this.todayTemps = todayTemps; this.todayAirs = todayAirs; - this.maxTemp = temps.get(1); - this.minTemp = temps.get(0); + String maxTemp = temps.get("max"); + String minTemp = temps.get("min"); + this.maxTemp = maxTemp; + this.minTemp = minTemp; if (!livings.isEmpty()) { this.feelLike = livings.get(0).getFeels_like(); diff --git a/src/main/java/com/haemil/backend/prepare/dto/PrepareNeedInfoDto.java b/src/main/java/com/haemil/backend/prepare/dto/PrepareNeedInfoDto.java new file mode 100644 index 0000000..bffd642 --- /dev/null +++ b/src/main/java/com/haemil/backend/prepare/dto/PrepareNeedInfoDto.java @@ -0,0 +1,11 @@ +package com.haemil.backend.prepare.dto; +import lombok.Data; +import org.springframework.stereotype.Component; + +@Data +@Component +public class PrepareNeedInfoDto { + private String mask; // 미세먼지 농도 값에 따른 마스크 착용 -> 옵션 ) 자율, 권고, 필수 + private String umbrella; // 강수량에 따른 우선 여부 + private String clothes; // 기온별 옷차림 -> 옵션 ) ex. "민소매, 반팔, 반바지, 원피스" +} diff --git a/src/main/java/com/haemil/backend/prepare/dto/PrepareWeatherDto.java b/src/main/java/com/haemil/backend/prepare/dto/PrepareWeatherDto.java new file mode 100644 index 0000000..3db79d4 --- /dev/null +++ b/src/main/java/com/haemil/backend/prepare/dto/PrepareWeatherDto.java @@ -0,0 +1,17 @@ +package com.haemil.backend.prepare.dto; + +import lombok.Data; +import org.springframework.stereotype.Component; + +@Data +@Component +public class PrepareWeatherDto { + private String pm10value; // 가장 최근꺼로 오늘꺼 미세먼지 수치 + private String pm25value; // 가장 최근꺼로 오늘꺼 미세먼지 수치 + + private String pop; // 강수 확률 + private String pcp; // 1시간 강수량 + + private String wsd; // 풍속(m/s) + private String uv; // 자외선 +} diff --git a/src/main/java/com/haemil/backend/prepare/service/PrepareService.java b/src/main/java/com/haemil/backend/prepare/service/PrepareService.java index 26749b3..ce0f666 100644 --- a/src/main/java/com/haemil/backend/prepare/service/PrepareService.java +++ b/src/main/java/com/haemil/backend/prepare/service/PrepareService.java @@ -6,6 +6,8 @@ import com.haemil.backend.global.config.ResponseStatus; import com.haemil.backend.prepare.dto.PrePareInfoDto; import com.haemil.backend.prepare.dto.PrepareDto; +import com.haemil.backend.prepare.dto.PrepareNeedInfoDto; +import com.haemil.backend.prepare.dto.PrepareWeatherDto; import com.haemil.backend.weather.dto.AirInfoDto; import com.haemil.backend.weather.dto.WeatherInfoDto; import lombok.RequiredArgsConstructor; @@ -39,6 +41,8 @@ public void filterWeatherData(List weatherInfoDtoList, PrepareDt prepareDto.setReh(weatherInfoDto.getFcstValue()); } else if (category.equals("SKY")) { prepareDto.setSky(weatherInfoDto.getFcstValue()); + } else if (category.equals("WSD")) { + prepareDto.setWsd(weatherInfoDto.getFcstValue()); } } } @@ -47,31 +51,63 @@ public void filterAirData(List airInfoDto, PrepareDto prepareDto) { AirInfoDto resultDto = airInfoDto.get(0); prepareDto.setPm10grade(resultDto.getPm10Grade()); prepareDto.setPm25grade(resultDto.getPm25Grade()); + prepareDto.setPm10value(resultDto.getPm10Value()); + prepareDto.setPm25value(resultDto.getPm25Value()); } - public String ParsingJson(List prepareDtoList) throws BaseException { + public List ParsingJson(List prepareDtoList) throws BaseException { List prePareInfoDtoList = new ArrayList<>(); - try { - for (PrepareDto prepareDto : prepareDtoList) { - PrePareInfoDto prePareInfoDto = new PrePareInfoDto(); - // PrepareDto의 필드 값을 PrePareInfoDto에 설정 - prePareInfoDto.setMask(getMaskValue(prepareDto.getPm10grade(), prepareDto.getPm25grade())); - prePareInfoDto.setClothes(getClothesValue(prepareDto.getMaxTemp(), prepareDto.getMinTemp(), prepareDto.getTmp())); - prePareInfoDto.setUmbrella(needUmbrella(prepareDto.getPop(), prepareDto.getPty())); - prePareInfoDto.setFeel_like(prepareDto.getFeelLike()); - int percent = getPercentValue(prepareDto); - prePareInfoDto.setPercent(percent); - - String result = getResultValue(percent); - prePareInfoDto.setResult(result); - - prePareInfoDtoList.add(prePareInfoDto); - } - return convertObjectToJson(prePareInfoDtoList); - } catch (JsonProcessingException e) { - throw new BaseException(ResponseStatus.CANNOT_CONVERT_JSON); + for (PrepareDto prepareDto : prepareDtoList) { + PrePareInfoDto prePareInfoDto = new PrePareInfoDto(); + + prePareInfoDto.setPm10value(prepareDto.getPm10value()); + prePareInfoDto.setClothes(getClothesValue(prepareDto.getMaxTemp(), prepareDto.getMinTemp(), prepareDto.getTmp())); + prePareInfoDto.setFeel_like(prepareDto.getFeelLike()); + prePareInfoDto.setUv(getUvStatus(prepareDto)); + + int percent = getPercentValue(prepareDto); + prePareInfoDto.setPercent(percent); + + String result = getResultValue(percent); + prePareInfoDto.setResult(result); + + prePareInfoDtoList.add(prePareInfoDto); + } + return prePareInfoDtoList; + } + + public List ParsingNeed(List prepareDtoList) throws BaseException { + List prePareInfoDtoList = new ArrayList<>(); + + for (PrepareDto prepareDto : prepareDtoList) { + PrepareNeedInfoDto prePareInfoDto = new PrepareNeedInfoDto(); + + prePareInfoDto.setMask(getMaskValue(prepareDto.getPm10grade(), prepareDto.getPm25grade())); + prePareInfoDto.setUmbrella(needUmbrella(prepareDto.getPop(), prepareDto.getPty())); + prePareInfoDto.setClothes(getClothesValue(prepareDto.getMaxTemp(), prepareDto.getMinTemp(), prepareDto.getTmp())); + + prePareInfoDtoList.add(prePareInfoDto); } + + return prePareInfoDtoList; + } + + public List ParsingWeather(List prepareDtoList) throws BaseException { + List prePareInfoDtoList = new ArrayList<>(); + + for (PrepareDto prepareDto : prepareDtoList) { + PrepareWeatherDto prePareInfoDto = new PrepareWeatherDto(); + prePareInfoDto.setPm10value(prepareDto.getPm10value()); + prePareInfoDto.setPm25value(prepareDto.getPm25value()); + prePareInfoDto.setPop(prepareDto.getPop()); + prePareInfoDto.setWsd(prepareDto.getWsd()); + prePareInfoDto.setPcp(prepareDto.getPcp()); + prePareInfoDto.setUv(prepareDto.getUv()); + + prePareInfoDtoList.add(prePareInfoDto); + } + return prePareInfoDtoList; } private String convertObjectToJson(Object object) throws JsonProcessingException { @@ -94,6 +130,22 @@ else if (result < 3) return "필수"; } + private String getUvStatus(PrepareDto prepareDto) { + int uvIndex = Integer.parseInt(prepareDto.getUv()); // 자외선 지수 + + if (uvIndex <= 2) { + return "아주 좋음"; + } else if (uvIndex >= 3 && uvIndex <= 5) { + return "좋음"; + } else if (uvIndex >= 6 && uvIndex <= 7) { + return "보통"; + } else if (uvIndex >= 8 && uvIndex <= 10) { + return "나쁨"; + } else { + return "아주 나쁨"; + } + } + // 기온에 따른 옷차림을 판단하는 메서드 //평균온도로 private String getClothesValue(String maxTemp, String minTemp, String temp) { @@ -122,12 +174,12 @@ private String getClothesValue(String maxTemp, String minTemp, String temp) { } // 강수 확률과 형태에 따른 우산 우선 여부를 판단하는 메서드 - private boolean needUmbrella(String pop, String pty) { - if (pop == "0" && pty == "0") { - return false; // 눈이나 비가 안옴 + private String needUmbrella(String pop, String pty) { + if (pop.equals("0") && pty.equals("0")) { + return "우산 필요 없음"; // 눈이나 비가 안옴 } else { - return true; // 눈이나 비가 옴 + return "우산 필요"; // 눈이나 비가 옴 } } diff --git a/src/main/java/com/haemil/backend/weather/controller/WeatherController.java b/src/main/java/com/haemil/backend/weather/controller/WeatherController.java index d0d4284..f902771 100644 --- a/src/main/java/com/haemil/backend/weather/controller/WeatherController.java +++ b/src/main/java/com/haemil/backend/weather/controller/WeatherController.java @@ -27,8 +27,9 @@ public class WeatherController { private final WeatherDto weatherDto; private final WeatherService weatherService; - public List tmnAndTmxData; + public Map transformedData; public List currentTimeData; + @GetMapping("/today") public ResponseEntity getTodayWeather() { // 오늘 현재 시간대 try { @@ -48,8 +49,9 @@ public ResponseEntity sendGetRequest() { // 모든 날씨 정보 String jsonString = weatherService.getWeatherInfo(weatherDto); weatherService.isJson(jsonString); List infoList = weatherService.ParsingJson(jsonString); + currentTimeData = weatherService.filterCurrentTimeData(infoList, weatherDto); - tmnAndTmxData = weatherService.filterTMNandTMXData(infoList, weatherDto); + transformedData = weatherService.transformWeatherData(infoList, currentTimeData, weatherDto); return new BaseResponse<>(infoList).convert(); } catch (BaseException e) { @@ -57,13 +59,29 @@ public ResponseEntity sendGetRequest() { // 모든 날씨 정보 } } + @GetMapping("/data") + public ResponseEntity getTMNandTMXData() { + try { + String jsonString = weatherService.getWeatherInfo(weatherDto); + weatherService.isJson(jsonString); + List infoList = weatherService.ParsingJson(jsonString); + List todayData = weatherService.filterCurrentTimeData(infoList, weatherDto); + + transformedData = weatherService.transformWeatherData(infoList, todayData, weatherDto); + + return new BaseResponse<>(transformedData).convert(); + } catch (BaseException e) { + return new BaseResponse<>(e.getStatus()).convert(); + } + } + @GetMapping("/tmps") - public ResponseEntity getTemperatures() { // 3일치 온도 가져오기 + public ResponseEntity getTemperatures() { // 3일치 온도&하늘상태 가져오기 try { String jsonString = weatherService.getWeatherInfo(weatherDto); weatherService.isJson(jsonString); List infoList = weatherService.ParsingJson(jsonString); - List temperatureData = weatherService.filterCurrentTimeAndSpecifiedDateData(infoList, "1500"); + List> temperatureData = weatherService.filterCurrentTimeAndSpecifiedDateData(infoList, "1500"); return new BaseResponse<>(temperatureData).convert(); } catch (BaseException e) { @@ -72,7 +90,7 @@ public ResponseEntity getTemperatures() { // 3일치 온도 가져 } @GetMapping("/times") - public ResponseEntity getNextHoursWeather() { + public ResponseEntity getNextHoursWeather() { // 시간대별 온도&하늘상태 가져오기 try { String jsonString = weatherService.getWeatherInfo(weatherDto); weatherService.isJson(jsonString); diff --git a/src/main/java/com/haemil/backend/weather/service/WeatherService.java b/src/main/java/com/haemil/backend/weather/service/WeatherService.java index 1342188..3744aee 100644 --- a/src/main/java/com/haemil/backend/weather/service/WeatherService.java +++ b/src/main/java/com/haemil/backend/weather/service/WeatherService.java @@ -19,10 +19,7 @@ import java.time.LocalDate; import java.time.LocalTime; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; @Slf4j @Service @@ -122,52 +119,71 @@ public List filterCurrentTimeData(List weatherIn return filteredList; } - public List filterTMNandTMXData(List weatherInfoDtoList, WeatherDto weatherDto) { - List TMNList = new ArrayList<>(); - List TMXList = new ArrayList<>(); - List TMNXList = new ArrayList<>(); + public Map transformWeatherData(List weatherInfoDtoList, List todayData, WeatherDto weatherDto) { + List Result = new ArrayList<>(); + Map resultData = new HashMap<>(); + + for (WeatherInfoDto today : todayData) { + String fcstValue = today.getFcstValue(); + String category = today.getCategory(); + + if (category.equals("TMP")) { + resultData.put("current", fcstValue); + break; + } + } for (WeatherInfoDto weatherInfoDto : weatherInfoDtoList) { String fcstDate = weatherInfoDto.getFcstDate(); + String fcstValue = weatherInfoDto.getFcstValue(); if (fcstDate.equals(weatherDto.getBase_date())) { String category = weatherInfoDto.getCategory(); if (category.equals("TMN")) { - TMNList.add(weatherInfoDto); + resultData.put("min", fcstValue); } else if (category.equals("TMX")) { - TMXList.add(weatherInfoDto); + resultData.put("max", fcstValue); } } } - for (WeatherInfoDto weatherInfoDto : TMNList) { - String fcstValue = weatherInfoDto.getFcstValue(); - TMNXList.add(fcstValue); - } - for (WeatherInfoDto weatherInfoDto : TMXList) { - String fcstValue = weatherInfoDto.getFcstValue(); - TMNXList.add(fcstValue); - } - - return TMNXList; + return resultData; } - public List filterCurrentTimeAndSpecifiedDateData(List weatherInfoDtoList, String specifiedTime) { - List filteredList = new ArrayList<>(); + public List> filterCurrentTimeAndSpecifiedDateData(List weatherInfoDtoList, String specifiedTime) { + Map> groupedData = new HashMap<>(); for (WeatherInfoDto weatherInfoDto : weatherInfoDtoList) { - String fcstTime = weatherInfoDto.getFcstTime(); String fcstDate = weatherInfoDto.getFcstDate(); + String fcstTime = weatherInfoDto.getFcstTime(); + String fcstValue = weatherInfoDto.getFcstValue(); + String category = weatherInfoDto.getCategory(); - // 지정한 시간과 지정한 날짜에 해당하는 데이터만 필터링 (오늘, 내일, 모레) - if (fcstTime.equals(specifiedTime) && isSpecifiedDate(fcstDate)) { - if (weatherInfoDto.getCategory().equals("TMP")) { - filteredList.add(weatherInfoDto); + // "fcstTime"이 "1500"이고 오늘, 내일 또는 모레인 데이터만 필터링 + if (fcstTime.equals(specifiedTime) && isSpecifiedDate(fcstDate) && (category.equals("TMP") || category.equals("SKY"))) { + // 날짜별로 데이터 그룹화 + String key = fcstDate + fcstTime; + groupedData.putIfAbsent(key, new HashMap<>()); + Map dataPoint = groupedData.get(key); + + dataPoint.put("fcstDate", fcstDate); + dataPoint.put("fcstTime", fcstTime); + + if (category.equals("TMP")) { + dataPoint.put("TMP", fcstValue); + } + + if (category.equals("SKY")) { + dataPoint.put("SKY", fcstValue); } } } - return filteredList; + + List> resultList = new ArrayList<>(groupedData.values()); + resultList.sort(Comparator.comparing(dataPoint -> dataPoint.get("fcstDate"))); + + return resultList; } private boolean isSpecifiedDate(String fcstDate) { @@ -178,11 +194,10 @@ private boolean isSpecifiedDate(String fcstDate) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); LocalDate parsedFcstDate = LocalDate.parse(fcstDate, formatter); - return parsedFcstDate.equals(today) || - parsedFcstDate.equals(tomorrow) || - parsedFcstDate.equals(dayAfterTomorrow); + return parsedFcstDate.equals(today) || parsedFcstDate.equals(tomorrow) || parsedFcstDate.equals(dayAfterTomorrow); } + public List> filterNextData(List weatherInfoDtoList, int numDataPoints) { List> filteredList = new ArrayList<>();