fix conflict

feature/top10
Razmig Sarkissian 7 years ago
commit 1afbc7acbb
  1. 143
      app/src/androidTest/java/net/pokeranalytics/android/ExampleInstrumentedUnitTest.kt
  2. 30
      app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt
  3. 4
      app/src/main/java/net/pokeranalytics/android/calculus/Stat.kt
  4. 5
      app/src/main/java/net/pokeranalytics/android/model/realm/Game.kt
  5. 20
      app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt
  6. 27
      app/src/main/java/net/pokeranalytics/android/model/realm/SessionSet.kt
  7. 119
      app/src/main/java/net/pokeranalytics/android/model/realm/TimeFrame.kt
  8. 38
      app/src/main/java/net/pokeranalytics/android/model/realm/TournamentType.kt
  9. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/CurrenciesFragment.kt
  10. 19
      app/src/main/java/net/pokeranalytics/android/ui/fragment/EditableDataFragment.kt
  11. 8
      app/src/main/java/net/pokeranalytics/android/ui/fragment/HistoryFragment.kt
  12. 8
      app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt
  13. 2
      app/src/main/java/net/pokeranalytics/android/ui/fragment/StatsFragment.kt
  14. 47
      app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt
  15. 4
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/HeaderRowRepresentable.kt
  16. 15
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt
  17. 2
      app/src/main/java/net/pokeranalytics/android/util/DateExtension.kt
  18. 11
      app/src/main/java/net/pokeranalytics/android/util/Global.kt
  19. 4
      app/src/main/java/net/pokeranalytics/android/util/NumbersExtension.kt
  20. 6
      app/src/main/java/net/pokeranalytics/android/util/Preferences.kt
  21. BIN
      app/src/main/res/drawable-xxhdpi/add_tournament.png
  22. BIN
      app/src/main/res/drawable-xxhdpi/add_tournoi.png
  23. 6
      app/src/main/res/layout/fragment_history.xml
  24. 84
      app/src/main/res/layout/row_follow_us.xml
  25. 0
      app/src/main/res/layout/row_header_title.xml
  26. 2
      app/src/main/res/layout/row_session_view.xml
  27. 3
      app/src/main/res/layout/row_stats_title_value.xml
  28. 2
      app/src/main/res/layout/row_title.xml
  29. 2
      app/src/main/res/layout/row_title_arrow.xml
  30. 2
      app/src/main/res/layout/row_title_value.xml
  31. 2
      app/src/main/res/layout/row_title_value_action.xml
  32. 2
      app/src/main/res/values/colors.xml
  33. 7
      app/src/main/res/values/styles.xml

