Skip to content

Commit b6ddec8

Browse files
Merge pull request #51 from boostcampwm-2022/25-feature-get-seoul-bus-last-time
서울 버스 막차 시간 구하기
2 parents 92a7b7e + 5a5c8a5 commit b6ddec8

33 files changed

+677
-353
lines changed

data/src/main/java/com/stop/data/di/NetworkModule.kt

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,8 @@ import dagger.Provides
1111
import dagger.hilt.InstallIn
1212
import dagger.hilt.components.SingletonComponent
1313
import okhttp3.Interceptor
14-
import okhttp3.MediaType.Companion.toMediaTypeOrNull
1514
import okhttp3.OkHttpClient
16-
import okhttp3.Protocol
1715
import okhttp3.Response
18-
import okhttp3.ResponseBody.Companion.toResponseBody
1916
import okhttp3.logging.HttpLoggingInterceptor
2017
import retrofit2.Retrofit
2118
import retrofit2.converter.moshi.MoshiConverterFactory
@@ -31,13 +28,6 @@ internal object NetworkModule {
3128
private const val APIS_KEY_NAME = "ServiceKey"
3229
private const val WS_KEY_NAME = "ServiceKey"
3330

34-
private const val T_MAP_ROUTE_URL = "transit/routes"
35-
36-
/**
37-
* resources에 fake 데이터가 담긴 파일을 넣어줘야 Fake TMap이 정상적으로 동작합니다.
38-
*/
39-
private const val FAKE_JSON_URI = "response.json"
40-
4131
@Provides
4232
@Singleton
4333
fun provideOkHttpClient(
@@ -54,7 +44,7 @@ internal object NetworkModule {
5444
@Provides
5545
@Singleton
5646
fun provideMoshi(): Moshi {
57-
return Moshi.Builder()
47+
return Moshi.Builder()
5848
.addLast(KotlinJsonAdapterFactory())
5949
.build()
6050
}
@@ -144,23 +134,15 @@ internal object NetworkModule {
144134
override fun intercept(chain: Interceptor.Chain): Response {
145135
val url = chain.request().url.toUri().toString()
146136

147-
if (url.contains(T_MAP_ROUTE_URL)) {
148-
val response = readJson(FAKE_JSON_URI)
149-
return chain.proceed(chain.request())
150-
.newBuilder()
151-
.code(200)
152-
.protocol(Protocol.HTTP_2)
153-
.message("success")
154-
.body(
155-
response.toByteArray()
156-
.toResponseBody("application/json".toMediaTypeOrNull())
157-
).addHeader("content-type", "application/json")
158-
.build()
159-
}
160-
161137
val (name: String, key: String) = when {
162-
url.contains(BuildConfig.OPEN_API_SEOUL_URL) -> Pair(OPEN_API_SEOUL_KEY_NAME, BuildConfig.BUS_KEY)
163-
url.contains(BuildConfig.T_MAP_URL) -> Pair(T_MAP_APP_KEY_NAME, BuildConfig.T_MAP_APP_KEY)
138+
url.contains(BuildConfig.OPEN_API_SEOUL_URL) -> Pair(
139+
OPEN_API_SEOUL_KEY_NAME,
140+
BuildConfig.BUS_KEY
141+
)
142+
url.contains(BuildConfig.T_MAP_URL) -> Pair(
143+
T_MAP_APP_KEY_NAME,
144+
BuildConfig.T_MAP_APP_KEY
145+
)
164146
url.contains(BuildConfig.APIS_URL) -> Pair(APIS_KEY_NAME, BuildConfig.BUS_KEY)
165147
url.contains(BuildConfig.WS_BUS_URL) -> Pair(WS_KEY_NAME, BuildConfig.BUS_KEY)
166148
else -> {
@@ -175,10 +157,5 @@ internal object NetworkModule {
175157
proceed(newRequest)
176158
}
177159
}
178-
179-
private fun readJson(fileName: String): String {
180-
return Thread.currentThread().contextClassLoader?.getResource(fileName)
181-
?.readText() ?: ""
182-
}
183160
}
184161
}

data/src/main/java/com/stop/data/remote/network/WsBusApiService.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.stop.data.remote.network
22

33
import com.stop.data.remote.model.NetworkResult
4+
import com.stop.domain.model.route.seoul.bus.GetBusLastTimeResponse
5+
import com.stop.domain.model.route.seoul.bus.GetBusLineResponse
46
import com.stop.domain.model.route.seoul.bus.GetBusStationArsIdResponse
57
import retrofit2.http.GET
68
import retrofit2.http.Query
@@ -13,7 +15,22 @@ internal interface WsBusApiService {
1315
@Query("resultType") resultType: String = "json",
1416
): NetworkResult<GetBusStationArsIdResponse>
1517

18+
@GET(GET_BUS_LINE_URL)
19+
suspend fun getBusLine(
20+
@Query("arsId") stationId: String,
21+
@Query("resultType") resultType: String = "json",
22+
): NetworkResult<GetBusLineResponse>
23+
24+
@GET(GET_BUS_LAST_TIME_URL)
25+
suspend fun getBusLastTime(
26+
@Query("arsId") stationId: String,
27+
@Query("busRouteId") lineId: String,
28+
@Query("resultType") resultType: String = "json",
29+
): NetworkResult<GetBusLastTimeResponse>
30+
1631
companion object {
1732
private const val GET_BUS_ARS_URL = "stationinfo/getStationByName"
33+
private const val GET_BUS_LINE_URL = "stationinfo/getRouteByStation"
34+
private const val GET_BUS_LAST_TIME_URL = "stationinfo/getBustimeByStation"
1835
}
1936
}

data/src/main/java/com/stop/data/remote/source/route/RouteRemoteDataSource.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package com.stop.data.remote.source.route
22

33
import com.stop.domain.model.geoLocation.AddressType
44
import com.stop.domain.model.route.gyeonggi.GetGyeonggiBusStationIdResponse
5+
import com.stop.domain.model.route.seoul.bus.GetBusLastTimeResponse
6+
import com.stop.domain.model.route.seoul.bus.GetBusLineResponse
57
import com.stop.domain.model.route.seoul.bus.GetBusStationArsIdResponse
68
import com.stop.domain.model.route.tmap.RouteRequest
79
import com.stop.domain.model.route.tmap.custom.Coordinate
@@ -18,5 +20,9 @@ internal interface RouteRemoteDataSource {
1820

1921
suspend fun getSeoulBusStationArsId(stationName: String): GetBusStationArsIdResponse
2022

23+
suspend fun getSeoulBusLine(stationId: String): GetBusLineResponse
24+
25+
suspend fun getSeoulBusLastTime(stationId: String, lineId: String): GetBusLastTimeResponse
26+
2127
suspend fun getGyeonggiBusStationId(stationName: String): GetGyeonggiBusStationIdResponse
2228
}

data/src/main/java/com/stop/data/remote/source/route/RouteRemoteDataSourceImpl.kt

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package com.stop.data.remote.source.route
22

33
import com.stop.data.remote.model.NetworkResult
44
import com.stop.data.remote.network.ApisDataService
5-
import com.stop.data.remote.network.FakeTmapApiService
65
import com.stop.data.remote.network.OpenApiSeoulService
6+
import com.stop.data.remote.network.TmapApiService
77
import com.stop.data.remote.network.WsBusApiService
88
import com.stop.domain.model.geoLocation.AddressType
99
import com.stop.domain.model.route.gyeonggi.GetGyeonggiBusStationIdResponse
10+
import com.stop.domain.model.route.seoul.bus.GetBusLastTimeResponse
11+
import com.stop.domain.model.route.seoul.bus.GetBusLineResponse
1012
import com.stop.domain.model.route.seoul.bus.GetBusStationArsIdResponse
1113
import com.stop.domain.model.route.seoul.subway.SubwayStationResponse
1214
import com.stop.domain.model.route.tmap.RouteRequest
@@ -16,24 +18,16 @@ import com.stop.domain.model.route.tmap.origin.RouteResponse
1618
import javax.inject.Inject
1719

1820
internal class RouteRemoteDataSourceImpl @Inject constructor(
19-
// private val tmapApiService: TmapApiService,
20-
private val fakeTmapApiService: FakeTmapApiService,
21+
private val tmapApiService: TmapApiService,
22+
// private val fakeTmapApiService: FakeTmapApiService,
2123
private val openApiSeoulService: OpenApiSeoulService,
2224
private val wsBusApiService: WsBusApiService,
2325
private val apisDataService: ApisDataService,
2426
) : RouteRemoteDataSource {
2527

2628
override suspend fun getRoute(routeRequest: RouteRequest): RouteResponse {
2729
with(
28-
fakeTmapApiService.getRoutes(
29-
startX = routeRequest.startX,
30-
startY = routeRequest.startY,
31-
endX = routeRequest.endX,
32-
endY = routeRequest.endY,
33-
lang = routeRequest.lang,
34-
format = routeRequest.format,
35-
count = routeRequest.count,
36-
)
30+
tmapApiService.getRoutes(routeRequest.toMap())
3731
) {
3832
return when (this) {
3933
is NetworkResult.Success -> this.data
@@ -45,7 +39,7 @@ internal class RouteRemoteDataSourceImpl @Inject constructor(
4539
}
4640

4741
override suspend fun reverseGeocoding(coordinate: Coordinate, addressType: AddressType): ReverseGeocodingResponse {
48-
with(fakeTmapApiService.getReverseGeocoding(coordinate.latitude, coordinate.longitude, addressType = addressType.type)) {
42+
with(tmapApiService.getReverseGeocoding(coordinate.latitude, coordinate.longitude, addressType = addressType.type)) {
4943
return when (this) {
5044
is NetworkResult.Success -> this.data
5145
is NetworkResult.Failure -> throw IllegalArgumentException(this.message)
@@ -85,6 +79,28 @@ internal class RouteRemoteDataSourceImpl @Inject constructor(
8579
}
8680
}
8781

82+
override suspend fun getSeoulBusLine(stationId: String): GetBusLineResponse {
83+
with(wsBusApiService.getBusLine(stationId)) {
84+
return when(this) {
85+
is NetworkResult.Success -> this.data
86+
is NetworkResult.Failure -> throw IllegalArgumentException(this.message)
87+
is NetworkResult.NetworkError -> throw this.exception
88+
is NetworkResult.Unexpected -> throw this.exception
89+
}
90+
}
91+
}
92+
93+
override suspend fun getSeoulBusLastTime(stationId: String, lineId: String): GetBusLastTimeResponse {
94+
with(wsBusApiService.getBusLastTime(stationId, lineId)) {
95+
return when(this) {
96+
is NetworkResult.Success -> this.data
97+
is NetworkResult.Failure -> throw IllegalArgumentException(this.message)
98+
is NetworkResult.NetworkError -> throw this.exception
99+
is NetworkResult.Unexpected -> throw this.exception
100+
}
101+
}
102+
}
103+
88104
override suspend fun getGyeonggiBusStationId(stationName: String): GetGyeonggiBusStationIdResponse {
89105
with(apisDataService.getBusStationId(stationName)) {
90106
return when (this) {

data/src/main/java/com/stop/data/repository/RouteRepositoryImpl.kt

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.stop.data.repository
33
import com.stop.data.remote.source.route.RouteRemoteDataSource
44
import com.stop.domain.model.geoLocation.AddressType
55
import com.stop.domain.model.route.gyeonggi.GetGyeonggiBusStationIdResponse
6+
import com.stop.domain.model.route.seoul.bus.GetBusLineResponse
67
import com.stop.domain.model.route.seoul.bus.GetBusStationArsIdResponse
78
import com.stop.domain.model.route.tmap.RouteRequest
89
import com.stop.domain.model.route.tmap.custom.Coordinate
@@ -13,13 +14,16 @@ import javax.inject.Inject
1314

1415
internal class RouteRepositoryImpl @Inject constructor(
1516
private val remoteDataSource: RouteRemoteDataSource
16-
): RouteRepository {
17+
) : RouteRepository {
1718

1819
override suspend fun getRoute(routeRequest: RouteRequest): RouteResponse {
1920
return remoteDataSource.getRoute(routeRequest)
2021
}
2122

22-
override suspend fun reverseGeocoding(coordinate: Coordinate, addressType: AddressType): ReverseGeocodingResponse {
23+
override suspend fun reverseGeocoding(
24+
coordinate: Coordinate,
25+
addressType: AddressType
26+
): ReverseGeocodingResponse {
2327
return remoteDataSource.reverseGeocoding(coordinate, addressType)
2428
}
2529

@@ -31,6 +35,18 @@ internal class RouteRepositoryImpl @Inject constructor(
3135
return remoteDataSource.getSeoulBusStationArsId(stationName)
3236
}
3337

38+
override suspend fun getSeoulBusLine(stationId: String): GetBusLineResponse {
39+
return remoteDataSource.getSeoulBusLine(stationId)
40+
}
41+
42+
override suspend fun getSeoulBusLastTime(stationId: String, lineId: String): String {
43+
return remoteDataSource.getSeoulBusLastTime(stationId, lineId)
44+
.lastTimeMsgBody
45+
.lastTimes
46+
.first()
47+
.lastTime
48+
}
49+
3450
override suspend fun getGyeonggiBusStationId(stationName: String): GetGyeonggiBusStationIdResponse {
3551
return remoteDataSource.getGyeonggiBusStationId(stationName)
3652
}

domain/src/main/java/com/stop/domain/di/UseCaseModule.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import com.stop.domain.usecase.geoLocation.GeoLocationUseCase
55
import com.stop.domain.usecase.geoLocation.GeoLocationUseCaseImpl
66
import com.stop.domain.usecase.nearplace.GetNearPlacesUseCase
77
import com.stop.domain.usecase.nearplace.GetNearPlacesUseCaseImpl
8+
import com.stop.domain.usecase.route.GetLastTransportTimeUseCase
9+
import com.stop.domain.usecase.route.GetLastTransportTimeUseCaseImpl
810
import com.stop.domain.usecase.route.GetRouteUseCase
911
import com.stop.domain.usecase.route.GetRouteUseCaseImpl
1012
import dagger.Binds
@@ -21,6 +23,12 @@ internal interface UseCaseModule {
2123
@Singleton
2224
fun provideGetRouteUseCase(getRouteUseCaseImpl: GetRouteUseCaseImpl): GetRouteUseCase
2325

26+
@Binds
27+
@Singleton
28+
fun provideGetLastTransportTimeUseCase(
29+
getLastTransportTimeUseCaseImpl: GetLastTransportTimeUseCaseImpl
30+
): GetLastTransportTimeUseCase
31+
2432
@Binds
2533
@Singleton
2634
fun provideGeoLocationUseCase(geoLocationUseCaseImpl: GeoLocationUseCaseImpl): GeoLocationUseCase
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.stop.domain.model.route
2+
3+
enum class Area(val cityName: String) {
4+
SEOUL("서울특별시"), GYEONGGI("경기도"), UN_SUPPORT_AREA("Unknown");
5+
6+
companion object {
7+
fun getAreaByName(name: String): Area {
8+
return values().firstOrNull {
9+
it.cityName == name
10+
} ?: UN_SUPPORT_AREA
11+
}
12+
}
13+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.stop.domain.model.route
2+
3+
import com.stop.domain.model.route.tmap.custom.Coordinate
4+
5+
data class TransportIdRequest(
6+
val transportMoveType: TransportMoveType,
7+
val stationId: String,
8+
val stationName: String,
9+
val coordinate: Coordinate,
10+
val stationType: Int,
11+
val area: Area,
12+
val lineId: String,
13+
val lineName: String,
14+
val term: Int, // 배차 간격, 서울 버스는 노선을 구하는 과정에서 얻을 수 있기 때문에 넣음
15+
) {
16+
fun changeStationId(newStationId: String): TransportIdRequest {
17+
return TransportIdRequest(
18+
transportMoveType = transportMoveType,
19+
stationId = newStationId,
20+
stationName = stationName,
21+
coordinate = coordinate,
22+
stationType = stationType,
23+
area = area,
24+
lineId = lineId,
25+
lineName = lineName,
26+
term = term,
27+
)
28+
}
29+
30+
fun changeLineId(newLineId: String, newTerm: Int?): TransportIdRequest {
31+
return TransportIdRequest(
32+
transportMoveType = transportMoveType,
33+
stationId = stationId,
34+
stationName = stationName,
35+
coordinate = coordinate,
36+
stationType = stationType,
37+
area = area,
38+
lineId = newLineId,
39+
lineName = lineName,
40+
term = newTerm ?: term,
41+
)
42+
}
43+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.stop.domain.model.route
2+
3+
data class TransportLastTimeInfo(
4+
val earliestTransportLastTime: String
5+
)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.stop.domain.model.route
2+
3+
enum class TransportMoveType {
4+
BUS, SUBWAY;
5+
6+
companion object {
7+
fun getMoveTypeByName(name: String): TransportMoveType? {
8+
return values().firstOrNull {
9+
it.name == name
10+
}
11+
}
12+
}
13+
}

0 commit comments

Comments
 (0)