mirror of
https://github.com/InsanusMokrassar/PsychomatrixBase.git
synced 2025-12-04 21:35:56 +00:00
first version
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
package com.github.insanusmokrassar.PsychomatrixBase
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.github.insanusmokrassar.PsychomatrixBase.domain.UseCases
|
||||
|
||||
import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.Psychomatrix
|
||||
import kotlinx.coroutines.experimental.Deferred
|
||||
import kotlinx.coroutines.experimental.channels.ReceiveChannel
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
|
||||
interface UserCanCalculatePsychomatrixByDate {
|
||||
suspend fun calculate(date: Long): Deferred<Psychomatrix>
|
||||
suspend fun calculate(date: DateTime): Deferred<Psychomatrix>
|
||||
suspend fun calculate(date: Date): Deferred<Psychomatrix>
|
||||
|
||||
suspend fun openPsychomatrixCreatedSubscription(): ReceiveChannel<Psychomatrix>
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.github.insanusmokrassar.PsychomatrixBase.domain.entities
|
||||
|
||||
import org.joda.time.DateTime
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlin.math.sqrt
|
||||
|
||||
private val dateFormat: DateFormat = SimpleDateFormat("dMyyyy", Locale.ROOT)
|
||||
private fun Int.toDigits(): List<Byte> {
|
||||
return "$this".map { "$it".toByte() }
|
||||
}
|
||||
|
||||
class Psychomatrix(val date: DateTime) {
|
||||
private val numbers: ByteArray = ByteArray(10)
|
||||
|
||||
/**
|
||||
* Always array 4*4 of values. In rows was put columns (
|
||||
*/
|
||||
val asMatrix: Array<Array<Byte>>
|
||||
get() = arrayOf(
|
||||
arrayOf(-1, -1, -1, getUpperDiagSum()),
|
||||
arrayOf(numbers[1], numbers[4], numbers[7], getRowSum(0)),
|
||||
arrayOf(numbers[2], numbers[5], numbers[8], getRowSum(1)),
|
||||
arrayOf(numbers[3], numbers[6], numbers[9], getRowSum(2)),
|
||||
arrayOf(getColumnSum(0), getColumnSum(1), getColumnSum(2), getDownDiagSum())
|
||||
)
|
||||
|
||||
init {
|
||||
val dateDigits = dateFormat.format(date).map { "$it".toByte() }.toMutableList()
|
||||
|
||||
val firstNumber = dateDigits.sum()
|
||||
val firstNumberDigits = firstNumber.toDigits()
|
||||
|
||||
val secondNumber = firstNumberDigits.sum()
|
||||
val secondNumberDigits = secondNumber.toDigits()
|
||||
|
||||
val thirdNumber = firstNumber - dateDigits[0] * 2
|
||||
val thirdNumberDigits = thirdNumber.toDigits()
|
||||
|
||||
val fourthNumber = thirdNumberDigits.sum()
|
||||
val fourthNumberDigits = fourthNumber.toDigits()
|
||||
|
||||
dateDigits.addAll(firstNumberDigits)
|
||||
dateDigits.addAll(secondNumberDigits)
|
||||
dateDigits.addAll(thirdNumberDigits)
|
||||
dateDigits.addAll(fourthNumberDigits)
|
||||
|
||||
(0 until numbers.size).forEach {
|
||||
index ->
|
||||
numbers[index] = dateDigits.count {
|
||||
it == index.toByte()
|
||||
}.toByte()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return count of numbers of `i`
|
||||
*/
|
||||
operator fun get(i: Int): Byte {
|
||||
return numbers[i]
|
||||
}
|
||||
|
||||
/**
|
||||
* 1 4 7 - zero row
|
||||
* 2 5 8 - first row
|
||||
* 3 6 9 - second row
|
||||
*/
|
||||
fun getRowSum(i: Int): Byte {
|
||||
return (i + 1 until numbers.size step 3).map { numbers[it] }.sum().toByte()
|
||||
}
|
||||
|
||||
/**
|
||||
* 1 4 7
|
||||
* 2 5 8
|
||||
* 3 6 9
|
||||
* | | |
|
||||
* z f s
|
||||
* e i e
|
||||
* r r c
|
||||
* o s o
|
||||
* t n
|
||||
* d
|
||||
*/
|
||||
fun getColumnSum(i: Int): Byte {
|
||||
val side = sqrt(numbers.size.toDouble() - 1).toInt()
|
||||
val first = side * i + 1
|
||||
return (first until first + side).map { numbers[it] }.sum().toByte()
|
||||
}
|
||||
|
||||
/**
|
||||
* upper
|
||||
* /
|
||||
* 1 4 7
|
||||
* 2 5 8
|
||||
* 3 6 9
|
||||
*/
|
||||
fun getUpperDiagSum(): Byte {
|
||||
val side = sqrt(numbers.size.toDouble() - 1).toInt()
|
||||
return (side .. numbers.size - side step side - 1).map { numbers[it] }.sum().toByte()
|
||||
}
|
||||
|
||||
/**
|
||||
* 1 4 7
|
||||
* 2 5 8
|
||||
* 3 6 9
|
||||
* \
|
||||
* down
|
||||
*/
|
||||
fun getDownDiagSum(): Byte {
|
||||
val side = sqrt(numbers.size.toDouble() - 1).toInt()
|
||||
return (1 until numbers.size step side + 1).map { numbers[it] }.sum().toByte()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return (" %2d\n" +
|
||||
"%2d %2d %2d %2d\n" +
|
||||
"%2d %2d %2d %2d\n" +
|
||||
"%2d %2d %2d %2d\n" +
|
||||
"%2d %2d %2d %2d").format(
|
||||
getUpperDiagSum(),
|
||||
numbers[1],
|
||||
numbers[4],
|
||||
numbers[7],
|
||||
getRowSum(0),
|
||||
numbers[2],
|
||||
numbers[5],
|
||||
numbers[8],
|
||||
getRowSum(1),
|
||||
numbers[3],
|
||||
numbers[6],
|
||||
numbers[9],
|
||||
getRowSum(2),
|
||||
getColumnSum(0),
|
||||
getColumnSum(1),
|
||||
getColumnSum(2),
|
||||
getDownDiagSum()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.github.insanusmokrassar.PsychomatrixBase.presentation.presenters
|
||||
|
||||
import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.Psychomatrix
|
||||
import kotlinx.coroutines.experimental.channels.ReceiveChannel
|
||||
import org.joda.time.DateTime
|
||||
|
||||
interface DatePickerPresenter {
|
||||
|
||||
suspend fun openPsychomatrixCreatedSubscription(): ReceiveChannel<Psychomatrix>
|
||||
|
||||
fun userPickDate(date: Long)
|
||||
fun userPickDate(date: DateTime)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.github.insanusmokrassar.PsychomatrixBase.utils.extensions
|
||||
|
||||
import java.util.*
|
||||
|
||||
fun Calendar.getYear(): Int = get(Calendar.YEAR)
|
||||
fun Calendar.getMonth(): Int = get(Calendar.MONTH)
|
||||
fun Calendar.getDayOfMonth(): Int = get(Calendar.DAY_OF_MONTH)
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.github.insanusmokrassar.PsychomatrixBase.utils.extensions
|
||||
|
||||
import kotlinx.coroutines.experimental.*
|
||||
import kotlinx.coroutines.experimental.channels.BroadcastChannel
|
||||
import kotlinx.coroutines.experimental.channels.ReceiveChannel
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
fun <T> ReceiveChannel<T>.subscribeChecking(
|
||||
throwableHandler: (Throwable) -> Boolean = {
|
||||
it.printStackTrace()
|
||||
true
|
||||
},
|
||||
by: suspend (T) -> Boolean
|
||||
): Job {
|
||||
return launch {
|
||||
while (isActive && !isClosedForReceive) {
|
||||
try {
|
||||
val received = receive()
|
||||
|
||||
launch {
|
||||
try {
|
||||
if (!by(received)) {
|
||||
cancel()
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
if (!throwableHandler(e)) {
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: CancellationException) {
|
||||
break
|
||||
}
|
||||
}
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> ReceiveChannel<T>.subscribe(
|
||||
throwableHandler: (Throwable) -> Boolean = {
|
||||
it.printStackTrace()
|
||||
true
|
||||
},
|
||||
by: suspend (T) -> Unit
|
||||
): Job {
|
||||
return subscribeChecking(throwableHandler) {
|
||||
by(it)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> ReceiveChannel<T>.debounce(delayMs: Long, awaitedSubscriptions: Int = 256): BroadcastChannel<T> {
|
||||
val channel = BroadcastChannel<T>(awaitedSubscriptions)
|
||||
var lastReceived: Pair<Long, T>? = null
|
||||
var job: Job? = null
|
||||
launch {
|
||||
while (isActive && !isClosedForReceive) {
|
||||
val received = receive()
|
||||
|
||||
lastReceived = Pair(System.currentTimeMillis() + delayMs, received)
|
||||
|
||||
job ?:let {
|
||||
job = launch {
|
||||
try {
|
||||
var now = System.currentTimeMillis()
|
||||
while (isActive && lastReceived?.first ?: now >= now) {
|
||||
delay((lastReceived ?.first ?: now) - now, TimeUnit.MILLISECONDS)
|
||||
now = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
lastReceived?.second?.also {
|
||||
channel.send(it)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
job = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cancel()
|
||||
}
|
||||
return channel
|
||||
}
|
||||
Reference in New Issue
Block a user