Skip to content

Commit afb0317

Browse files
authored
Merge pull request #21 from Nexters/feature/20-resort-congestion-api
스키장 혼잡도 조회 API
2 parents 3a8d54d + ba33bbd commit afb0317

File tree

8 files changed

+250
-37
lines changed

8 files changed

+250
-37
lines changed

http/API-TEST.http

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ POST http://localhost:8080/api/snow-maker/{{resortId}}/vote?isPositive=false
1919
### 설질 투표 API(긍정)
2020
POST http://localhost:8080/api/snow-maker/{{resortId}}/vote?isPositive=true
2121

22+
### 혼잡도 조회
23+
GET http://localhost:8080/api/congestion/{{resortId}}

init.sql

Lines changed: 166 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,26 @@ DROP TABLE IF EXISTS ski_resorts;
2323
CREATE TABLE ski_resorts
2424
(
2525
resort_id BIGINT AUTO_INCREMENT PRIMARY KEY,
26-
`name` VARCHAR(255) NOT NULL,
27-
status VARCHAR(255) NOT NULL COMMENT '운영중, 운영종료, 예정',
28-
opening_date DATE NULL,
29-
closing_date DATE NULL,
30-
open_slopes INT NOT NULL DEFAULT 0,
31-
total_slopes INT NOT NULL DEFAULT 0,
32-
day_operating_hours VARCHAR(50) NULL COMMENT '주간 운영시간',
33-
night_operating_hours VARCHAR(50) NULL COMMENT '야간 운영시간',
34-
late_night_operating_hours VARCHAR(50) NULL COMMENT '심야 운영시간',
35-
dawn_operating_hours VARCHAR(50) NULL COMMENT '새벽 운영시간',
36-
midnight_operating_hours VARCHAR(50) NULL COMMENT '자정 운영시간',
37-
snowfall_time VARCHAR(50) NULL COMMENT '정설 시간',
38-
x_coordinate VARCHAR(10) NOT NULL COMMENT '위도 매핑 값',
39-
y_coordinate VARCHAR(10) NOT NULL COMMENT '경도 매핑 값',
40-
detailed_area_code VARCHAR(10) NULL COMMENT '예보 구역 코드(기온 예보에 사용)',
41-
broad_area_code VARCHAR(10) NULL COMMENT '광역 지역 코드(육상 예보에 사용)',
42-
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
43-
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
26+
`name` VARCHAR(255) NOT NULL,
27+
status VARCHAR(255) NOT NULL COMMENT '운영중, 운영종료, 예정',
28+
opening_date DATE NULL,
29+
closing_date DATE NULL,
30+
open_slopes INT NOT NULL DEFAULT 0,
31+
total_slopes INT NOT NULL DEFAULT 0,
32+
day_operating_hours VARCHAR(50) NULL COMMENT '주간 운영시간',
33+
night_operating_hours VARCHAR(50) NULL COMMENT '야간 운영시간',
34+
late_night_operating_hours VARCHAR(50) NULL COMMENT '심야 운영시간',
35+
dawn_operating_hours VARCHAR(50) NULL COMMENT '새벽 운영시간',
36+
midnight_operating_hours VARCHAR(50) NULL COMMENT '자정 운영시간',
37+
snowfall_time VARCHAR(50) NULL COMMENT '정설 시간',
38+
x_coordinate VARCHAR(10) NOT NULL COMMENT '위도 매핑 값',
39+
y_coordinate VARCHAR(10) NOT NULL COMMENT '경도 매핑 값',
40+
x_real_coordinate DECIMAL(10, 7) NULL COMMENT '위도 실제 값',
41+
y_real_coordinate DECIMAL(10, 7) NULL COMMENT '경도 실제 값',
42+
detailed_area_code VARCHAR(10) NULL COMMENT '예보 구역 코드(기온 예보에 사용)',
43+
broad_area_code VARCHAR(10) NULL COMMENT '광역 지역 코드(육상 예보에 사용)',
44+
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
45+
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
4446
);
4547

