first version

This commit is contained in:
2018-09-04 09:49:52 +08:00
parent c1bd167689
commit ebdcd372fc
8 changed files with 487 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
package com.github.insanusmokrassar.PsychomatrixBase
fun main(args: Array<String>) {
}

View File

@@ -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>
}

View File

@@ -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()
)
}
}

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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
}