Skip to content

Commit

Permalink
Merge pull request #504 from BCSDLab/feature/call_ab_test
Browse files Browse the repository at this point in the history
[Feature] 전화하기 버튼 위치 A/B테스트 구현
  • Loading branch information
skdud0629 authored Dec 15, 2024
2 parents 8b5f6b7 + 538a377 commit 98e810d
Show file tree
Hide file tree
Showing 22 changed files with 415 additions and 159 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ enum class Experiment(
BENEFIT_STORE("Benefit", ExperimentGroup.A, ExperimentGroup.B),
DINING_SHARE("campus_share_v1", ExperimentGroup.SHARE_ORIGINAL, ExperimentGroup.SHARE_NEW),
MAIN_DINING_SEE_MORE("c_main_dining_v1", ExperimentGroup.MAIN_DINING_ORIGINAL, ExperimentGroup.MAIN_DINING_NEW),
MAIN_ARTICLE_KEYWORD_BANNER("c_keyword_ banner_v1", ExperimentGroup.MAIN_BANNER_ORIGINAL, ExperimentGroup.MAIN_BANNER_NEW);
MAIN_ARTICLE_KEYWORD_BANNER("c_keyword_ banner_v1", ExperimentGroup.MAIN_BANNER_ORIGINAL, ExperimentGroup.MAIN_BANNER_NEW),
BUSINESS_CALL("business_call", ExperimentGroup.CALL_NUMBER, ExperimentGroup.CALL_FLOATING);

init {
require(experimentGroups.isNotEmpty()) { "Experiment should have at least one group" }
Expand All @@ -27,4 +28,7 @@ object ExperimentGroup {

const val MAIN_BANNER_ORIGINAL = "banner_original"
const val MAIN_BANNER_NEW = "banner_new"
}

const val CALL_NUMBER = "call_number"
const val CALL_FLOATING = "call_floating"
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ object EventLogger {
logEvent(action, EventCategory.CLICK, label, value, *extras)
}



/**
* 스크롤 이벤트 로깅
* @param action: 이벤트 발생 도메인(BUSINESS, CAMPUS, USER)
Expand Down Expand Up @@ -71,6 +73,8 @@ object EventLogger {
param(EVENT_LABEL, "$label (debug)")
param(VALUE, value)
}
println("EventLoggerCustom: ${action}, ${category}, $label, $value, ")

} else {
Firebase.analytics.logEvent(action) {
param(EVENT_CATEGORY, category)
Expand All @@ -96,6 +100,7 @@ object EventLogger {
param("${it.key}_debug", it.value)
}
}
println("EventLogger: ${action.value}, ${category.value}, $label, $value, ${extras.joinToString { ", ${it.key}: ${it.value}" }}")
} else {
Firebase.analytics.logEvent(action.value) {
param(EVENT_CATEGORY, category.value)
Expand All @@ -112,14 +117,14 @@ object EventLogger {
enum class EventAction(val value: String) {
BUSINESS("BUSINESS"),
CAMPUS("CAMPUS"),
USER("USER")
USER("USER"),
}

enum class EventCategory(val value: String) {
CLICK("click"),
SCROLL("scroll"),
SWIPE("swipe"), // 하단 뒤로가기(아이폰의 swipe 뒤로가기와 대응)
NOTIFICATION("notification")
NOTIFICATION("notification"),
}

data class EventExtra(val key: String, val value: String)
data class EventExtra(val key: String, val value: String)
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,12 @@ object AnalyticsConstant {
const val CAMPUS_NOTICE_1 = "CAMPUS_notice_1"
const val POPULAR_NOTICE_BANNER = "popular_notice_banner"
const val TO_MANAGE_KEYWORD = "to_manage_keyword"

const val BUSINESS_CALL_NUMBER = " BUSINESS_call_1"
const val BUSINESS_CALL_FLOATING = "BUSINESS_call_1"
}

const val PREVIOUS_PAGE = "previous_page"
const val CURRENT_PAGE = "current_page"
const val DURATION_TIME = "duration_time"
}
}
Binary file added core/src/main/res/drawable/ic_benefit_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion core/src/main/res/drawable/rounded_corners_black.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/black" />
<corners android:radius="5dp" />
<corners android:radius="16dp" />
</shape>
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ fun StoreItemResponse.toStore(): Store = Store(
closeTime = it.closeTime ?: ""
)
}.orEmpty().getOrElse(0) { Store.OpenData(localDayOfWeekName, false, "00:00", "00:00") },
categoryIds = categoryIds
categoryIds = categoryIds,
benefitDetails = benefitDetails ?: benefitDetail?.toStringArray() ?: emptyList(),

)

fun StoreEventItemReponse.toStoreEvent(): StoreEvent = StoreEvent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ data class StoreItemResponse(
@SerializedName("is_event") val isEvent: Boolean?,
@SerializedName("is_open") val isOpen: Boolean?,
@SerializedName("average_rate") val averageRate : Double,
@SerializedName("review_count") val reviewCount : Int
@SerializedName("review_count") val reviewCount : Int,
@SerializedName("benefit_details") val benefitDetails: List<String>?,
@SerializedName("benefit_detail") val benefitDetail: String?,
) {
data class OpenResponseDTO(
@SerializedName("day_of_week")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ data class Store(
val averageRate : Double,
val reviewCount : Int,
val open: OpenData,
val categoryIds: List<Int>
val categoryIds: List<Int>,
val benefitDetails: List<String>,
) {
data class OpenData(
val dayOfWeek: String,
Expand All @@ -44,4 +45,4 @@ data class Store(
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ package `in`.koreatech.koin.domain.model.store

data class StoreCategories(
val id: Int,
val imageUrl: String,
val imageUrl: Any,
val name: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
Expand Down Expand Up @@ -48,6 +49,7 @@ import `in`.koreatech.koin.databinding.ActivityMainBinding
import `in`.koreatech.koin.domain.model.bus.BusType
import `in`.koreatech.koin.domain.model.bus.timer.BusArrivalInfo
import `in`.koreatech.koin.domain.model.dining.DiningPlace
import `in`.koreatech.koin.domain.model.store.StoreCategories
import `in`.koreatech.koin.ui.article.ArticleActivity
import `in`.koreatech.koin.ui.bus.BusActivity
import `in`.koreatech.koin.ui.dining.DiningActivity
Expand Down Expand Up @@ -147,15 +149,28 @@ class MainActivity : KoinNavigationDrawerTimeActivity() {

private val storeCategoriesRecyclerAdapter = StoreCategoriesRecyclerAdapter().apply {
setOnItemClickListener { id, name ->
EventLogger.logClickEvent(
EventAction.BUSINESS,
AnalyticsConstant.Label.MAIN_SHOP_CATEGORIES,
name,
EventExtra(AnalyticsConstant.PREVIOUS_PAGE, "메인"),
EventExtra(AnalyticsConstant.CURRENT_PAGE, name),
EventExtra(AnalyticsConstant.DURATION_TIME, getElapsedTimeAndReset().toString())
)
gotoStoreActivity(id + 1)
if(id == 0){
startActivity(Intent(this@MainActivity, CallBenefitStoreActivity::class.java))
EventLogger.logClickEvent(
EventAction.BUSINESS,
AnalyticsConstant.Label.MAIN_SHOP_BENEFIT,
name,
EventExtra(AnalyticsConstant.PREVIOUS_PAGE, "메인"),
EventExtra(AnalyticsConstant.CURRENT_PAGE, "benefit"),
EventExtra(AnalyticsConstant.DURATION_TIME, getElapsedTimeAndReset().toString())
)
}
else{
EventLogger.logClickEvent(
EventAction.BUSINESS,
AnalyticsConstant.Label.MAIN_SHOP_CATEGORIES,
name,
EventExtra(AnalyticsConstant.PREVIOUS_PAGE, "메인"),
EventExtra(AnalyticsConstant.CURRENT_PAGE, name),
EventExtra(AnalyticsConstant.DURATION_TIME, getElapsedTimeAndReset().toString())
)
gotoStoreActivity(id)
}
}
}

Expand Down Expand Up @@ -199,6 +214,7 @@ class MainActivity : KoinNavigationDrawerTimeActivity() {
scrollPercentage = 100.0f * offset / (range - extent)
}
viewModel.postABTestAssign(Experiment.BENEFIT_STORE.experimentTitle)

storeListButton.setOnClickListener {
gotoStoreActivity(0)
}
Expand Down Expand Up @@ -265,8 +281,7 @@ class MainActivity : KoinNavigationDrawerTimeActivity() {
}

recyclerViewStoreCategory.apply {
layoutManager =
LinearLayoutManager(this@MainActivity, RecyclerView.HORIZONTAL, false)
layoutManager = GridLayoutManager(this@MainActivity, 6)
adapter = storeCategoriesRecyclerAdapter
}

Expand Down Expand Up @@ -303,6 +318,44 @@ class MainActivity : KoinNavigationDrawerTimeActivity() {
}

private fun initViewModel() = with(viewModel) {
getStoreCategories(StoreCategories(-1, R.drawable.ic_benefit_icon, "혜택"))

observeLiveData(variableName) {
when (viewModel.variableName.value) {
ExperimentGroup.A -> {
EventLogger.logCustomEvent(
action = "AB_TEST",
category = "a/b test 로깅(3차 스프린트, 혜택페이지)",
label = "BUSINESS_benefit_1",
value = "혜택X"
)
binding.storeButtonLayout.visibility = View.GONE
binding.recyclerViewStoreCategory.visibility = View.VISIBLE
}

ExperimentGroup.B -> {
EventLogger.logCustomEvent(
action = "AB_TEST",
category = "a/b test 로깅(3차 스프린트, 혜택페이지)",
label = "BUSINESS_benefit_1",
value = "혜택O"
)
binding.storeButtonLayout.visibility = View.VISIBLE
binding.recyclerViewStoreCategory.visibility = View.GONE
}

else -> {
EventLogger.logCustomEvent(
action = "AB_TEST",
category = "a/b test 로깅(3차 스프린트, 혜택페이지)",
label = "BUSINESS_benefit_1",
value = "혜택X"
)
binding.storeButtonLayout.visibility = View.GONE
binding.recyclerViewStoreCategory.visibility = View.VISIBLE
}
}
}
observeLiveData(isLoading) {
binding.mainSwipeRefreshLayout.isRefreshing = it
}
Expand All @@ -319,7 +372,7 @@ class MainActivity : KoinNavigationDrawerTimeActivity() {
}
}
observeLiveData(storeCategories) {
storeCategoriesRecyclerAdapter.submitList(it.drop(1))
storeCategoriesRecyclerAdapter.submitList(it)
}
binding.recyclerViewStoreCategory.visibility = View.GONE
binding.storeButtonLayout.visibility = View.VISIBLE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,23 @@ import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import `in`.koreatech.koin.databinding.MainItemStoreBinding
import `in`.koreatech.koin.databinding.StoreCategoryItemBinding
import `in`.koreatech.koin.domain.model.store.StoreCategories

class StoreCategoriesRecyclerAdapter(): ListAdapter<StoreCategories,StoreCategoriesRecyclerAdapter.StoreCategoriesViewHolder>(
diffCallback
){
var onItemClickListener: OnItemClickListener? = null

inner class StoreCategoriesViewHolder(val binding: MainItemStoreBinding) : RecyclerView.ViewHolder(binding.root){
inner class StoreCategoriesViewHolder(val binding: StoreCategoryItemBinding) : RecyclerView.ViewHolder(binding.root){
val container = binding.container
val storeCategoryImage = binding.imageViewStoreCategory
val storeCategoryName = binding.textViewStoreCategory
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StoreCategoriesRecyclerAdapter.StoreCategoriesViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = MainItemStoreBinding.inflate(inflater, parent, false)
val binding = StoreCategoryItemBinding.inflate(inflater, parent, false)
return StoreCategoriesViewHolder(binding)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ class MainActivityViewModel @Inject constructor(

init {
updateDining()
getStoreCategories()
}

fun postABTestAssign(title: String) = viewModelScope.launchWithLoading {
Expand Down Expand Up @@ -234,9 +233,11 @@ class MainActivityViewModel @Inject constructor(
}
}

fun getStoreCategories() {
fun getStoreCategories(storeCategory: StoreCategories) {
viewModelScope.launchWithLoading {
_storeCategories.value = getStoreCategoriesUseCase()
val categoryList = getStoreCategoriesUseCase().drop(1).toMutableList()
categoryList.add(0, storeCategory)
_storeCategories.value = categoryList
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package `in`.koreatech.koin.ui.store.activity

import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
Expand Down Expand Up @@ -35,6 +36,7 @@ import `in`.koreatech.koin.core.viewpager.HorizontalMarginItemDecoration
import `in`.koreatech.koin.databinding.StoreActivityMainBinding
import `in`.koreatech.koin.domain.model.store.StoreEvent
import `in`.koreatech.koin.domain.model.store.StoreSorter
import `in`.koreatech.koin.ui.businesssignup.BusinessSignUpCheckActivity
import `in`.koreatech.koin.ui.navigation.KoinNavigationDrawerTimeActivity
import `in`.koreatech.koin.ui.navigation.state.MenuState
import `in`.koreatech.koin.ui.store.adapter.StoreCategoriesRecyclerAdapter
Expand Down Expand Up @@ -100,18 +102,6 @@ class StoreActivity : KoinNavigationDrawerTimeActivity() {
EventExtra(AnalyticsConstant.DURATION_TIME, getElapsedTimeAndReset().toString())
)
}

EventLogger.logClickEvent(
EventAction.BUSINESS,
AnalyticsConstant.Label.SHOP_CLICK,
it.name,
EventExtra(
AnalyticsConstant.PREVIOUS_PAGE,
viewModel.category.value?.name ?: "Unknown"
),
EventExtra(AnalyticsConstant.CURRENT_PAGE, it.name),
EventExtra(AnalyticsConstant.DURATION_TIME, getElapsedTimeAndReset().toString())
)
}
}

Expand Down Expand Up @@ -389,7 +379,6 @@ class StoreActivity : KoinNavigationDrawerTimeActivity() {

with(binding) {
storeManyReviewCheckbox.setOnClickListener {

if (storeManyReviewCheckbox.isChecked) {
EventLogger.logClickEvent(
EventAction.BUSINESS,
Expand Down Expand Up @@ -490,6 +479,10 @@ class StoreActivity : KoinNavigationDrawerTimeActivity() {

viewModel.filterStoreIsDelivery(storeIsDeliveryCheckbox.isChecked)
}

goToBenefitActivityButton.setOnClickListener {
startActivity(Intent(this@StoreActivity, CallBenefitStoreActivity::class.java))
}
}
}

Expand Down
Loading

0 comments on commit 98e810d

Please sign in to comment.