@ -7,6 +7,7 @@ import net.pokeranalytics.android.calculus.ComputedResults
import net.pokeranalytics.android.calculus.SessionGroup import net.pokeranalytics.android.calculus.SessionGroup
import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.SessionSet
import net.pokeranalytics.android.model.realm.TimeFrame import net.pokeranalytics.android.model.realm.TimeFrame
import org.junit.Assert import org.junit.Assert
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
@ -26,7 +27,7 @@ class ExampleInstrumentedUnitTest : RealmInstrumentedUnitTest() {
// convenience extension // convenience extension
fun Session.Companion.testInstance(netResult: Double, startDate: Date, endDate: Date?): Session { fun Session.Companion.testInstance(netResult: Double, startDate: Date, endDate: Date?): Session {
val session: Session = Session.newInstance() val session: Session = Session.newInstance(super.mockRealm, false)
session.result?.netResult = netResult session.result?.netResult = netResult
session.timeFrame?.setDate(startDate, endDate) session.timeFrame?.setDate(startDate, endDate)
return session return session
@ -67,8 +68,8 @@ class ExampleInstrumentedUnitTest : RealmInstrumentedUnitTest() {
realm.beginTransaction() realm.beginTransaction()
s1.timeFrame?.setDate(sd1, ed1) // duration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800 s1.timeFrame?.setDate(sd1, ed1) // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800
s2.timeFrame?.setDate(sd2, ed2) // duration = 3h, hourly = 100, bb100 = 150 / 75 * 100 = +200 s2.timeFrame?.setDate(sd2, ed2) // netDuration = 3h, hourly = 100, bb100 = 150 / 75 * 100 = +200
realm.copyToRealmOrUpdate(s1) realm.copyToRealmOrUpdate(s1)
realm.copyToRealmOrUpdate(s2) realm.copyToRealmOrUpdate(s2)
@ -102,7 +103,7 @@ class ExampleInstrumentedUnitTest : RealmInstrumentedUnitTest() {
if (duration != null) { if (duration != null) {
assertEquals(4.0, duration.value, delta) assertEquals(4.0, duration.value, delta)
} else { } else {
Assert.fail("No duration stat") Assert.fail("No netDuration stat")
} }
val hourlyRate = results.computedStat(Stat.HOURLY_RATE) val hourlyRate = results.computedStat(Stat.HOURLY_RATE)
@ -207,7 +208,6 @@ class ExampleInstrumentedUnitTest : RealmInstrumentedUnitTest() {
realm.insert(s1) realm.insert(s1)
realm.insert(s2) realm.insert(s2)
realm.commitTransaction()
val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") val sdf = SimpleDateFormat("dd/M/yyyy hh:mm")
@ -216,10 +216,9 @@ class ExampleInstrumentedUnitTest : RealmInstrumentedUnitTest() {
val sd2 = sdf.parse("01/1/2019 08:00") val sd2 = sdf.parse("01/1/2019 08:00")
val ed2 = sdf.parse("01/1/2019 11:00") val ed2 = sdf.parse("01/1/2019 11:00")
realm.beginTransaction()
s1.timeFrame?.setDate(sd1, ed1) // duration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800 s1.timeFrame?.setDate(sd1, ed1) // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800
s2.timeFrame?.setDate(sd2, ed2) // duration = 4h, hourly = 100, bb100 = 150 / 75 * 100 = +200 s2.timeFrame?.setDate(sd2, ed2) // netDuration = 4h, hourly = 100, bb100 = 150 / 75 * 100 = +200
realm.copyToRealmOrUpdate(s1) realm.copyToRealmOrUpdate(s1)
realm.copyToRealmOrUpdate(s2) realm.copyToRealmOrUpdate(s2)
@ -274,7 +273,6 @@ class ExampleInstrumentedUnitTest : RealmInstrumentedUnitTest() {
realm.insert(s1) realm.insert(s1)
realm.insert(s2) realm.insert(s2)
realm.insert(s3) realm.insert(s3)
realm.commitTransaction()
val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") val sdf = SimpleDateFormat("dd/M/yyyy hh:mm")
@ -285,11 +283,9 @@ class ExampleInstrumentedUnitTest : RealmInstrumentedUnitTest() {
val sd3 = sdf.parse("01/1/2019 03:00") val sd3 = sdf.parse("01/1/2019 03:00")
val ed3 = sdf.parse("01/1/2019 06:00") val ed3 = sdf.parse("01/1/2019 06:00")
realm.beginTransaction() s1.timeFrame?.setDate(sd1, ed1) // netDuration = 4h
s2.timeFrame?.setDate(sd2, ed2) // netDuration = 4h
s1.timeFrame?.setDate(sd1, ed1) // duration = 4h s3.timeFrame?.setDate(sd3, ed3) // netDuration = 3h
s2.timeFrame?.setDate(sd2, ed2) // duration = 4h
s3.timeFrame?.setDate(sd3, ed3) // duration = 3h
realm.copyToRealmOrUpdate(s1) realm.copyToRealmOrUpdate(s1)
realm.copyToRealmOrUpdate(s2) realm.copyToRealmOrUpdate(s2)
@ -370,9 +366,9 @@ class ExampleInstrumentedUnitTest : RealmInstrumentedUnitTest() {
realm.beginTransaction() realm.beginTransaction()
s1.timeFrame?.setDate(sd1, ed1) // duration = 4h s1.timeFrame?.setDate(sd1, ed1) // netDuration = 4h
s2.timeFrame?.setDate(sd2, ed2) // duration = 4h s2.timeFrame?.setDate(sd2, ed2) // netDuration = 4h
s3.timeFrame?.setDate(sd3, ed3) // duration = 3h s3.timeFrame?.setDate(sd3, ed3) // netDuration = 3h
realm.copyToRealmOrUpdate(s1) realm.copyToRealmOrUpdate(s1)
realm.copyToRealmOrUpdate(s2) realm.copyToRealmOrUpdate(s2)
@ -393,12 +389,9 @@ class ExampleInstrumentedUnitTest : RealmInstrumentedUnitTest() {
if (duration != null) { if (duration != null) {
assertEquals(8.0, duration.value, delta) assertEquals(8.0, duration.value, delta)
} else { } else {
Assert.fail("No duration stat") Assert.fail("No netDuration stat")
} }
// realm.beginTransaction()
// s1.deleteFromRealm()
// realm.commitTransaction()
realm.executeTransaction { realm.executeTransaction {
s1.deleteFromRealm() s1.deleteFromRealm()
} }
@ -414,4 +407,112 @@ class ExampleInstrumentedUnitTest : RealmInstrumentedUnitTest() {
} }
} }
@Test
fun testSessionSetCount() {
val realm = this.mockRealm
realm.beginTransaction()
val s1 = realm.createObject(Session::class.java, "1")
s1.timeFrame = realm.createObject(TimeFrame::class.java)
s1.result = realm.createObject(net.pokeranalytics.android.model.realm.Result::class.java)
realm.insert(s1)
val sdf = SimpleDateFormat("dd/M/yyyy hh:mm")
val sd1 = sdf.parse("01/1/2019 09:00")
val ed1 = sdf.parse("01/1/2019 10:00")
s1.timeFrame?.setDate(sd1, ed1) // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800
realm.copyToRealmOrUpdate(s1)
realm.commitTransaction()
val sets = realm.where(SessionSet::class.java).findAll()
Assert.assertEquals(1, sets.size)
val set = sets.first()
if (set != null) {
Assert.assertEquals(sd1.time, set.timeFrame?.startDate?.time)
Assert.assertEquals(ed1.time, set.timeFrame?.endDate?.time)
} else {
Assert.fail("No set")
}
}
@Test
fun testSessionSetCount2() {
val realm = this.mockRealm
realm.beginTransaction()
val s1 = realm.createObject(Session::class.java, "1")
val s2 = realm.createObject(Session::class.java, "2")
s1.timeFrame = realm.createObject(TimeFrame::class.java)
s2.timeFrame = realm.createObject(TimeFrame::class.java)
s1.result = realm.createObject(net.pokeranalytics.android.model.realm.Result::class.java)
s2.result = realm.createObject(net.pokeranalytics.android.model.realm.Result::class.java)
realm.insert(s1)
realm.insert(s2)
val sdf = SimpleDateFormat("dd/M/yyyy hh:mm")
val sd1 = sdf.parse("01/1/2019 09:00")
val ed1 = sdf.parse("01/1/2019 10:00")
val sd2 = sdf.parse("01/2/2018 09:00")
val ed2 = sdf.parse("01/2/2018 10:00")
s1.timeFrame?.let {
it.setStart(sd1)
it.setEnd(ed1)
}
s2.timeFrame?.let {
it.setStart(sd2)
it.setEnd(ed2)
}
// s1.timeFrame?.setDate(sd1, ed1) // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800
// s2.timeFrame?.setDate(sd2, ed2) // netDuration = 1h, hourly = -100, bb100 = -200bb / 25hands * 100 = -800
realm.copyToRealmOrUpdate(s1)
realm.copyToRealmOrUpdate(s2)
realm.commitTransaction()
val sets = realm.where(SessionSet::class.java).findAll()
Assert.assertEquals(2, sets.size)
// val set = sets.first()
// if (set != null) {
// Assert.assertEquals(sd1.time, set.timeFrame?.startDate?.time)
// Assert.assertEquals(ed1.time, set.timeFrame?.endDate?.time)
// } else {
// Assert.fail("No set")
// }
}
// @Test
// fun testDurationConversion() {
//
// val duration = 6.7555561274509826
// val longDuration = duration.toLong()
// val formatted = longDuration.toMinutes()
//
// assert(formatted == "11:00")
// }
} }

@ -131,8 +131,8 @@ class PokerAnalyticsApplication : Application() {
for (index in 0..50) { for (index in 0..50) {
realm.executeTransaction { realm.executeTransaction {
val session = Session() val session = Session.newInstance(realm, false)
session.id = UUID.randomUUID().toString() // session.id = UUID.randomUUID().toString()
val calendar = Calendar.getInstance() val calendar = Calendar.getInstance()
calendar.set( calendar.set(
@ -148,21 +148,27 @@ class PokerAnalyticsApplication : Application() {
calendar.add(Calendar.MINUTE, (0..59).random()) calendar.add(Calendar.MINUTE, (0..59).random())
val endDate = calendar.time val endDate = calendar.time
val timeFrame = TimeFrame() // val timeFrame = TimeFrame()
timeFrame.setDate(startDate, endDate)
session.timeFrame = timeFrame session.timeFrame?.let {
// it.startDate = startDate
// it.endDate = endDate
it.setDate(startDate, endDate)
}
// session.timeFrame = timeFrame
session.creationDate = startDate session.creationDate = startDate
session.limit = Limit.values().random().ordinal session.limit = Limit.values().random().ordinal
session.game = realm.where<Game>().findAll().random() session.game = realm.where<Game>().findAll().random()
val result = Result() session.result?.let { result ->
result.buyin = arrayListOf(100, 200, 300, 500, 1000, 2000).random().toDouble() result.buyin = arrayListOf(100, 200, 300, 500, 1000, 2000).random().toDouble()
result.netResult = arrayListOf( result.netResult = arrayListOf(
-2500.0, -2000.0, -1500.0, -1000.0, -500.0, 200.0, 1000.0, 1500.0, -2500.0, -2000.0, -1500.0, -1000.0, -500.0, 200.0, 1000.0, 1500.0,
2500.0 2500.0
).random() ).random()
session.result = result }
realm.copyToRealmOrUpdate(session) realm.copyToRealmOrUpdate(session)
} }
@ -172,6 +178,16 @@ class PokerAnalyticsApplication : Application() {
realm.close() realm.close()
val sets = realm.where(SessionSet::class.java).findAll()
// Timber.d("sets = ${sets.size}")
//
// sets.forEach { set ->
// Timber.d("set sd = : ${set.timeFrame?.startDate}, ed = ${set.timeFrame?.endDate}")
// }
} }
} }

@ -7,7 +7,7 @@ import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.FormatUtils import net.pokeranalytics.android.util.FormatUtils
import net.pokeranalytics.android.util.formatted import net.pokeranalytics.android.util.formatted
import net.pokeranalytics.android.util.toMinutes import net.pokeranalytics.android.util.formattedHourlyDuration
/** /**
* An enum representing all the types of Session statistics * An enum representing all the types of Session statistics
@ -138,7 +138,7 @@ class ComputedStat(stat: Stat, value: Double) {
return TextFormat("${value.toInt()}") return TextFormat("${value.toInt()}")
} // white durations } // white durations
Stat.DURATION, Stat.AVERAGE_DURATION -> { Stat.DURATION, Stat.AVERAGE_DURATION -> {
return TextFormat("${value.toLong().toMinutes()}") return TextFormat(value.formattedHourlyDuration())
} // red/green percentages } // red/green percentages
Stat.WIN_RATIO, Stat.ROI -> { Stat.WIN_RATIO, Stat.ROI -> {
val color = if (value >= this.stat.threshold) R.color.green else R.color.red val color = if (value >= this.stat.threshold) R.color.green else R.color.red

@ -11,8 +11,7 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
open class Game : RealmObject(), Savable, StaticRowRepresentableDataSource, open class Game : RealmObject(), Savable, StaticRowRepresentableDataSource, RowRepresentable {
RowRepresentable {
@PrimaryKey @PrimaryKey
var id = UUID.randomUUID().toString() var id = UUID.randomUUID().toString()
@ -41,7 +40,7 @@ open class Game : RealmObject(), Savable, StaticRowRepresentableDataSource,
override fun stringForRow(row: RowRepresentable): String { override fun stringForRow(row: RowRepresentable): String {
return when (row) { return when (row) {
SimpleRow.NAME -> this.name SimpleRow.NAME -> this.name
GameRow.SHORT_NAME -> this.shortName?:"" GameRow.SHORT_NAME -> this.shortName ?: ""
else -> return super.stringForRow(row) else -> return super.stringForRow(row)
} }
} }

@ -37,6 +37,7 @@ open class Session : RealmObject(), SessionInterface, Savable,
companion object { companion object {
fun newInstance(realm: Realm, isTournament: Boolean): Session { fun newInstance(realm: Realm, isTournament: Boolean): Session {
val session = Session() val session = Session()
session.timeFrame = TimeFrame()
session.result = Result() session.result = Result()
session.bankroll = realm.where<Bankroll>().findFirst() session.bankroll = realm.where<Bankroll>().findFirst()
session.type = if (isTournament) Session.Type.TOURNAMENT.ordinal else Session.Type.CASH_GAME.ordinal session.type = if (isTournament) Session.Type.TOURNAMENT.ordinal else Session.Type.CASH_GAME.ordinal
@ -59,7 +60,7 @@ open class Session : RealmObject(), SessionInterface, Savable,
var timeFrame: TimeFrame? = null var timeFrame: TimeFrame? = null
set(value) { set(value) {
field = value field = value
value?.let { it.notifySessionDateChange(this) } // value?.let { it.notifySessionDateChange(this) }
} }
// The time frame sessionGroup, which can contain multiple sessions // The time frame sessionGroup, which can contain multiple sessions
@ -142,7 +143,8 @@ open class Session : RealmObject(), SessionInterface, Savable,
when (getState()) { when (getState()) {
SessionState.PENDING, SessionState.PLANNED -> { SessionState.PENDING, SessionState.PLANNED -> {
val sessionTimeFrame = this.timeFrame ?: realm.createObject(TimeFrame::class.java) val sessionTimeFrame = this.timeFrame ?: realm.createObject(TimeFrame::class.java)
sessionTimeFrame.setDate(Date(), null) sessionTimeFrame.setStart(Date())
// sessionTimeFrame.setDate(Date(), null)
this.timeFrame = sessionTimeFrame this.timeFrame = sessionTimeFrame
} }
SessionState.PAUSED -> { SessionState.PAUSED -> {
@ -178,7 +180,8 @@ open class Session : RealmObject(), SessionInterface, Savable,
SessionState.STARTED, SessionState.PAUSED -> { SessionState.STARTED, SessionState.PAUSED -> {
this.timeFrame?.paused = false this.timeFrame?.paused = false
this.timeFrame?.pauseDate = null this.timeFrame?.pauseDate = null
this.timeFrame?.setDate(null, Date()) this.timeFrame?.setEnd(Date())
// this.timeFrame?.setDate(null, Date())
} }
else -> throw Exception("Stopping session in unmanaged state") else -> throw Exception("Stopping session in unmanaged state")
} }
@ -198,7 +201,7 @@ open class Session : RealmObject(), SessionInterface, Savable,
} }
/** /**
* Return the duration of the current session * Return the netDuration of the current session
*/ */
fun getDuration(): String { fun getDuration(): String {
val startDate = timeFrame?.startDate ?: Date() val startDate = timeFrame?.startDate ?: Date()
@ -467,6 +470,7 @@ open class Session : RealmObject(), SessionInterface, Savable,
result?.cashout?.round(), result?.cashout?.round(),
inputType = InputType.TYPE_CLASS_NUMBER inputType = InputType.TYPE_CLASS_NUMBER
or InputType.TYPE_NUMBER_FLAG_DECIMAL or InputType.TYPE_NUMBER_FLAG_DECIMAL
or InputType.TYPE_NUMBER_FLAG_SIGNED
) )
) )
} }
@ -569,7 +573,7 @@ open class Session : RealmObject(), SessionInterface, Savable,
localResult.cashout = (value as String).toDouble() localResult.cashout = (value as String).toDouble()
val timeFrameToUpdate = val timeFrameToUpdate =
if (timeFrame != null) timeFrame as TimeFrame else realm.createObject(TimeFrame::class.java) if (timeFrame != null) timeFrame as TimeFrame else realm.createObject(TimeFrame::class.java)
timeFrameToUpdate.setDate(null, Date()) timeFrameToUpdate.setEnd(Date())
timeFrame = timeFrameToUpdate timeFrame = timeFrameToUpdate
} }
@ -580,7 +584,8 @@ open class Session : RealmObject(), SessionInterface, Savable,
SessionRow.END_DATE -> if (value is Date?) { SessionRow.END_DATE -> if (value is Date?) {
val timeFrameToUpdate = val timeFrameToUpdate =
if (timeFrame != null) timeFrame as TimeFrame else realm.createObject(TimeFrame::class.java) if (timeFrame != null) timeFrame as TimeFrame else realm.createObject(TimeFrame::class.java)
timeFrameToUpdate.setDate(null, value) // timeFrameToUpdate.setDate(null, value)
timeFrameToUpdate.setEnd(value)
timeFrame = timeFrameToUpdate timeFrame = timeFrameToUpdate
} }
SessionRow.GAME -> { SessionRow.GAME -> {
@ -614,7 +619,8 @@ open class Session : RealmObject(), SessionInterface, Savable,
} else { } else {
val timeFrameToUpdate = val timeFrameToUpdate =
if (timeFrame != null) timeFrame as TimeFrame else realm.createObject(TimeFrame::class.java) if (timeFrame != null) timeFrame as TimeFrame else realm.createObject(TimeFrame::class.java)
timeFrameToUpdate.setDate(value, null) timeFrameToUpdate.setStart(value)
// timeFrameToUpdate.setDate(value, null)
timeFrame = timeFrameToUpdate timeFrame = timeFrameToUpdate
} }
} }

@ -9,6 +9,16 @@ import io.realm.annotations.LinkingObjects
open class SessionSet() : RealmObject() { open class SessionSet() : RealmObject() {
companion object {
fun newInstance(realm: Realm) : SessionSet {
val sessionSet: SessionSet = realm.createObject(SessionSet::class.java)
sessionSet.timeFrame = realm.createObject(TimeFrame::class.java)
return realm.copyToRealm(sessionSet)
}
}
/** /**
* The timeframe of the set, i.e. its start & end date * The timeframe of the set, i.e. its start & end date
*/ */
@ -21,13 +31,13 @@ open class SessionSet() : RealmObject() {
@LinkingObjects("sessionSet") @LinkingObjects("sessionSet")
val sessions: RealmResults<Session>? = null val sessions: RealmResults<Session>? = null
@Ignore // a duration shortcut @Ignore // a netDuration shortcut
var duration: Long = 0L var duration: Long = 0L
get() { get() {
return this.timeFrame?.duration ?: 0L return this.timeFrame?.netDuration ?: 0L
} }
@Ignore // a duration in hour @Ignore // a netDuration in hour
var hourlyDuration: Double = 0.0 var hourlyDuration: Double = 0.0
get() { get() {
return this.timeFrame?.hourlyDuration ?: 0.0 return this.timeFrame?.hourlyDuration ?: 0.0
@ -39,7 +49,7 @@ open class SessionSet() : RealmObject() {
return this.sessions?.sumByDouble { it.value } ?: 0.0 return this.sessions?.sumByDouble { it.value } ?: 0.0
} }
@Ignore // a duration shortcut @Ignore // a netDuration shortcut
var hourlyRate: Double = 0.0 var hourlyRate: Double = 0.0
get () { get () {
return this.netResult / this.hourlyDuration return this.netResult / this.hourlyDuration
@ -51,15 +61,6 @@ open class SessionSet() : RealmObject() {
@Ignore @Ignore
var bbNetResult: Double = 0.0 var bbNetResult: Double = 0.0
companion object {
fun newInstance(realm: Realm) : SessionSet {
val sessionSet: SessionSet = realm.createObject(SessionSet::class.java)
sessionSet.timeFrame = realm.createObject(TimeFrame::class.java)
return sessionSet
}
}
} }

@ -1,6 +1,5 @@
package net.pokeranalytics.android.model.realm package net.pokeranalytics.android.model.realm
import io.realm.Realm
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.RealmQuery import io.realm.RealmQuery
import io.realm.RealmResults import io.realm.RealmResults
@ -38,20 +37,20 @@ open class TimeFrame : RealmObject() {
this.computeDuration() this.computeDuration()
} }
// The break duration // The break netDuration
var breakDuration: Long = 0L var breakDuration: Long = 0L
set(value) { set(value) {
field = value field = value
this.computeDuration() this.computeDuration()
} }
// the total duration // the total netDuration
var duration: Long = 0L var netDuration: Long = 0L
private set private set
var hourlyDuration: Double = 0.0 var hourlyDuration: Double = 0.0
get() { get() {
return this.duration / 3600000.0 // 3.6 millions of milliseconds return this.netDuration / 3600000.0 // 3.6 millions of milliseconds
} }
// indicates a state of pause // indicates a state of pause
@ -73,29 +72,35 @@ open class TimeFrame : RealmObject() {
var set: SessionSet? = null var set: SessionSet? = null
get() = this.sets?.first() get() = this.sets?.first()
fun setDate(startDate: Date?, endDate: Date?) { fun setStart(startDate: Date) {
startDate?.let {
this.startDate = startDate this.startDate = startDate
this.session?.let {
this.notifySessionDateChange(it)
}
} }
fun setEnd(endDate: Date?) {
this.endDate = endDate this.endDate = endDate
this.session?.let {
this.notifySessionDateChange(it)
}
}
this.computeDuration() fun setDate(startDate: Date, endDate: Date?) {
this.startDate = startDate
this.endDate = endDate
this.session?.let { this.session?.let {
this.notifySessionDateChange(it) this.notifySessionDateChange(it)
} }
} }
/** /**
* Computes the net duration of the session * Computes the net netDuration of the session
*/ */
private fun computeDuration() { private fun computeDuration() {
var endDate: Date = this.endDate ?: Date() var endDate: Date = this.endDate ?: Date()
val netDuration = endDate.time - this.startDate.time - this.breakDuration this.netDuration = endDate.time - this.startDate.time - this.breakDuration
this.duration = netDuration
} }
/** /**
@ -103,25 +108,35 @@ open class TimeFrame : RealmObject() {
* Makes all necessary changes to keep sequential time frames * Makes all necessary changes to keep sequential time frames
*/ */
fun notifySessionDateChange(owner: Session) { fun notifySessionDateChange(owner: Session) {
val realm = Realm.getDefaultInstance()
var query: RealmQuery<SessionSet> = realm.where(SessionSet::class.java) var query: RealmQuery<SessionSet> = this.realm.where(SessionSet::class.java)
query.isNotNull("timeFrame") query.isNotNull("timeFrame")
// Timber.d("this> sd = : ${this.startDate}, ed = ${this.endDate}") // Timber.d("this> sd = : ${this.startDate}, ed = ${this.endDate}")
val sets = realm.where(SessionSet::class.java).findAll()
// Timber.d("set count = ${sets.size}")
if (this.endDate == null) { if (this.endDate == null) {
query.greaterThan("timeFrame.startDate", this.startDate).or().greaterThan("timeFrame.endDate", this.startDate) query.greaterThanOrEqualTo("timeFrame.startDate", this.startDate)
.or()
.greaterThanOrEqualTo("timeFrame.endDate", this.startDate)
.or()
.isNull("timeFrame.endDate")
} else { } else {
val endDate = this.endDate!! val endDate = this.endDate!!
query query
.lessThan("timeFrame.startDate", this.startDate) .lessThanOrEqualTo("timeFrame.startDate", this.startDate)
.greaterThan("timeFrame.endDate", this.startDate) .greaterThanOrEqualTo("timeFrame.endDate", this.startDate)
.or()
.lessThanOrEqualTo("timeFrame.startDate", endDate)
.greaterThanOrEqualTo("timeFrame.endDate", endDate)
.or() .or()
.lessThan("timeFrame.startDate", endDate) .greaterThanOrEqualTo("timeFrame.startDate", this.startDate)
.greaterThan("timeFrame.endDate", endDate) .lessThanOrEqualTo("timeFrame.endDate", endDate)
.or() .or()
.greaterThan("timeFrame.startDate", this.startDate) .isNull("timeFrame.endDate")
.lessThan("timeFrame.endDate", endDate) .lessThanOrEqualTo("timeFrame.startDate", endDate)
} }
val sessionGroups = query.findAll() val sessionGroups = query.findAll()
@ -137,7 +152,7 @@ open class TimeFrame : RealmObject() {
when (sessionSets.size) { when (sessionSets.size) {
0 -> this.createSessionGroup(owner) 0 -> this.createSessionGroup(owner)
1 -> this.updateSingleSessionGroup(owner, sessionSets.first()!!) 1 -> this.updateSessionGroup(owner, sessionSets.first()!!)
else -> this.mergeSessionGroups(owner, sessionSets) else -> this.mergeSessionGroups(owner, sessionSets)
} }
@ -148,9 +163,7 @@ open class TimeFrame : RealmObject() {
*/ */
private fun createSessionGroup(owner: Session) { private fun createSessionGroup(owner: Session) {
val realm = Realm.getDefaultInstance() val set: SessionSet = SessionSet.newInstance(this.realm)
val set: SessionSet = SessionSet.newInstance(realm)
set.timeFrame?.let { set.timeFrame?.let {
it.startDate = this.startDate it.startDate = this.startDate
it.endDate = this.endDate it.endDate = this.endDate
@ -160,30 +173,54 @@ open class TimeFrame : RealmObject() {
owner.sessionSet = set owner.sessionSet = set
Timber.d("sd = : ${set.timeFrame?.startDate}, ed = ${set.timeFrame?.endDate}") // Timber.d("sd = : ${set.timeFrame?.startDate}, ed = ${set.timeFrame?.endDate}")
Timber.d("netDuration 1 = : ${set.timeFrame?.netDuration}")
} }
/** /**
* Single session sessionGroup update * Single SessionSet update, the session might be the owner
* Changes the sessionGroup timeframe using the current timeframe dates * Changes the sessionGroup timeframe using the current timeframe dates
*/ */
private fun updateSingleSessionGroup(owner: Session, sessionSet: SessionSet) { private fun updateSessionGroup(owner: Session, sessionSet: SessionSet) {
var groupTimeFrame: TimeFrame = sessionSet.timeFrame!! // tested in the query var timeFrame: TimeFrame = sessionSet.timeFrame!! // tested in the query
// timeFrame.setDate(this.startDate, this.endDate)
val sisterSessions = sessionSet.sessions!! // shouldn't crash ever
// if we have only one session in the set and that it corresponds to the set
if (sessionSet.sessions?.size == 1 && sessionSet.sessions?.first() == owner) {
timeFrame.setDate(this.startDate, this.endDate)
} else { // there are 2+ sessions to manage and possible splits
if (this.startDate.before(groupTimeFrame.startDate)) {
groupTimeFrame.startDate = this.startDate
}
val endDate = this.endDate val endDate = this.endDate
if (endDate != null && groupTimeFrame.endDate != null && endDate.after(groupTimeFrame.endDate)) {
groupTimeFrame.endDate = endDate // case where all sessions are over but the set is not, we might have a split, so we delete the set and save everything again
if (endDate != null && sisterSessions.all { it.timeFrame?.endDate != null } && timeFrame.endDate == null) {
var sessions = mutableListOf<Session>(owner)
sessionSet.sessions?.forEach { sessions.add(it) }
sessionSet.deleteFromRealm()
sessions.forEach { it.timeFrame?.notifySessionDateChange(it) }
} else {
if (this.startDate.before(timeFrame.startDate)) {
timeFrame.startDate = this.startDate
}
if (endDate != null && timeFrame.endDate != null && endDate.after(timeFrame.endDate)) {
timeFrame.endDate = endDate
} else if (endDate == null) { } else if (endDate == null) {
groupTimeFrame.endDate = null timeFrame.endDate = null
} }
owner.sessionSet = sessionSet owner.sessionSet = sessionSet
// Timber.d("sd = : ${sessionSet.timeFrame?.startDate}, ed = ${sessionSet.timeFrame?.endDate}")
Timber.d("netDuration 2 = : ${sessionSet.timeFrame?.netDuration}")
}
}
} }
/** /**
@ -216,16 +253,17 @@ open class TimeFrame : RealmObject() {
// get all sessions from sets // get all sessions from sets
var sessions = mutableSetOf<Session>() var sessions = mutableSetOf<Session>()
sessionSets.forEach { it.sessions?.asIterable()?.let { it1 -> sessions.addAll(it1) } } sessionSets.forEach { set ->
set.sessions?.asIterable()?.let { sessions.addAll(it) }
}
// delete all sets // delete all sets
sessionSets.deleteAllFromRealm() sessionSets.deleteAllFromRealm()
// Create a new sets // Create a new sets
val set: SessionSet = SessionSet.newInstance(realm) val set: SessionSet = SessionSet.newInstance(this.realm)
set.timeFrame?.let { set.timeFrame?.let {
it.startDate = startDate it.setDate(startDate, endDate)
it.endDate = endDate
} ?: run { } ?: run {
throw ModelException("TimeFrame should never be null here") throw ModelException("TimeFrame should never be null here")
} }
@ -235,6 +273,7 @@ open class TimeFrame : RealmObject() {
// Add all orphan sessions // Add all orphan sessions
sessions.forEach { it.sessionSet = set } sessions.forEach { it.sessionSet = set }
Timber.d("netDuration 3 = : ${set.timeFrame?.netDuration}")
} }

@ -3,13 +3,15 @@ package net.pokeranalytics.android.model.realm
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.annotations.PrimaryKey import io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.model.interfaces.Savable import net.pokeranalytics.android.model.interfaces.Savable
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow
import java.util.* import java.util.*
import kotlin.collections.ArrayList
open class TournamentType : RealmObject(), Savable, RowRepresentable { open class TournamentType : RealmObject(), Savable, StaticRowRepresentableDataSource, RowRepresentable {
@PrimaryKey @PrimaryKey
var id = UUID.randomUUID().toString() var id = UUID.randomUUID().toString()
@ -31,4 +33,36 @@ open class TournamentType : RealmObject(), Savable, RowRepresentable {
} }
} }
override fun adapterRows(): List<RowRepresentable>? {
val rows = ArrayList<RowRepresentable>()
rows.add(SimpleRow.NAME)
//rows.addAll(TournamentType.values())
return rows
}
override fun stringForRow(row: RowRepresentable): String {
return when (row) {
SimpleRow.NAME -> this.name
else -> return super.stringForRow(row)
}
}
override fun editDescriptors(row: RowRepresentable): ArrayList<RowRepresentableEditDescriptor> {
val data = java.util.ArrayList<RowRepresentableEditDescriptor>()
when (row) {
SimpleRow.NAME -> data.add(
RowRepresentableEditDescriptor(
this.name,
SimpleRow.NAME.resId
)
)
}
return data
}
override fun isValidForSave(): Boolean {
return this.name.isNotEmpty()
}
} }

@ -73,7 +73,7 @@ class CurrenciesFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataS
override fun adapterRows(): List<RowRepresentable>? { override fun adapterRows(): List<RowRepresentable>? {
val rows = ArrayList<RowRepresentable>() val rows = ArrayList<RowRepresentable>()
rows.addAll(mostUsedCurrencies) rows.addAll(mostUsedCurrencies)
rows.add(HeaderRowRepresentable(customViewType = RowViewType.HEADER_SESSION, resId = R.string.currency)) rows.add(HeaderRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.currency))
rows.addAll(availableCurrencies) rows.addAll(availableCurrencies)
return rows return rows

@ -14,15 +14,19 @@ import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.Identifiable
import net.pokeranalytics.android.model.interfaces.Savable import net.pokeranalytics.android.model.interfaces.Savable
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.TournamentType
import net.pokeranalytics.android.ui.activity.EditableDataActivity import net.pokeranalytics.android.ui.activity.EditableDataActivity
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.helpers.PlacePickerManager
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment 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.BottomSheetDelegate
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment 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
import net.pokeranalytics.android.ui.view.rowrepresentable.LocationRow import net.pokeranalytics.android.ui.view.rowrepresentable.LocationRow
@ -137,10 +141,21 @@ class EditableDataFragment : PokerAnalyticsFragment(), RowRepresentableDelegate,
finishActivityWithResult(uniqueIdentifier) finishActivityWithResult(uniqueIdentifier)
} }
} else { } else {
val message = when(item) {
is Bankroll -> R.string.empty_name_for_br_error
is Location -> R.string.location_empty_field_error
is Game -> R.string.location_empty_field_error
is TournamentType -> R.string.tt_empty_field_error
//is TransactionType -> R.string.operation_type_empty_field_error
else -> throw IllegalStateException("Need to manage ${item::class.java} error")
}
val builder = AlertDialog.Builder(requireContext()) val builder = AlertDialog.Builder(requireContext())
.setMessage(R.string.empty_name_for_br_error) .setMessage(message)
.setNegativeButton(R.string.ok, null) .setNegativeButton(R.string.ok, null)
builder.show() builder.show()
} }
} }

@ -127,7 +127,7 @@ class HistoryFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSource
if (!calendar.isSameDay(currentCalendar) || index == 0) { if (!calendar.isSameDay(currentCalendar) || index == 0) {
calendar.time = currentCalendar.time calendar.time = currentCalendar.time
val header = HeaderRowRepresentable( val header = HeaderRowRepresentable(
customViewType = RowViewType.HEADER_SESSION, customViewType = RowViewType.HEADER_TITLE,
title = session.creationDate.longDate() title = session.creationDate.longDate()
) )
rows.add(header) rows.add(header)
@ -136,7 +136,7 @@ class HistoryFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSource
if (!calendar.isSameMonth(currentCalendar) || index == 0) { if (!calendar.isSameMonth(currentCalendar) || index == 0) {
calendar.time = currentCalendar.time calendar.time = currentCalendar.time
val header = HeaderRowRepresentable( val header = HeaderRowRepresentable(
customViewType = RowViewType.HEADER_SESSION, customViewType = RowViewType.HEADER_TITLE,
title = session.creationDate.getMonthAndYear() title = session.creationDate.getMonthAndYear()
) )
rows.add(header) rows.add(header)
@ -165,8 +165,8 @@ class HistoryFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSource
} }
override fun viewTypeForPosition(position: Int): Int { override fun viewTypeForPosition(position: Int): Int {
return if (rows[position].viewType == RowViewType.HEADER_SESSION.ordinal) { return if (rows[position].viewType == RowViewType.HEADER_TITLE.ordinal) {
RowViewType.HEADER_SESSION.ordinal RowViewType.HEADER_TITLE.ordinal
} else { } else {
RowViewType.ROW_SESSION.ordinal RowViewType.ROW_SESSION.ordinal
} }

@ -73,6 +73,14 @@ class SettingsFragment : PokerAnalyticsFragment(), RowRepresentableDelegate, Sta
SettingRow.CURRENCY -> { SettingRow.CURRENCY -> {
CurrenciesActivity.newInstance(requireContext()) CurrenciesActivity.newInstance(requireContext())
} }
SettingRow.FOLLOW_US -> {
when(position) {
0 -> parentActivity.openUrl(BLOG)
1 -> parentActivity.openUrl(INSTAGRAM)
2 -> parentActivity.openUrl(TWITTER)
3 -> parentActivity.openUrl(FACEBOOK)
}
}
SettingRow.PRIVACY_POLICY -> parentActivity.openUrl(URL_PRIVACY_POLICY) SettingRow.PRIVACY_POLICY -> parentActivity.openUrl(URL_PRIVACY_POLICY)
SettingRow.TERMS_OF_USE -> parentActivity.openUrl(URL_TERMS) SettingRow.TERMS_OF_USE -> parentActivity.openUrl(URL_TERMS)
SettingRow.GDPR -> Toast.makeText(requireContext(), "Show GDPR", Toast.LENGTH_SHORT).show() SettingRow.GDPR -> Toast.makeText(requireContext(), "Show GDPR", Toast.LENGTH_SHORT).show()

@ -141,7 +141,7 @@ class StatsFragment : SessionObserverFragment(), StaticRowRepresentableDataSourc
val rows: ArrayList<RowRepresentable> = ArrayList() val rows: ArrayList<RowRepresentable> = ArrayList()
results.forEach { results -> results.forEach { results ->
rows.add(HeaderRowRepresentable(RowViewType.TITLE, title = results.group.name)) rows.add(HeaderRowRepresentable(title = results.group.name))
results.group.stats?.forEach { stat -> results.group.stats?.forEach { stat ->
rows.add(StatRepresentable(stat, results.computedStat(stat))) rows.add(StatRepresentable(stat, results.computedStat(stat)))
} }

@ -3,15 +3,16 @@ package net.pokeranalytics.android.ui.view
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView import androidx.appcompat.widget.AppCompatTextView
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.row_bottom_sheet_grid_title.view.* import kotlinx.android.synthetic.main.row_bottom_sheet_grid_title.view.*
import kotlinx.android.synthetic.main.row_bottom_sheet_title.view.* import kotlinx.android.synthetic.main.row_bottom_sheet_title.view.*
import kotlinx.android.synthetic.main.row_header_title.view.*
import kotlinx.android.synthetic.main.row_header_title_amount.view.* import kotlinx.android.synthetic.main.row_header_title_amount.view.*
import kotlinx.android.synthetic.main.row_header_title_value.view.* import kotlinx.android.synthetic.main.row_header_title_value.view.*
import kotlinx.android.synthetic.main.row_history_session.view.* import kotlinx.android.synthetic.main.row_history_session.view.*
import kotlinx.android.synthetic.main.row_history_session_header.view.*
import kotlinx.android.synthetic.main.row_stats_title_value.view.* import kotlinx.android.synthetic.main.row_stats_title_value.view.*
import kotlinx.android.synthetic.main.row_title.view.* import kotlinx.android.synthetic.main.row_title.view.*
import kotlinx.android.synthetic.main.row_title_switch.view.* import kotlinx.android.synthetic.main.row_title_switch.view.*
@ -28,19 +29,16 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.HeaderRowRepresentabl
* An interface used to factor the configuration of RecyclerView.ViewHolder * An interface used to factor the configuration of RecyclerView.ViewHolder
*/ */
interface BindableHolder { interface BindableHolder {
fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) { fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
} }
} }
enum class RowViewType { enum class RowViewType {
HEADER,
HEADER_TITLE_VALUE, HEADER_TITLE_VALUE,
HEADER_TITLE_AMOUNT, HEADER_TITLE_AMOUNT,
HEADER_TITLE_AMOUNT_BIG, HEADER_TITLE_AMOUNT_BIG,
HEADER_SESSION, HEADER_TITLE,
EDIT_TEXT, EDIT_TEXT,
TITLE, TITLE,
TITLE_ARROW, TITLE_ARROW,
@ -52,6 +50,7 @@ enum class RowViewType {
TITLE_GRID, TITLE_GRID,
ROW_SESSION, ROW_SESSION,
BUTTON, BUTTON,
FOLLOW_US,
STAT; STAT;
/** /**
@ -136,10 +135,10 @@ enum class RowViewType {
false false
) )
) )
HEADER_SESSION -> { HEADER_TITLE -> {
HeaderSessionViewHolder( HeaderSessionViewHolder(
LayoutInflater.from(parent.context).inflate( LayoutInflater.from(parent.context).inflate(
R.layout.row_history_session_header, R.layout.row_header_title,
parent, parent,
false false
) )
@ -161,6 +160,15 @@ enum class RowViewType {
) )
) )
} }
FOLLOW_US -> {
FollowUsViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.row_follow_us,
parent,
false
)
)
}
STAT -> StatsTitleValueViewHolder( STAT -> StatsTitleValueViewHolder(
LayoutInflater.from(parent.context).inflate( LayoutInflater.from(parent.context).inflate(
R.layout.row_stats_title_value, R.layout.row_stats_title_value,
@ -176,12 +184,12 @@ enum class RowViewType {
BindableHolder { BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) { override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
itemView.rowHeaderTitleValue_title.text = row.localizedTitle(itemView.context) itemView.rowHeaderTitleValue_title.text = row.localizedTitle(itemView.context)
adapter.dataSource?.let { adapter.dataSource.let {
itemView.rowHeaderTitleValue_value.text = it.stringForRow(row, itemView.context) itemView.rowHeaderTitleValue_value.text = it.stringForRow(row, itemView.context)
} }
// val listener = View.OnClickListener { //val listener = View.OnClickListener {
// adapter.delegate?.onRowSelected(position, row) // adapter.delegate?.onRowSelected(position, row)
// } //}
//itemView.rowHeaderTitleValue_container.setOnClickListener(listener) //itemView.rowHeaderTitleValue_container.setOnClickListener(listener)
itemView.rowHeaderTitleValue_separator.visibility = if (row.needSeparator) View.VISIBLE else View.GONE itemView.rowHeaderTitleValue_separator.visibility = if (row.needSeparator) View.VISIBLE else View.GONE
} }
@ -236,6 +244,23 @@ enum class RowViewType {
} }
} }
inner class FollowUsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
itemView.findViewById<AppCompatImageView>(R.id.icon1).setOnClickListener {
adapter.delegate?.onRowSelected(0, row)
}
itemView.findViewById<AppCompatImageView>(R.id.icon2).setOnClickListener {
adapter.delegate?.onRowSelected(1, row)
}
itemView.findViewById<AppCompatImageView>(R.id.icon3).setOnClickListener {
adapter.delegate?.onRowSelected(2, row)
}
itemView.findViewById<AppCompatImageView>(R.id.icon4).setOnClickListener {
adapter.delegate?.onRowSelected(3, row)
}
}
}
inner class StatsTitleValueViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), inner class StatsTitleValueViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder { BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) { override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {

@ -8,7 +8,7 @@ import net.pokeranalytics.android.ui.view.RowViewType
* A class to display headers as row representable * A class to display headers as row representable
*/ */
class HeaderRowRepresentable( class HeaderRowRepresentable(
var customViewType: RowViewType? = RowViewType.HEADER, var customViewType: RowViewType? = RowViewType.HEADER_TITLE,
override var resId: Int? = null, override var resId: Int? = null,
var title: String? = null, var title: String? = null,
var value: String? = null var value: String? = null
@ -26,6 +26,6 @@ class HeaderRowRepresentable(
} }
override val viewType: Int = customViewType?.ordinal ?: RowViewType.HEADER.ordinal override val viewType: Int = customViewType?.ordinal ?: RowViewType.HEADER_TITLE.ordinal
} }

@ -25,7 +25,6 @@ enum class SettingRow : RowRepresentable {
GAME, GAME,
LOCATION, LOCATION,
TOURNAMENT_TYPE, TOURNAMENT_TYPE,
TRANSACTION_TYPE,
// Terms // Terms
PRIVACY_POLICY, PRIVACY_POLICY,
@ -40,24 +39,24 @@ enum class SettingRow : RowRepresentable {
fun getRows(): ArrayList<RowRepresentable> { fun getRows(): ArrayList<RowRepresentable> {
val rows = ArrayList<RowRepresentable>() val rows = ArrayList<RowRepresentable>()
rows.add(HeaderRowRepresentable(customViewType = RowViewType.HEADER_SESSION, resId = R.string.information)) rows.add(HeaderRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.information))
rows.addAll(arrayListOf(VERSION, RATE_APP, CONTACT_US, BUG_REPORT)) rows.addAll(arrayListOf(VERSION, RATE_APP, CONTACT_US, BUG_REPORT))
rows.add(HeaderRowRepresentable(customViewType = RowViewType.HEADER_SESSION, resId = R.string.follow_us)) rows.add(HeaderRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.follow_us))
rows.addAll(arrayListOf(FOLLOW_US)) rows.addAll(arrayListOf(FOLLOW_US))
rows.add(HeaderRowRepresentable(customViewType = RowViewType.HEADER_SESSION, resId = R.string.preferences)) rows.add(HeaderRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.preferences))
rows.addAll(arrayListOf(CURRENCY)) rows.addAll(arrayListOf(CURRENCY))
rows.add( rows.add(
HeaderRowRepresentable( HeaderRowRepresentable(
customViewType = RowViewType.HEADER_SESSION, customViewType = RowViewType.HEADER_TITLE,
resId = R.string.data_management resId = R.string.data_management
) )
) )
rows.addAll(arrayListOf(BANKROLL, GAME, LOCATION, TOURNAMENT_TYPE, TRANSACTION_TYPE)) rows.addAll(arrayListOf(BANKROLL, GAME, LOCATION, TOURNAMENT_TYPE))
rows.add(HeaderRowRepresentable(customViewType = RowViewType.HEADER_SESSION, resId = R.string.terms)) rows.add(HeaderRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.terms))
rows.addAll(arrayListOf(PRIVACY_POLICY, TERMS_OF_USE, GDPR)) rows.addAll(arrayListOf(PRIVACY_POLICY, TERMS_OF_USE, GDPR))
return rows return rows
@ -90,6 +89,7 @@ enum class SettingRow : RowRepresentable {
get() { get() {
return when (this) { return when (this) {
VERSION -> RowViewType.TITLE_VALUE.ordinal VERSION -> RowViewType.TITLE_VALUE.ordinal
FOLLOW_US -> RowViewType.FOLLOW_US.ordinal
else -> RowViewType.TITLE_ARROW.ordinal else -> RowViewType.TITLE_ARROW.ordinal
} }
} }
@ -101,7 +101,6 @@ enum class SettingRow : RowRepresentable {
GAME -> LiveData.GAME GAME -> LiveData.GAME
LOCATION -> LiveData.LOCATION LOCATION -> LiveData.LOCATION
TOURNAMENT_TYPE -> LiveData.TOURNAMENT_TYPE TOURNAMENT_TYPE -> LiveData.TOURNAMENT_TYPE
TRANSACTION_TYPE -> LiveData.TRANSACTION_TYPE
else -> null else -> null
} }
} }

@ -84,7 +84,7 @@ fun Date.getMonthAndYear(): String {
return SimpleDateFormat("MMMM YYYY", Locale.getDefault()).format(this).capitalize() return SimpleDateFormat("MMMM YYYY", Locale.getDefault()).format(this).capitalize()
} }
// Return the duration between two dates // Return the netDuration between two dates
fun Date.getDuration(toDate: Date) : String { fun Date.getDuration(toDate: Date) : String {
val difference = (toDate.time - this.time).toInt() val difference = (toDate.time - this.time).toInt()
val numOfDays = (difference / (1000 * 60 * 60 * 24)) val numOfDays = (difference / (1000 * 60 * 60 * 24))

@ -1,8 +1,17 @@
package net.pokeranalytics.android.util package net.pokeranalytics.android.util
val NULL_TEXT: String = "--"
// Support
const val SUPPORT_EMAIL = "support@pokeranalytics.net" const val SUPPORT_EMAIL = "support@pokeranalytics.net"
// Terms
const val URL_PRIVACY_POLICY = "https://www.poker-analytics.net/privacypolicy.html" const val URL_PRIVACY_POLICY = "https://www.poker-analytics.net/privacypolicy.html"
const val URL_TERMS = "https://www.poker-analytics.net/terms.html" const val URL_TERMS = "https://www.poker-analytics.net/terms.html"
val NULL_TEXT: String = "--" // Social Network
const val BLOG = "https://medium.com/poker-analytics"
const val INSTAGRAM = "https://www.instagram.com/pokeranalytics"
const val TWITTER = "https://twitter.com/paapptweet"
const val FACEBOOK = "https://www.facebook.com/171053452998758"

@ -25,6 +25,10 @@ fun Double.toCurrency(): String {
return format.format(this) return format.format(this)
} }
fun Double.formattedHourlyDuration() : String {
return (this * 1000 * 3600).toLong().toMinutes()
}
// Return the time from milliseconds to hours:minutes // Return the time from milliseconds to hours:minutes
fun Long.toMinutes() : String { fun Long.toMinutes() : String {
val totalMinutes = this / (1000 * 60) val totalMinutes = this / (1000 * 60)

@ -6,7 +6,7 @@ import java.util.*
class Preferences { class Preferences {
enum class Keys(identifier: String) { enum class Keys(var identifier: String) {
CURRENCY_LANGUAGE("CurrencyLanguage") CURRENCY_LANGUAGE("CurrencyLanguage")
} }
@ -15,13 +15,13 @@ class Preferences {
fun setString(key: Keys, value: String, context: Context) { fun setString(key: Keys, value: String, context: Context) {
var preferences = PreferenceManager.getDefaultSharedPreferences(context) var preferences = PreferenceManager.getDefaultSharedPreferences(context)
var editor = preferences.edit() var editor = preferences.edit()
editor.putString(key.toString(), value) editor.putString(key.identifier, value)
editor.commit() editor.commit()
} }
fun getString(key: Keys, context: Context) : String? { fun getString(key: Keys, context: Context) : String? {
var preferences = PreferenceManager.getDefaultSharedPreferences(context) var preferences = PreferenceManager.getDefaultSharedPreferences(context)
return preferences.getString(key.name, null) return preferences.getString(key.identifier, null)
} }
fun setCurrencyLanguage(language: String, context: Context) { fun setCurrencyLanguage(language: String, context: Context) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

@ -82,7 +82,7 @@
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:text="@string/new_cash_game" android:text="@string/new_cash_game"
app:icon="@drawable/add_cash_game" app:icon="@drawable/add_cash_game"
app:iconSize="32dp" app:iconSize="28dp"
app:layout_constraintEnd_toStartOf="@+id/newTournament" app:layout_constraintEnd_toStartOf="@+id/newTournament"
app:layout_constraintHorizontal_bias="0.5" app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_chainStyle="spread" app:layout_constraintHorizontal_chainStyle="spread"
@ -99,8 +99,8 @@
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:text="@string/new_tournament" android:text="@string/new_tournament"
app:icon="@drawable/add_tournoi" app:icon="@drawable/add_tournament"
app:iconSize="32dp" app:iconSize="28dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5" app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/newCashGame" app:layout_constraintStart_toEndOf="@+id/newCashGame"

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/rowTitle.container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon1"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:background="?selectableItemBackgroundBorderless"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/icon2"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="@+id/guidelineStart"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/blog" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon2"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:background="?selectableItemBackgroundBorderless"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/icon3"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/icon1"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/insta" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon3"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:background="?selectableItemBackgroundBorderless"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/icon4"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/icon2"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/twitter" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon4"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:background="?selectableItemBackgroundBorderless"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guidelineEnd"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/icon3"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/facebook" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guidelineStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="16dp" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guidelineEnd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -3,7 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="56dp"
android:background="?selectableItemBackground"> android:background="?selectableItemBackground">
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView

@ -31,7 +31,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:paddingTop="-8dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/nextArrow" app:layout_constraintEnd_toStartOf="@+id/nextArrow"
app:layout_constraintStart_toStartOf="@+id/guidelineStart" app:layout_constraintStart_toStartOf="@+id/guidelineStart"
@ -44,11 +43,11 @@
android:layout_height="24dp" android:layout_height="24dp"
android:src="@drawable/ic_arrow_right" android:src="@drawable/ic_arrow_right"
android:tint="@color/gray_light" android:tint="@color/gray_light"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/guidelineEnd" app:layout_constraintEnd_toEndOf="@+id/guidelineEnd"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Guideline <androidx.constraintlayout.widget.Guideline
android:id="@+id/guidelineStart" android:id="@+id/guidelineStart"
android:layout_width="wrap_content" android:layout_width="wrap_content"

@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rowTitle.container" android:id="@+id/rowTitle.container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="48dp"
android:background="?selectableItemBackground"> android:background="?selectableItemBackground">
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView

@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rowTitle.container" android:id="@+id/rowTitle.container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="48dp"
android:background="?selectableItemBackground"> android:background="?selectableItemBackground">
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView

@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rowTitleValue.container" android:id="@+id/rowTitleValue.container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="48dp"
android:orientation="vertical"> android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout

@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rowTitleValueAction.container" android:id="@+id/rowTitleValueAction.container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="48dp"
android:background="?selectableItemBackground"> android:background="?selectableItemBackground">
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView

@ -8,7 +8,7 @@
<color name="white">#FFFFFF</color> <color name="white">#FFFFFF</color>
<color name="white_transparent">#30FFFFFF</color> <color name="white_transparent">#30FFFFFF</color>
<color name="gray_light">#6AFFFFFF</color> <color name="gray_light">#8AFFFFFF</color>
<color name="gray_darker">#141414</color> <color name="gray_darker">#141414</color>
<color name="gray_dark">#1B1F1B</color> <color name="gray_dark">#1B1F1B</color>

@ -111,7 +111,7 @@
</style> </style>
<style name="PokerAnalyticsTheme.TextView.RowStatsValue"> <style name="PokerAnalyticsTheme.TextView.RowStatsValue">
<item name="android:textSize">24sp</item> <item name="android:textSize">28sp</item>
<item name="android:textColor">@color/white</item> <item name="android:textColor">@color/white</item>
<item name="android:fontFamily">@font/roboto_light</item> <item name="android:fontFamily">@font/roboto_light</item>
<item name="android:maxLines">1</item> <item name="android:maxLines">1</item>
@ -130,7 +130,7 @@
<item name="android:textColor">@color/kaki_medium</item> <item name="android:textColor">@color/kaki_medium</item>
<item name="android:maxLines">1</item> <item name="android:maxLines">1</item>
<item name="android:ellipsize">end</item> <item name="android:ellipsize">end</item>
<item name="android:fontFamily">@font/roboto_bold</item> <item name="android:fontFamily">@font/roboto_medium</item>
<item name="android:textSize">16sp</item> <item name="android:textSize">16sp</item>
</style> </style>
@ -200,8 +200,9 @@
<!-- Button --> <!-- Button -->
<style name="PokerAnalyticsTheme.Button" parent="Widget.MaterialComponents.Button"> <style name="PokerAnalyticsTheme.Button" parent="Widget.MaterialComponents.Button">
<item name="iconPadding">0dp</item> <item name="iconPadding">0dp</item>
<item name="android:height">48dp</item>
<item name="iconTint">@color/black</item> <item name="iconTint">@color/black</item>
<item name="android:letterSpacing">-0.02</item> <item name="android:letterSpacing">0</item>
<item name="android:fontFamily">@font/roboto_medium</item> <item name="android:fontFamily">@font/roboto_medium</item>
<item name="android:textColor">@color/black</item> <item name="android:textColor">@color/black</item>
<item name="android:paddingStart">4dp</item> <item name="android:paddingStart">4dp</item>

Loading…
Cancel
Save