Skip to content

Commit

Permalink
Merge pull request #28 from horizontalsystems/time-period-all
Browse files Browse the repository at this point in the history
Time period all
  • Loading branch information
abdrasulov authored Jan 26, 2023
2 parents c0d8d21 + ec5bf3a commit 8150ae4
Show file tree
Hide file tree
Showing 14 changed files with 161 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit

class MainViewModel(private val marketKit: MarketKit) : ViewModel() {
private val disposables = CompositeDisposable()
Expand Down Expand Up @@ -86,7 +87,10 @@ class MainViewModel(private val marketKit: MarketKit) : ViewModel() {
fun runGetChartInfo() {
val coinUid = "ethereum"
val currencyCode = "USD"
val interval = HsTimePeriod.Month1

val time = Date().time / 1000 - TimeUnit.DAYS.toSeconds(7)

val interval = HsPeriodType.ByStartTime(time)
//get stored chart info
val storedChartInfo = marketKit.chartInfo(coinUid, currencyCode, interval)
Log.w("AAA", "storedChartInfo: ${storedChartInfo?.points}")
Expand All @@ -98,6 +102,17 @@ class MainViewModel(private val marketKit: MarketKit) : ViewModel() {
Log.w("AAA", "fetchChartInfo: ${it.points}")
}, {
Log.e("AAA", "fetchChartInfo Error", it)
})
.let {
disposables.add(it)
}

marketKit.chartStartTimeSingle(coinUid)
.subscribeOn(Schedulers.io())
.subscribe({
Log.w("AAA", "chartStartTimeSingle: $it")
}, {
Log.e("AAA", "chartStartTimeSingle Error", it)

})
.let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,20 +229,24 @@ class MarketKit(

// Chart Info

fun chartInfo(coinUid: String, currencyCode: String, interval: HsTimePeriod): ChartInfo? {
return chartManager.getChartInfo(coinUid, currencyCode, interval)
fun chartInfo(coinUid: String, currencyCode: String, periodType: HsPeriodType): ChartInfo? {
return chartManager.getChartInfo(coinUid, currencyCode, periodType)
}

fun chartInfoSingle(coinUid: String, currencyCode: String, interval: HsTimePeriod): Single<ChartInfo> {
return chartManager.chartInfoSingle(coinUid, currencyCode, interval)
fun chartInfoSingle(coinUid: String, currencyCode: String, periodType: HsPeriodType): Single<ChartInfo> {
return chartManager.chartInfoSingle(coinUid, currencyCode, periodType)
}

fun chartStartTimeSingle(coinUid: String): Single<Long> {
return chartManager.chartStartTimeSingle(coinUid)
}

fun getChartInfoAsync(
coinUid: String,
currencyCode: String,
interval: HsTimePeriod
periodType: HsPeriodType
): Observable<ChartInfo> {
return chartSyncManager.chartInfoObservable(coinUid, currencyCode, interval)
return chartSyncManager.chartInfoObservable(coinUid, currencyCode, periodType)
}

// Global Market Info
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,33 @@ class ChartManager(
fun noChartInfo(key: ChartInfoKey)
}

private fun chartInfo(points: List<ChartPoint>, interval: HsTimePeriod): ChartInfo? {
private fun chartInfo(points: List<ChartPoint>, periodType: HsPeriodType): ChartInfo? {
val lastPoint = points.lastOrNull() ?: return null

val lastPointTimestamp = lastPoint.timestamp
val startTimestamp = lastPointTimestamp - interval.range
val intervalRange = periodType.range
val startTimestamp = intervalRange?.let {
lastPointTimestamp - it
} ?: points.first().timestamp

val currentTimestamp = Date().time / 1000
val lastPointGap = currentTimestamp - lastPointTimestamp

// if points not in visible window (too early) just return null
if (lastPointGap > interval.range) {
if (intervalRange != null && lastPointGap > intervalRange) {
return null
}

return ChartInfo(
points,
startTimestamp,
currentTimestamp,
isExpired = lastPointGap > interval.expiration
isExpired = lastPointGap > periodType.expiration
)
}

private fun storedChartPoints(key: ChartInfoKey): List<ChartPoint> {
return storage.getList(key.coin.uid, key.currencyCode, key.interval).map { point ->
return storage.getList(key.coin.uid, key.currencyCode, key.periodType).map { point ->
ChartPoint(
point.value,
point.timestamp,
Expand All @@ -58,7 +62,7 @@ class ChartManager(
ChartPointEntity(
key.coin.uid,
key.currencyCode,
key.interval,
key.periodType,
point.value,
point.extra[ChartPointType.Volume],
point.timestamp,
Expand All @@ -68,7 +72,7 @@ class ChartManager(
storage.delete(key)
storage.save(records)

val chartInfo = chartInfo(points, key.interval)
val chartInfo = chartInfo(points, key.periodType)

if (chartInfo == null) {
listener?.noChartInfo(key)
Expand All @@ -85,32 +89,36 @@ class ChartManager(
return storedChartPoints(key).lastOrNull()?.timestamp
}

fun getChartInfo(coinUid: String, currencyCode: String, interval: HsTimePeriod): ChartInfo? {
fun getChartInfo(coinUid: String, currencyCode: String, periodType: HsPeriodType): ChartInfo? {
val fullCoin = coinManager.fullCoins(listOf(coinUid)).firstOrNull() ?: return null
val key = ChartInfoKey(fullCoin.coin, currencyCode, interval)
return chartInfo(storedChartPoints(key), interval)
val key = ChartInfoKey(fullCoin.coin, currencyCode, periodType)
return chartInfo(storedChartPoints(key), periodType)
}

fun chartInfoSingle(
coinUid: String,
currencyCode: String,
interval: HsTimePeriod
periodType: HsPeriodType
): Single<ChartInfo> {
val fullCoin = coinManager.fullCoins(listOf(coinUid)).firstOrNull()
?: return Single.error(NoChartData())

return provider.coinPriceChartSingle(
fullCoin.coin.uid,
currencyCode,
interval,
periodType,
indicatorPoints
)
.flatMap { response ->
val points = response.map { it.chartPoint }

chartInfo(points, interval)?.let {
chartInfo(points, periodType)?.let {
Single.just(it)
} ?: Single.error(NoChartData())
}
}

fun chartStartTimeSingle(coinUid: String): Single<Long> {
return provider.coinPriceChartStartTime(coinUid)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ class ChartSchedulerProvider(
get() = manager.getLastSyncTimestamp(key)

override val expirationInterval: Long
get() = key.interval.expiration
get() = key.periodType.expiration

override val syncSingle: Single<Unit>
get() = provider.coinPriceChartSingle(key.coin.uid, key.currencyCode, key.interval, indicatorPoints)
get() = provider.coinPriceChartSingle(key.coin.uid, key.currencyCode, key.periodType, indicatorPoints)
.doOnSuccess { response ->
val points = response.map { it.chartPoint }
manager.update(points, key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import io.horizontalsystems.marketkit.managers.CoinManager
import io.horizontalsystems.marketkit.models.ChartInfo
import io.horizontalsystems.marketkit.models.ChartInfoKey
import io.horizontalsystems.marketkit.chart.scheduler.ChartScheduler
import io.horizontalsystems.marketkit.models.HsTimePeriod
import io.horizontalsystems.marketkit.models.HsPeriodType
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
import io.reactivex.subjects.PublishSubject
Expand All @@ -25,7 +25,7 @@ class ChartSyncManager(
private val failedKeys = ConcurrentLinkedQueue<ChartInfoKey>()
private val disposables = ConcurrentHashMap<ChartInfoKey, Disposable>()

fun chartInfoObservable(coinUid: String, currencyCode: String, interval: HsTimePeriod): Observable<ChartInfo> {
fun chartInfoObservable(coinUid: String, currencyCode: String, interval: HsPeriodType): Observable<ChartInfo> {

val fullCoin = coinManager.fullCoins(listOf(coinUid)).firstOrNull() ?: return Observable.error(NoChartInfo())

Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,50 @@
package io.horizontalsystems.marketkit.chart

import io.horizontalsystems.marketkit.models.HsPeriodType
import io.horizontalsystems.marketkit.models.HsPointTimePeriod
import io.horizontalsystems.marketkit.models.HsTimePeriod
import java.util.*

object HsChartRequestHelper {

fun pointInterval(interval: HsTimePeriod): HsPointTimePeriod {
return when (interval) {
HsTimePeriod.Day1 -> HsPointTimePeriod.Minute30
HsTimePeriod.Week1 -> HsPointTimePeriod.Hour4
HsTimePeriod.Week2 -> HsPointTimePeriod.Hour8
else -> HsPointTimePeriod.Day1
fun pointInterval(periodType: HsPeriodType) = when (periodType) {
is HsPeriodType.ByPeriod -> {
when (periodType.timePeriod) {
HsTimePeriod.Day1 -> HsPointTimePeriod.Minute30
HsTimePeriod.Week1 -> HsPointTimePeriod.Hour4
HsTimePeriod.Week2 -> HsPointTimePeriod.Hour8
else -> HsPointTimePeriod.Day1
}
}
is HsPeriodType.ByStartTime -> {
val currentTime = Date().time / 1000
val seconds = currentTime - periodType.startTime

when {
seconds <= HsTimePeriod.Day1.range -> HsPointTimePeriod.Minute30
seconds <= HsTimePeriod.Week1.range -> HsPointTimePeriod.Hour4
seconds <= HsTimePeriod.Week2.range -> HsPointTimePeriod.Hour8
seconds <= HsTimePeriod.Year2.range -> HsPointTimePeriod.Day1
else -> HsPointTimePeriod.Week1
}
}
}

fun fromTimestamp(timestamp: Long, interval: HsTimePeriod, indicatorPoints: Int) : Long {
// time needed for build indicators
val pointInterval = pointInterval(interval)
val additionalTime = indicatorPoints * pointInterval.interval
fun fromTimestamp(timestamp: Long, periodType: HsPeriodType, indicatorPoints: Int) : Long {
return when (periodType) {
is HsPeriodType.ByPeriod -> {
val timePeriod = periodType.timePeriod
val range = timePeriod.range

return timestamp - interval.range - additionalTime
// time needed for build indicators
val pointInterval = pointInterval(periodType)
val additionalTime = indicatorPoints * pointInterval.interval

return timestamp - range - additionalTime
}
is HsPeriodType.ByStartTime -> {
periodType.startTime
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package io.horizontalsystems.marketkit.models
data class ChartInfoKey(
val coin: Coin,
val currencyCode: String,
val interval: HsTimePeriod
val periodType: HsPeriodType
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import java.math.BigDecimal
data class ChartPointEntity(
val coinUid: String,
val currencyCode: String,
val interval: HsTimePeriod,
val interval: HsPeriodType,
val value: BigDecimal,
val volume: BigDecimal?,
val timestamp: Long
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ enum class HsPointTimePeriod(val value: String) {
Hour1("1h"),
Hour4("4h"),
Hour8("8h"),
Day1("1d");
Day1("1d"),
Week1("1w");

val interval: Long
get() = when (this) {
Expand All @@ -14,5 +15,6 @@ enum class HsPointTimePeriod(val value: String) {
Hour4 -> 4 * 60 * 60
Hour8 -> 8 * 60 * 60
Day1 -> 24 * 60 * 60
Week1 -> 7 * 24 * 60 * 60
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.horizontalsystems.marketkit.models

import io.horizontalsystems.marketkit.chart.HsChartRequestHelper

enum class HsTimePeriod(val value: String) {
Day1("1d"),
Week1("1w"),
Expand All @@ -10,14 +12,6 @@ enum class HsTimePeriod(val value: String) {
Year1("1y"),
Year2("2y");

val expiration: Long
get() = when (this) {
Day1 -> 30 * 60
Week1 -> 4 * 60 * 60
Week2 -> 8 * 60 * 60
Month1, Month3, Month6, Year1, Year2 -> day
}

val range: Long
get() = when (this) {
Day1 -> day
Expand All @@ -32,3 +26,42 @@ enum class HsTimePeriod(val value: String) {

private val day = (24 * 60 * 60).toLong()
}

sealed class HsPeriodType {

data class ByPeriod(val timePeriod: HsTimePeriod) : HsPeriodType()
data class ByStartTime(val startTime: Long) : HsPeriodType()

val expiration: Long
get() = HsChartRequestHelper.pointInterval(this).interval

val range: Long?
get() = when (this) {
is ByPeriod -> timePeriod.range
is ByStartTime -> null
}

fun serialize() = when (this) {
is ByPeriod -> "period:${timePeriod.value}"
is ByStartTime -> "startTime:$startTime"
}

companion object {
fun deserialize(v: String): HsPeriodType? {
val (type, value) = v.split(":")

return when (type) {
"period" -> {
HsTimePeriod
.values()
.firstOrNull { it.value == value }
?.let { ByPeriod(it) }
}
"startTime" -> ByStartTime(value.toLong())
else -> null
}
}
}


}
Loading

0 comments on commit 8150ae4

Please sign in to comment.