Coding History/Team Project

팀플) 유성우 가시성 데이터 로직 수정 및 API 재배포

BlackBirdIT 2024. 11. 24. 14:59

그니까 뭐가 맘에 안들었냐 하면 지금 로직은 UTC 시각 기준으로 하루만 요청을 하는데 이러면 24시간중 UTC 시간 기준으로 0시만 요청하게 되어서 데이터의 의미가 없어짐.

이게 이유를 설명하자면

지구는 자전중임. -> UTC기준 0시만 검증함. -> 위도 경도 값을 받는 이유가 없어짐. -> 왜? 애진작 UTC 기준으로 0시만 요청하면 위도 경도를 받아봤자 가시성에 대한 평가는 명확하게 처리를 못함. -> 그래서 로직 자체를 UTC 기준 24시간을 1시간 단위로 나눠서 하기로 함.

일단 이게 결론인데, 또 다른 문제는 피크타임의 start_date에서만 이 계산을 했다는거.

그래서 피크타임의 시작점과 끝점을 순회하면서 고도와 달의 위상을 비교해서 Best_time을 뽑아내고 그 결과를 포함한 결과를 보여주도록 로직을 수정하자고.

def find_best_peak_date(start_date, end_date, ra, dec, distance, latitude, longitude):
    best_date = start_date
    best_time = None
    best_conditions = {"altitude": -1, "moon_phase": None, "illumination": None, "phase_description": None, "direction": None}  # 초기 조건 설정

    current_date = start_date
    while current_date <= end_date:
        for hour in range(0, 24):
            observation_time = current_date + timedelta(hours=hour)

            # 고도와 방위각 계산
            altitude, azimuth = calculate_altitude_azimuth(ra, dec, distance, latitude, longitude, 0, observation_time)

            # 방위각 -> 방향 변환
            direction = azimuth_to_direction(azimuth)

            # 달의 위상 정보 가져오기
            moon_phase_info = get_moon_phase_for_date(observation_time)
            # print(f"Moon Phase Info for {observation_time}: {moon_phase_info}")

            # `moon_phase`와 `illumination` 값 가져오기
            moon_phase = moon_phase_info.get("moon_phase", "Unknown")
            illumination = moon_phase_info.get("illumination", 0.0)

            # `phase_description` 계산
            phase_description = get_phase_description(
                moon_phase,
                moon_phase_info.get("phase_angle_average", 0.0),
                illumination
            )

            # 관측 조건 평가
            if altitude > best_conditions["altitude"] and "error" not in moon_phase_info:
                best_date = current_date
                best_time = observation_time
                best_conditions = {
                    "altitude": altitude,
                    "moon_phase": moon_phase,
                    "illumination": illumination,
                    "phase_description": phase_description,
                    "direction": direction  # 방향 정보 추가
                }
                print(f"Updated Best Conditions: {best_conditions}")

        current_date += timedelta(days=1)

    print(f"Best Date and Time: {best_time}, Final Conditions: {best_conditions}")
    return {"best_date": best_time, "conditions": best_conditions}

해당 함수 추가해서 검증을 거쳤고 이왕하는김에 UTC 시간 변환까지 하기로 했음. 그래서 기존의 일몰 일출 함수 호출 및 베스트타임 날짜의 일몰 일출 결과까지 태워 보내도록함.


get_single_day_sunrise_sunset함수 도입하고서 오류를 반환해서 문제 찾는데 조금 걸렸다.

best_datedatetime.date 객체로 추출하고 있는데, 이를 datetime.datetime으로 변환하는 로직을 추가해서 해결하려고 시도함.

# `best_date`가 datetime.date라면 변환
if isinstance(best_date, datetime.date) and not isinstance(best_date, datetime.datetime):
    best_date = datetime(best_date.year, best_date.month, best_date.day)

해당 코드로 해결..

하려고 했는데 문제가 생겼음.

isinstance() 함수에서 두 번째 인자로 타입을 전달해야 하는데, datetime.datedatetime.datetime을 함께 검사하려고 하다가 문제가 발생.

최종적으로

if type(best_date) is datetime.date:
    best_date = datetime(best_date.year, best_date.month, best_date.day)

이렇게 바꿈. 타입을 튜플로 묶어 전달해서 해결.

튜플이 이제 여러 타입을 묶는 역할이고, isinstance는 첫 번째 인자가 두 번째 인자(타입)와 일치하는지 확인하는 함수임.

여튼 결과는

이럼.

서울 기준 요청이고 해당 결과는 이제 고도를 기준으로 최적의 관측 날짜를 뽑음.

그럼 이제 달의 위상값까지 조건에 묶어주자. (지금은 가져오기만 했음.)

