@@ -38,6 +38,7 @@ public class TrackingSessionStatsService {
3838 private static final String F_DISTANCE_TOTAL = "distance_total" ;
3939 private static final String F_ASCENT_TOTAL = "ascent_total" ;
4040 private static final String F_DESCENT_TOTAL = "descent_total" ;
41+ private static final String F_MAX_ALTITUDE = "max_altitude" ;
4142 private static final String F_POINT_COUNT = "point_count" ;
4243
4344 private final StringRedisTemplate redisTemplate ;
@@ -50,6 +51,7 @@ public void recordPoint(Long sessionId, double lat, double lng, Double altitude,
5051 double distanceTotal = parseDouble (prev .get (F_DISTANCE_TOTAL ));
5152 double ascentTotal = parseDouble (prev .get (F_ASCENT_TOTAL ));
5253 double descentTotal = parseDouble (prev .get (F_DESCENT_TOTAL ));
54+ Double maxAltitude = parseNullableDouble (prev .get (F_MAX_ALTITUDE ));
5355 long pointCount = parseLong (prev .get (F_POINT_COUNT ));
5456
5557 Double prevLat = parseNullableDouble (prev .get (F_LAST_LAT ));
@@ -66,6 +68,9 @@ public void recordPoint(Long sessionId, double lat, double lng, Double altitude,
6668 descentTotal += -delta ;
6769 }
6870 }
71+ if (altitude != null && (maxAltitude == null || altitude > maxAltitude )) {
72+ maxAltitude = altitude ;
73+ }
6974 pointCount += 1 ;
7075
7176 Map <String , String > next = new HashMap <>();
@@ -78,6 +83,9 @@ public void recordPoint(Long sessionId, double lat, double lng, Double altitude,
7883 next .put (F_DISTANCE_TOTAL , String .valueOf (distanceTotal ));
7984 next .put (F_ASCENT_TOTAL , String .valueOf (ascentTotal ));
8085 next .put (F_DESCENT_TOTAL , String .valueOf (descentTotal ));
86+ if (maxAltitude != null ) {
87+ next .put (F_MAX_ALTITUDE , String .valueOf (maxAltitude ));
88+ }
8189 next .put (F_POINT_COUNT , String .valueOf (pointCount ));
8290
8391 hash .putAll (key , next );
@@ -88,6 +96,35 @@ public static String statsKey(Long sessionId) {
8896 return KEY_PREFIX + sessionId + STATS_SUFFIX ;
8997 }
9098
99+ /**
100+ * 세션 종료 시 통계 스냅샷 조회 — HikingRecord 생성에 사용된다.
101+ * 점이 한 번도 들어오지 않았으면 모든 필드 0/null.
102+ */
103+ public Stats getStats (Long sessionId ) {
104+ Map <String , String > entries = redisTemplate .opsForHash ().entries (statsKey (sessionId ))
105+ .entrySet ().stream ()
106+ .collect (java .util .stream .Collectors .toMap (
107+ e -> String .valueOf (e .getKey ()),
108+ e -> String .valueOf (e .getValue ())
109+ ));
110+ return new Stats (
111+ parseDouble (entries .get (F_DISTANCE_TOTAL )),
112+ parseDouble (entries .get (F_ASCENT_TOTAL )),
113+ parseDouble (entries .get (F_DESCENT_TOTAL )),
114+ parseNullableDouble (entries .get (F_MAX_ALTITUDE )),
115+ parseLong (entries .get (F_POINT_COUNT ))
116+ );
117+ }
118+
119+ public record Stats (
120+ double distanceMeters ,
121+ double ascentMeters ,
122+ double descentMeters ,
123+ Double maxAltitudeMeters ,
124+ long pointCount
125+ ) {
126+ }
127+
91128 /** Haversine 거리(m). */
92129 static double haversineMeters (double lat1 , double lng1 , double lat2 , double lng2 ) {
93130 double dLat = Math .toRadians (lat2 - lat1 );
0 commit comments