source, targetDate 그룹에서 최신만 선택

- 조회 시, 과거 데이터 무시
- 저장 자체를 최신 데이터만 해도 되긴하는데, 디버깅 용도 혹은 다른 방법으로 쓰일 걸 염두에 두고, 그냥 냅둔다.
This commit is contained in:
2025-12-09 22:54:32 +09:00
parent 70c7bbf591
commit f3a172ad3c
7 changed files with 293 additions and 19 deletions

View File

@@ -90,12 +90,41 @@ func (*Flow) mergeWeathers(dateKey string, location *time.Location, weathers []*
date, _ := time.Parse("2006-01-02", dateKey)
date = time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, location)
high := float64(weathers[0].Temperature().Value)
low := float64(weathers[0].Temperature().Value)
worstCondition := weathers[0].Condition()
// Source와 TargetDate가 동일한 경우, ForecastDate가 최신 항목만 선택
filteredWeathers := make(map[string]*domain.Weather)
for _, w := range weathers {
temp := float64(w.Temperature().Value)
for _, weather := range weathers {
key := string(weather.Source()) + weather.TargetDate().Format("2006-01-02")
existing, ok := filteredWeathers[key]
if !ok {
filteredWeathers[key] = weather
continue
}
if weather.ForecastDate().Before(existing.ForecastDate()) {
continue
}
filteredWeathers[key] = weather
}
var filteredSlice []*domain.Weather
for _, weather := range filteredWeathers {
filteredSlice = append(filteredSlice, weather)
}
if len(filteredSlice) == 0 {
panic("no weather found")
}
high := float64(filteredSlice[0].Temperature().Value)
low := float64(filteredSlice[0].Temperature().Value)
worstCondition := filteredSlice[0].Condition()
for _, weather := range filteredSlice {
temp := float64(weather.Temperature().Value)
if temp > high {
high = temp
}
@@ -104,19 +133,17 @@ func (*Flow) mergeWeathers(dateKey string, location *time.Location, weathers []*
low = temp
}
if w.Condition().IsWorseThan(worstCondition) {
worstCondition = w.Condition()
if weather.Condition().IsWorseThan(worstCondition) {
worstCondition = weather.Condition()
}
}
newVar := &DailyWeather{
return &DailyWeather{
Date: date,
High: high,
Low: low,
Condition: string(worstCondition),
}
return newVar
}
func (*Flow) groupByDate(weathers []*domain.Weather, location *time.Location) map[string][]*domain.Weather {

View File

@@ -0,0 +1,111 @@
//nolint:dupl
package flow_test
import (
"context"
"testing"
"time"
"github.com/neatflowcv/seven-skies/internal/app/flow"
"github.com/neatflowcv/seven-skies/internal/pkg/domain"
"github.com/neatflowcv/seven-skies/internal/pkg/repository/mocks"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
)
func TestFlow_ListDailyWeathers(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
mock := mocks.NewMockRepository(ctrl)
now := time.Now()
mock.EXPECT().ListWeathers(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*domain.Weather{
domain.NewWeather(
"1",
domain.WeatherSourceOpenWeather,
now,
now.Add(time.Hour*24),
domain.WeatherConditionClear,
domain.Temperature{Value: domain.Celsius(20)},
),
}, nil)
flow := flow.NewFlow(mock)
weathers, err := flow.ListDailyWeathers(context.Background(), "Asia/Seoul", now)
require.NoError(t, err)
require.Len(t, weathers, 1)
require.InDelta(t, 20.0, weathers[0].High, 0.01)
require.InDelta(t, 20.0, weathers[0].Low, 0.01)
require.Equal(t, "CLEAR", weathers[0].Condition)
}
func TestFlow_ListDailyWeathers_SameSourceAndTargetDate(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
mock := mocks.NewMockRepository(ctrl)
now := time.Now()
mock.EXPECT().ListWeathers(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*domain.Weather{
domain.NewWeather(
"1",
domain.WeatherSourceOpenWeather,
now,
now,
domain.WeatherConditionClear,
domain.Temperature{Value: domain.Celsius(20)},
),
domain.NewWeather(
"2",
domain.WeatherSourceOpenWeather,
now,
now.Add(time.Hour*24),
domain.WeatherConditionCloudy,
domain.Temperature{Value: domain.Celsius(30)},
),
}, nil)
flow := flow.NewFlow(mock)
weathers, err := flow.ListDailyWeathers(context.Background(), "Asia/Seoul", time.Now())
require.NoError(t, err)
require.Len(t, weathers, 1)
require.InDelta(t, 30.0, weathers[0].High, 0.01)
require.InDelta(t, 30.0, weathers[0].Low, 0.01)
require.Equal(t, "CLOUDY", weathers[0].Condition)
}
func TestFlow_ListDailyWeathers_DifferentSourceAndTargetDate(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
mock := mocks.NewMockRepository(ctrl)
now := time.Now()
mock.EXPECT().ListWeathers(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*domain.Weather{
domain.NewWeather(
"1",
domain.WeatherSourceOpenWeather,
now,
now,
domain.WeatherConditionClear,
domain.Temperature{Value: domain.Celsius(20)},
),
domain.NewWeather(
"2",
domain.WeatherSourceKMA,
now,
now.Add(time.Hour*24),
domain.WeatherConditionCloudy,
domain.Temperature{Value: domain.Celsius(30)},
),
}, nil)
flow := flow.NewFlow(mock)
weathers, err := flow.ListDailyWeathers(context.Background(), "Asia/Seoul", time.Now())
require.NoError(t, err)
require.Len(t, weathers, 1)
require.InDelta(t, 30.0, weathers[0].High, 0.01)
require.InDelta(t, 20.0, weathers[0].Low, 0.01)
require.Equal(t, "CLOUDY", weathers[0].Condition)
}