-
-
Notifications
You must be signed in to change notification settings - Fork 691
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into Notification_time_ago
- Loading branch information
Showing
62 changed files
with
1,319 additions
and
139 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
app/src/main/java/org/wikipedia/analytics/eventplatform/ABTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package org.wikipedia.analytics.eventplatform | ||
|
||
import org.wikipedia.settings.PrefsIoUtil | ||
import kotlin.random.Random | ||
|
||
open class ABTest(private val abTestName: String, private val abTestGroupCount: Int) { | ||
|
||
val group: Int | ||
get() { | ||
testGroup = PrefsIoUtil.getInt(AB_TEST_KEY_PREFIX + abTestName, -1) | ||
if (testGroup == -1) { | ||
assignGroup() | ||
PrefsIoUtil.setInt(AB_TEST_KEY_PREFIX + abTestName, testGroup) | ||
} | ||
return testGroup | ||
} | ||
|
||
protected var testGroup: Int = -1 | ||
|
||
protected open fun assignGroup() { | ||
testGroup = Random(System.currentTimeMillis()).nextInt(Int.MAX_VALUE).mod(abTestGroupCount) | ||
} | ||
|
||
companion object { | ||
private const val AB_TEST_KEY_PREFIX = "ab_test_" | ||
const val GROUP_SIZE_2 = 2 | ||
const val GROUP_1 = 0 | ||
const val GROUP_2 = 1 | ||
const val GROUP_3 = 2 | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
...n/java/org/wikipedia/analytics/eventplatform/MachineGeneratedArticleDescriptionABCTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package org.wikipedia.analytics.eventplatform | ||
|
||
import kotlinx.coroutines.runBlocking | ||
import org.wikipedia.WikipediaApp | ||
import org.wikipedia.auth.AccountUtil | ||
import org.wikipedia.settings.Prefs | ||
import org.wikipedia.util.log.L | ||
|
||
class MachineGeneratedArticleDescriptionABCTest : ABTest("mBART25", GROUP_SIZE_2) { | ||
|
||
override fun assignGroup() { | ||
super.assignGroup() | ||
if (AccountUtil.isLoggedIn) { | ||
runBlocking { | ||
try { | ||
MachineGeneratedArticleDescriptionsAnalyticsHelper.setUserExperienced() | ||
if (testGroup == GROUP_2 && Prefs.suggestedEditsMachineGeneratedDescriptionsIsExperienced) { | ||
testGroup = GROUP_3 | ||
} | ||
} catch (e: Exception) { | ||
L.e(e) | ||
} | ||
} | ||
} | ||
MachineGeneratedArticleDescriptionsAnalyticsHelper().logGroupAssigned(WikipediaApp.instance, testGroup) | ||
} | ||
} |
123 changes: 110 additions & 13 deletions
123
...g/wikipedia/analytics/eventplatform/MachineGeneratedArticleDescriptionsAnalyticsHelper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,121 @@ | ||
package org.wikipedia.analytics.eventplatform | ||
|
||
import android.content.Context | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.withContext | ||
import org.wikipedia.WikipediaApp | ||
import org.wikipedia.auth.AccountUtil | ||
import org.wikipedia.dataclient.ServiceFactory | ||
import org.wikipedia.page.PageTitle | ||
import org.wikipedia.settings.Prefs | ||
import org.wikipedia.util.ActiveTimer | ||
|
||
object MachineGeneratedArticleDescriptionsAnalyticsHelper { | ||
class MachineGeneratedArticleDescriptionsAnalyticsHelper { | ||
|
||
private var apiFailed = false | ||
var apiOrderList = emptyList<String>() | ||
var displayOrderList = emptyList<String>() | ||
private var chosenSuggestion = "" | ||
val timer = ActiveTimer() | ||
|
||
fun articleDescriptionEditingStart(context: Context) { | ||
EventPlatformClient.submit( | ||
BreadCrumbLogEvent( | ||
BreadCrumbViewUtil.getReadableScreenName(context), | ||
"ArticleDescriptionEditing.start" | ||
) | ||
) | ||
log(context, composeGroupString() + ".start") | ||
} | ||
|
||
fun articleDescriptionEditingEnd(context: Context) { | ||
EventPlatformClient.submit( | ||
BreadCrumbLogEvent( | ||
BreadCrumbViewUtil.getReadableScreenName(context), | ||
"ArticleDescriptionEditing.end" | ||
) | ||
) | ||
log(context, composeGroupString() + ".end") | ||
} | ||
|
||
fun logAttempt(context: Context, finalDescription: String, wasChosen: Boolean, wasModified: Boolean, title: PageTitle) { | ||
log(context, composeLogString(title) + ".attempt:$finalDescription" + | ||
".suggestion1:${encode(apiOrderList.first())}" + (if (apiOrderList.size > 1) ".suggestion2:${encode(apiOrderList.last())}" else "") + | ||
getOrderString(wasChosen, chosenSuggestion) + ".modified:$wasModified.timeSpentMs:${timer.elapsedMillis}") | ||
} | ||
|
||
fun logSuccess(context: Context, finalDescription: String, wasChosen: Boolean, wasModified: Boolean, title: PageTitle, revId: Long) { | ||
log(context, composeLogString(title) + ".success:$finalDescription" + | ||
".suggestion1:${encode(apiOrderList.first())}" + (if (apiOrderList.size > 1) ".suggestion2:${encode(apiOrderList.last())}" else "") + | ||
getOrderString(wasChosen, chosenSuggestion) + ".modified:$wasModified.timeSpentMs:${timer.elapsedMillis}.revId:$revId") | ||
} | ||
|
||
fun logSuggestionsReceived(context: Context, isBlp: Boolean, title: PageTitle) { | ||
apiFailed = false | ||
log(context, composeLogString(title) + ".blp:$isBlp.count:${apiOrderList.size}.suggestion1:${encode(apiOrderList.first())}" + | ||
if (apiOrderList.size > 1) ".suggestion2:${encode(apiOrderList.last())}" else "") | ||
} | ||
|
||
fun logSuggestionsShown(context: Context, title: PageTitle) { | ||
log(context, composeLogString(title) + ".count:${displayOrderList.size}.display1:${encode(displayOrderList.first())}" + | ||
if (displayOrderList.size > 1) ".display2:${encode(displayOrderList.last())}" else "") | ||
} | ||
|
||
fun logSuggestionChosen(context: Context, suggestion: String, title: PageTitle) { | ||
chosenSuggestion = suggestion | ||
log(context, composeLogString(title) + ".selected:${encode(suggestion)}${getOrderString(true, suggestion)}") | ||
} | ||
|
||
fun logSuggestionsDismissed(context: Context, title: PageTitle) { | ||
log(context, composeLogString(title) + ".suggestionsDialog.dismissed") | ||
} | ||
|
||
fun logSuggestionReported(context: Context, suggestion: String, reportReasonsList: List<String>, title: PageTitle) { | ||
val reportReasons = reportReasonsList.joinToString("|") | ||
log(context, composeLogString(title) + ".reportDialog.suggestion:${encode(suggestion)}${getOrderString(true, suggestion)}.reasons:$reportReasons.reported") | ||
} | ||
|
||
fun logReportDialogDismissed(context: Context) { | ||
log(context, composeGroupString() + ".reportDialog.dismissed") | ||
} | ||
|
||
fun logOnboardingShown(context: Context) { | ||
log(context, composeGroupString() + ".onboardingShown") | ||
} | ||
|
||
fun logGroupAssigned(context: Context, testGroup: Int) { | ||
log(context, "$MACHINE_GEN_DESC_SUGGESTIONS.groupAssigned:$testGroup") | ||
} | ||
|
||
fun logApiFailed(context: Context, throwable: Throwable, title: PageTitle) { | ||
log(context, composeLogString(title) + ".apiError:${throwable.message}") | ||
apiFailed = true | ||
} | ||
|
||
private fun log(context: Context, logString: String) { | ||
if (!isUserInExperiment || apiFailed) { | ||
return | ||
} | ||
EventPlatformClient.submit(BreadCrumbLogEvent(BreadCrumbViewUtil.getReadableScreenName(context), logString)) | ||
} | ||
|
||
private fun getOrderString(wasChosen: Boolean, suggestion: String): String { | ||
return ".chosenApiIndex:${if (!wasChosen) -1 else apiOrderList.indexOf(suggestion) + 1}" + | ||
".chosenDisplayIndex:${if (!wasChosen) -1 else displayOrderList.indexOf(suggestion) + 1}" | ||
} | ||
|
||
private fun composeLogString(title: PageTitle): String { | ||
return "${composeGroupString()}.lang:${title.wikiSite.languageCode}.title:${encode(title.prefixedText)}" | ||
} | ||
|
||
private fun composeGroupString(): String { | ||
return "$MACHINE_GEN_DESC_SUGGESTIONS.group:${abcTest.group}.experienced:${Prefs.suggestedEditsMachineGeneratedDescriptionsIsExperienced}" | ||
} | ||
|
||
companion object { | ||
private const val MACHINE_GEN_DESC_SUGGESTIONS = "machineSuggestions" | ||
val abcTest = MachineGeneratedArticleDescriptionABCTest() | ||
var isUserInExperiment = false | ||
|
||
// HACK: We're using periods and colons as delimiting characters in these events, so let's | ||
// urlencode just those characters, if they appear in our strings. | ||
private fun encode(str: String): String { | ||
return str.replace(".", "%2E").replace(":", "%3A") | ||
} | ||
|
||
suspend fun setUserExperienced() = | ||
withContext(Dispatchers.Default) { | ||
val totalContributions = ServiceFactory.get(WikipediaApp.instance.wikiSite) | ||
.globalUserInfo(AccountUtil.userName!!).query?.globalUserInfo?.editCount ?: 0 | ||
Prefs.suggestedEditsMachineGeneratedDescriptionsIsExperienced = totalContributions > 50 | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.