diff --git a/app/src/androidTest/java/net/pokeranalytics/android/StatsInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/StatsInstrumentedUnitTest.kt index 1a5c7e84..fdd5a18f 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/StatsInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/StatsInstrumentedUnitTest.kt @@ -51,6 +51,8 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { s1.cgBigBlind = 0.5 // bb net result = -200bb s2.cgBigBlind = 2.0 // bb net result = 150bb + s2.tableSize = 5 + realm.insert(s1) realm.insert(s2) realm.commitTransaction() @@ -58,9 +60,9 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") val sd1 = sdf.parse("01/1/2019 10:00") - val ed1 = sdf.parse("01/1/2019 11:00") + val ed1 = sdf.parse("01/1/2019 11:00") // 1 hour val sd2 = sdf.parse("02/1/2019 08:00") - val ed2 = sdf.parse("02/1/2019 11:00") + val ed2 = sdf.parse("02/1/2019 11:00") // 3 hours realm.beginTransaction() @@ -112,7 +114,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { } val handsPlayed = results.computedStat(Stat.HANDS_PLAYED) if (handsPlayed != null) { - assertEquals(100.0, handsPlayed.value, delta) + assertEquals(177.77, handsPlayed.value, delta) } else { Assert.fail("No hands played stat") } @@ -161,7 +163,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { } val netbbPer100Hands = results.computedStat(Stat.NET_BB_PER_100_HANDS) if (netbbPer100Hands != null) { - assertEquals(-50.0, netbbPer100Hands.value, delta) + assertEquals(-28.12, netbbPer100Hands.value, delta) } else { Assert.fail("No netbbPer100Hands stat") } @@ -182,7 +184,7 @@ class StatsInstrumentedUnitTest : RealmInstrumentedUnitTest() { val std100 = results.computedStat(Stat.STANDARD_DEVIATION_BB_PER_100_HANDS) if (std100 != null) { - assertEquals(559.01, std100.value, delta) + assertEquals(497.54, std100.value, delta) } else { Assert.fail("No std100 stat") } diff --git a/app/src/main/java/net/pokeranalytics/android/model/LiveData.kt b/app/src/main/java/net/pokeranalytics/android/model/LiveData.kt index 22e93f4d..027dc856 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/LiveData.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/LiveData.kt @@ -6,7 +6,7 @@ import io.realm.RealmObject import io.realm.RealmResults import io.realm.Sort import net.pokeranalytics.android.R -import net.pokeranalytics.android.model.interfaces.Savable +import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.model.realm.* import net.pokeranalytics.android.ui.view.Localizable @@ -58,11 +58,11 @@ enum class LiveData : Localizable { } } - fun deleteData(realm:Realm, data:Savable) { - realm.where(this.relatedEntity).equalTo("id", data.uniqueIdentifier()).findAll().deleteAllFromRealm() - } + fun deleteData(realm: Realm, data: Manageable) { + realm.where(this.relatedEntity).equalTo("id", data.uniqueIdentifier()).findAll().deleteAllFromRealm() + } - fun updateOrCreate(realm:Realm, primaryKey:String?): RealmObject { + fun updateOrCreate(realm: Realm, primaryKey: String?): RealmObject { val proxyItem: RealmObject? = this.getData(realm, primaryKey) proxyItem?.let { return realm.copyFromRealm(it) diff --git a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt new file mode 100644 index 00000000..24ca10e7 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt @@ -0,0 +1,68 @@ +package net.pokeranalytics.android.model.interfaces + +import net.pokeranalytics.android.R +import net.pokeranalytics.android.ui.view.RowRepresentable + +/** + * An interface to grouped object which are managed by the database + */ +interface Manageable : Savable, Deletable, Identifiable + +/** + * An interface associate a unique identifier to an object + */ +interface Identifiable { + + /** + * A unique identifier getter + */ + fun uniqueIdentifier(): String + +} + +/** + * An interface to easily handle the validity of any object we want to save + */ +interface Savable { + /** + * A method to define if an object is safe for saving in database + */ + fun isValidForSave(): Boolean { + //TODO should be by default to false + return true + } + + /** + * A method to get the reason why the object can't be saved + */ + fun getFailedSaveMessage(): Int { + return R.string.none + } + + /** + * a method to handle the modification of the object. + * Through [RowRepresentable] the object is able to update the right variable with the new value. + */ + fun updateValue(value: Any?, row: RowRepresentable) +} + + +/** + * An interface to easily handle the validity of any object we want to delete + */ +interface Deletable { + + /** + * A method to define if an object is safe for deletion in database + */ + fun isValidForDelete(): Boolean { + return true + } + + /** + * A method to get the reason why the object can't be deleted + */ + fun getFailedDeleteMessage(): Int { + return R.string.none + } +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Savable.kt b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Savable.kt deleted file mode 100644 index d84c1332..00000000 --- a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Savable.kt +++ /dev/null @@ -1,31 +0,0 @@ -package net.pokeranalytics.android.model.interfaces - -import net.pokeranalytics.android.ui.view.RowRepresentable - -interface Identifiable { - - /** - * A unique identifier getter - */ - fun uniqueIdentifier(): String - -} - -/** - * An interface to easily handle the validity of any object we want to save - */ -interface Savable : Identifiable { - /** - * A method to define if an object is safe for saving in database - */ - fun isValidForSave(): Boolean { - //TODO should be by default to false - return true - } - - /** - * a method to handle the modification of the object. - * Through [RowRepresentable] the object is able to update the right variable with the new value. - */ - fun updateValue(value: Any?, row: RowRepresentable) -} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt index 7803b4f1..08316cda 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Timed.kt @@ -26,8 +26,7 @@ interface Timed { } } - var hourlyDuration: Double + val hourlyDuration: Double get() = this.netDuration / 3600000.0 - set(value) = TODO() } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt index 83337bbe..94249270 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt @@ -3,7 +3,9 @@ package net.pokeranalytics.android.model.realm import io.realm.RealmList import io.realm.RealmObject import io.realm.annotations.PrimaryKey -import net.pokeranalytics.android.model.interfaces.Savable +import io.realm.kotlin.where +import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor @@ -12,7 +14,7 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow import java.util.* import kotlin.collections.ArrayList -open class Bankroll(name: String = "") : RealmObject(), Savable, +open class Bankroll(name: String = "") : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable { companion object { @@ -94,4 +96,16 @@ open class Bankroll(name: String = "") : RealmObject(), Savable, return this.name.isNotEmpty() } + override fun getFailedSaveMessage(): Int { + return R.string.empty_name_for_br_error + } + + override fun isValidForDelete(): Boolean { + return this.realm.where().equalTo("bankroll.id", id).findAll().isEmpty() + } + + override fun getFailedDeleteMessage(): Int { + return R.string.bankroll_relationship_error + } + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Game.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Game.kt index 6e82814d..79097858 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Game.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Game.kt @@ -2,7 +2,8 @@ package net.pokeranalytics.android.model.realm import io.realm.RealmObject import io.realm.annotations.PrimaryKey -import net.pokeranalytics.android.model.interfaces.Savable +import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor @@ -11,7 +12,7 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow import java.util.* import kotlin.collections.ArrayList -open class Game : RealmObject(), Savable, StaticRowRepresentableDataSource, RowRepresentable { +open class Game : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable { @PrimaryKey var id = UUID.randomUUID().toString() @@ -75,4 +76,8 @@ open class Game : RealmObject(), Savable, StaticRowRepresentableDataSource, RowR return this.name.isNotEmpty() } + override fun getFailedSaveMessage(): Int { + return R.string.variant_empty_name_error + } + } diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Location.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Location.kt index 501d43dc..028e06fa 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Location.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Location.kt @@ -4,7 +4,8 @@ import com.google.android.libraries.places.api.model.Place import io.realm.RealmObject import io.realm.annotations.Ignore import io.realm.annotations.PrimaryKey -import net.pokeranalytics.android.model.interfaces.Savable +import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor @@ -14,7 +15,7 @@ import java.util.* import kotlin.collections.ArrayList -open class Location : RealmObject(), Savable, StaticRowRepresentableDataSource, RowRepresentable { +open class Location : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable { @PrimaryKey var id = UUID.randomUUID().toString() @@ -101,6 +102,10 @@ open class Location : RealmObject(), Savable, StaticRowRepresentableDataSource, return this.name.isNotEmpty() } + override fun getFailedSaveMessage(): Int { + return R.string.location_empty_field_error + } + /** * Fill the location attributes with a place object */ diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt index 845f5819..42db95e4 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt @@ -19,7 +19,7 @@ import net.pokeranalytics.android.model.TableSize import net.pokeranalytics.android.model.TournamentKind import net.pokeranalytics.android.model.extensions.SessionState import net.pokeranalytics.android.model.extensions.getState -import net.pokeranalytics.android.model.interfaces.Savable +import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.model.interfaces.Timed import net.pokeranalytics.android.model.utils.SessionSetManager import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource @@ -35,7 +35,7 @@ import java.util.* import java.util.Currency import kotlin.collections.ArrayList -open class Session : RealmObject(), SessionInterface, Savable, StaticRowRepresentableDataSource, RowRepresentable, +open class Session : RealmObject(), SessionInterface, Manageable, StaticRowRepresentableDataSource, RowRepresentable, Timed { enum class Type { @@ -222,8 +222,40 @@ open class Session : RealmObject(), SessionInterface, Savable, StaticRowRepresen return this.result?.net ?: 0.0 } +/* + public var numberOfHandsPerHour: Double { + + var playersHandsPerHour: Int = Session.livePlayersHandsPerHour // default is live + if let bankroll = self.bankroll { + playersHandsPerHour = bankroll.isLive() ? Session.livePlayersHandsPerHour : Session.onlinePlayersHandsPerHour + } + var numberOfPlayers: Int = 9 // default is 9 players + if let playersAtTable = self.tableSize?.intValue { + numberOfPlayers = playersAtTable + } + + return Double(playersHandsPerHour) / Double(numberOfPlayers) + } +*/ + + @Ignore + val ONLINE_PLAYER_HANDS_PER_HOUR = 400.0 + @Ignore + val LIVE_PLAYER_HANDS_PER_HOUR = 250.0 + + /** + * Approximates the number of hands played per hour at the table + */ + val numberOfHandsPerHour: Double + get() { + val tableSize = this.tableSize ?: 9 + val isLive = this.bankroll?.live ?: true + val playerHandsPerHour = if (isLive) LIVE_PLAYER_HANDS_PER_HOUR else ONLINE_PLAYER_HANDS_PER_HOUR + return playerHandsPerHour / tableSize.toDouble() + } + @Ignore - override var estimatedHands: Double = 25.0 * this.hourlyDuration + override var estimatedHands: Double = this.numberOfHandsPerHour * this.hourlyDuration @Ignore override var bbNetResult: Double = 0.0 diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt index b2bed1e7..8b211cdc 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt @@ -51,7 +51,6 @@ open class SessionSet : RealmObject(), Timed { fun newInstance(realm: Realm) : SessionSet { val sessionSet: SessionSet = realm.createObject(SessionSet::class.java) -// sessionSet.timeFrame = realm.createObject(TimeFrame::class.java) return realm.copyToRealm(sessionSet) } @@ -75,7 +74,7 @@ open class SessionSet : RealmObject(), Timed { val hourlyRate: Double = this.ratedNet / this.hourlyDuration @Ignore - val estimatedHands: Double = 25.0 * this.hourlyDuration + val estimatedHands: Double = this.sessions?.sumByDouble { it.estimatedHands } ?: 0.0 @Ignore var bbNetResult: Double = this.sessions?.sumByDouble { it.bbNetResult } ?: 0.0 diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentFeature.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentFeature.kt index dcda7dd1..7373bddd 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentFeature.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentFeature.kt @@ -3,7 +3,7 @@ package net.pokeranalytics.android.model.realm import android.text.InputType import io.realm.RealmObject import io.realm.annotations.PrimaryKey -import net.pokeranalytics.android.model.interfaces.Savable +import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor @@ -12,7 +12,7 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.TournamentFeatureRow import java.util.* import kotlin.collections.ArrayList -open class TournamentFeature : RealmObject(), Savable, StaticRowRepresentableDataSource, RowRepresentable { +open class TournamentFeature : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable { @PrimaryKey var id = UUID.randomUUID().toString() diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentName.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentName.kt index 5a3c2789..b76c03fc 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentName.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/TournamentName.kt @@ -2,6 +2,8 @@ package net.pokeranalytics.android.model.realm import io.realm.RealmObject import io.realm.annotations.PrimaryKey +import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.model.interfaces.Savable import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.view.RowRepresentable @@ -12,7 +14,7 @@ import java.util.* import kotlin.collections.ArrayList -open class TournamentName : RealmObject(), Savable, StaticRowRepresentableDataSource, RowRepresentable { +open class TournamentName : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable { @PrimaryKey var id = UUID.randomUUID().toString() @@ -65,5 +67,8 @@ open class TournamentName : RealmObject(), Savable, StaticRowRepresentableDataSo return this.name.isNotEmpty() } + override fun getFailedSaveMessage(): Int { + return R.string.tt_empty_field_error + } } diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt index 4641418f..87dd38bc 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt @@ -3,6 +3,7 @@ package net.pokeranalytics.android.model.realm import android.text.InputType import io.realm.RealmObject import io.realm.annotations.PrimaryKey +import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.model.interfaces.Savable import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.view.RowRepresentable @@ -13,7 +14,7 @@ import java.util.* import kotlin.collections.ArrayList -open class TransactionType : RealmObject(), Savable, StaticRowRepresentableDataSource, RowRepresentable { +open class TransactionType : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable { @PrimaryKey var id = UUID.randomUUID().toString() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/EditableDataActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/EditableDataActivity.kt index 56315b5f..1333f2d7 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/EditableDataActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/EditableDataActivity.kt @@ -4,13 +4,14 @@ import android.content.Context import android.content.Intent import android.os.Bundle import androidx.fragment.app.Fragment -import kotlinx.android.synthetic.main.activity_editable_data.* import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.fragment.EditableDataFragment +import net.pokeranalytics.android.ui.fragment.LocationDataFragment class EditableDataActivity : PokerAnalyticsActivity() { - enum class IntentKey(val keyName : String) { + enum class IntentKey(val keyName: String) { DATA_TYPE("DATA_TYPE"), PRIMARY_KEY("PRIMARY_KEY"); } @@ -55,7 +56,16 @@ class EditableDataActivity : PokerAnalyticsActivity() { val dataType = intent.getIntExtra(IntentKey.DATA_TYPE.keyName, 0) val primaryKey = intent.getStringExtra(IntentKey.PRIMARY_KEY.keyName) - val fragment = editableDataFragment as EditableDataFragment + + val fragmentManager = supportFragmentManager + val fragmentTransaction = fragmentManager.beginTransaction() + val fragment: EditableDataFragment = when (dataType) { + LiveData.LOCATION.ordinal -> LocationDataFragment() + else -> EditableDataFragment() + } + + fragmentTransaction.add(R.id.container, fragment) + fragmentTransaction.commit() fragment.setData(dataType, primaryKey) } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt index e0bc7ee8..c6492cf2 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt @@ -12,7 +12,7 @@ import io.realm.RealmObject import io.realm.RealmResults import kotlinx.android.synthetic.main.fragment_data_list.* import net.pokeranalytics.android.R -import net.pokeranalytics.android.model.interfaces.Savable +import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.ui.activity.EditableDataActivity import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.adapter.LiveRowRepresentableDataSource @@ -23,6 +23,7 @@ import net.pokeranalytics.android.ui.helpers.SwipeToDeleteCallback import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.SettingRow +import net.pokeranalytics.android.util.showAlertDialog class DataListFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSource, RowRepresentableDelegate { @@ -69,7 +70,7 @@ class DataListFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSourc EditableDataActivity.newInstance( requireContext(), it.ordinal, - (row as Savable).uniqueIdentifier() + (row as Manageable).uniqueIdentifier() ) } } @@ -98,12 +99,19 @@ class DataListFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSourc lastDeletedItemPosition = position if (mRecentlyDeletedItem is RealmObject) { - deletedItem = getRealm().copyFromRealm(mRecentlyDeletedItem) - getRealm().executeTransaction { - mRecentlyDeletedItem.deleteFromRealm() + + // Check if the object is valid for the deletion + if ((mRecentlyDeletedItem as Manageable).isValidForDelete()) { + deletedItem = getRealm().copyFromRealm(mRecentlyDeletedItem) + getRealm().executeTransaction { + mRecentlyDeletedItem.deleteFromRealm() + } + dataListAdapter.notifyItemRemoved(position) + showUndoSnackBar() + } else { + dataListAdapter.notifyItemChanged(position) + showAlertDialog(R.string.warning, (mRecentlyDeletedItem as Manageable).getFailedDeleteMessage()) } - dataListAdapter.notifyItemRemoved(position) - showUndoSnackBar() } } @@ -134,9 +142,9 @@ class DataListFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSourc val message = String.format(getString(R.string.data_deleted), this.dataType.localizedTitle(requireContext())) val snackBar = Snackbar.make(constraintLayout, message, Snackbar.LENGTH_LONG) snackBar.setAction(R.string.cancel) { - getRealm().executeTransaction {realm -> + getRealm().executeTransaction { realm -> deletedItem?.let { - realm.copyToRealm(it) + realm.copyToRealmOrUpdate(it) dataListAdapter.notifyItemInserted(lastDeletedItemPosition) } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/EditableDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/EditableDataFragment.kt index c7aaee2b..3ef2ae24 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/EditableDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/EditableDataFragment.kt @@ -11,10 +11,10 @@ import io.realm.RealmObject import kotlinx.android.synthetic.main.fragment_editable_data.* import kotlinx.android.synthetic.main.fragment_editable_data.view.* import net.pokeranalytics.android.R -import net.pokeranalytics.android.exceptions.TypeException import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.TournamentKind import net.pokeranalytics.android.model.interfaces.Identifiable +import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.model.interfaces.Savable import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.Game @@ -28,19 +28,19 @@ import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetDelegate import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment -import net.pokeranalytics.android.ui.helpers.PlacePickerManager import net.pokeranalytics.android.ui.view.RowRepresentable -import net.pokeranalytics.android.ui.view.rowrepresentable.LocationRow -class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, BottomSheetDelegate { +open class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, BottomSheetDelegate { + + lateinit var parentActivity: PokerAnalyticsActivity + lateinit var item: RealmObject + lateinit var liveDataType: LiveData + lateinit var rowRepresentableAdapter: RowRepresentableAdapter - private lateinit var parentActivity: PokerAnalyticsActivity - private lateinit var item: RealmObject - private lateinit var liveDataType: LiveData - private lateinit var rowRepresentableAdapter: RowRepresentableAdapter private var editableMenu: Menu? = null private var dataType: Int? = null + private var primaryKey: String? = null private var isUpdating = false override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { @@ -50,6 +50,7 @@ class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) initUI() + initData() } override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { @@ -69,18 +70,7 @@ class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, } override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { - when (row) { - LocationRow.LOCATE_ME -> { - if (item is Location) { - (item as Location).isLookingForPlaces = true - PlacePickerManager.create(parentActivity, row, this) - rowRepresentableAdapter.refreshRow(row) - } else { - throw TypeException("Need to manage LocationRow.LOCATE_ME for ${item::class.java}") - } - } - else -> BottomSheetFragment.create(fragmentManager, row, this, (this.item as RowRepresentableDataSource).editDescriptors(row)) - } + BottomSheetFragment.create(fragmentManager, row, this, (this.item as RowRepresentableDataSource).editDescriptors(row)) } override fun clickOnAdd(row: RowRepresentable) { @@ -91,12 +81,7 @@ class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, this.getRealm().executeTransaction { (this.item as Savable).updateValue(value, row) } - when (row) { - LocationRow.LOCATE_ME -> { - rowRepresentableAdapter.notifyDataSetChanged() - } - else -> rowRepresentableAdapter.refreshRow(row) - } + rowRepresentableAdapter.refreshRow(row) } /** @@ -116,6 +101,36 @@ class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, } } + + /** + * Init data + */ + private fun initData() { + if (this.dataType != null) { + val proxyItem: RealmObject? = this.liveDataType.getData(this.getRealm(), primaryKey) + proxyItem?.let { + this.appBar.toolbar.title = "Update ${this.liveDataType.name.toLowerCase().capitalize()}" + isUpdating = true + } ?: run { + this.appBar.toolbar.title = "New ${this.liveDataType.name.toLowerCase().capitalize()}" + } + this.item = this.liveDataType.updateOrCreate(this.getRealm(), primaryKey) + this.rowRepresentableAdapter = RowRepresentableAdapter( + (this.item as RowRepresentableDataSource), + this + ) + this.recyclerView.adapter = rowRepresentableAdapter + + // When creating an object, open automatically the keyboard for the first row + if (!isUpdating && this.item is RowRepresentableDataSource) { + val row = (this.item as RowRepresentableDataSource).adapterRows()?.firstOrNull() + row?.let { + onRowSelected(0, it) + } + } + } + } + /** * Update menu UI */ @@ -139,7 +154,7 @@ class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, finishActivityWithResult(uniqueIdentifier) } } else { - + /* val message = when (item) { is Bankroll -> R.string.empty_name_for_br_error is Location -> R.string.location_empty_field_error @@ -148,12 +163,12 @@ class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, is TournamentKind -> R.string.tt_empty_field_error else -> throw IllegalStateException("Need to manage ${item::class.java} error") } - + */ + val message = (this.item as Savable).getFailedSaveMessage() val builder = AlertDialog.Builder(requireContext()) .setMessage(message) .setNegativeButton(R.string.ok, null) builder.show() - } } @@ -168,7 +183,7 @@ class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, .setPositiveButton(R.string.yes) { _, _ -> //TODO: Maybe update this code, does the object need to be managed? this.getRealm().executeTransaction { - this.liveDataType.deleteData(it, (this.item as Savable)) + this.liveDataType.deleteData(it, (this.item as Manageable)) } this.activity?.finish() } @@ -192,7 +207,10 @@ class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, fun setData(dataType: Int, primaryKey: String?) { this.dataType = dataType this.liveDataType = LiveData.values()[dataType] + + /* val proxyItem: RealmObject? = this.liveDataType.getData(this.getRealm(), primaryKey) + proxyItem?.let { this.appBar.toolbar.title = "Update ${this.liveDataType.localizedTitle(this.parentActivity).toLowerCase().capitalize()}" isUpdating = true @@ -213,5 +231,8 @@ class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, onRowSelected(0, it) } } + */ + this.primaryKey = primaryKey } + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/HistoryFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/HistoryFragment.kt index 3397fcb3..5cb2b52d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/HistoryFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/HistoryFragment.kt @@ -13,7 +13,7 @@ import kotlinx.android.synthetic.main.fragment_history.* import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import net.pokeranalytics.android.R -import net.pokeranalytics.android.model.interfaces.Savable +import net.pokeranalytics.android.model.interfaces.Manageable import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.ui.activity.SessionActivity import net.pokeranalytics.android.ui.adapter.LiveRowRepresentableDataSource @@ -175,6 +175,6 @@ class HistoryFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSource } override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { - SessionActivity.newInstance(requireContext(), sessionId = (row as Savable).uniqueIdentifier()) + SessionActivity.newInstance(requireContext(), sessionId = (row as Manageable).uniqueIdentifier()) } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/LocationDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/LocationDataFragment.kt new file mode 100644 index 00000000..a4643159 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/LocationDataFragment.kt @@ -0,0 +1,38 @@ +package net.pokeranalytics.android.ui.fragment + +import net.pokeranalytics.android.exceptions.TypeException +import net.pokeranalytics.android.model.realm.Location +import net.pokeranalytics.android.ui.helpers.PlacePickerManager +import net.pokeranalytics.android.ui.view.RowRepresentable +import net.pokeranalytics.android.ui.view.rowrepresentable.LocationRow + +/** + * Custom EditableDataFragment to manage the LOCATE_ME case + */ +class LocationDataFragment: EditableDataFragment() { + + override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { + when(row) { + LocationRow.LOCATE_ME -> { + if (item is Location) { + (item as Location).isLookingForPlaces = true + PlacePickerManager.create(parentActivity, row, this) + rowRepresentableAdapter.refreshRow(row) + } else { + throw TypeException("Need to manage LocationRow.LOCATE_ME for ${item::class.java}") + } + } + else -> super.onRowSelected(position, row, fromAction) + } + } + + override fun onRowValueChanged(value: Any?, row: RowRepresentable) { + super.onRowValueChanged(value, row) + when (row) { + LocationRow.LOCATE_ME -> { + rowRepresentableAdapter.notifyDataSetChanged() + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/PokerAnalyticsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/PokerAnalyticsFragment.kt index 1c6365f5..b333ee94 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/PokerAnalyticsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/PokerAnalyticsFragment.kt @@ -3,24 +3,26 @@ package net.pokeranalytics.android.ui.fragment.components import android.os.Bundle import androidx.fragment.app.Fragment import io.realm.Realm -import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity open class PokerAnalyticsFragment: Fragment() { + private lateinit var realm: Realm + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + realm = Realm.getDefaultInstance() } override fun onDestroyView() { super.onDestroyView() + realm.close() } /** * Get the realm instance */ fun getRealm(): Realm { - val pokerAnalyticsActivity = activity as PokerAnalyticsActivity - return pokerAnalyticsActivity.getRealm() + return realm } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/util/UIExtensions.kt b/app/src/main/java/net/pokeranalytics/android/util/UIExtensions.kt index 39d7e0c6..563afad1 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/UIExtensions.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/UIExtensions.kt @@ -1,10 +1,12 @@ package net.pokeranalytics.android.util import android.content.ActivityNotFoundException +import android.content.Context import android.content.Intent import android.content.res.Resources import android.net.Uri import android.widget.Toast +import androidx.appcompat.app.AlertDialog import androidx.browser.customtabs.CustomTabsIntent import androidx.core.content.ContextCompat import net.pokeranalytics.android.BuildConfig @@ -28,6 +30,7 @@ val Float.px: Float fun PokerAnalyticsActivity.toast(message: String) { Toast.makeText(this, message, Toast.LENGTH_SHORT).show() } + fun PokerAnalyticsFragment.toast(message: String) { Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() } @@ -71,3 +74,28 @@ fun PokerAnalyticsActivity.openUrl(url: String) { val customTabsIntent = builder.build() customTabsIntent.launchUrl(this, Uri.parse(url)) } + +// Display Alert Dialog +fun PokerAnalyticsActivity.showAlertDialog(title: Int? = null, message: Int? = null) { + showAlertDialog(this, title, message) +} +fun PokerAnalyticsFragment.showAlertDialog(title: Int? = null, message: Int? = null) { + context?.let { + showAlertDialog(it, title, message) + } +} + +/** + * Create and show an alert dialog + */ +fun showAlertDialog(context: Context, title: Int? = null, message: Int? = null) { + val builder = AlertDialog.Builder(context) + title?.let { + builder.setTitle(title) + } + message?.let { + builder.setMessage(message) + } + builder.setPositiveButton(R.string.ok, null) + builder.show() +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_editable_data.xml b/app/src/main/res/layout/activity_editable_data.xml index d8f373b8..70454fb9 100644 --- a/app/src/main/res/layout/activity_editable_data.xml +++ b/app/src/main/res/layout/activity_editable_data.xml @@ -1,15 +1,7 @@ - + android:layout_height="match_parent"> - - - \ No newline at end of file + \ No newline at end of file