내가 말한 로직을 추가해서 평가를 점수화 까지 했음.

결과.

그럼 이걸 내가 뭐 확인을 할 수는 없으니까 대충 GPT한테 24년도 Eta Aquariid 유성우의 관측에 대한 결과가 어땠냐고 물어보면 될듯.

뭐 이렇다더라.

좀 더 과거의 데이터로 검증해보자.

23년도 요청을 해봤는데,

에러뜸. 로우데이터 베이스에 데이터가 없음.. 이건 과거라 내가 업데이트 해줘야되는데 귀찮으니까 패스하자걍.

그럼 같은 HalleyOrionid도 두 년도 비교해보자.

아 씨 결과가 만족스럽지 않아서 보니까 내가 극대기를 너무 넓게 설정함. 그래서 만족스럽지 않은데 극대기의 날짜를 좁히고 데이터베이스의 데이터도 지우고 다시 생성해야됨. 그럼 재배포할 때도 이 데이터를 적용해야됨. 일이 좀 커졌는데 해야지 뭐 어떡하냐.


우선 날짜는 수정했고 데이터베이스에 접근함.


과감하게 지움.

docker-compose stop app && docker-compose build app && docker-compose up -d --no-deps app로 다시 어플리케이션 재시작 시키면 SQLAlchemy가 다시 테이블 만들어주니까 거따가 post 데이터 업데이트 해주자.

업데이트 함.

굳. 이제 배포땐 또 알아서 하도록 하고 일단은 데이터 확인부터.

Eta Aquariid:

Orionid:

Ursid:

Perseid:

일치도 분석:

  1. Eta Aquariid (2024):
    • 최적 날짜: 5월 4일 (실제 5월 5일)
    • 일치도: 약 90% (추천 날짜와 실제 날짜는 매우 가까움)
    • 달의 위상: Waning Crescent로, 실제 5월 5일도 유사.
    • 관측 등급: "Excellent" - 실제로 매우 일치.
  2. Orionid (2024):
    • 최적 날짜: 10월 21일 (실제 10월 23일)
    • 일치도: 80% (추천 날짜와 실제 날짜는 근접하지만, 약간 차이 있음)
    • 달의 위상: Waning Gibbous - 실제 달의 위상과 거의 일치.
    • 관측 등급: "Good" - 실제로 Good로 평가된 조건과 일치.
  3. Ursid (2024):
    • 최적 날짜: 12월 23일 (실제 12월 22일)
    • 일치도: 85% (추천 날짜가 실제 날짜와 비교적 비슷)
    • 달의 위상: Waning Crescent - 실제 달의 위상과 유사.
    • 관측 등급: "Good" - 실제 관측 조건과 일치.
  4. Perseid (2024):
    • 최적 날짜: 8월 11일 (실제 8월 12일)
    • 일치도: 90% (추천 날짜와 실제 날짜는 매우 가까움)
    • 달의 위상: Waxing Crescent - 실제 달의 위상과 매우 유사.
    • 관측 등급: "Good" - 실제 관측 조건과 일치.

이 정도면...

만족한다... 내가 제공하는 데이터는 관측에 집중하기 때문에 이런 오차가 약간씩 나게 되었는데 달의 조명률까지 상정을 한 결과라서 당연하다고 생각함.

그럼 이제 뭐.. 재배포 해야겠지?


재배포.

이번 재배포는 양상이 조금 다르다. 이미지 push, pull 이후 docker-compose로 빌드 시킨 뒤 DB에서 meteor_shower_info 테이블 삭제하고 Post요청으로 데이터 베이스 업데이트 해준 뒤에 검토까지 해봐야됨.

그럼 뭐 일단 순차적으로 진행해보자.

push 부터 진행중.

도중에 기존 이미지 삭제

하는 와중에 push 다 되어서, pull 진행

pull이 완료되면 docker-compose빌드하고 DB 테이블 삭제 이후 테이블 삽입, 데이터 삽입까지 다시 해주면 된다.

우선은 올린 코드가 제대로 동작하는지부터 확인

내가 도입한 코드가 정확히 일치함을 확인함. 근데 생각해보니까 내가 캐싱을 잠깐 꺼둔 곳들이 있는데 다시 켜고 pull다시 해야겠다..

여튼 다시 가져와서 실행했고

DB 처리중

끝 이제 post요청 후 테이블 조회 해보면 됨

Postman으로 요청 끝냈고,

삽입도 끝.

오케이!! 배포까지 끝 어유 근데 이거 로그가 너무 많이 떠서 코드 확인하면서 로그들 좀 지워야겠다.

지우고 재배포는 나중에 해야징