-
Notifications
You must be signed in to change notification settings - Fork 9
Mc/matchmaking poc1 #339
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Mc/matchmaking poc1 #339
Changes from 5 commits
aed77cb
1261c53
9335d53
94b9e77
848665b
893d1d1
2f5cadc
ea9d232
8afe269
776d8aa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,7 +39,7 @@ POM_DEVELOPER_NAME=PubNub | |
| [email protected] | ||
|
|
||
| IOS_SIMULATOR_ID=iPhone 15 Pro | ||
| #SWIFT_PATH=../swift | ||
| #SWIFT_PATH=../swift # swift project sourcecode is in the same folder as kotlin source | ||
|
|
||
| ENABLE_TARGET_JS=true | ||
| ENABLE_TARGET_IOS_OTHER=false | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| plugins { | ||
| alias(libs.plugins.benmanes.versions) | ||
| id("pubnub.kotlin-library") | ||
| id("pubnub.dokka") | ||
| } | ||
|
|
||
| dependencies { | ||
| api(project(":pubnub-matchmaking-kotlin:pubnub-matchmaking-kotlin-api")) | ||
| implementation(project(":pubnub-matchmaking-kotlin:pubnub-matchmaking-kotlin-impl")) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| import com.pubnub.gradle.enableAnyIosTarget // why ENABLE_TARGET_IOS_OTHER=false | ||
| import com.pubnub.gradle.enableJsTarget | ||
|
|
||
| plugins { | ||
| alias(libs.plugins.benmanes.versions) | ||
| id("pubnub.shared") | ||
| id("pubnub.dokka") | ||
| id("pubnub.multiplatform") // adds plugin to enables KMP | ||
| id("pubnub.ios-simulator-test") // todo what is this -> do odpalania testów na symulatorze ios | ||
| } | ||
|
|
||
| kotlin { | ||
| sourceSets { | ||
| val commonMain by getting { | ||
| dependencies { | ||
| api(project(":pubnub-kotlin:pubnub-kotlin-api")) | ||
| // todo do sprawdzania na projekcie z niższym kotlinem wymuszając niższa wersję odpowiednią komenda | ||
| implementation(libs.kotlinx.atomicfu) // todo in kotlin 2.1.2 this will be in standard library | ||
| } | ||
| } | ||
| val jvmMain by getting { | ||
| dependencies { | ||
| api(libs.retrofit2) | ||
| api(libs.okhttp) | ||
| api(libs.okhttp.logging) | ||
| api(libs.gson) | ||
| implementation(libs.slf4j) | ||
| } | ||
| } | ||
| if (enableAnyIosTarget) { | ||
| val appleMain by getting { | ||
| dependencies { | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (enableJsTarget) { | ||
| val jsMain by getting { | ||
| dependencies { | ||
| } | ||
| } | ||
| } | ||
|
|
||
| val commonTest by getting { | ||
| dependencies { | ||
| // implementation(project(":pubnub-kotlin:pubnub-kotlin-test")) // todo not needed for now | ||
| implementation(kotlin("test")) | ||
| implementation(libs.kotlinx.coroutines.test) | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| package com.pubnub.matchmaking | ||
|
|
||
| import com.pubnub.api.PubNub | ||
| import com.pubnub.api.models.consumer.objects.PNKey | ||
| import com.pubnub.api.models.consumer.objects.PNPage | ||
| import com.pubnub.api.models.consumer.objects.PNSortKey | ||
| import com.pubnub.kmp.CustomObject | ||
| import com.pubnub.kmp.PNFuture | ||
| import com.pubnub.matchmaking.entities.FindMatchResult | ||
| import com.pubnub.matchmaking.entities.GetUsersResponse | ||
| import com.pubnub.matchmaking.entities.MatchmakingStatus | ||
|
|
||
| interface Matchmaking { | ||
| val pubNub: PubNub | ||
|
|
||
| fun createUser( | ||
| id: String, | ||
| name: String? = null, | ||
| externalId: String? = null, | ||
| profileUrl: String? = null, | ||
| email: String? = null, | ||
| custom: Any? = null, | ||
| status: String? = null, | ||
| type: String? = null, | ||
| ): PNFuture<User> | ||
|
|
||
| fun getUser(userId: String): PNFuture<User> | ||
|
|
||
| /** | ||
| * Returns a paginated list of all users and their details | ||
| * | ||
| * @param filter Expression used to filter the results. Returns only these users whose properties satisfy the | ||
| * given expression are returned. The filtering language is defined in [documentation](https://www.pubnub.com/docs/general/metadata/filtering). | ||
| * @param sort A collection to specify the sort order. Available options are id, name, and updated. Use asc or desc | ||
| * @param limit Number of objects to return in response. The default (and maximum) value is 100. | ||
| * @param page Object used for pagination to define which previous or next result page you want to fetch. | ||
| * | ||
| * @return [PNFuture] containing a set of users with pagination information (next, prev, total). | ||
| */ | ||
| fun getUsers( | ||
| filter: String? = null, | ||
| sort: Collection<PNSortKey<PNKey>> = listOf(), | ||
| limit: Int? = null, | ||
| page: PNPage? = null, | ||
| ): GetUsersResponse | ||
|
|
||
| fun updateUser( | ||
| id: String, | ||
| // TODO change nulls to Optionals when there is support. In Kotlin SDK there should be possibility to handle PatchValue | ||
| name: String? = null, | ||
| externalId: String? = null, | ||
| profileUrl: String? = null, | ||
| email: String? = null, | ||
| custom: CustomObject? = null, | ||
| status: String? = null, | ||
| type: String? = null, | ||
| ): PNFuture<User> | ||
|
|
||
| fun deleteUser(id: String, soft: Boolean = false): PNFuture<User?> | ||
|
|
||
| fun findMatch(userId: String): PNFuture<String> | ||
|
|
||
| fun findMatch(userId: String, callback: ((MatchmakingStatus) -> Unit)?): PNFuture<FindMatchResult> | ||
|
|
||
| fun getMatchStatus(userId: String): PNFuture<MatchmakingStatus> | ||
|
|
||
| fun cancelMatchmaking(userId: String): PNFuture<Unit> | ||
|
|
||
| // todo implement | ||
| fun addMissingUserToMatch(userId: String): PNFuture<Unit> | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| package com.pubnub.matchmaking | ||
|
|
||
| import com.pubnub.kmp.CustomObject | ||
| import com.pubnub.kmp.PNFuture | ||
|
|
||
| // todo add kdoc | ||
| interface User { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's concerning that we're copying and creating yet another implementation of this could use some more thought to find the best solution |
||
| val matchmaking: Matchmaking | ||
| val id: String | ||
| val name: String? | ||
| val externalId: String? | ||
| val profileUrl: String? | ||
| val email: String? | ||
| val custom: Map<String, Any?>? | ||
| val status: String? | ||
| val type: String? | ||
| val updated: String? | ||
| val eTag: String? | ||
|
|
||
| fun update( | ||
| name: String? = null, | ||
| externalId: String? = null, | ||
| profileUrl: String? = null, | ||
| email: String? = null, | ||
| custom: CustomObject? = null, | ||
| status: String? = null, | ||
| type: String? = null, | ||
| ): PNFuture<User> | ||
|
|
||
| fun update( | ||
| updateAction: UpdatableValues.( | ||
| user: User | ||
| ) -> Unit | ||
| ): PNFuture<User> | ||
|
|
||
| fun delete(soft: Boolean = false): PNFuture<User?> | ||
|
|
||
| class UpdatableValues( | ||
| /** | ||
| * The new value for [User.name]. | ||
| */ | ||
| var name: String? = null, | ||
| /** | ||
| * The new value for [User.externalId]. | ||
| */ | ||
| var externalId: String? = null, | ||
| /** | ||
| * The new value for [User.profileUrl]. | ||
| */ | ||
| var profileUrl: String? = null, | ||
| /** | ||
| * The new value for [User.email]. | ||
| */ | ||
| var email: String? = null, | ||
| /** | ||
| * The new value for [User.custom]. | ||
| */ | ||
| var custom: CustomObject? = null, | ||
| /** | ||
| * The new value for [User.status]. | ||
| */ | ||
| var status: String? = null, | ||
| /** | ||
| * The new value for [User.type]. | ||
| */ | ||
| var type: String? = null, | ||
| ) | ||
|
|
||
| companion object | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package com.pubnub.matchmaking.entities | ||
|
|
||
| class FindMatchResult( | ||
| val result: String, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. String? what's inside? |
||
| val disconnect: AutoCloseable? | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package com.pubnub.matchmaking.entities | ||
|
|
||
| import com.pubnub.api.models.consumer.objects.PNPage | ||
| import com.pubnub.matchmaking.User | ||
|
|
||
| class GetUsersResponse( | ||
| val users: List<User>, | ||
| val next: PNPage.PNNext?, | ||
| val prev: PNPage.PNPrev?, | ||
| val total: Int, | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package com.pubnub.matchmaking.entities | ||
|
|
||
| interface MatchmakingCallback { | ||
| fun onMatchFound(match: MatchmakingGroup?) | ||
|
|
||
| fun onMatchmakingFailed(reason: String?) | ||
|
|
||
| fun onStatusChange(status: MatchmakingStatus?) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| package com.pubnub.matchmaking.entities | ||
|
|
||
| import com.pubnub.matchmaking.User | ||
|
|
||
| class MatchmakingGroup(val users: Set<User>) // todo currently we returns Set<User>. What about Set<userid> ? |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package com.pubnub.matchmaking.entities | ||
|
|
||
| enum class MatchmakingStatus { | ||
| IN_QUEUE, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what can a user do with all those statuses? for example, why do we have an UNKNOWN status? we control this code, so shouldn't all of them be known? can we figure out the minimum list of statuses to make this work? |
||
| MATCHMAKING_STARTED, | ||
| RE_ADDED_TO_QUEUE, | ||
| MATCH_FOUND, | ||
| CANCELLED, // todo how to cancel matchmaking? | ||
| FAILED, | ||
| UNKNOWN, | ||
|
|
||
| INITIALLY_MATCHED, // todo do we need it, | ||
| WAITING_FOR_CONFIRMATION; // todo do we need it, | ||
|
|
||
| companion object { | ||
| fun fromString(value: String): MatchmakingStatus { | ||
| return values().find { it.name.equals(value, ignoreCase = true) } ?: UNKNOWN | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| @file:OptIn(ExperimentalKotlinGradlePluginApi::class) | ||
|
|
||
| import com.pubnub.gradle.enableAnyIosTarget | ||
| import com.pubnub.gradle.enableJsTarget | ||
| import com.pubnub.gradle.tasks.GenerateVersionTask | ||
| import org.gradle.kotlin.dsl.register | ||
| import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi | ||
| import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension | ||
|
|
||
| plugins { | ||
| alias(libs.plugins.kotlinx.atomicfu) // todo do we need lib for atomic operations | ||
| id("pubnub.ios-simulator-test") // start x-code ios simulator before ios test run | ||
| id("pubnub.shared") | ||
| id("pubnub.dokka") | ||
| id("pubnub.multiplatform") | ||
| // alias(libs.plugins.mokkery) // todo downgrade version in libs.version.toml to be compatible with used kotlin version(2.0.21) | ||
| } | ||
|
|
||
| kotlin { | ||
| sourceSets { | ||
| val commonMain by getting { | ||
| dependencies { | ||
| api(libs.kotlinx.coroutines.core) // todo this is needed for Service that simulates matchmaking REST api call | ||
| implementation(project(":pubnub-matchmaking-kotlin:pubnub-matchmaking-kotlin-api")) | ||
| implementation(project(":pubnub-kotlin:pubnub-kotlin-api")) | ||
| implementation(libs.kotlinx.atomicfu) // todo this is needed for Service that simulates matchmaking REST api call | ||
| implementation(libs.touchlab.kermit) | ||
| } | ||
| } | ||
|
|
||
| val commonTest by getting { | ||
| dependencies { | ||
| implementation(kotlin("test")) | ||
| // implementation(project(":pubnub-chat-test")) | ||
| } | ||
| } | ||
|
|
||
| val jvmMain by getting { | ||
| dependencies { | ||
| // implementation(project(":pubnub-kotlin")) //todo it shouldn't be required but because of some error might be | ||
| implementation(kotlin("test-junit")) | ||
| } | ||
| } | ||
|
|
||
| if (enableJsTarget) { | ||
| val jsTest by getting { | ||
| dependencies { | ||
| implementation(kotlin("test-js")) // to jest potrzebne bo testy KMP na targecie JS nie działały, mimo, że powinny | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (enableAnyIosTarget) { | ||
| (this as ExtensionAware).extensions.configure<CocoapodsExtension> { | ||
| summary = "Some description for a Kotlin/Native module" | ||
| homepage = "Link to a Kotlin/Native module homepage" | ||
| } | ||
| } | ||
| } | ||
|
|
||
| val generateVersion = | ||
| tasks.register<GenerateVersionTask>("generateVersion") { | ||
| fileName.set("MatchmakingVersion") | ||
| packageName.set("com.pubnub.matchmaking.internal") | ||
| constName.set("PUBNUB_MATCHMAKING_VERSION") | ||
| version.set(providers.gradleProperty("VERSION_NAME")) | ||
| outputDirectory.set( | ||
| layout.buildDirectory.map { | ||
| it.dir("generated/sources/generateVersion") | ||
| }, | ||
| ) | ||
| } | ||
|
|
||
| kotlin.sourceSets.getByName("commonMain").kotlin.srcDir(generateVersion) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems overly complicated, couldn't the whole API be just one method -
where MatchResult contains the set of users that were matched or the ID of the game or some other means of starting the game or confirming the match?
in case of error you would get an exception with details of the error, in case of success you get the result
why would I want to observe statuses like IN_QUEUE, RE_ADDED_TO_QUEUE etc, it's not useful?