4648
-- 현재 날씨 테이블
@@ -64,7 +66,8 @@ CREATE TABLE hourly_weather
6466
(
6567
id BIGINT AUTO_INCREMENT PRIMARY KEY,
6668
resort_id BIGINT NOT NULL,
67-
forecast_time DATETIME NOT NULL,
69+
forecast_time VARCHAR(10) NOT NULL COMMENT '예보 시간(오전 8시)',
70+
priority INT NOT NULL COMMENT '우선순위(1, 2, 3, 4, 5)',
6871
temperature INT NOT NULL,
6972
precipitation_chance INT NOT NULL,
7073
`condition` VARCHAR(255) NOT NULL COMMENT '맑음, 흐림, 흐리고 비, 비, 눈, 안개',
@@ -108,7 +111,7 @@ CREATE TABLE slopes
108111
id BIGINT AUTO_INCREMENT PRIMARY KEY,
109112
resort_id BIGINT NOT NULL,
110113
`name` VARCHAR(255) NOT NULL,
111-
webcam_number INT NULL,
114+
webcam_number INT NULL,
112115
difficulty VARCHAR(255) NOT NULL COMMENT '초급, 중급, 중상급, 최상급, 파크',
113116
is_day_operating BOOLEAN DEFAULT FALSE,
114117
is_night_operating BOOLEAN DEFAULT FALSE,
@@ -124,43 +127,169 @@ CREATE TABLE slopes
124127
CREATE TABLE webcams
125128
(
126129
id BIGINT AUTO_INCREMENT PRIMARY KEY,
127-
resort_id BIGINT NOT NULL,
130+
resort_id BIGINT NOT NULL,
128131
`name` VARCHAR(255) NULL,
129-
number INT NULL,
132+
number INT NULL,
130133
description VARCHAR(255) NULL,
131134
url VARCHAR(255) NULL,
132-
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
133-
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
135+
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
136+
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
137+
FOREIGN KEY (resort_id) REFERENCES ski_resorts (resort_id)
138+
);
139+
140+
-- 혼잡도 테이블
141+
CREATE TABLE congestion
142+
(
143+
id BIGINT AUTO_INCREMENT PRIMARY KEY,
144+
resort_id BIGINT NOT NULL,
145+
congestion INT NOT NULL COMMENT '혼잡도(1, 2, 3, 4)',
146+
description VARCHAR(255) NULL COMMENT '여유(1), 보통(2), 혼잡(3), 매우 혼잡(4)',
147+
time VARCHAR(10) NOT NULL COMMENT '시간(오전 8시)',
148+
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
149+
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
134150
FOREIGN KEY (resort_id) REFERENCES ski_resorts (resort_id)
135151
);
136152

153+
INSERT INTO congestion (resort_id, congestion, description, time)
154+
VALUES (1, 1, '여유', '오전 8시'),
155+
(1, 3, '혼잡', '오전 10시'),
156+
(1, 1, '여유', '오후 12시'),
157+
(1, 3, '혼잡', '오후 2시'),
158+
(1, 1, '여유', '오후 4시'),
159+
(1, 3, '혼잡', '오후 6시'),
160+
(1, 1, '여유', '오후 8시'),
161+
(1, 3, '혼잡', '오후 10시'),
162+
(1, 4, '매우 혼잡', '오전 12시'),
163+
(1, 4, '매우 혼잡', '오전 2시'),
164+
(2, 1, '여유', '오전 8시'),
165+
(2, 3, '혼잡', '오전 10시'),
166+
(2, 1, '여유', '오후 12시'),
167+
(2, 3, '혼잡', '오후 2시'),
168+
(2, 1, '여유', '오후 4시'),
169+
(2, 3, '혼잡', '오후 6시'),
170+
(2, 1, '여유', '오후 8시'),
171+
(2, 3, '혼잡', '오후 10시'),
172+
(2, 4, '매우 혼잡', '오전 12시'),
173+
(2, 4, '매우 혼잡', '오전 2시'),
174+
(3, 1, '여유', '오전 8시'),
175+
(3, 3, '혼잡', '오전 10시'),
176+
(3, 1, '여유', '오후 12시'),
177+
(3, 3, '혼잡', '오후 2시'),
178+
(3, 1, '여유', '오후 4시'),
179+
(3, 3, '혼잡', '오후 6시'),
180+
(3, 1, '여유', '오후 8시'),
181+
(3, 3, '혼잡', '오후 10시'),
182+
(3, 4, '매우 혼잡', '오전 12시'),
183+
(3, 4, '매우 혼잡', '오전 2시'),
184+
(4, 1, '여유', '오전 8시'),
185+
(4, 3, '혼잡', '오전 10시'),
186+
(4, 1, '여유', '오후 12시'),
187+
(4, 3, '혼잡', '오후 2시'),
188+
(4, 4, '매우 혼잡', '오후 4시'),
189+
(4, 4, '매우 혼잡', '오후 6시'),
190+
(4, 4, '매우 혼잡', '오후 8시'),
191+
(4, 4, '매우 혼잡', '오후 10시'),
192+
(4, 4, '매우 혼잡', '오전 12시'),
193+
(4, 4, '매우 혼잡', '오전 2시'),
194+
(5, 1, '여유', '오전 8시'),
195+
(5, 3, '혼잡', '오전 10시'),
196+
(5, 1, '여유', '오후 12시'),
197+
(5, 3, '혼잡', '오후 2시'),
198+
(5, 1, '여유', '오후 4시'),
199+
(5, 3, '혼잡', '오후 6시'),
200+
(5, 1, '여유', '오후 8시'),
201+
(5, 3, '혼잡', '오후 10시'),
202+
(5, 4, '매우 혼잡', '오전 12시'),
203+
(5, 4, '매우 혼잡', '오전 2시'),
204+
(6, 1, '여유', '오전 8시'),
205+
(6, 3, '혼잡', '오전 10시'),
206+
(6, 1, '여유', '오후 12시'),
207+
(6, 3, '혼잡', '오후 2시'),
208+
(6, 1, '여유', '오후 4시'),
209+
(6, 3, '혼잡', '오후 6시'),
210+
(6, 1, '여유', '오후 8시'),
211+
(6, 3, '혼잡', '오후 10시'),
212+
(6, 4, '매우 혼잡', '오전 12시'),
213+
(6, 3, '혼잡', '오전 2시'),
214+
(7, 1, '여유', '오전 8시'),
215+
(7, 3, '혼잡', '오전 10시'),
216+
(7, 1, '여유', '오후 12시'),
217+
(7, 3, '혼잡', '오후 2시'),
218+
(7, 1, '여유', '오후 4시'),
219+
(7, 3, '혼잡', '오후 6시'),
220+
(7, 1, '여유', '오후 8시'),
221+
(7, 3, '혼잡', '오후 10시'),
222+
(7, 4, '매우 혼잡', '오전 12시'),
223+
(7, 4, '매우 혼잡', '오전 2시'),
224+
(8, 1, '여유', '오전 8시'),
225+
(8, 3, '혼잡', '오전 10시'),
226+
(8, 1, '여유', '오후 12시'),
227+
(8, 3, '혼잡', '오후 2시'),
228+
(8, 1, '여유', '오후 4시'),
229+
(8, 3, '혼잡', '오후 6시'),
230+
(8, 1, '여유', '오후 8시'),
231+
(8, 3, '혼잡', '오후 10시'),
232+
(8, 4, '매우 혼잡', '오전 12시'),
233+
(8, 4, '매우 혼잡', '오전 2시'),
234+
(9, 1, '여유', '오전 8시'),
235+
(9, 3, '혼잡', '오전 10시'),
236+
(9, 1, '여유', '오후 12시'),
237+
(9, 3, '혼잡', '오후 2시'),
238+
(9, 1, '여유', '오후 4시'),
239+
(9, 3, '혼잡', '오후 6시'),
240+
(9, 1, '여유', '오후 8시'),
241+
(9, 3, '혼잡', '오후 10시'),
242+
(9, 4, '매우 혼잡', '오전 12시'),
243+
(9, 4, '매우 혼잡', '오전 2시'),
244+
(10, 1, '여유', '오전 8시'),
245+
(10, 3, '혼잡', '오전 10시'),
246+
(10, 1, '여유', '오후 12시'),
247+
(10, 3, '혼잡', '오후 2시'),
248+
(10, 1, '여유', '오후 4시'),
249+
(10, 3, '혼잡', '오후 6시'),
250+
(10, 1, '여유', '오후 8시'),
251+
(10, 3, '혼잡', '오후 10시'),
252+
(10, 4, '매우 혼잡', '오전 12시'),
253+
(10, 4, '매우 혼잡', '오전 2시'),
254+
(11, 1, '여유', '오전 8시'),
255+
(11, 3, '혼잡', '오전 10시'),
256+
(11, 1, '여유', '오후 12시'),
257+
(11, 3, '혼잡', '오후 2시'),
258+
(11, 1, '여유', '오후 4시'),
259+
(11, 3, '혼잡', '오후 6시'),
260+
(11, 1, '여유', '오후 8시'),
261+
(11, 3, '혼잡', '오후 10시'),
262+
(11, 4, '매우 혼잡', '오전 12시'),
263+
(11, 4, '매우 혼잡', '오전 2시');
264+
137265
-- 스키장 정보
138266
INSERT INTO ski_resorts (`name`, status, opening_date, closing_date, open_slopes, total_slopes, day_operating_hours,
139267
night_operating_hours, late_night_operating_hours, dawn_operating_hours,
140-
midnight_operating_hours, snowfall_time, x_coordinate, y_coordinate, detailed_area_code,
141-
broad_area_code)
268+
midnight_operating_hours, snowfall_time, x_coordinate, y_coordinate, x_real_coordinate,
269+
y_real_coordinate, detailed_area_code, broad_area_code)
142270
VALUES ('지산 리조트', '예정', STR_TO_DATE('2024.12.04', '%Y.%m.%d'), NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, '69',
143-
'119', '11B20701', '11B00000'),
271+
'119', 37.2180444, 127.3458046, '11B20701', '11B00000'),
144272
('곤지암 스키장', '예정', STR_TO_DATE('2024.12.03', '%Y.%m.%d'), NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, '69',
145-
'119', '11B20702', '11B00000'),
273+
'119', 37.3388535, 127.2913164, '11B20702', '11B00000'),
146274
('비발디파크', '예정', STR_TO_DATE('2024.11.25', '%Y.%m.%d'), NULL, 0, 0, '08:30~16:30', '18:30~22:30', NULL, NULL,
147-
NULL, '16:30~18:30', '72', '129', '11D10302', '11D10000'),
275+
NULL, '16:30~18:30', '72', '129', 37.6485927, 127.6816583, '11D10302', '11D10000'),
148276
('엘리시안 강촌', '예정', STR_TO_DATE('2024.11.30', '%Y.%m.%d'), NULL, 0, 0, '09:00~17:00', '18:30~24:00', '18:30~03:00',
149-
NULL, NULL, '17:00~18:30', '71', '132', '11D10301', '11D10000'),
277+
NULL, NULL, '17:00~18:30', '71', '132', 37.8269481, 127.5795879, '11D10301', '11D10000'),
150278
('웰리힐리파크', '예정', STR_TO_DATE('2024.11.30', '%Y.%m.%d'), NULL, 0, 0, '09:00~16:30', '18:30~22:30', '22:30~24:00',
151-
NULL, NULL, '16:30~18:30', '81', '126', '11D10402', '11D10000'),
279+
NULL, NULL, '16:30~18:30', '81', '126', 37.4854756, 128.2431349, '11D10402', '11D10000'),
152280
('휘닉스파크', '예정', STR_TO_DATE('2024.11.22', '%Y.%m.%d'), NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, '14:30~18:00',
153-
'84', '128', '11D10503', '11D10000'),
281+
'84', '128', 37.5837935, 128.3241444, '11D10503', '11D10000'),
154282
('하이원 스키장', '예정', STR_TO_DATE('2024.12.06', '%Y.%m.%d'), NULL, 0, 0, '09:00~16:00', '18:00~22:00', NULL, NULL,
155-
NULL, '16:00~18:00', '92', '120', '11D10502', '11D10000'),
283+
NULL, '16:00~18:00', '92', '120', 37.2085908, 128.8244331, '11D10502', '11D10000'),
156284
('용평스키장 모나', '예정', STR_TO_DATE('2024.11.22', '%Y.%m.%d'), NULL, 0, 0, '09:00~17:00', '19:00~22:00', NULL, NULL,
157-
NULL, '17:00~19:00', '89', '130', '11D20201', '11D20000'),
285+
NULL, '17:00~19:00', '89', '130', 37.6442675, 128.6776039, '11D20201', '11D20000'),
158286
('무주덕유산', '예정', STR_TO_DATE('2024.12.06', '%Y.%m.%d'), NULL, 0, 0, '07:00~16:00', '18:00~21:00', NULL, NULL,
159-
NULL, '16:30~18:30', '75', '93', '11F10302', '11F10000'),
287+
NULL, '16:30~18:30', '75', '93', 35.8942139, 127.7421179, '11F10302', '11F10000'),
160288
('에덴벨리(양산)', '예정', STR_TO_DATE('2024.11.23', '%Y.%m.%d'), NULL, 0, 0, NULL, NULL, NULL, NULL, NULL,
161-
'17:30~19:00', '95', '80', '11H20102', '11H20000'),
289+
'17:30~19:00', '95', '80', 35.4291289, 128.9817966, '11H20102', '11H20000'),
162290
('오투리조트', '예정', STR_TO_DATE('2024.11.29', '%Y.%m.%d'), NULL, 0, 0, '09:30~16:30', '18:00~21:30', NULL, NULL,
163-
NULL, '16:30~18:00', '95', '119', '11D20301', '11D20000');
291+
NULL, '16:30~18:00', '95', '119', 37.1766149, 128.9402658, '11D20301', '11D20000');
292+
164293

