Skip to content

Commit

Permalink
Adding team data layer. (#87)
Browse files Browse the repository at this point in the history
  • Loading branch information
AdamMc331 committed Apr 11, 2022
1 parent 2e555f0 commit c7d70e1
Show file tree
Hide file tree
Showing 23 changed files with 386 additions and 7 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ local.properties
/event-api/build/
/event-implementation/build/
/feature-eventsummarylist/build/
/team-api/build/
/team-implementation/build/
/buildSrc/build/
PocketLeagueiOS/PocketLeagueiOS.xcodeproj/project.xcworkspace/xcuserdata/amcneilly.xcuserdatad/UserInterfaceState.xcuserstate
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import kotlinx.serialization.json.Json
/**
* Defines the API client information for communicating with the octane.gg API.
*/
class OctaneGGAPIClient {
internal class OctaneGGAPIClient {
val baseURL = "https://zsr.octane.gg/"

val httpClient = HttpClient {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import kotlinx.serialization.Serializable
* A data class mapping to an Event from the octane.gg API.
*/
@Serializable
data class EventDTO(
internal data class EventDTO(
@SerialName("_id")
val id: String,
val endDate: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import kotlinx.serialization.Serializable
* A DTO that maps to an event list response from the octane.gg API.
*/
@Serializable
data class EventListResponseDTO(
internal data class EventListResponseDTO(
val events: List<EventDTO>,
val page: Int,
val perPage: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import kotlinx.serialization.Serializable
* A data class mapping to a location from the octane.gg API.
*/
@Serializable
data class LocationDTO(
internal data class LocationDTO(
val city: String? = null,
val country: String? = null,
val venue: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import kotlinx.serialization.Serializable
* A data class mapping to a prize entity from the octane.gg API.
*/
@Serializable
data class PrizeDTO(
internal data class PrizeDTO(
val amount: Double? = null,
val currency: String? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import kotlinx.serialization.Serializable
* A data class mapping to a stage from the octane.gg API.
*/
@Serializable
data class StageDTO(
internal data class StageDTO(
@SerialName("_id")
val id: Int,
val endDate: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import kotlinx.datetime.TimeZone
/**
* Converts an [EventDTO] from octane.gg into an [EventSummary].
*/
fun EventDTO.toEventSummary(): EventSummary {
internal fun EventDTO.toEventSummary(): EventSummary {
return EventSummary(
id = this.id,
eventName = this.name ?: "N/A",
Expand Down
2 changes: 2 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ include ':event-api'
include ':event-implementation'
include ':feature-eventsummarylist'
include ':core-datetime'
include ':team-api'
include ':team-implementation'
62 changes: 62 additions & 0 deletions team-api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
plugins {
kotlin("multiplatform")
id("com.android.library")
}

kotlin {
android()

listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach {
it.binaries.framework {
baseName = "team-api"
}
}

sourceSets {
val commonMain by getting {
dependencies {
api(project(":core-models"))
api(project(":core-data"))
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.coroutines}")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val androidMain by getting
val androidTest by getting
val iosX64Main by getting
val iosArm64Main by getting
val iosSimulatorArm64Main by getting
val iosMain by creating {
dependsOn(commonMain)
iosX64Main.dependsOn(this)
iosArm64Main.dependsOn(this)
iosSimulatorArm64Main.dependsOn(this)
}
val iosX64Test by getting
val iosArm64Test by getting
val iosSimulatorArm64Test by getting
val iosTest by creating {
dependsOn(commonTest)
iosX64Test.dependsOn(this)
iosArm64Test.dependsOn(this)
iosSimulatorArm64Test.dependsOn(this)
}
}
}

android {
compileSdk = AndroidConfig.compileSDK
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = AndroidConfig.minSDK
targetSdk = AndroidConfig.targetSDK
}
}
2 changes: 2 additions & 0 deletions team-api/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.adammcneilly.pocketleague.team.api" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.adammcneilly.pocketleague.team.api

import com.adammcneilly.pocketleague.core.data.DataResult
import com.adammcneilly.pocketleague.core.models.Team
import kotlinx.coroutines.flow.Flow

/**
* An interface defining the data contract for all requests within the
* team domain.
*/
interface TeamRepository {

/**
* Requests a list of [Team] entities for all of the active teams within RLCS.
*/
fun fetchActiveTeams(): Flow<DataResult<List<Team>>>
}
74 changes: 74 additions & 0 deletions team-implementation/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
plugins {
kotlin("multiplatform")
kotlin("plugin.serialization")
id("com.android.library")
}

kotlin {
android()

listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach {
it.binaries.framework {
baseName = "team-implementation"
}
}

sourceSets {
val commonMain by getting {
dependencies {
implementation(project(":team-api"))
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
implementation("io.ktor:ktor-client-core:${Versions.ktor}")
implementation("io.ktor:ktor-client-json:${Versions.ktor}")
implementation("io.ktor:ktor-client-logging:${Versions.ktor}")
implementation("io.ktor:ktor-client-serialization:${Versions.ktor}")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val androidMain by getting {
dependencies {
implementation("io.ktor:ktor-client-android:${Versions.ktor}")
}
}
val androidTest by getting
val iosX64Main by getting
val iosArm64Main by getting
val iosSimulatorArm64Main by getting
val iosMain by creating {
dependsOn(commonMain)
iosX64Main.dependsOn(this)
iosArm64Main.dependsOn(this)
iosSimulatorArm64Main.dependsOn(this)

dependencies {
implementation("io.ktor:ktor-client-ios:${Versions.ktor}")
}
}
val iosX64Test by getting
val iosArm64Test by getting
val iosSimulatorArm64Test by getting
val iosTest by creating {
dependsOn(commonTest)
iosX64Test.dependsOn(this)
iosArm64Test.dependsOn(this)
iosSimulatorArm64Test.dependsOn(this)
}
}
}

android {
compileSdk = AndroidConfig.compileSDK
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = AndroidConfig.minSDK
targetSdk = AndroidConfig.targetSDK
}
}
2 changes: 2 additions & 0 deletions team-implementation/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.adammcneilly.pocketleague.team.implementation" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.adammcneilly.pocketleague.team.implementation.octanegg

import com.adammcneilly.pocketleague.core.data.DataResult
import io.ktor.client.HttpClient
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.serializer.KotlinxSerializer
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.get
import io.ktor.http.ContentType
import kotlinx.serialization.json.Json

/**
* Defines the API client information for communicating with the octane.gg API.
*/
internal class OctaneGGAPIClient {
val baseURL = "https://zsr.octane.gg/"

val httpClient = HttpClient {
install(JsonFeature) {
serializer = KotlinxSerializer(
Json {
ignoreUnknownKeys = true
acceptContentTypes = acceptContentTypes + ContentType.Any
}
)
}
}

/**
* A helper function to wrap all of our API requests in a try/catch and return a [DataResult]
* object.
*/
suspend inline fun <reified T : Any> getResponse(
endpoint: String,
requestBuilder: HttpRequestBuilder.() -> Unit = {},
): DataResult<T> {
val url = "$baseURL$endpoint"

return try {
// KTOR will switch to a different dispatcher, so we don't need to.
DataResult.Success(httpClient.get(url, requestBuilder))
} catch (e: Exception) {
DataResult.Error(e)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.adammcneilly.pocketleague.team.implementation.octanegg

import com.adammcneilly.pocketleague.core.data.DataResult
import com.adammcneilly.pocketleague.core.models.Team
import com.adammcneilly.pocketleague.team.api.TeamRepository
import com.adammcneilly.pocketleague.team.implementation.octanegg.dtos.TeamDTO
import com.adammcneilly.pocketleague.team.implementation.octanegg.dtos.TeamListResponseDTO
import com.adammcneilly.pocketleague.team.implementation.octanegg.mappers.toTeam
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

/**
* A concrete implementation of [TeamRepository] to request information from the octane.gg API.
*/
class OctaneGGTeamService : TeamRepository {

private val apiClient = OctaneGGAPIClient()

override fun fetchActiveTeams(): Flow<DataResult<List<Team>>> {
return flow {
val apiResult = apiClient.getResponse<TeamListResponseDTO>("teams/active")

val mappedResult: DataResult<List<Team>> = when (apiResult) {
is DataResult.Success -> {
val mappedTeams = apiResult.data.teams?.map(TeamDTO::toTeam).orEmpty()

DataResult.Success(mappedTeams)
}
is DataResult.Error -> {
DataResult.Error(apiResult.error)
}
}

emit(mappedResult)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.adammcneilly.pocketleague.team.implementation.octanegg.dtos

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/**
* Represents a [PlayerDTO] account within the octane.gg API.
*/
@Serializable
internal data class AccountDTO(
@SerialName("id")
val id: String? = null,
@SerialName("platform")
val platform: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.adammcneilly.pocketleague.team.implementation.octanegg.dtos

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/**
* Represents a person who is a player for a [TeamDTO] in the octane.gg API.
*/
@Serializable
internal data class PlayerDTO(
@SerialName("accounts")
val accounts: List<AccountDTO>? = null,
@SerialName("coach")
val coach: Boolean? = null,
@SerialName("country")
val country: String? = null,
@SerialName("_id")
val id: String? = null,
@SerialName("name")
val name: String? = null,
@SerialName("relevant")
val relevant: Boolean? = null,
@SerialName("slug")
val slug: String? = null,
@SerialName("substitute")
val substitute: Boolean? = null,
@SerialName("tag")
val tag: String? = null,
@SerialName("team")
val team: TeamOverviewDTO? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.adammcneilly.pocketleague.team.implementation.octanegg.dtos

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/**
* Represents a team within the octane.gg API domain.
*/
@Serializable
internal data class TeamDTO(
@SerialName("players")
val players: List<PlayerDTO>? = null,
@SerialName("team")
val team: TeamOverviewDTO? = null,
)
Loading

0 comments on commit c7d70e1

Please sign in to comment.