diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b7e5f47c..6edfa7d8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -74,6 +74,11 @@ android:launchMode="singleTop" android:screenOrientation="portrait" /> + + () + if (isTournament()) { + + tournamentEntryFee?.let { + parameters.add(it.toCurrency(currency)) + } + + tournamentName?.let { + parameters.add(it.name) + } ?: run { + parameters.add(getFormattedGame()) + tournamentType?.let { type -> + parameters.add(TournamentType.values()[type].localizedTitle(context)) + } + } + if (parameters.size == 0) { + parameters.add(context.getString(R.string.tournament).capitalize()) + } + } else { + if (cgSmallBlind != null && cgBigBlind != null) { + parameters.add(getFormattedBlinds()) + } + game?.let { + parameters.add(getFormattedGame()) + } + + if (parameters.size == 0) { + parameters.add(context.getString(R.string.cash_game).capitalize()) + } + } + return parameters.joinToString(separator = " ") } val AbstractList.hourlyDuration: Double @@ -95,4 +137,4 @@ fun MutableList.update(timeInterval: TimeInterval): MutableList BankrollActivity.newInstance(requireContext()) + MoreTabRow.TOP_10 -> Top10Activity.newInstance(requireContext()) MoreTabRow.SETTINGS -> SettingsActivity.newInstance(requireContext()) } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt index b4b9a985..1f679742 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt @@ -113,9 +113,8 @@ class SettingsFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Sta override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { when (row) { - SettingRow.BANKROLL_REPORT -> { - BankrollActivity.newInstance(requireContext()) - } + SettingRow.BANKROLL_REPORT -> BankrollActivity.newInstance(requireContext()) + SettingRow.TOP_10 -> Top10Activity.newInstance(requireContext()) SettingRow.SUBSCRIPTION -> { if (!AppGuard.isProUser) { BillingActivity.newInstanceForResult(this, false) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/Top10Fragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/Top10Fragment.kt new file mode 100644 index 00000000..de66ee2b --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/Top10Fragment.kt @@ -0,0 +1,147 @@ +package net.pokeranalytics.android.ui.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.google.android.material.tabs.TabLayout +import io.realm.RealmResults +import io.realm.Sort +import io.realm.kotlin.where +import kotlinx.android.synthetic.main.fragment_top_10.* +import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.realm.Session +import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter +import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource +import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate +import net.pokeranalytics.android.ui.fragment.components.RealmFragment +import net.pokeranalytics.android.ui.view.RowRepresentable +import net.pokeranalytics.android.ui.view.RowViewType +import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager + + +class Top10Fragment : RealmFragment(), RowRepresentableDataSource, RowRepresentableDelegate { + + private enum class Tab { + CASH_GAMES, + TOURNAMENTS + } + + companion object { + fun newInstance(): Top10Fragment { + val fragment = Top10Fragment() + val bundle = Bundle() + fragment.arguments = bundle + return fragment + } + } + + private lateinit var dataListAdapter: RowRepresentableAdapter + private lateinit var realmCashGames: RealmResults + private lateinit var realmTournaments: RealmResults + + private var currentTab: Tab = Tab.CASH_GAMES + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + super.onCreateView(inflater, container, savedInstanceState) + return inflater.inflate(R.layout.fragment_top_10, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + initUI() + initData() + } + + /** + * Init data + */ + private fun initData() { + + this.realmCashGames = getRealm().where() + .equalTo("type", Session.Type.CASH_GAME.ordinal) + .greaterThanOrEqualTo("result.net", 0.0) + .sort("result.net", Sort.DESCENDING) + .limit(10) + .findAll() + this.realmCashGames.addChangeListener { _, _ -> + this.dataListAdapter.notifyDataSetChanged() + } + + this.realmTournaments = getRealm().where() + .equalTo("type", Session.Type.TOURNAMENT.ordinal) + .greaterThanOrEqualTo("result.net", 0.0) + .sort("result.net", Sort.DESCENDING) + .limit(10) + .findAll() + this.realmTournaments.addChangeListener { _, _ -> + this.dataListAdapter.notifyDataSetChanged() + } + + dataListAdapter = RowRepresentableAdapter(this, this) + recyclerView.adapter = dataListAdapter + } + + override fun adapterRows(): List? { + return when (currentTab) { + Tab.CASH_GAMES -> realmCashGames + Tab.TOURNAMENTS -> realmTournaments + } + } + + override fun rowRepresentableForPosition(position: Int): RowRepresentable? { + return when (currentTab) { + Tab.CASH_GAMES -> realmCashGames[position] + Tab.TOURNAMENTS -> realmTournaments[position] + } + } + + override fun numberOfRows(): Int { + return when (currentTab) { + Tab.CASH_GAMES -> realmCashGames.size + Tab.TOURNAMENTS -> realmTournaments.size + } + } + + override fun viewTypeForPosition(position: Int): Int { + return RowViewType.ROW_TOP_10.ordinal + } + + /** + * Init UI + */ + private fun initUI() { + + setDisplayHomeAsUpEnabled(true) + + tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { + override fun onTabSelected(tab: TabLayout.Tab) { + when (tab.position) { + 0 -> { + currentTab = Tab.CASH_GAMES + dataListAdapter.notifyDataSetChanged() + } + 1 -> { + currentTab = Tab.TOURNAMENTS + } + } + dataListAdapter.notifyDataSetChanged() + } + + override fun onTabUnselected(tab: TabLayout.Tab) { + } + + override fun onTabReselected(tab: TabLayout.Tab) { + } + }) + + + val viewManager = SmoothScrollLinearLayoutManager(requireContext()) + recyclerView.apply { + setHasFixedSize(true) + layoutManager = viewManager + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt index d5044187..d0b739f0 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt @@ -23,6 +23,8 @@ import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.ComputedStat import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager +import net.pokeranalytics.android.model.TableSize +import net.pokeranalytics.android.model.extensions.getFormattedGameType import net.pokeranalytics.android.model.realm.CustomField import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Transaction @@ -35,6 +37,7 @@ import net.pokeranalytics.android.ui.fragment.BankrollRowRepresentable import net.pokeranalytics.android.ui.graph.AxisFormatting import net.pokeranalytics.android.ui.graph.setStyle import net.pokeranalytics.android.ui.view.rowrepresentable.* +import net.pokeranalytics.android.util.extensions.longDate /** * An interface used to factor the configuration of RecyclerView.ViewHolder @@ -76,6 +79,7 @@ enum class RowViewType(private var layoutRes: Int) { // Custom row ROW_SESSION(R.layout.row_feed_session), ROW_TRANSACTION(R.layout.row_transaction), + ROW_TOP_10(R.layout.row_top_10), ROW_BUTTON(R.layout.row_button), ROW_FOLLOW_US(R.layout.row_follow_us), STATS(R.layout.row_stats_title_value), @@ -108,6 +112,9 @@ enum class RowViewType(private var layoutRes: Int) { // Row Transaction ROW_TRANSACTION -> RowTransactionViewHolder(layout) + // Row Transaction + ROW_TOP_10 -> RowTop10ViewHolder(layout) + // Row Button ROW_BUTTON -> RowButtonViewHolder(layout) @@ -550,6 +557,67 @@ enum class RowViewType(private var layoutRes: Int) { } } + + /** + * Display a top 10 row + */ + inner class RowTop10ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { + override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) { + + if (row is Session) { + + itemView.findViewById(R.id.gameResult)?.let { gameResult -> + val result = row.result?.net ?: 0.0 + val formattedStat = ComputedStat(Stat.NET_RESULT, result, currency = row.currency).format() + gameResult.setTextFormat(formattedStat, itemView.context) + } + + itemView.findViewById(R.id.sessionGameType)?.let { part1 -> + part1.text = row.getFormattedGameType(itemView.context) + } + + // Duration + val durationIcon = itemView.findViewById(R.id.sessionInfoDurationIcon) + val durationText = itemView.findViewById(R.id.sessionInfoDuration) + durationIcon?.isVisible = true + durationText?.isVisible = true + durationText?.text = row.getFormattedDuration() + + // Location + val locationIcon = itemView.findViewById(R.id.sessionInfoLocationIcon) + val locationText = itemView.findViewById(R.id.sessionInfoLocation) + + if (!row.location?.name.isNullOrEmpty()) { + locationIcon?.isVisible = true + locationText?.isVisible = true + locationText?.text = row.location?.name + } else { + locationIcon?.isVisible = false + locationText?.isVisible = false + } + + // Table Size + val tableSizeIcon = itemView.findViewById(R.id.sessionInfoTableSizeIcon) + val tableSizeText = itemView.findViewById(R.id.sessionInfoTableSize) + + row.tableSize?.let { + tableSizeIcon?.isVisible = true + tableSizeText?.isVisible = true + tableSizeText?.text = TableSize(it).localizedTitle(itemView.context) + } ?: run { + tableSizeIcon?.isVisible = false + tableSizeText?.isVisible = false + } + + itemView.findViewById(R.id.sessionDate)?.let { part3 -> + part3.text = row.creationDate.longDate() + } + } + + } + } + + /** * Display a separator */ diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt index 40db96da..69edd181 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/SessionRowView.kt @@ -11,15 +11,14 @@ import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.ComputedStat import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.model.TableSize -import net.pokeranalytics.android.model.TournamentType import net.pokeranalytics.android.model.extensions.SessionState +import net.pokeranalytics.android.model.extensions.getFormattedGameType import net.pokeranalytics.android.model.extensions.getState import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.ui.extensions.setTextFormat import net.pokeranalytics.android.util.extensions.getDayNumber import net.pokeranalytics.android.util.extensions.getShortDayName import net.pokeranalytics.android.util.extensions.shortTime -import net.pokeranalytics.android.util.extensions.toCurrency /** * Display a row session @@ -65,41 +64,7 @@ class SessionRowView : FrameLayout { rowSession.dateNumber.text = date.getDayNumber() // Title / Game type - - var parameters = mutableListOf() - if (session.isTournament()) { - - session.tournamentEntryFee?.let { - parameters.add(it.toCurrency(session.currency)) - } - - session.tournamentName?.let { - parameters.add(it.name) - } ?: run { - parameters.add(session.getFormattedGame()) - session.tournamentType?.let { type -> - parameters.add(TournamentType.values()[type].localizedTitle(context)) - } - } - - if (parameters.size == 0) { - parameters.add(context.getString(R.string.tournament).capitalize()) - } - } else { - if (session.cgSmallBlind != null && session.cgBigBlind != null) { - parameters.add(session.getFormattedBlinds()) - } - session.game?.let { - parameters.add(session.getFormattedGame()) - } - - if (parameters.size == 0) { - parameters.add(context.getString(R.string.cash_game).capitalize()) - } - } - val title = parameters.joinToString(separator = " ") - - rowSession.sessionTitle.text = title + rowSession.sessionTitle.text = session.getFormattedGameType(context) // Duration rowSession.sessionInfoDurationValue.text = session.getFormattedDuration() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/MoreTabRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/MoreTabRow.kt index 4e2fe8bc..3885a4a1 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/MoreTabRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/MoreTabRow.kt @@ -9,12 +9,14 @@ import net.pokeranalytics.android.ui.view.RowViewType */ enum class MoreTabRow : RowRepresentable { BANKROLL, + TOP_10, SETTINGS; override val resId: Int? get() { return when(this) { BANKROLL -> R.string.bankroll + TOP_10 -> R.string.top_10 SETTINGS -> R.string.services } } @@ -23,6 +25,7 @@ enum class MoreTabRow : RowRepresentable { get() { return when(this) { BANKROLL -> R.drawable.ic_outline_lock + TOP_10 -> R.drawable.ic_outline_star SETTINGS -> R.drawable.ic_outline_settings } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt index b5514060..5ed0d293 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt @@ -10,6 +10,7 @@ enum class SettingRow : RowRepresentable { // More BANKROLL_REPORT, + TOP_10, // About SUBSCRIPTION, @@ -49,7 +50,7 @@ enum class SettingRow : RowRepresentable { val rows = ArrayList() rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.reports)) - rows.addAll(arrayListOf(BANKROLL_REPORT)) + rows.addAll(arrayListOf(BANKROLL_REPORT, TOP_10)) rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.information)) // rows.addAll(arrayListOf(VERSION, RATE_APP, CONTACT_US, BUG_REPORT)) @@ -84,6 +85,7 @@ enum class SettingRow : RowRepresentable { } ?: run { return when (this) { BANKROLL_REPORT -> R.string.bankroll + TOP_10 -> R.string.top_10 SUBSCRIPTION -> R.string.subscription VERSION -> R.string.version RATE_APP -> R.string.releasenote_rating @@ -104,7 +106,7 @@ enum class SettingRow : RowRepresentable { override val viewType: Int get() { return when (this) { - BANKROLL_REPORT -> RowViewType.TITLE_ICON_ARROW.ordinal + BANKROLL_REPORT, TOP_10 -> RowViewType.TITLE_ICON_ARROW.ordinal VERSION, SUBSCRIPTION -> RowViewType.TITLE_VALUE.ordinal LANGUAGE, CURRENCY -> RowViewType.TITLE_VALUE_ARROW.ordinal FOLLOW_US -> RowViewType.ROW_FOLLOW_US.ordinal @@ -116,6 +118,7 @@ enum class SettingRow : RowRepresentable { get() { return when(this) { BANKROLL_REPORT -> R.drawable.ic_outline_lock + TOP_10 -> R.drawable.ic_outline_star else -> null } } diff --git a/app/src/main/java/net/pokeranalytics/android/util/FakeDataManager.kt b/app/src/main/java/net/pokeranalytics/android/util/FakeDataManager.kt index 604b19f7..9abac93c 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/FakeDataManager.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/FakeDataManager.kt @@ -5,7 +5,9 @@ import io.realm.kotlin.where import net.pokeranalytics.android.model.Limit import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.Game +import net.pokeranalytics.android.model.realm.Location import net.pokeranalytics.android.model.realm.Session +import net.pokeranalytics.android.util.extensions.getOrCreate import timber.log.Timber import java.util.* @@ -30,6 +32,15 @@ class FakeDataManager { val realm = Realm.getDefaultInstance() val games = realm.where().findAll() val bankroll = realm.where().findAll().firstOrNull() + val locations = realm.where().findAll() + + if (locations.size == 0) { + realm.executeTransaction { + listOf("Bellagio", "Aria", "Borgata").map { + realm.getOrCreate(it) + } + } + } // Test endedSessions @@ -47,11 +58,8 @@ class FakeDataManager { realm.beginTransaction() } - val session = Session.newInstance(realm, Math.random() > 0.5, bankroll) - - val bigBlind = arrayListOf(1.0, 2.0, 4.0).random() - session.cgBigBlind = bigBlind - session.cgSmallBlind = bigBlind / 2.0 + val isTournament = Math.random() > 0.5 + val session = Session.newInstance(realm, isTournament, bankroll) val calendar = Calendar.getInstance() val twoDaysBetweenEachSession: Long = (2 * numberOfSessions) * 24 * 60 * 60 * 1000L // approx! @@ -70,13 +78,23 @@ class FakeDataManager { session.limit = Limit.values().random().ordinal session.game = games.random() + session.location = locations.random() + session.tableSize = (2..10).random() + val buyin = buyinList.random() session.result?.let { result -> - val buyin = buyinList.random() result.buyin = buyinList.random() result.cashout = resultsList.random() + buyin } + if (isTournament) { + session.tournamentEntryFee = buyin + } else { + val bigBlind = arrayListOf(1.0, 2.0, 4.0).random() + session.cgBigBlind = bigBlind + session.cgSmallBlind = bigBlind / 2.0 + } + } realm.commitTransaction() diff --git a/app/src/main/res/drawable/ic_outline_star.xml b/app/src/main/res/drawable/ic_outline_star.xml new file mode 100644 index 00000000..3fc251d1 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_star.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_top_10.xml b/app/src/main/res/layout/activity_top_10.xml new file mode 100644 index 00000000..44318e12 --- /dev/null +++ b/app/src/main/res/layout/activity_top_10.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_top_10.xml b/app/src/main/res/layout/fragment_top_10.xml new file mode 100644 index 00000000..2c8b6cc8 --- /dev/null +++ b/app/src/main/res/layout/fragment_top_10.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/row_top_10.xml b/app/src/main/res/layout/row_top_10.xml new file mode 100644 index 00000000..88506205 --- /dev/null +++ b/app/src/main/res/layout/row_top_10.xml @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index c0562ef6..a9828a89 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -233,6 +233,22 @@ @color/green + + + + + +