From c0fe1f4ee9155111dd1e754edd28ed838eacf74a Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 15 Mar 2019 10:54:38 +0800 Subject: [PATCH] migrate to gradle --- .gitignore | 4 + build.gradle | 43 +++++ gradle.properties | 10 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 55436 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 +++++++++++++++++ gradlew.bat | 84 ++++++++ pom.xml => old.pom.xml | 0 settings.gradle | 18 ++ .../data/repository/HistoryDatesRepository.kt | 4 +- .../HistoryDatesRepositoryImpl.kt | 16 +- .../CalculatePsychomatrixByDateUseCase.kt | 4 +- .../domain/UseCases/CeilDescriptionUseCase.kt | 2 +- .../UseCases/ModifyPsychomatrixUseCase.kt | 2 +- ...latePsychomatrixByDateUseCaseInteractor.kt | 13 +- .../interactors/CeilDescriptionInteractor.kt | 17 +- .../ModifyPsychomatrixUseCaseInteractor.kt | 14 +- .../presenters/CeilDescriptionPresenter.kt | 2 +- .../presenters/DatePickerPresenter.kt | 2 +- .../CeilDescriptionPresenterImpl.kt | 6 +- .../DatePickerPresenterImpl.kt | 15 +- .../ModifyPsychomatrixPresenterImpl.kt | 2 +- .../presenters/ModifyPsychomatrixPresenter.kt | 2 +- .../CeilDescriptions/CeilInfoResolver.kt | 7 +- .../CeilDescriptions/models/CeilInfoConfig.kt | 2 + .../CeilDescriptions/models/CeilsInfosRoot.kt | 2 + .../utils/extensions/ReceiveChannel.kt | 179 ++++++++++++------ .../PsychomatrixDescriptions.json | 0 .../characteristics/en_US.json | 0 .../characteristics/ru_RU.json | 0 30 files changed, 518 insertions(+), 110 deletions(-) create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat rename pom.xml => old.pom.xml (100%) create mode 100644 settings.gradle rename src/main/{res => resources}/PsychomatrixDescriptions.json (100%) rename src/main/{res => resources}/characteristics/en_US.json (100%) rename src/main/{res => resources}/characteristics/ru_RU.json (100%) diff --git a/.gitignore b/.gitignore index 26c4834..5dc177e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,7 @@ out/* target settings.xml + +.gradle/ +build/ +out/ diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..89f97a9 --- /dev/null +++ b/build.gradle @@ -0,0 +1,43 @@ +project.version = "0.0.1" +project.group = "com.github.insanusmokrassar" + +buildscript { + repositories { + mavenLocal() + jcenter() + mavenCentral() + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" + classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version" + } +} + +apply plugin: 'java-library' +apply plugin: 'kotlin' +apply plugin: 'kotlinx-serialization' + +repositories { + mavenLocal() + jcenter() + mavenCentral() + maven { url "https://kotlin.bintray.com/kotlinx" } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$kotlin_serialisation_runtime_version" + implementation "joda-time:joda-time:$joda_time_version" + + // Use JUnit test framework + testImplementation 'junit:junit:4.12' +} + +compileKotlin { + kotlinOptions { + freeCompilerArgs = [ disableImplicitReflectionSerializerAnnotation ] + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..30d76e6 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,10 @@ +kotlin.code.style=official +kotlin_version=1.3.21 +kotlin_coroutines_version=1.1.1 +kotlin_serialisation_runtime_version=0.10.0 +joda_time_version=2.10.1 +ktor_version=1.1.2 + +gradle_bintray_plugin_version=1.8.4 + +disableImplicitReflectionSerializerAnnotation=-Xexperimental=kotlinx.serialization.ImplicitReflectionSerializer diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..37837ba1c51ad0c3eb8f92637a6b4b98acf97015 GIT binary patch literal 55436 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�M!C3? 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 \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save ( ) { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..e95643d --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pom.xml b/old.pom.xml similarity index 100% rename from pom.xml rename to old.pom.xml diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..09f9ee6 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,18 @@ +/* + * This settings file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * In a single project build this file can be empty or even removed. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user guide at https://docs.gradle.org/3.4.1/userguide/multi_project_builds.html + */ + +/* +// To declare projects as part of a multi-project build use the 'include' method +include 'shared' +include 'api' +include 'services:webservice' +*/ + +rootProject.name = 'PsychomatrixBase' diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/data/repository/HistoryDatesRepository.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/data/repository/HistoryDatesRepository.kt index 06bb863..b2cdc81 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/data/repository/HistoryDatesRepository.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/data/repository/HistoryDatesRepository.kt @@ -1,7 +1,7 @@ package com.github.insanusmokrassar.PsychomatrixBase.data.repository -import kotlinx.coroutines.experimental.Deferred -import kotlinx.coroutines.experimental.channels.ReceiveChannel +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.channels.ReceiveChannel import org.joda.time.DateTime interface HistoryDatesRepository { diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/data/repository/realisations/HistoryDatesRepositoryImpl.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/data/repository/realisations/HistoryDatesRepositoryImpl.kt index 743aa22..64feb7e 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/data/repository/realisations/HistoryDatesRepositoryImpl.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/data/repository/realisations/HistoryDatesRepositoryImpl.kt @@ -2,21 +2,21 @@ package com.github.insanusmokrassar.PsychomatrixBase.data.repository.realisation import com.github.insanusmokrassar.PsychomatrixBase.data.repository.HistoryDatesRepository import com.github.insanusmokrassar.PsychomatrixBase.domain.UseCases.CalculatePsychomatrixByDateUseCase -import com.github.insanusmokrassar.PsychomatrixBase.utils.extensions.SUBSCRIPTIONS_EXTRA_SMALL import com.github.insanusmokrassar.PsychomatrixBase.utils.extensions.subscribe -import kotlinx.coroutines.experimental.* -import kotlinx.coroutines.experimental.channels.BroadcastChannel -import kotlinx.coroutines.experimental.channels.ReceiveChannel +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.BroadcastChannel +import kotlinx.coroutines.channels.ReceiveChannel import org.joda.time.DateTime abstract class HistoryDatesRepositoryImpl( calculatePsychomatrixByDateUseCase: CalculatePsychomatrixByDateUseCase ) : HistoryDatesRepository { - private val dateAddedBroadcast = BroadcastChannel(SUBSCRIPTIONS_EXTRA_SMALL) - private val dateRemovedBroadcast = BroadcastChannel(SUBSCRIPTIONS_EXTRA_SMALL) + private val scope = CoroutineScope(Dispatchers.Default) + private val dateAddedBroadcast = BroadcastChannel(8) + private val dateRemovedBroadcast = BroadcastChannel(8) init { - launch { + scope.launch { calculatePsychomatrixByDateUseCase.openPsychomatrixCreatedSubscription().subscribe { it.date.also { date -> @@ -41,7 +41,7 @@ abstract class HistoryDatesRepositoryImpl( protected abstract fun onDateCalculated(dateTime: DateTime) override suspend fun removeDate(date: DateTime): Deferred { - return async { + return scope.async { internalRemoveDate(date).also { if (it) { dateRemovedBroadcast.send(date) diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/UseCases/CalculatePsychomatrixByDateUseCase.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/UseCases/CalculatePsychomatrixByDateUseCase.kt index be7f5bc..7dc9693 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/UseCases/CalculatePsychomatrixByDateUseCase.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/UseCases/CalculatePsychomatrixByDateUseCase.kt @@ -1,8 +1,8 @@ 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 kotlinx.coroutines.Deferred +import kotlinx.coroutines.channels.ReceiveChannel import org.joda.time.DateTime import java.util.* diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/UseCases/CeilDescriptionUseCase.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/UseCases/CeilDescriptionUseCase.kt index 352c67d..e1eb018 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/UseCases/CeilDescriptionUseCase.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/UseCases/CeilDescriptionUseCase.kt @@ -2,7 +2,7 @@ package com.github.insanusmokrassar.PsychomatrixBase.domain.UseCases import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.CeilInfo import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.CeilState -import kotlinx.coroutines.experimental.channels.ReceiveChannel +import kotlinx.coroutines.channels.ReceiveChannel typealias CeilDescriptionReady = Pair diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/UseCases/ModifyPsychomatrixUseCase.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/UseCases/ModifyPsychomatrixUseCase.kt index b7d9f2d..2f75164 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/UseCases/ModifyPsychomatrixUseCase.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/UseCases/ModifyPsychomatrixUseCase.kt @@ -3,7 +3,7 @@ package com.github.insanusmokrassar.PsychomatrixBase.domain.UseCases import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.MutablePsychomatrix import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.Psychomatrix import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.operations.Operation -import kotlinx.coroutines.experimental.channels.ReceiveChannel +import kotlinx.coroutines.channels.ReceiveChannel typealias PsychomatrixOperationIsConvert = Pair> diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/interactors/CalculatePsychomatrixByDateUseCaseInteractor.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/interactors/CalculatePsychomatrixByDateUseCaseInteractor.kt index 3c14b89..c16f937 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/interactors/CalculatePsychomatrixByDateUseCaseInteractor.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/interactors/CalculatePsychomatrixByDateUseCaseInteractor.kt @@ -2,23 +2,22 @@ package com.github.insanusmokrassar.PsychomatrixBase.domain.interactors import com.github.insanusmokrassar.PsychomatrixBase.domain.UseCases.CalculatePsychomatrixByDateUseCase import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.Psychomatrix -import com.github.insanusmokrassar.PsychomatrixBase.utils.extensions.SUBSCRIPTIONS_MEDIUM -import kotlinx.coroutines.experimental.Deferred -import kotlinx.coroutines.experimental.async -import kotlinx.coroutines.experimental.channels.BroadcastChannel -import kotlinx.coroutines.experimental.channels.ReceiveChannel +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.BroadcastChannel +import kotlinx.coroutines.channels.ReceiveChannel import org.joda.time.DateTime import java.util.* class CalculatePsychomatrixByDateUseCaseInteractor : CalculatePsychomatrixByDateUseCase { - private val psychomatrixCreatedBroadcast = BroadcastChannel(SUBSCRIPTIONS_MEDIUM) + private val scope = CoroutineScope(Dispatchers.Default) + private val psychomatrixCreatedBroadcast = BroadcastChannel(16) override suspend fun calculate(date: Long): Deferred { return calculate(DateTime(date)) } override suspend fun calculate(date: DateTime): Deferred { - return async { + return scope.async { Psychomatrix(date).also { psychomatrixCreatedBroadcast.send(it) } diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/interactors/CeilDescriptionInteractor.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/interactors/CeilDescriptionInteractor.kt index 678964f..379c1fd 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/interactors/CeilDescriptionInteractor.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/interactors/CeilDescriptionInteractor.kt @@ -4,18 +4,17 @@ import com.github.insanusmokrassar.PsychomatrixBase.domain.UseCases.CeilDescript import com.github.insanusmokrassar.PsychomatrixBase.domain.UseCases.CeilDescriptionUseCase import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.CeilInfo import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.CeilState -import com.github.insanusmokrassar.PsychomatrixBase.utils.extensions.SUBSCRIPTIONS_EXTRA_SMALL -import com.github.insanusmokrassar.PsychomatrixBase.utils.extensions.SUBSCRIPTIONS_SMALL -import kotlinx.coroutines.experimental.channels.BroadcastChannel -import kotlinx.coroutines.experimental.channels.ReceiveChannel -import kotlinx.coroutines.experimental.launch +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.BroadcastChannel +import kotlinx.coroutines.channels.ReceiveChannel class CeilDescriptionInteractor : CeilDescriptionUseCase { + private val scope = CoroutineScope(Dispatchers.Default) private val ceilDescriptionReadyBroadcastChannel = BroadcastChannel( - SUBSCRIPTIONS_SMALL + 16 ) private val ceilDescriptionRequestedBroadcastChannel = BroadcastChannel( - SUBSCRIPTIONS_EXTRA_SMALL + 8 ) override fun openCeilDescriptionReadySubscription(): ReceiveChannel { @@ -27,13 +26,13 @@ class CeilDescriptionInteractor : CeilDescriptionUseCase { } override fun descriptionReady(ceilState: CeilState, ceilInfo: CeilInfo) { - launch { + scope.launch { ceilDescriptionReadyBroadcastChannel.send(ceilState to ceilInfo) } } override fun requestDescription(ceilState: CeilState) { - launch { + scope.launch { ceilDescriptionRequestedBroadcastChannel.send( ceilState ) diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/interactors/ModifyPsychomatrixUseCaseInteractor.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/interactors/ModifyPsychomatrixUseCaseInteractor.kt index 0b9e871..18b0c7f 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/interactors/ModifyPsychomatrixUseCaseInteractor.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/domain/interactors/ModifyPsychomatrixUseCaseInteractor.kt @@ -5,15 +5,15 @@ import com.github.insanusmokrassar.PsychomatrixBase.domain.UseCases.Psychomatrix import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.MutablePsychomatrix import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.Psychomatrix import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.operations.Operation -import com.github.insanusmokrassar.PsychomatrixBase.utils.extensions.SUBSCRIPTIONS_MEDIUM -import kotlinx.coroutines.experimental.channels.BroadcastChannel -import kotlinx.coroutines.experimental.channels.ReceiveChannel -import kotlinx.coroutines.experimental.launch +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.BroadcastChannel +import kotlinx.coroutines.channels.ReceiveChannel class ModifyPsychomatrixUseCaseInteractor : ModifyPsychomatrixUseCase { + private val scope = CoroutineScope(Dispatchers.Default) private val currentPsychomatrixes: MutableList = ArrayList() - private val psychomatrixChangedBroadcastChannel = BroadcastChannel(SUBSCRIPTIONS_MEDIUM) + private val psychomatrixChangedBroadcastChannel = BroadcastChannel(16) override fun openPsychomatrixChangedSubscription(): ReceiveChannel { return psychomatrixChangedBroadcastChannel.openSubscription() @@ -22,7 +22,7 @@ class ModifyPsychomatrixUseCaseInteractor : ModifyPsychomatrixUseCase { override fun makeConvert(psychomatrix: MutablePsychomatrix, operation: Operation): Boolean { return asMutablePsychomatrix(psychomatrix).applyConvert(operation).also { if (it) { - launch { + scope.launch { psychomatrixChangedBroadcastChannel.send(psychomatrix to (operation to true)) } } @@ -31,7 +31,7 @@ class ModifyPsychomatrixUseCaseInteractor : ModifyPsychomatrixUseCase { override fun makeInvert(psychomatrix: MutablePsychomatrix, operation: Operation): Boolean { return asMutablePsychomatrix(psychomatrix).applyInvert(operation).also { - launch { + scope.launch { psychomatrixChangedBroadcastChannel.send(psychomatrix to (operation to false)) } } diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/CeilDescriptionPresenter.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/CeilDescriptionPresenter.kt index b17ab22..179e1ad 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/CeilDescriptionPresenter.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/CeilDescriptionPresenter.kt @@ -2,7 +2,7 @@ package com.github.insanusmokrassar.PsychomatrixBase.presentation.presenters import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.CeilInfo import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.CeilState -import kotlinx.coroutines.experimental.Deferred +import kotlinx.coroutines.Deferred interface CeilDescriptionPresenter { fun onUserChooseCeil(ceilState: CeilState): Deferred diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DatePickerPresenter.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DatePickerPresenter.kt index 9ff49e6..5e04e2b 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DatePickerPresenter.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DatePickerPresenter.kt @@ -1,7 +1,7 @@ package com.github.insanusmokrassar.PsychomatrixBase.presentation.presenters import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.Psychomatrix -import kotlinx.coroutines.experimental.channels.ReceiveChannel +import kotlinx.coroutines.channels.ReceiveChannel import org.joda.time.DateTime interface DatePickerPresenter { diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DefaultRealisations/CeilDescriptionPresenterImpl.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DefaultRealisations/CeilDescriptionPresenterImpl.kt index 960c150..c56d4a5 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DefaultRealisations/CeilDescriptionPresenterImpl.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DefaultRealisations/CeilDescriptionPresenterImpl.kt @@ -6,13 +6,15 @@ import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.CeilState import com.github.insanusmokrassar.PsychomatrixBase.presentation.presenters.CeilDescriptionPresenter import com.github.insanusmokrassar.PsychomatrixBase.utils.Container import com.github.insanusmokrassar.PsychomatrixBase.utils.extensions.subscribeChecking -import kotlinx.coroutines.experimental.* +import kotlinx.coroutines.* class CeilDescriptionPresenterImpl( private val ceilDescriptionUseCase: CeilDescriptionUseCase ) : CeilDescriptionPresenter { + private val scope = CoroutineScope(Dispatchers.Default) + override fun onUserChooseCeil(ceilState: CeilState): Deferred { - return async { + return scope.async { val container = Container() val subscription = ceilDescriptionUseCase.openCeilDescriptionReadySubscription().subscribeChecking( { diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DefaultRealisations/DatePickerPresenterImpl.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DefaultRealisations/DatePickerPresenterImpl.kt index e564115..7e9b306 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DefaultRealisations/DatePickerPresenterImpl.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DefaultRealisations/DatePickerPresenterImpl.kt @@ -3,16 +3,17 @@ package com.github.insanusmokrassar.PsychomatrixBase.presentation.presenters.Def import com.github.insanusmokrassar.PsychomatrixBase.domain.UseCases.CalculatePsychomatrixByDateUseCase import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.Psychomatrix import com.github.insanusmokrassar.PsychomatrixBase.presentation.presenters.DatePickerPresenter -import com.github.insanusmokrassar.PsychomatrixBase.utils.extensions.SUBSCRIPTIONS_MEDIUM -import kotlinx.coroutines.experimental.channels.BroadcastChannel -import kotlinx.coroutines.experimental.channels.ReceiveChannel -import kotlinx.coroutines.experimental.launch +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.BroadcastChannel +import kotlinx.coroutines.channels.ReceiveChannel import org.joda.time.DateTime class DatePickerPresenterImpl( - private val CalculatePsychomatrixByDateUseCase: CalculatePsychomatrixByDateUseCase + private val CalculatePsychomatrixByDateUseCase: CalculatePsychomatrixByDateUseCase, + broadcastChannelCapacity: Int = 4 ) : DatePickerPresenter { - private val psychomatrixCreateBroadcastChannel = BroadcastChannel(SUBSCRIPTIONS_MEDIUM) + private val scope = CoroutineScope(Dispatchers.Default) + private val psychomatrixCreateBroadcastChannel = BroadcastChannel(broadcastChannelCapacity) override suspend fun openPsychomatrixCreatedSubscription(): ReceiveChannel { return psychomatrixCreateBroadcastChannel.openSubscription() @@ -23,7 +24,7 @@ class DatePickerPresenterImpl( } override fun userPickDate(date: DateTime) { - launch { + scope.launch { CalculatePsychomatrixByDateUseCase.calculate(date).await().also { psychomatrixCreateBroadcastChannel.send(it) } diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DefaultRealisations/ModifyPsychomatrixPresenterImpl.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DefaultRealisations/ModifyPsychomatrixPresenterImpl.kt index 6c4211e..42a94f4 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DefaultRealisations/ModifyPsychomatrixPresenterImpl.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/DefaultRealisations/ModifyPsychomatrixPresenterImpl.kt @@ -6,7 +6,7 @@ import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.MutablePsych import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.Psychomatrix import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.operations.Operation import com.github.insanusmokrassar.PsychomatrixBase.presentation.presenters.ModifyPsychomatrixPresenter -import kotlinx.coroutines.experimental.channels.ReceiveChannel +import kotlinx.coroutines.channels.ReceiveChannel class ModifyPsychomatrixPresenterImpl( private val modifyPsychomatrixUseCase: ModifyPsychomatrixUseCase diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/ModifyPsychomatrixPresenter.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/ModifyPsychomatrixPresenter.kt index 62fb555..5419be1 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/ModifyPsychomatrixPresenter.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/presentation/presenters/ModifyPsychomatrixPresenter.kt @@ -4,7 +4,7 @@ import com.github.insanusmokrassar.PsychomatrixBase.domain.UseCases.Psychomatrix import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.MutablePsychomatrix import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.Psychomatrix import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.operations.Operation -import kotlinx.coroutines.experimental.channels.ReceiveChannel +import kotlinx.coroutines.channels.ReceiveChannel interface ModifyPsychomatrixPresenter { diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/CeilDescriptions/CeilInfoResolver.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/CeilDescriptions/CeilInfoResolver.kt index 44c2438..c20e2b0 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/CeilDescriptions/CeilInfoResolver.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/CeilDescriptions/CeilInfoResolver.kt @@ -2,14 +2,11 @@ package com.github.insanusmokrassar.PsychomatrixBase.utils.CeilDescriptions import com.github.insanusmokrassar.PsychomatrixBase.utils.CeilDescriptions.models.CeilsInfosRoot import com.github.insanusmokrassar.PsychomatrixBase.utils.FilesLoader.load -import com.google.gson.Gson -import com.google.gson.GsonBuilder +import kotlinx.serialization.json.Json import java.io.InputStreamReader const val characteristicsFolder = "characteristics" -private val gson: Gson = GsonBuilder().create() - val availableTranslations = listOf( "en_US", "ru_RU" @@ -30,6 +27,6 @@ private fun findSubTranslation(language: String): String { fun resolveCeilsDescriptionsByLanguage(language: String = "en_US"): CeilsInfosRoot { return load("$characteristicsFolder/${findSubTranslation(language)}.json").let { - gson.fromJson(InputStreamReader(it), CeilsInfosRoot::class.java) + Json.nonstrict.parse(CeilsInfosRoot.serializer(), InputStreamReader(it).readText()) } } diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/CeilDescriptions/models/CeilInfoConfig.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/CeilDescriptions/models/CeilInfoConfig.kt index 354d2c6..8fb7775 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/CeilDescriptions/models/CeilInfoConfig.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/CeilDescriptions/models/CeilInfoConfig.kt @@ -1,7 +1,9 @@ package com.github.insanusmokrassar.PsychomatrixBase.utils.CeilDescriptions.models import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.CeilInfo +import kotlinx.serialization.Serializable +@Serializable data class CeilInfoConfig( val title: String = "", val description: String = "", diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/CeilDescriptions/models/CeilsInfosRoot.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/CeilDescriptions/models/CeilsInfosRoot.kt index e1babb5..0968a55 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/CeilDescriptions/models/CeilsInfosRoot.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/CeilDescriptions/models/CeilsInfosRoot.kt @@ -2,7 +2,9 @@ package com.github.insanusmokrassar.PsychomatrixBase.utils.CeilDescriptions.mode import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.CeilInfo import com.github.insanusmokrassar.PsychomatrixBase.domain.entities.CeilState +import kotlinx.serialization.Serializable +@Serializable data class CeilsInfosRoot( val language: String? = "en_US", private val descriptionsList: List> = emptyList() diff --git a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/extensions/ReceiveChannel.kt b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/extensions/ReceiveChannel.kt index a4aa951..f0cd065 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/extensions/ReceiveChannel.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/PsychomatrixBase/utils/extensions/ReceiveChannel.kt @@ -1,44 +1,128 @@ package com.github.insanusmokrassar.PsychomatrixBase.utils.extensions -import kotlinx.coroutines.experimental.* -import kotlinx.coroutines.experimental.channels.BroadcastChannel -import kotlinx.coroutines.experimental.channels.ReceiveChannel +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.* import java.util.concurrent.TimeUnit -const val SUBSCRIPTIONS_LARGE = 256 -const val SUBSCRIPTIONS_MEDIUM = 128 -const val SUBSCRIPTIONS_SMALL = 64 -const val SUBSCRIPTIONS_EXTRA_SMALL = 32 -const val SUBSCRIPTIONS_SINGLE = 1 +private sealed class DebounceAction { + abstract val value: T +} + +private data class AddValue(override val value: T) : DebounceAction() +private data class RemoveJob(override val value: T, val job: Job) : DebounceAction() + +fun ReceiveChannel.debounceByValue( + delayMillis: Long, + scope: CoroutineScope = CoroutineScope(Dispatchers.Default), + resultBroadcastChannelCapacity: Int = 32 +): ReceiveChannel { + val outChannel = Channel(resultBroadcastChannelCapacity) + val values = HashMap() + + val channel = Channel>(Channel.UNLIMITED) + scope.launch { + for (action in channel) { + when (action) { + is AddValue -> { + val msg = action.value + values[msg] ?.cancel() + lateinit var job: Job + job = launch { + delay(delayMillis) + + outChannel.send(msg) + channel.send(RemoveJob(msg, job)) + } + values[msg] = job + } + is RemoveJob -> if (values[action.value] == action.job) { + values.remove(action.value) + } + } + + } + } + + scope.launch { + for (msg in this@debounceByValue) { + channel.send(AddValue(msg)) + } + } + + return outChannel +} + +typealias AccumulatedValues = Pair> + +fun ReceiveChannel>.accumulateByKey( + delayMillis: Long, + scope: CoroutineScope = CoroutineScope(Dispatchers.Default), + resultBroadcastChannelCapacity: Int = 32 +): ReceiveChannel> { + val outChannel = Channel>(resultBroadcastChannelCapacity) + val values = HashMap>() + val jobs = HashMap() + + val channel = Channel>>(Channel.UNLIMITED) + scope.launch { + for (action in channel) { + val (key, value) = action.value + when (action) { + is AddValue -> { + jobs[key] ?.cancel() + (values[key] ?: mutableListOf().also { values[key] = it }).add(value) + lateinit var job: Job + job = launch { + delay(delayMillis) + + values[key] ?.let { + outChannel.send(key to it) + channel.send(RemoveJob(key to value, job)) + } + } + jobs[key] = job + } + is RemoveJob -> if (values[key] == action.job) { + values.remove(key) + jobs.remove(key) + } + } + + } + } + + scope.launch { + for (msg in this@accumulateByKey) { + channel.send(AddValue(msg)) + } + } + + return outChannel +} fun ReceiveChannel.subscribeChecking( throwableHandler: (Throwable) -> Boolean = { it.printStackTrace() true }, + scope: CoroutineScope = CoroutineScope(Dispatchers.Default), 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() - } + val channel = this + return scope.launch { + for (data in channel) { + launch { + try { + if (!by(data)) { + channel.cancel() + } + } catch (e: Throwable) { + if (!throwableHandler(e)) { + channel.cancel() } } - } catch (e: CancellationException) { - break } } - cancel() } } @@ -47,45 +131,30 @@ fun ReceiveChannel.subscribe( it.printStackTrace() true }, + scope: CoroutineScope = CoroutineScope(Dispatchers.Default), by: suspend (T) -> Unit ): Job { - return subscribeChecking(throwableHandler) { + return subscribeChecking(throwableHandler, scope) { by(it) true } } -fun ReceiveChannel.debounce(delayMs: Long, awaitedSubscriptions: Int = 256): BroadcastChannel { - val channel = BroadcastChannel(awaitedSubscriptions) - var lastReceived: Pair? = null - var job: Job? = null - launch { - while (isActive && !isClosedForReceive) { - val received = receive() +fun ReceiveChannel.debounce( + delay: Long, + timeUnit: TimeUnit = TimeUnit.MILLISECONDS, + scope: CoroutineScope = CoroutineScope(Dispatchers.Default), + resultBroadcastChannelCapacity: Int = 1 +): BroadcastChannel { + return BroadcastChannel(resultBroadcastChannelCapacity).also { outBroadcast -> + var lastReceived: Job? = null + subscribe(scope = scope) { + lastReceived ?.cancel() + lastReceived = scope.launch { + delay(timeUnit.toMillis(delay)) - 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 - } - } + outBroadcast.send(it) } } - cancel() } - return channel } diff --git a/src/main/res/PsychomatrixDescriptions.json b/src/main/resources/PsychomatrixDescriptions.json similarity index 100% rename from src/main/res/PsychomatrixDescriptions.json rename to src/main/resources/PsychomatrixDescriptions.json diff --git a/src/main/res/characteristics/en_US.json b/src/main/resources/characteristics/en_US.json similarity index 100% rename from src/main/res/characteristics/en_US.json rename to src/main/resources/characteristics/en_US.json diff --git a/src/main/res/characteristics/ru_RU.json b/src/main/resources/characteristics/ru_RU.json similarity index 100% rename from src/main/res/characteristics/ru_RU.json rename to src/main/resources/characteristics/ru_RU.json