165294
-- 하이윈 스키장 슬로프 정보 (resort_id = 7)
166295
INSERT INTO slopes (resort_id, `name`, difficulty, is_day_operating, is_night_operating, is_late_night_operating,
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package nexters.weski.congestion
2+
3+
import jakarta.persistence.*
4+
import nexters.weski.common.BaseEntity
5+
import nexters.weski.ski_resort.SkiResort
6+
7+
@Entity
8+
@Table(name = "congestion")
9+
data class Congestion(
10+
@Id
11+
@GeneratedValue(strategy = GenerationType.IDENTITY)
12+
val id: Long = 0,
13+
val time: String,
14+
val congestion: Int,
15+
val description: String, // 여유, 보통, 혼잡, 매우혼잡
16+
@ManyToOne
17+
@JoinColumn(name = "resort_id")
18+
val skiResort: SkiResort
19+
) : BaseEntity()
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package nexters.weski.congestion
2+
3+
import io.swagger.v3.oas.annotations.Operation
4+
import io.swagger.v3.oas.annotations.tags.Tag
5+
import org.springframework.web.bind.annotation.GetMapping
6+
import org.springframework.web.bind.annotation.PathVariable
7+
import org.springframework.web.bind.annotation.RestController
8+
9+
@Tag(name = "혼잡도 정보 조회 API", description = "특정 스키장의 혼잡도 정보 조회")
10+
@RestController
11+
class CongestionController(
12+
private val congestionService: CongestionService
13+
) {
14+
@Operation(summary = "특정 스키장의 혼잡도 조회 API")
15+
@GetMapping("/api/congestion/{resortId}")
16+
fun getResortCongestion(@PathVariable resortId: String): List<CongestionResponseDto> {
17+
return congestionService.getCongestion(resortId)
18+
}
19+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package nexters.weski.congestion
2+
3+
import org.springframework.data.jpa.repository.JpaRepository
4+
5+
interface CongestionRepository : JpaRepository<Congestion, Long> {
6+
fun findAllBySkiResortResortId(resortId: Long): List<Congestion>
7+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package nexters.weski.congestion
2+
3+
import io.swagger.v3.oas.annotations.media.Schema
4+
5+
@Schema(description = "스키장 혼잡도 응답 DTO")
6+
data class CongestionResponseDto(
7+
val time: String,
8+
val congestion: Int,
9+
val description: String
10+
) {
11+
companion object {
12+
fun fromEntity(congestion: Congestion): CongestionResponseDto {
13+
return CongestionResponseDto(
14+
time = congestion.time,
15+
congestion = congestion.congestion,
16+
description = congestion.description
17+
)
18+
}
19+
}
20+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package nexters.weski.congestion
2+
3+
import org.springframework.stereotype.Service
4+
5+
@Service
6+
class CongestionService(
7+
private val congestionRepository: CongestionRepository
8+
) {
9+
fun getCongestion(resortId: String): List<CongestionResponseDto> {
10+
return congestionRepository.findAllBySkiResortResortId(resortId = resortId.toLong())
11+
.map { CongestionResponseDto.fromEntity(it) }
12+
}
13+
14+
}

src/main/resources/application.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ springdoc:
2424
weather:
2525
api:
2626
key: p6zNXOJrrBY4cuX7OYtdDMtmR8hiGeUaBLf0z6BXnm/qniV8wB0SuPwBgqKDTKV/24EW7xiRY3DCS21Ess/42Q==
27+
tamp:
28+
api:
29+
key: hzztwqD56d3rBN9hEo1rY1yJiCqtfWY55Obn4Ocj

0 commit comments

Comments
 (0)