diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/entities/MutablePsychomatrix.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/entities/MutablePsychomatrix.kt new file mode 100644 index 0000000..6082149 --- /dev/null +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/entities/MutablePsychomatrix.kt @@ -0,0 +1,12 @@ +package com.github.insanusmokrassar.PsychomatrixBase.domain.entities + +import org.joda.time.DateTime + +class MutablePsychomatrix(date: DateTime) : Psychomatrix(date) { + private var mutableNumbers = super.numbers + + override val numbers: ByteArray + get() = mutableNumbers + + +} diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/entities/Psychomatrix.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/entities/Psychomatrix.kt index 2a9dc31..4d7adfd 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/entities/Psychomatrix.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/entities/Psychomatrix.kt @@ -10,8 +10,8 @@ private fun Int.toDigits(): List { return "$this".map { "$it".toByte() } } -class Psychomatrix(val date: DateTime) { - private val numbers: ByteArray = ByteArray(10) +open class Psychomatrix(val date: DateTime) { + protected open val numbers: ByteArray = ByteArray(10) /** * Always array 4*4 of values. In rows was put columns ( diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/entities/operations/Operation.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/entities/operations/Operation.kt new file mode 100644 index 0000000..d4c767f --- /dev/null +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/entities/operations/Operation.kt @@ -0,0 +1,240 @@ +package com.github.insanusmokrassar.PsychomatrixBase.domain.entities.operations + +import java.io.IOException + +private const val oneAsByte: Byte = 1 +private const val twoAsByte: Byte = 2 +private const val fourAsByte: Byte = 4 +private const val fiveAsByte: Byte = 5 +private const val sixAsByte: Byte = 6 +private const val sevenAsByte: Byte = 7 +private const val eightAsByte: Byte = 8 +private const val nineAsByte: Byte = 9 + +class ConverterException: IOException("This converter can't convert input numbers") + +val List.canGrowSimpleWay: Boolean + get() = contains(SixGrowSeven) + +private val operations = listOf( + TwoGrowFour, + FourGrowTwo, + OneGrowEight, + EightGrowOne, + SixGrowSeven, + SevenGrowSix, + FiveGrowNine, + NineGrowFive +) + +suspend fun availableConverts(numbers: MutableList, operations: List): List { + return operations.filter { it.canConvert(numbers, operations) } +} + +suspend fun availableInverts(numbers: MutableList, operations: List): List { + return operations.filter { it.canInvert(numbers, operations) } +} + +sealed class Operation { + abstract suspend fun canConvert(numbers: MutableList, changesHistory: List): Boolean + abstract suspend fun canInvert(numbers: MutableList, changesHistory: List): Boolean + suspend fun convert(numbers: MutableList, changesHistory: MutableList? = null) { + if (changesHistory ?.let { canConvert(numbers, changesHistory) } == true || changesHistory == null) { + doConvert(numbers, changesHistory) + changesHistory ?.add(this) + } + } + + suspend fun invert(numbers: MutableList, changesHistory: MutableList? = null) { + if (changesHistory == null || (changesHistory.contains(this) && canInvert(numbers, changesHistory))) { + doInvert(numbers, changesHistory) + changesHistory ?.remove(this) + } + } + + protected abstract suspend fun doConvert(numbers: MutableList, changesHistory: MutableList?) + protected abstract suspend fun doInvert(numbers: MutableList, changesHistory: MutableList?) +} + +object TwoGrowFour : Operation() { + override suspend fun canConvert(numbers: MutableList, changesHistory: List): Boolean { + return numbers.count { it == twoAsByte } / 2 > changesHistory.count { it == FourGrowTwo } + } + override suspend fun canInvert(numbers: MutableList, changesHistory: List): Boolean { + return numbers.contains(fourAsByte) && changesHistory.contains(this) + } + + override suspend fun doConvert(numbers: MutableList, changesHistory: MutableList?) { + numbers.apply { + remove(twoAsByte) + remove(twoAsByte) + add(fourAsByte) + } + } + + override suspend fun doInvert(numbers: MutableList, changesHistory: MutableList?) { + numbers.apply { + add(twoAsByte) + add(twoAsByte) + remove(fourAsByte) + } + } +} + +object FourGrowTwo : Operation() { + override suspend fun canConvert(numbers: MutableList, changesHistory: List): Boolean { + return numbers.count { it == fourAsByte } > changesHistory.count { it == TwoGrowFour } + } + override suspend fun canInvert(numbers: MutableList, changesHistory: List): Boolean { + return numbers.count { it == twoAsByte } > 1 && changesHistory.contains(this) + } + + override suspend fun doConvert(numbers: MutableList, changesHistory: MutableList?) { + TwoGrowFour.invert(numbers) + } + + override suspend fun doInvert(numbers: MutableList, changesHistory: MutableList?) { + TwoGrowFour.convert(numbers) + } +} + +object EightGrowOne : Operation() { + override suspend fun canConvert(numbers: MutableList, changesHistory: List): Boolean { + return numbers.contains(eightAsByte) + && (TwoGrowFour.canConvert(numbers, changesHistory) || FourGrowTwo.canConvert(numbers, changesHistory)) + } + override suspend fun canInvert(numbers: MutableList, changesHistory: List): Boolean { + return numbers.count { it == oneAsByte } > 1 && changesHistory.contains(this) + } + + override suspend fun doConvert(numbers: MutableList, changesHistory: MutableList?) { + numbers.apply { + if (count { it == twoAsByte} <= 1) { + FourGrowTwo.convert(numbers, changesHistory) + } + remove(twoAsByte) + remove(twoAsByte) + remove(eightAsByte) + add(oneAsByte) + add(oneAsByte) + } + } + + override suspend fun doInvert(numbers: MutableList, changesHistory: MutableList?) { + numbers.apply { + FourGrowTwo.invert(numbers, changesHistory) + add(eightAsByte) + remove(oneAsByte) + remove(oneAsByte) + } + } +} + +object OneGrowEight : Operation() { + override suspend fun canConvert(numbers: MutableList, changesHistory: List): Boolean { + return numbers.count { it == oneAsByte} > 1 + } + override suspend fun canInvert(numbers: MutableList, changesHistory: List): Boolean { + return numbers.contains(eightAsByte) && changesHistory.contains(this) + } + + override suspend fun doConvert(numbers: MutableList, changesHistory: MutableList?) { + EightGrowOne.invert(numbers) + } + + override suspend fun doInvert(numbers: MutableList, changesHistory: MutableList?) { + EightGrowOne.convert(numbers) + } +} + +object SixGrowSeven : Operation() { + override suspend fun canConvert(numbers: MutableList, changesHistory: List): Boolean { + return numbers.contains(sixAsByte) && OneGrowEight.canConvert(numbers, changesHistory) + } + override suspend fun canInvert(numbers: MutableList, changesHistory: List): Boolean { + return numbers.contains(sevenAsByte) && EightGrowOne.canConvert(numbers, changesHistory) && changesHistory.contains(this) + && !changesHistory.contains(FiveGrowNine) && !changesHistory.contains(NineGrowFive) + } + + override suspend fun doConvert(numbers: MutableList, changesHistory: MutableList?) { + numbers.apply { + OneGrowEight.convert(numbers, changesHistory) + remove(sixAsByte) + add(sevenAsByte) + } + } + + override suspend fun doInvert(numbers: MutableList, changesHistory: MutableList?) { + numbers.apply { + OneGrowEight.invert(numbers, changesHistory) + add(sixAsByte) + remove(sevenAsByte) + } + } +} + +object SevenGrowSix : Operation() { + override suspend fun canConvert(numbers: MutableList, changesHistory: List): Boolean { + return numbers.contains(sevenAsByte) && EightGrowOne.canConvert(numbers, changesHistory) + && !changesHistory.contains(FiveGrowNine) && !changesHistory.contains(NineGrowFive) + } + override suspend fun canInvert(numbers: MutableList, changesHistory: List): Boolean { + return numbers.contains(sixAsByte) && OneGrowEight.canConvert(numbers, changesHistory) && changesHistory.contains(this) + } + + override suspend fun doConvert(numbers: MutableList, changesHistory: MutableList?) { + EightGrowOne.convert(numbers, changesHistory) + SixGrowSeven.invert(numbers) + } + + override suspend fun doInvert(numbers: MutableList, changesHistory: MutableList?) { + EightGrowOne.invert(numbers, changesHistory) + SixGrowSeven.convert(numbers) + } +} + +object FiveGrowNine : Operation() { + override suspend fun canConvert(numbers: MutableList, changesHistory: List): Boolean { + return changesHistory.canGrowSimpleWay + && ( + numbers.count { + it == fiveAsByte + } / 2 - (changesHistory.count { it == NineGrowFive }) + ) > changesHistory.count { it == this } + } + + override suspend fun canInvert(numbers: MutableList, changesHistory: List): Boolean { + return changesHistory.contains(this) + } + + override suspend fun doConvert(numbers: MutableList, changesHistory: MutableList?) { + numbers.add(nineAsByte) + } + + override suspend fun doInvert(numbers: MutableList, changesHistory: MutableList?) { + numbers.remove(nineAsByte) + } +} + +object NineGrowFive : Operation() { + override suspend fun canConvert(numbers: MutableList, changesHistory: List): Boolean { + return changesHistory.canGrowSimpleWay + && (numbers.count { it == nineAsByte } - changesHistory.count { it == FiveGrowNine }) > changesHistory.count { it == this } + } + + override suspend fun canInvert(numbers: MutableList, changesHistory: List): Boolean { + return changesHistory.contains(this) + } + + override suspend fun doConvert(numbers: MutableList, changesHistory: MutableList?) { + numbers.add(fiveAsByte) + numbers.add(fiveAsByte) + } + + override suspend fun doInvert(numbers: MutableList, changesHistory: MutableList?) { + numbers.remove(fiveAsByte) + numbers.remove(fiveAsByte) + } +} + +class GrowCustom()