migrate out of app module
|
@ -90,18 +90,10 @@
|
||||||
android:name=".activities.TreatmentsActivity"
|
android:name=".activities.TreatmentsActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:theme="@style/AppTheme" />
|
android:theme="@style/AppTheme" />
|
||||||
<activity
|
|
||||||
android:name=".activities.SurveyActivity"
|
|
||||||
android:exported="false"
|
|
||||||
android:theme="@style/AppTheme" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.ProfileHelperActivity"
|
android:name=".activities.ProfileHelperActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:theme="@style/AppTheme" />
|
android:theme="@style/AppTheme" />
|
||||||
<activity
|
|
||||||
android:name=".activities.StatsActivity"
|
|
||||||
android:exported="false"
|
|
||||||
android:theme="@style/AppTheme" />
|
|
||||||
|
|
||||||
<!-- Receive new BG readings from other local apps -->
|
<!-- Receive new BG readings from other local apps -->
|
||||||
<receiver
|
<receiver
|
||||||
|
@ -212,7 +204,7 @@
|
||||||
android:name=".plugins.general.maintenance.activities.LogSettingActivity"
|
android:name=".plugins.general.maintenance.activities.LogSettingActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.RequestDexcomPermissionActivity"
|
android:name=".plugins.source.activities.RequestDexcomPermissionActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<uses-library
|
<uses-library
|
||||||
|
|
|
@ -30,7 +30,12 @@ import com.google.android.material.tabs.TabLayoutMediator
|
||||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import com.joanzapata.iconify.Iconify
|
import com.joanzapata.iconify.Iconify
|
||||||
import com.joanzapata.iconify.fonts.FontAwesomeModule
|
import com.joanzapata.iconify.fonts.FontAwesomeModule
|
||||||
import info.nightscout.androidaps.activities.*
|
import info.nightscout.androidaps.activities.HistoryBrowseActivity
|
||||||
|
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
|
||||||
|
import info.nightscout.androidaps.activities.PreferencesActivity
|
||||||
|
import info.nightscout.androidaps.activities.ProfileHelperActivity
|
||||||
|
import info.nightscout.androidaps.activities.SingleFragmentActivity
|
||||||
|
import info.nightscout.androidaps.activities.TreatmentsActivity
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
||||||
import info.nightscout.androidaps.databinding.ActivityMainBinding
|
import info.nightscout.androidaps.databinding.ActivityMainBinding
|
||||||
|
@ -38,9 +43,17 @@ import info.nightscout.androidaps.events.EventAppExit
|
||||||
import info.nightscout.androidaps.events.EventInitializationChanged
|
import info.nightscout.androidaps.events.EventInitializationChanged
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||||
import info.nightscout.androidaps.events.EventRebuildTabs
|
import info.nightscout.androidaps.events.EventRebuildTabs
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.interfaces.AndroidPermission
|
||||||
|
import info.nightscout.androidaps.interfaces.BuildHelper
|
||||||
|
import info.nightscout.androidaps.interfaces.Config
|
||||||
import info.nightscout.androidaps.interfaces.Constraints
|
import info.nightscout.androidaps.interfaces.Constraints
|
||||||
|
import info.nightscout.androidaps.interfaces.IconsProvider
|
||||||
|
import info.nightscout.androidaps.interfaces.Loop
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginBase
|
||||||
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
|
import info.nightscout.androidaps.interfaces.SmsCommunicator
|
||||||
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin
|
import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin
|
||||||
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
|
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
|
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
|
||||||
|
@ -56,9 +69,10 @@ import info.nightscout.androidaps.utils.tabs.TabPageAdapter
|
||||||
import info.nightscout.androidaps.utils.ui.UIRunnable
|
import info.nightscout.androidaps.utils.ui.UIRunnable
|
||||||
import info.nightscout.shared.logging.LTag
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.ui.activities.StatsActivity
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import java.util.*
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
|
|
@ -41,13 +41,13 @@ import info.nightscout.androidaps.receivers.KeepAliveWorker
|
||||||
import info.nightscout.androidaps.receivers.NetworkChangeReceiver
|
import info.nightscout.androidaps.receivers.NetworkChangeReceiver
|
||||||
import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver
|
import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver
|
||||||
import info.nightscout.androidaps.services.AlarmSoundServiceHelper
|
import info.nightscout.androidaps.services.AlarmSoundServiceHelper
|
||||||
import info.nightscout.androidaps.utils.ActivityMonitor
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.ProcessLifecycleListener
|
import info.nightscout.androidaps.utils.ProcessLifecycleListener
|
||||||
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.logging.LTag
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.ui.utils.ActivityMonitor
|
||||||
import info.nightscout.ui.widget.Widget
|
import info.nightscout.ui.widget.Widget
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.exceptions.UndeliverableException
|
import io.reactivex.rxjava3.exceptions.UndeliverableException
|
||||||
|
@ -55,7 +55,6 @@ import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import io.reactivex.rxjava3.plugins.RxJavaPlugins
|
import io.reactivex.rxjava3.plugins.RxJavaPlugins
|
||||||
import rxdogtag2.RxDogTag
|
import rxdogtag2.RxDogTag
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.net.SocketException
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Provider
|
import javax.inject.Provider
|
||||||
|
@ -76,7 +75,7 @@ class MainApp : DaggerApplication() {
|
||||||
@Inject lateinit var compatDBHelper: CompatDBHelper
|
@Inject lateinit var compatDBHelper: CompatDBHelper
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
@Inject lateinit var dateUtil: DateUtil
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
@Inject lateinit var staticInjector: StaticInjector// TODO avoid , here fake only to initialize
|
@Suppress("unused") @Inject lateinit var staticInjector: StaticInjector// TODO avoid , here fake only to initialize
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
@Inject lateinit var alarmSoundServiceHelper: AlarmSoundServiceHelper
|
@Inject lateinit var alarmSoundServiceHelper: AlarmSoundServiceHelper
|
||||||
@Inject lateinit var notificationStore: NotificationStore
|
@Inject lateinit var notificationStore: NotificationStore
|
||||||
|
@ -166,7 +165,7 @@ class MainApp : DaggerApplication() {
|
||||||
if (e is UndeliverableException) {
|
if (e is UndeliverableException) {
|
||||||
e = e.cause!!
|
e = e.cause!!
|
||||||
}
|
}
|
||||||
if (e is IOException || e is SocketException) {
|
if (e is IOException) {
|
||||||
// fine, irrelevant network problem or API that throws on cancellation
|
// fine, irrelevant network problem or API that throws on cancellation
|
||||||
return@setErrorHandler
|
return@setErrorHandler
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,10 @@ import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.utils.ToastUtils
|
import info.nightscout.androidaps.utils.ToastUtils
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
import info.nightscout.androidaps.utils.defaultProfile.DefaultProfile
|
import info.nightscout.ui.defaultProfile.DefaultProfile
|
||||||
import info.nightscout.androidaps.utils.defaultProfile.DefaultProfileDPV
|
import info.nightscout.ui.defaultProfile.DefaultProfileDPV
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.androidaps.utils.stats.TddCalculator
|
import info.nightscout.androidaps.interfaces.stats.TddCalculator
|
||||||
import io.reactivex.rxjava3.core.Single
|
import io.reactivex.rxjava3.core.Single
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
|
@ -183,25 +183,25 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
||||||
for (i in 0..1) {
|
for (i in 0..1) {
|
||||||
if (typeSelected[i] == ProfileType.MOTOL_DEFAULT) {
|
if (typeSelected[i] == ProfileType.MOTOL_DEFAULT) {
|
||||||
if (ageUsed[i] < 1 || ageUsed[i] > 18) {
|
if (ageUsed[i] < 1 || ageUsed[i] > 18) {
|
||||||
ToastUtils.warnToast(this, R.string.invalidage)
|
ToastUtils.warnToast(this, R.string.invalid_age)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
if ((weightUsed[i] < 5 || weightUsed[i] > 150) && tddUsed[i] == 0.0) {
|
if ((weightUsed[i] < 5 || weightUsed[i] > 150) && tddUsed[i] == 0.0) {
|
||||||
ToastUtils.warnToast(this, R.string.invalidweight)
|
ToastUtils.warnToast(this, R.string.invalid_weight)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
if ((tddUsed[i] < 5 || tddUsed[i] > 150) && weightUsed[i] == 0.0) {
|
if ((tddUsed[i] < 5 || tddUsed[i] > 150) && weightUsed[i] == 0.0) {
|
||||||
ToastUtils.warnToast(this, R.string.invalidweight)
|
ToastUtils.warnToast(this, R.string.invalid_weight)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeSelected[i] == ProfileType.DPV_DEFAULT) {
|
if (typeSelected[i] == ProfileType.DPV_DEFAULT) {
|
||||||
if (ageUsed[i] < 1 || ageUsed[i] > 18) {
|
if (ageUsed[i] < 1 || ageUsed[i] > 18) {
|
||||||
ToastUtils.warnToast(this, R.string.invalidage)
|
ToastUtils.warnToast(this, R.string.invalid_age)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
if (tddUsed[i] < 5 || tddUsed[i] > 150) {
|
if (tddUsed[i] < 5 || tddUsed[i] > 150) {
|
||||||
ToastUtils.warnToast(this, R.string.invalidweight)
|
ToastUtils.warnToast(this, R.string.invalid_weight)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
if ((pctUsed[i] < 32 || pctUsed[i] > 37)) {
|
if ((pctUsed[i] < 32 || pctUsed[i] > 37)) {
|
||||||
|
|
|
@ -3,10 +3,14 @@ package info.nightscout.androidaps.di
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.android.ContributesAndroidInjector
|
import dagger.android.ContributesAndroidInjector
|
||||||
import info.nightscout.androidaps.MainActivity
|
import info.nightscout.androidaps.MainActivity
|
||||||
import info.nightscout.androidaps.activities.*
|
|
||||||
import info.nightscout.androidaps.activities.HistoryBrowseActivity
|
import info.nightscout.androidaps.activities.HistoryBrowseActivity
|
||||||
|
import info.nightscout.androidaps.activities.PreferencesActivity
|
||||||
|
import info.nightscout.androidaps.activities.ProfileHelperActivity
|
||||||
|
import info.nightscout.androidaps.activities.SingleFragmentActivity
|
||||||
|
import info.nightscout.androidaps.activities.TreatmentsActivity
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity
|
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity
|
||||||
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity
|
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity
|
||||||
|
import info.nightscout.androidaps.plugins.source.activities.RequestDexcomPermissionActivity
|
||||||
import info.nightscout.androidaps.setupwizard.SetupWizardActivity
|
import info.nightscout.androidaps.setupwizard.SetupWizardActivity
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
|
@ -22,8 +26,6 @@ abstract class ActivitiesModule {
|
||||||
@ContributesAndroidInjector abstract fun contributesRequestDexcomPermissionActivity(): RequestDexcomPermissionActivity
|
@ContributesAndroidInjector abstract fun contributesRequestDexcomPermissionActivity(): RequestDexcomPermissionActivity
|
||||||
@ContributesAndroidInjector abstract fun contributesSetupWizardActivity(): SetupWizardActivity
|
@ContributesAndroidInjector abstract fun contributesSetupWizardActivity(): SetupWizardActivity
|
||||||
@ContributesAndroidInjector abstract fun contributesSingleFragmentActivity(): SingleFragmentActivity
|
@ContributesAndroidInjector abstract fun contributesSingleFragmentActivity(): SingleFragmentActivity
|
||||||
@ContributesAndroidInjector abstract fun contributesStatsActivity(): StatsActivity
|
|
||||||
@ContributesAndroidInjector abstract fun contributesSurveyActivity(): SurveyActivity
|
|
||||||
@ContributesAndroidInjector abstract fun contributesDefaultProfileActivity(): ProfileHelperActivity
|
@ContributesAndroidInjector abstract fun contributesDefaultProfileActivity(): ProfileHelperActivity
|
||||||
|
|
||||||
}
|
}
|
|
@ -34,6 +34,9 @@ import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||||
import info.nightscout.androidaps.interfaces.SmsCommunicator
|
import info.nightscout.androidaps.interfaces.SmsCommunicator
|
||||||
import info.nightscout.androidaps.interfaces.TrendCalculator
|
import info.nightscout.androidaps.interfaces.TrendCalculator
|
||||||
import info.nightscout.androidaps.interfaces.XDripBroadcast
|
import info.nightscout.androidaps.interfaces.XDripBroadcast
|
||||||
|
import info.nightscout.androidaps.interfaces.stats.DexcomTirCalculator
|
||||||
|
import info.nightscout.androidaps.interfaces.stats.TddCalculator
|
||||||
|
import info.nightscout.androidaps.interfaces.stats.TirCalculator
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||||
|
@ -65,24 +68,31 @@ import info.nightscout.implementation.TrendCalculatorImpl
|
||||||
import info.nightscout.implementation.XDripBroadcastImpl
|
import info.nightscout.implementation.XDripBroadcastImpl
|
||||||
import info.nightscout.implementation.constraints.ConstraintsImpl
|
import info.nightscout.implementation.constraints.ConstraintsImpl
|
||||||
import info.nightscout.implementation.queue.CommandQueueImplementation
|
import info.nightscout.implementation.queue.CommandQueueImplementation
|
||||||
|
import info.nightscout.implementation.stats.DexcomTirCalculatorImpl
|
||||||
|
import info.nightscout.implementation.stats.TddCalculatorImpl
|
||||||
|
import info.nightscout.implementation.stats.TirCalculatorImpl
|
||||||
import info.nightscout.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
import info.nightscout.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@Module(includes = [
|
@Module(
|
||||||
AppModule.AppBindings::class
|
includes = [
|
||||||
])
|
AppModule.AppBindings::class
|
||||||
|
]
|
||||||
|
)
|
||||||
open class AppModule {
|
open class AppModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
fun providesPlugins(config: Config, buildHelper: BuildHelper,
|
fun providesPlugins(
|
||||||
@PluginsModule.AllConfigs allConfigs: Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>,
|
config: Config, buildHelper: BuildHelper,
|
||||||
@PluginsModule.PumpDriver pumpDrivers: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
|
@PluginsModule.AllConfigs allConfigs: Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>,
|
||||||
@PluginsModule.NotNSClient notNsClient: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
|
@PluginsModule.PumpDriver pumpDrivers: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
|
||||||
@PluginsModule.APS aps: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
|
@PluginsModule.NotNSClient notNsClient: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
|
||||||
@PluginsModule.Unfinished unfinished: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>)
|
@PluginsModule.APS aps: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
|
||||||
|
@PluginsModule.Unfinished unfinished: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>
|
||||||
|
)
|
||||||
: List<@JvmSuppressWildcards PluginBase> {
|
: List<@JvmSuppressWildcards PluginBase> {
|
||||||
val plugins = allConfigs.toMutableMap()
|
val plugins = allConfigs.toMutableMap()
|
||||||
if (config.PUMPDRIVERS) plugins += pumpDrivers.get()
|
if (config.PUMPDRIVERS) plugins += pumpDrivers.get()
|
||||||
|
@ -120,6 +130,7 @@ open class AppModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
internal fun provideConstraints(activePlugin: ActivePlugin): Constraints = ConstraintsImpl(activePlugin)
|
internal fun provideConstraints(activePlugin: ActivePlugin): Constraints = ConstraintsImpl(activePlugin)
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
interface AppBindings {
|
interface AppBindings {
|
||||||
|
|
||||||
|
@ -146,6 +157,9 @@ open class AppModule {
|
||||||
@Binds fun bindLocalAlertUtilsInterface(localAlertUtils: LocalAlertUtilsImpl): LocalAlertUtils
|
@Binds fun bindLocalAlertUtilsInterface(localAlertUtils: LocalAlertUtilsImpl): LocalAlertUtils
|
||||||
@Binds fun bindActivityNamesInterface(activityNames: ActivityNamesImpl): ActivityNames
|
@Binds fun bindActivityNamesInterface(activityNames: ActivityNamesImpl): ActivityNames
|
||||||
@Binds fun bindTrendCalculatorInterface(trendCalculator: TrendCalculatorImpl): TrendCalculator
|
@Binds fun bindTrendCalculatorInterface(trendCalculator: TrendCalculatorImpl): TrendCalculator
|
||||||
|
@Binds fun bindTddCalculatorInterface(tddCalculator: TddCalculatorImpl): TddCalculator
|
||||||
|
@Binds fun bindTirCalculatorInterface(tirCalculator: TirCalculatorImpl): TirCalculator
|
||||||
|
@Binds fun bindDexcomTirCalculatorInterface(dexcomTirCalculator: DexcomTirCalculatorImpl): DexcomTirCalculator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.Round
|
import info.nightscout.androidaps.utils.Round
|
||||||
import info.nightscout.androidaps.utils.stats.TddCalculator
|
import info.nightscout.androidaps.interfaces.stats.TddCalculator
|
||||||
import info.nightscout.shared.SafeParse
|
import info.nightscout.shared.SafeParse
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.logging.LTag
|
import info.nightscout.shared.logging.LTag
|
||||||
|
|
|
@ -9,7 +9,7 @@ import androidx.work.WorkerParameters
|
||||||
import androidx.work.workDataOf
|
import androidx.work.workDataOf
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.activities.RequestDexcomPermissionActivity
|
import info.nightscout.androidaps.plugins.source.activities.RequestDexcomPermissionActivity
|
||||||
import info.nightscout.androidaps.database.AppRepository
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.database.entities.GlucoseValue
|
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||||
import info.nightscout.androidaps.database.entities.TherapyEvent
|
import info.nightscout.androidaps.database.entities.TherapyEvent
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package info.nightscout.androidaps.activities
|
package info.nightscout.androidaps.plugins.source.activities
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import info.nightscout.androidaps.activities.DialogAppCompatActivity
|
||||||
import info.nightscout.androidaps.plugins.source.DexcomPlugin
|
import info.nightscout.androidaps.plugins.source.DexcomPlugin
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class RequestDexcomPermissionActivity : DialogAppCompatActivity() {
|
class RequestDexcomPermissionActivity : DialogAppCompatActivity() {
|
||||||
@Inject lateinit var dexcomPlugin: DexcomPlugin
|
|
||||||
|
|
||||||
private val requestCode = "AndroidAPS <3".map { it.code }.sum()
|
private val requestCode = "AndroidAPS <3".map { it.code }.sum()
|
||||||
|
|
|
@ -253,7 +253,6 @@
|
||||||
<string name="short_tabtitles">Shorten tab titles</string>
|
<string name="short_tabtitles">Shorten tab titles</string>
|
||||||
<string name="always_use_shortavg">Always use short average delta instead of simple delta</string>
|
<string name="always_use_shortavg">Always use short average delta instead of simple delta</string>
|
||||||
<string name="always_use_shortavg_summary">Useful when data from unfiltered sources like xDrip+ gets noisy.</string>
|
<string name="always_use_shortavg_summary">Useful when data from unfiltered sources like xDrip+ gets noisy.</string>
|
||||||
<string name="profile">Profile</string>
|
|
||||||
<string name="openapsama_max_daily_safety_multiplier_summary">Default value: 3 This is a key OpenAPS safety cap. What this does is limit your basals to be 3x (in this people) your biggest basal rate. You likely will not need to change this, but you should be aware that’s what is discussed about “3x max daily; 4x current” for safety caps.</string>
|
<string name="openapsama_max_daily_safety_multiplier_summary">Default value: 3 This is a key OpenAPS safety cap. What this does is limit your basals to be 3x (in this people) your biggest basal rate. You likely will not need to change this, but you should be aware that’s what is discussed about “3x max daily; 4x current” for safety caps.</string>
|
||||||
<string name="openapsama_current_basal_safety_multiplier_summary">Default value: 4 This is the other half of the key OpenAPS safety caps, and the other half of “3x max daily; 4x current” of the safety caps. This means your basal, regardless of max basal set on your pump, cannot be any higher than this number times the current level of your basal. This is to prevent people from getting into dangerous territory by setting excessively high max basals before understanding how the algorithm works. Again, the default is 4x; most people will never need to adjust this and are instead more likely to need to adjust other settings if they feel like they are “running into” this safety cap.</string>
|
<string name="openapsama_current_basal_safety_multiplier_summary">Default value: 4 This is the other half of the key OpenAPS safety caps, and the other half of “3x max daily; 4x current” of the safety caps. This means your basal, regardless of max basal set on your pump, cannot be any higher than this number times the current level of your basal. This is to prevent people from getting into dangerous territory by setting excessively high max basals before understanding how the algorithm works. Again, the default is 4x; most people will never need to adjust this and are instead more likely to need to adjust other settings if they feel like they are “running into” this safety cap.</string>
|
||||||
<string name="openapsama_autosens_max_summary">Default value: 1.2\nThis is a multiplier cap for autosens (and soon autotune) to set a 20%% max limit on how high the autosens ratio can be, which in turn determines how high autosens can adjust basals, how low it can adjust ISF, and how low it can set the BG target.</string>
|
<string name="openapsama_autosens_max_summary">Default value: 1.2\nThis is a multiplier cap for autosens (and soon autotune) to set a 20%% max limit on how high the autosens ratio can be, which in turn determines how high autosens can adjust basals, how low it can adjust ISF, and how low it can set the BG target.</string>
|
||||||
|
@ -589,7 +588,6 @@
|
||||||
<string name="smbnotallowedinopenloopmode">SMB not allowed in open loop mode</string>
|
<string name="smbnotallowedinopenloopmode">SMB not allowed in open loop mode</string>
|
||||||
<string name="food_short">Food</string>
|
<string name="food_short">Food</string>
|
||||||
<string name="iobcobcalculator" translatable="false">IobCobCalculator</string>
|
<string name="iobcobcalculator" translatable="false">IobCobCalculator</string>
|
||||||
<string name="reset">reset</string>
|
|
||||||
<string name="key_openapssmb_max_iob" translatable="false">openapsmb_max_iob</string>
|
<string name="key_openapssmb_max_iob" translatable="false">openapsmb_max_iob</string>
|
||||||
<string name="openapssmb_maxiob_title">Maximum total IOB OpenAPS can\'t go over [U]</string>
|
<string name="openapssmb_maxiob_title">Maximum total IOB OpenAPS can\'t go over [U]</string>
|
||||||
<string name="openapssmb_maxiob_summary">This value is called Max IOB in OpenAPS context\nOpenAPS will not add more insulin if current IOB is greater than this value</string>
|
<string name="openapssmb_maxiob_summary">This value is called Max IOB in OpenAPS context\nOpenAPS will not add more insulin if current IOB is greater than this value</string>
|
||||||
|
@ -802,25 +800,7 @@
|
||||||
<string name="profilenamecontainsdot">Profile name contains dots.\nThis is not supported by NS.\nProfile is not uploaded to NS.</string>
|
<string name="profilenamecontainsdot">Profile name contains dots.\nThis is not supported by NS.\nProfile is not uploaded to NS.</string>
|
||||||
<string name="low_mark_comment">Lower value of in range area (display only)</string>
|
<string name="low_mark_comment">Lower value of in range area (display only)</string>
|
||||||
<string name="high_mark_comment">Higher value of in range area (display only)</string>
|
<string name="high_mark_comment">Higher value of in range area (display only)</string>
|
||||||
<string name="age">Age</string>
|
|
||||||
<string name="weight_label">Weight</string>
|
|
||||||
<string name="id">ID:</string>
|
|
||||||
<string name="submit">Submit</string>
|
|
||||||
<string name="mostcommonprofile">Most common profile:</string>
|
|
||||||
<string name="survey_comment">Note: Only data visible on this screen will be anonymously uploaded. ID is assigned to this installation of AAPS. You can submit data again if your main profile get changed but let it running at least for a week to make result visible in time in range. Your help is appreciated.</string>
|
|
||||||
<string name="invalidage">Invalid age entry</string>
|
|
||||||
<string name="invalidweight">Invalid weight entry</string>
|
|
||||||
<string name="invalidpct">Invalid % entry</string>
|
<string name="invalidpct">Invalid % entry</string>
|
||||||
<string name="average">Average</string>
|
|
||||||
<string name="tir">TIR</string>
|
|
||||||
<string name="day_tir">Day TIR</string>
|
|
||||||
<string name="night_tir">Night TIR</string>
|
|
||||||
<string name="detailed_14_days">Detailed 14 days</string>
|
|
||||||
<string name="std_deviation">SD: %1$s</string>
|
|
||||||
<string name="hba1c">HbA1c: </string>
|
|
||||||
<string name="activitymonitor">Activity monitor</string>
|
|
||||||
<string name="doyouwantresetstats">Do you want to reset activity stats?</string>
|
|
||||||
<string name="statistics">Statistics</string>
|
|
||||||
<string name="randombg">Random BG</string>
|
<string name="randombg">Random BG</string>
|
||||||
<string name="description_source_randombg">Generate random BG data (Demo mode only)</string>
|
<string name="description_source_randombg">Generate random BG data (Demo mode only)</string>
|
||||||
<string name="randombg_short">BG</string>
|
<string name="randombg_short">BG</string>
|
||||||
|
@ -927,7 +907,6 @@
|
||||||
<string name="key_ns_receive_cgm" translatable="false">ns_receive_cgm</string>
|
<string name="key_ns_receive_cgm" translatable="false">ns_receive_cgm</string>
|
||||||
<string name="ns_receive_cgm">Receive/backfill CGM data</string>
|
<string name="ns_receive_cgm">Receive/backfill CGM data</string>
|
||||||
<string name="ns_receive_cgm_summary">Accept CGM data from NS</string>
|
<string name="ns_receive_cgm_summary">Accept CGM data from NS</string>
|
||||||
<string name="calculation_in_progress">Calculation in progress</string>
|
|
||||||
<string name="missing_profile_name">Missing profile name</string>
|
<string name="missing_profile_name">Missing profile name</string>
|
||||||
<string name="error_in_ic_values">Error in IC values</string>
|
<string name="error_in_ic_values">Error in IC values</string>
|
||||||
<string name="error_in_basal_values">Error in basal values</string>
|
<string name="error_in_basal_values">Error in basal values</string>
|
||||||
|
@ -1023,13 +1002,6 @@
|
||||||
<string name="show_loop">Show loop</string>
|
<string name="show_loop">Show loop</string>
|
||||||
<string name="count_selected">%1$d selected</string>
|
<string name="count_selected">%1$d selected</string>
|
||||||
<string name="sort_label">Sort</string>
|
<string name="sort_label">Sort</string>
|
||||||
<string name="veryLow" comment="below 3.1">Very low</string>
|
|
||||||
<string name="low" comment="3.1-3.9">Low</string>
|
|
||||||
<string name="high" comment="10.0-13.9">High</string>
|
|
||||||
<string name="veryHigh" comment="above 13.9">Very high</string>
|
|
||||||
<string name="below" comment="below "in range"">Below</string>
|
|
||||||
<string name="in_range">In range</string>
|
|
||||||
<string name="above" comment="above "in range"">Above</string>
|
|
||||||
<string name="show_loop_records">Show loop records</string>
|
<string name="show_loop_records">Show loop records</string>
|
||||||
<string name="show_hide_records">Hide loop records</string>
|
<string name="show_hide_records">Hide loop records</string>
|
||||||
<string name="loop_status">Loop status</string>
|
<string name="loop_status">Loop status</string>
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.treatments
|
|
||||||
|
|
||||||
import dagger.android.AndroidInjector
|
|
||||||
import dagger.android.HasAndroidInjector
|
|
||||||
import info.nightscout.androidaps.TestBaseWithProfile
|
|
||||||
import info.nightscout.androidaps.database.AppRepository
|
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
|
||||||
import org.junit.Test
|
|
||||||
import org.mockito.Mock
|
|
||||||
|
|
||||||
@Suppress("SpellCheckingInspection")
|
|
||||||
class TreatmentsPluginTest : TestBaseWithProfile() {
|
|
||||||
|
|
||||||
@Mock lateinit var sp: SP
|
|
||||||
@Mock lateinit var repository: AppRepository
|
|
||||||
|
|
||||||
val injector = HasAndroidInjector {
|
|
||||||
AndroidInjector {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test fun dummy() {}
|
|
||||||
/*
|
|
||||||
private lateinit var insulinOrefRapidActingPlugin: InsulinOrefRapidActingPlugin
|
|
||||||
private lateinit var sot: TreatmentsPlugin
|
|
||||||
|
|
||||||
@Before
|
|
||||||
fun prepare() {
|
|
||||||
insulinOrefRapidActingPlugin = InsulinOrefRapidActingPlugin(profileInjector, rh, profileFunction, rxBus, aapsLogger)
|
|
||||||
|
|
||||||
`when`(profileFunction.getProfile(ArgumentMatchers.anyLong())).thenReturn(validProfile)
|
|
||||||
`when`(activePluginProvider.activeInsulin).thenReturn(insulinOrefRapidActingPlugin)
|
|
||||||
|
|
||||||
sot = TreatmentsPlugin(profileInjector, aapsLogger, rxBus, aapsSchedulers, rh, context, sp, profileFunction, activePluginProvider, nsUpload, fabricPrivacy, dateUtil, databaseHelper, repository)
|
|
||||||
sot.service = treatmentService
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `zero TBR should produce zero absolute insulin`() {
|
|
||||||
val now = dateUtil._now()
|
|
||||||
val tbrs: MutableList<TemporaryBasal> = ArrayList()
|
|
||||||
tbrs.add(TemporaryBasal(injector).date(now - T.hours(30).msecs()).duration(10000).percent(0))
|
|
||||||
|
|
||||||
`when`(databaseHelper.getTemporaryBasalsDataFromTime(ArgumentMatchers.anyLong(), ArgumentMatchers.anyBoolean())).thenReturn(tbrs)
|
|
||||||
sot.initializeData(T.hours(30).msecs())
|
|
||||||
val iob = sot.getAbsoluteIOBTempBasals(now)
|
|
||||||
Assert.assertEquals(0.0, iob.iob, 0.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `90pct TBR and should produce less absolute insulin`() {
|
|
||||||
val now = dateUtil._now()
|
|
||||||
val tbrs: MutableList<TemporaryBasal> = ArrayList()
|
|
||||||
`when`(databaseHelper.getTemporaryBasalsDataFromTime(ArgumentMatchers.anyLong(), ArgumentMatchers.anyBoolean())).thenReturn(tbrs)
|
|
||||||
sot.initializeData(T.hours(30).msecs())
|
|
||||||
val iob100pct = sot.getAbsoluteIOBTempBasals(now)
|
|
||||||
|
|
||||||
tbrs.add(TemporaryBasal(injector).date(now - T.hours(30).msecs()).duration(10000).percent(90))
|
|
||||||
sot.initializeData(T.hours(30).msecs())
|
|
||||||
val iob90pct = sot.getAbsoluteIOBTempBasals(now)
|
|
||||||
Assert.assertTrue(iob100pct.basaliob > iob90pct.basaliob)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `110pct TBR and should produce 10pct more absolute insulin`() {
|
|
||||||
val now = dateUtil._now()
|
|
||||||
val tbrs: MutableList<TemporaryBasal> = ArrayList()
|
|
||||||
`when`(databaseHelper.getTemporaryBasalsDataFromTime(ArgumentMatchers.anyLong(), ArgumentMatchers.anyBoolean())).thenReturn(tbrs)
|
|
||||||
sot.initializeData(T.hours(30).msecs())
|
|
||||||
val iob100pct = sot.getAbsoluteIOBTempBasals(now)
|
|
||||||
|
|
||||||
tbrs.add(TemporaryBasal(injector).date(now - T.hours(30).msecs()).duration(10000).percent(110))
|
|
||||||
sot.initializeData(T.hours(30).msecs())
|
|
||||||
val iob110pct = sot.getAbsoluteIOBTempBasals(now)
|
|
||||||
Assert.assertEquals(1.1, iob110pct.basaliob / iob100pct.basaliob, 0.0001)
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package info.nightscout.androidaps.interfaces.stats
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.widget.TableRow
|
||||||
|
import android.widget.TextView
|
||||||
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
|
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||||
|
|
||||||
|
interface DexcomTIR {
|
||||||
|
|
||||||
|
fun calculateSD(): Double
|
||||||
|
fun toHbA1cView(context: Context, rh: ResourceHelper): TextView
|
||||||
|
fun toSDView(context: Context, rh: ResourceHelper, profileFunction: ProfileFunction): TextView
|
||||||
|
fun toRangeHeaderView(context: Context, rh: ResourceHelper, profileFunction: ProfileFunction): TextView
|
||||||
|
fun toTableRowHeader(context: Context, rh: ResourceHelper): TableRow
|
||||||
|
fun toTableRow(context: Context, rh: ResourceHelper): TableRow
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package info.nightscout.androidaps.interfaces.stats
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.widget.TableLayout
|
||||||
|
|
||||||
|
interface DexcomTirCalculator {
|
||||||
|
|
||||||
|
fun calculate(): DexcomTIR
|
||||||
|
fun stats(context: Context): TableLayout
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package info.nightscout.androidaps.interfaces.stats
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.widget.TableRow
|
||||||
|
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
|
||||||
|
interface TIR {
|
||||||
|
|
||||||
|
val date: Long
|
||||||
|
val lowThreshold: Double
|
||||||
|
val highThreshold: Double
|
||||||
|
var below: Int
|
||||||
|
var inRange: Int
|
||||||
|
var above: Int
|
||||||
|
var error: Int
|
||||||
|
var count: Int
|
||||||
|
fun error()
|
||||||
|
fun below()
|
||||||
|
fun inRange()
|
||||||
|
fun above()
|
||||||
|
|
||||||
|
fun toTableRow(context: Context, rh: ResourceHelper, dateUtil: DateUtil): TableRow
|
||||||
|
fun toTableRow(context: Context, rh: ResourceHelper, days: Int): TableRow
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package info.nightscout.androidaps.interfaces.stats
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.LongSparseArray
|
||||||
|
import android.widget.TableLayout
|
||||||
|
import info.nightscout.androidaps.database.entities.TotalDailyDose
|
||||||
|
|
||||||
|
interface TddCalculator {
|
||||||
|
|
||||||
|
fun calculate(days: Long): LongSparseArray<TotalDailyDose>
|
||||||
|
fun calculateToday(): TotalDailyDose
|
||||||
|
fun calculateDaily(startHours: Long, endHours: Long): TotalDailyDose
|
||||||
|
fun calculate(startTime: Long, endTime: Long): TotalDailyDose
|
||||||
|
fun averageTDD(tdds: LongSparseArray<TotalDailyDose>): TotalDailyDose?
|
||||||
|
fun stats(context: Context): TableLayout
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package info.nightscout.androidaps.interfaces.stats
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.LongSparseArray
|
||||||
|
import android.widget.TableLayout
|
||||||
|
|
||||||
|
interface TirCalculator {
|
||||||
|
|
||||||
|
fun calculate(days: Long, lowMgdl: Double, highMgdl: Double): LongSparseArray<TIR>
|
||||||
|
fun stats(context: Context): TableLayout
|
||||||
|
}
|
|
@ -225,6 +225,9 @@
|
||||||
<string name="a11y_high">high</string>
|
<string name="a11y_high">high</string>
|
||||||
<string name="a11y_inrange">in range</string>
|
<string name="a11y_inrange">in range</string>
|
||||||
<string name="a11y_low">low</string>
|
<string name="a11y_low">low</string>
|
||||||
|
<string name="average">Average</string>
|
||||||
|
<string name="tir">TIR</string>
|
||||||
|
<string name="tdd_total">TDD Total</string>
|
||||||
|
|
||||||
<!-- Constraints-->
|
<!-- Constraints-->
|
||||||
<string name="limitingbasalratio">Limiting max basal rate to %1$.2f U/h because of %2$s</string>
|
<string name="limitingbasalratio">Limiting max basal rate to %1$.2f U/h because of %2$s</string>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package info.nightscout.androidaps.utils.stats
|
package info.nightscout.implementation.stats
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
@ -7,6 +7,8 @@ import android.widget.TableLayout
|
||||||
import info.nightscout.androidaps.database.AppRepository
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.interfaces.stats.DexcomTIR
|
||||||
|
import info.nightscout.androidaps.interfaces.stats.DexcomTirCalculator
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.MidnightTime
|
import info.nightscout.androidaps.utils.MidnightTime
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
|
@ -14,26 +16,27 @@ import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class DexcomTirCalculator @Inject constructor(
|
class DexcomTirCalculatorImpl @Inject constructor(
|
||||||
private val rh: ResourceHelper,
|
private val rh: ResourceHelper,
|
||||||
private val profileFunction: ProfileFunction,
|
private val profileFunction: ProfileFunction,
|
||||||
private val dateUtil: DateUtil,
|
private val dateUtil: DateUtil,
|
||||||
private val repository: AppRepository
|
private val repository: AppRepository
|
||||||
) {
|
) : DexcomTirCalculator {
|
||||||
|
|
||||||
val days = 14L
|
val days = 14L
|
||||||
|
|
||||||
fun calculate(): DexcomTIR {
|
override fun calculate(): DexcomTIR {
|
||||||
val startTime = MidnightTime.calc(dateUtil.now() - T.days(days).msecs())
|
val startTime = MidnightTime.calc(dateUtil.now() - T.days(days).msecs())
|
||||||
val endTime = MidnightTime.calc(dateUtil.now())
|
val endTime = MidnightTime.calc(dateUtil.now())
|
||||||
|
|
||||||
val bgReadings = repository.compatGetBgReadingsDataFromTime(startTime, endTime, true).blockingGet()
|
val bgReadings = repository.compatGetBgReadingsDataFromTime(startTime, endTime, true).blockingGet()
|
||||||
val result = DexcomTIR()
|
val result = DexcomTirImpl()
|
||||||
for (bg in bgReadings) result.add(bg.timestamp, bg.value)
|
for (bg in bgReadings) result.add(bg.timestamp, bg.value)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun stats(context: Context): TableLayout =
|
override fun stats(context: Context): TableLayout =
|
||||||
TableLayout(context).also { layout ->
|
TableLayout(context).also { layout ->
|
||||||
val tir = calculate()
|
val tir = calculate()
|
||||||
layout.layoutParams = TableLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)
|
layout.layoutParams = TableLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)
|
|
@ -1,4 +1,4 @@
|
||||||
package info.nightscout.androidaps.utils.stats
|
package info.nightscout.implementation.stats
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
@ -7,16 +7,17 @@ import android.view.Gravity
|
||||||
import android.widget.TableRow
|
import android.widget.TableRow
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.R
|
|
||||||
import info.nightscout.androidaps.interfaces.Profile
|
import info.nightscout.androidaps.interfaces.Profile
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.interfaces.stats.DexcomTIR
|
||||||
|
import info.nightscout.implementation.R
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
class DexcomTIR {
|
class DexcomTirImpl : DexcomTIR {
|
||||||
|
|
||||||
private var veryLow = 0
|
private var veryLow = 0
|
||||||
private var low = 0
|
private var low = 0
|
||||||
|
@ -26,7 +27,7 @@ class DexcomTIR {
|
||||||
private var error = 0
|
private var error = 0
|
||||||
private var count = 0
|
private var count = 0
|
||||||
|
|
||||||
var sum = 0.0
|
private var sum = 0.0
|
||||||
val values = mutableListOf<Double>()
|
val values = mutableListOf<Double>()
|
||||||
|
|
||||||
private val veryLowTirMgdl = Constants.STATS_RANGE_VERY_LOW_MMOL * Constants.MMOLL_TO_MGDL
|
private val veryLowTirMgdl = Constants.STATS_RANGE_VERY_LOW_MMOL * Constants.MMOLL_TO_MGDL
|
||||||
|
@ -65,14 +66,14 @@ class DexcomTIR {
|
||||||
private fun veryHighPct() = if (count > 0) veryHigh.toDouble() / count * 100.0 else 0.0
|
private fun veryHighPct() = if (count > 0) veryHigh.toDouble() / count * 100.0 else 0.0
|
||||||
private fun mean() = sum / count
|
private fun mean() = sum / count
|
||||||
|
|
||||||
fun calculateSD(): Double {
|
override fun calculateSD(): Double {
|
||||||
if (count == 0) return 0.0
|
if (count == 0) return 0.0
|
||||||
var standardDeviation = 0.0
|
var standardDeviation = 0.0
|
||||||
for (num in values) standardDeviation += (num - mean()).pow(2.0)
|
for (num in values) standardDeviation += (num - mean()).pow(2.0)
|
||||||
return sqrt(standardDeviation / count)
|
return sqrt(standardDeviation / count)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toHbA1cView(context: Context, rh: ResourceHelper): TextView =
|
override fun toHbA1cView(context: Context, rh: ResourceHelper): TextView =
|
||||||
TextView(context).apply {
|
TextView(context).apply {
|
||||||
text =
|
text =
|
||||||
if (count == 0) ""
|
if (count == 0) ""
|
||||||
|
@ -86,7 +87,7 @@ class DexcomTIR {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun toSDView(context: Context, rh: ResourceHelper, profileFunction: ProfileFunction): TextView =
|
override fun toSDView(context: Context, rh: ResourceHelper, profileFunction: ProfileFunction): TextView =
|
||||||
TextView(context).apply {
|
TextView(context).apply {
|
||||||
val sd = calculateSD()
|
val sd = calculateSD()
|
||||||
text = "\n" + rh.gs(R.string.std_deviation, Profile.toUnitsString(sd, sd * Constants.MGDL_TO_MMOLL, profileFunction.getUnits()))
|
text = "\n" + rh.gs(R.string.std_deviation, Profile.toUnitsString(sd, sd * Constants.MGDL_TO_MMOLL, profileFunction.getUnits()))
|
||||||
|
@ -94,7 +95,7 @@ class DexcomTIR {
|
||||||
gravity = Gravity.CENTER_HORIZONTAL
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toRangeHeaderView(context: Context, rh: ResourceHelper, profileFunction: ProfileFunction): TextView =
|
override fun toRangeHeaderView(context: Context, rh: ResourceHelper, profileFunction: ProfileFunction): TextView =
|
||||||
TextView(context).apply {
|
TextView(context).apply {
|
||||||
text = StringBuilder()
|
text = StringBuilder()
|
||||||
.append(rh.gs(R.string.detailed_14_days))
|
.append(rh.gs(R.string.detailed_14_days))
|
||||||
|
@ -129,7 +130,7 @@ class DexcomTIR {
|
||||||
setTextAppearance(android.R.style.TextAppearance_Material_Medium)
|
setTextAppearance(android.R.style.TextAppearance_Material_Medium)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toTableRowHeader(context: Context, rh: ResourceHelper): TableRow =
|
override fun toTableRowHeader(context: Context, rh: ResourceHelper): TableRow =
|
||||||
TableRow(context).also { header ->
|
TableRow(context).also { header ->
|
||||||
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)
|
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)
|
||||||
header.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
|
header.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
|
||||||
|
@ -142,7 +143,7 @@ class DexcomTIR {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun toTableRow(context: Context, rh: ResourceHelper): TableRow =
|
override fun toTableRow(context: Context, rh: ResourceHelper): TableRow =
|
||||||
TableRow(context).also { row ->
|
TableRow(context).also { row ->
|
||||||
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, 1f)
|
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, 1f)
|
||||||
row.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
|
row.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
|
|
@ -1,4 +1,4 @@
|
||||||
package info.nightscout.androidaps.utils.stats
|
package info.nightscout.implementation.stats
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
|
@ -8,27 +8,29 @@ import android.view.ViewGroup
|
||||||
import android.widget.TableLayout
|
import android.widget.TableLayout
|
||||||
import android.widget.TableRow
|
import android.widget.TableRow
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import info.nightscout.androidaps.R
|
|
||||||
import info.nightscout.androidaps.database.AppRepository
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.database.ValueWrapper
|
import info.nightscout.androidaps.database.ValueWrapper
|
||||||
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
import info.nightscout.androidaps.database.entities.Bolus
|
import info.nightscout.androidaps.database.entities.Bolus
|
||||||
import info.nightscout.androidaps.database.entities.TotalDailyDose
|
import info.nightscout.androidaps.database.entities.TotalDailyDose
|
||||||
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
|
||||||
import info.nightscout.androidaps.extensions.toTableRow
|
import info.nightscout.androidaps.extensions.toTableRow
|
||||||
import info.nightscout.androidaps.extensions.toTableRowHeader
|
import info.nightscout.androidaps.extensions.toTableRowHeader
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.interfaces.stats.TddCalculator
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.MidnightTime
|
import info.nightscout.androidaps.utils.MidnightTime
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
|
import info.nightscout.implementation.R
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.logging.LTag
|
import info.nightscout.shared.logging.LTag
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
class TddCalculator @Inject constructor(
|
@Singleton
|
||||||
|
class TddCalculatorImpl @Inject constructor(
|
||||||
private val aapsLogger: AAPSLogger,
|
private val aapsLogger: AAPSLogger,
|
||||||
private val rh: ResourceHelper,
|
private val rh: ResourceHelper,
|
||||||
private val activePlugin: ActivePlugin,
|
private val activePlugin: ActivePlugin,
|
||||||
|
@ -36,9 +38,9 @@ class TddCalculator @Inject constructor(
|
||||||
private val dateUtil: DateUtil,
|
private val dateUtil: DateUtil,
|
||||||
private val iobCobCalculator: IobCobCalculator,
|
private val iobCobCalculator: IobCobCalculator,
|
||||||
private val repository: AppRepository
|
private val repository: AppRepository
|
||||||
) {
|
) : TddCalculator {
|
||||||
|
|
||||||
fun calculate(days: Long): LongSparseArray<TotalDailyDose> {
|
override fun calculate(days: Long): LongSparseArray<TotalDailyDose> {
|
||||||
var startTime = MidnightTime.calc(dateUtil.now() - T.days(days).msecs())
|
var startTime = MidnightTime.calc(dateUtil.now() - T.days(days).msecs())
|
||||||
val endTime = MidnightTime.calc(dateUtil.now())
|
val endTime = MidnightTime.calc(dateUtil.now())
|
||||||
val stepSize = T.hours(24).msecs()
|
val stepSize = T.hours(24).msecs()
|
||||||
|
@ -69,19 +71,19 @@ class TddCalculator @Inject constructor(
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculateToday(): TotalDailyDose {
|
override fun calculateToday(): TotalDailyDose {
|
||||||
val startTime = MidnightTime.calc(dateUtil.now())
|
val startTime = MidnightTime.calc(dateUtil.now())
|
||||||
val endTime = dateUtil.now()
|
val endTime = dateUtil.now()
|
||||||
return calculate(startTime, endTime)
|
return calculate(startTime, endTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculateDaily(startHours: Long, endHours: Long): TotalDailyDose {
|
override fun calculateDaily(startHours: Long, endHours: Long): TotalDailyDose {
|
||||||
val startTime = dateUtil.now() + T.hours(hour = startHours).msecs()
|
val startTime = dateUtil.now() + T.hours(hour = startHours).msecs()
|
||||||
val endTime = dateUtil.now() + T.hours(hour = endHours).msecs()
|
val endTime = dateUtil.now() + T.hours(hour = endHours).msecs()
|
||||||
return calculate(startTime, endTime)
|
return calculate(startTime, endTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculate(startTime: Long, endTime: Long): TotalDailyDose {
|
override fun calculate(startTime: Long, endTime: Long): TotalDailyDose {
|
||||||
val startTimeAligned = startTime - startTime % (5 * 60 * 1000)
|
val startTimeAligned = startTime - startTime % (5 * 60 * 1000)
|
||||||
val endTimeAligned = endTime - endTime % (5 * 60 * 1000)
|
val endTimeAligned = endTime - endTime % (5 * 60 * 1000)
|
||||||
val tdd = TotalDailyDose(timestamp = startTimeAligned)
|
val tdd = TotalDailyDose(timestamp = startTimeAligned)
|
||||||
|
@ -112,7 +114,7 @@ class TddCalculator @Inject constructor(
|
||||||
return tdd
|
return tdd
|
||||||
}
|
}
|
||||||
|
|
||||||
fun averageTDD(tdds: LongSparseArray<TotalDailyDose>): TotalDailyDose? {
|
override fun averageTDD(tdds: LongSparseArray<TotalDailyDose>): TotalDailyDose? {
|
||||||
val totalTdd = TotalDailyDose(timestamp = dateUtil.now())
|
val totalTdd = TotalDailyDose(timestamp = dateUtil.now())
|
||||||
if (tdds.size() == 0) return null
|
if (tdds.size() == 0) return null
|
||||||
for (i in 0 until tdds.size()) {
|
for (i in 0 until tdds.size()) {
|
||||||
|
@ -129,7 +131,7 @@ class TddCalculator @Inject constructor(
|
||||||
return totalTdd
|
return totalTdd
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stats(context: Context): TableLayout {
|
override fun stats(context: Context): TableLayout {
|
||||||
val tdds = calculate(7)
|
val tdds = calculate(7)
|
||||||
val averageTdd = averageTDD(tdds)
|
val averageTdd = averageTDD(tdds)
|
||||||
val todayTdd = calculateToday()
|
val todayTdd = calculateToday()
|
|
@ -1,4 +1,4 @@
|
||||||
package info.nightscout.androidaps.utils.stats
|
package info.nightscout.implementation.stats
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
@ -9,26 +9,28 @@ import android.view.ViewGroup
|
||||||
import android.widget.TableLayout
|
import android.widget.TableLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.R
|
|
||||||
import info.nightscout.androidaps.database.AppRepository
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.interfaces.Profile
|
import info.nightscout.androidaps.interfaces.Profile
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
|
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.interfaces.stats.TIR
|
||||||
|
import info.nightscout.androidaps.interfaces.stats.TirCalculator
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.MidnightTime
|
import info.nightscout.androidaps.utils.MidnightTime
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
import info.nightscout.implementation.R
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class TirCalculator @Inject constructor(
|
class TirCalculatorImpl @Inject constructor(
|
||||||
private val rh: ResourceHelper,
|
private val rh: ResourceHelper,
|
||||||
private val profileFunction: ProfileFunction,
|
private val profileFunction: ProfileFunction,
|
||||||
private val dateUtil: DateUtil,
|
private val dateUtil: DateUtil,
|
||||||
private val repository: AppRepository
|
private val repository: AppRepository
|
||||||
) {
|
) : TirCalculator {
|
||||||
|
|
||||||
fun calculate(days: Long, lowMgdl: Double, highMgdl: Double): LongSparseArray<TIR> {
|
override fun calculate(days: Long, lowMgdl: Double, highMgdl: Double): LongSparseArray<TIR> {
|
||||||
if (lowMgdl < 39) throw RuntimeException("Low below 39")
|
if (lowMgdl < 39) throw RuntimeException("Low below 39")
|
||||||
if (lowMgdl > highMgdl) throw RuntimeException("Low > High")
|
if (lowMgdl > highMgdl) throw RuntimeException("Low > High")
|
||||||
val startTime = MidnightTime.calc(dateUtil.now() - T.days(days).msecs())
|
val startTime = MidnightTime.calc(dateUtil.now() - T.days(days).msecs())
|
||||||
|
@ -40,7 +42,7 @@ class TirCalculator @Inject constructor(
|
||||||
val midnight = MidnightTime.calc(bg.timestamp)
|
val midnight = MidnightTime.calc(bg.timestamp)
|
||||||
var tir = result[midnight]
|
var tir = result[midnight]
|
||||||
if (tir == null) {
|
if (tir == null) {
|
||||||
tir = TIR(midnight, lowMgdl, highMgdl)
|
tir = TirImpl(midnight, lowMgdl, highMgdl)
|
||||||
result.append(midnight, tir)
|
result.append(midnight, tir)
|
||||||
}
|
}
|
||||||
if (bg.value < 39) tir.error()
|
if (bg.value < 39) tir.error()
|
||||||
|
@ -53,9 +55,9 @@ class TirCalculator @Inject constructor(
|
||||||
|
|
||||||
private fun averageTIR(tirs: LongSparseArray<TIR>): TIR {
|
private fun averageTIR(tirs: LongSparseArray<TIR>): TIR {
|
||||||
val totalTir = if (tirs.size() > 0) {
|
val totalTir = if (tirs.size() > 0) {
|
||||||
TIR(tirs.valueAt(0).date, tirs.valueAt(0).lowThreshold, tirs.valueAt(0).highThreshold)
|
TirImpl(tirs.valueAt(0).date, tirs.valueAt(0).lowThreshold, tirs.valueAt(0).highThreshold)
|
||||||
} else {
|
} else {
|
||||||
TIR(7, 70.0, 180.0)
|
TirImpl(7, 70.0, 180.0)
|
||||||
}
|
}
|
||||||
for (i in 0 until tirs.size()) {
|
for (i in 0 until tirs.size()) {
|
||||||
val tir = tirs.valueAt(i)
|
val tir = tirs.valueAt(i)
|
||||||
|
@ -69,7 +71,7 @@ class TirCalculator @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun stats(context: Context): TableLayout =
|
override fun stats(context: Context): TableLayout =
|
||||||
TableLayout(context).also { layout ->
|
TableLayout(context).also { layout ->
|
||||||
val lowTirMgdl = Constants.STATS_RANGE_LOW_MMOL * Constants.MMOLL_TO_MGDL
|
val lowTirMgdl = Constants.STATS_RANGE_LOW_MMOL * Constants.MMOLL_TO_MGDL
|
||||||
val highTirMgdl = Constants.STATS_RANGE_HIGH_MMOL * Constants.MMOLL_TO_MGDL
|
val highTirMgdl = Constants.STATS_RANGE_HIGH_MMOL * Constants.MMOLL_TO_MGDL
|
||||||
|
@ -92,7 +94,7 @@ class TirCalculator @Inject constructor(
|
||||||
gravity = Gravity.CENTER_HORIZONTAL
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
setTextAppearance(android.R.style.TextAppearance_Material_Medium)
|
setTextAppearance(android.R.style.TextAppearance_Material_Medium)
|
||||||
})
|
})
|
||||||
layout.addView(TIR.toTableRowHeader(context, rh))
|
layout.addView(TirImpl.toTableRowHeader(context, rh))
|
||||||
for (i in 0 until tir7.size()) layout.addView(tir7.valueAt(i).toTableRow(context, rh, dateUtil))
|
for (i in 0 until tir7.size()) layout.addView(tir7.valueAt(i).toTableRow(context, rh, dateUtil))
|
||||||
layout.addView(
|
layout.addView(
|
||||||
TextView(context).apply {
|
TextView(context).apply {
|
|
@ -1,26 +1,38 @@
|
||||||
package info.nightscout.androidaps.utils.stats
|
package info.nightscout.implementation.stats
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.widget.TableRow
|
import android.widget.TableRow
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import info.nightscout.androidaps.R
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
|
||||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.interfaces.stats.TIR
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.implementation.R
|
||||||
|
|
||||||
class TIR(val date: Long, val lowThreshold: Double, val highThreshold: Double) {
|
class TirImpl(override val date: Long, override val lowThreshold: Double, override val highThreshold: Double) : TIR {
|
||||||
|
|
||||||
internal var below = 0
|
override var below = 0
|
||||||
internal var inRange = 0
|
override var inRange = 0
|
||||||
internal var above = 0
|
override var above = 0
|
||||||
internal var error = 0
|
override var error = 0
|
||||||
internal var count = 0
|
override var count = 0
|
||||||
|
|
||||||
fun error() = run { error++ }
|
override fun error() {
|
||||||
fun below() = run { below++; count++ }
|
error++
|
||||||
fun inRange() = run { inRange++; count++ }
|
}
|
||||||
fun above() = run { above++; count++ }
|
|
||||||
|
override fun below() {
|
||||||
|
below++; count++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun inRange() {
|
||||||
|
inRange++; count++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun above() {
|
||||||
|
above++; count++
|
||||||
|
}
|
||||||
|
|
||||||
private fun belowPct() = if (count > 0) below.toDouble() / count * 100.0 else 0.0
|
private fun belowPct() = if (count > 0) below.toDouble() / count * 100.0 else 0.0
|
||||||
private fun inRangePct() = if (count > 0) 100 - belowPct() - abovePct() else 0.0
|
private fun inRangePct() = if (count > 0) 100 - belowPct() - abovePct() else 0.0
|
||||||
|
@ -40,7 +52,7 @@ class TIR(val date: Long, val lowThreshold: Double, val highThreshold: Double) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toTableRow(context: Context, rh: ResourceHelper, dateUtil: DateUtil): TableRow =
|
override fun toTableRow(context: Context, rh: ResourceHelper, dateUtil: DateUtil): TableRow =
|
||||||
TableRow(context).also { row ->
|
TableRow(context).also { row ->
|
||||||
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, 1f)
|
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, 1f)
|
||||||
row.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
|
row.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
|
||||||
|
@ -52,7 +64,7 @@ class TIR(val date: Long, val lowThreshold: Double, val highThreshold: Double) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun toTableRow(context: Context, rh: ResourceHelper, days: Int): TableRow =
|
override fun toTableRow(context: Context, rh: ResourceHelper, days: Int): TableRow =
|
||||||
TableRow(context).also { row ->
|
TableRow(context).also { row ->
|
||||||
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, 1f)
|
val lp = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, 1f)
|
||||||
row.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
|
row.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)
|
|
@ -23,4 +23,18 @@
|
||||||
<string name="error_asking_for_permissions">Error asking for permissions</string>
|
<string name="error_asking_for_permissions">Error asking for permissions</string>
|
||||||
<string name="alert_dialog_permission_battery_optimization_failed">This device does not appear to support battery optimization whitelisting - you may experience performance issues.</string>
|
<string name="alert_dialog_permission_battery_optimization_failed">This device does not appear to support battery optimization whitelisting - you may experience performance issues.</string>
|
||||||
|
|
||||||
|
<!-- Stats -->
|
||||||
|
<string name="veryLow" comment="below 3.1">Very low</string>
|
||||||
|
<string name="low" comment="3.1-3.9">Low</string>
|
||||||
|
<string name="high" comment="10.0-13.9">High</string>
|
||||||
|
<string name="veryHigh" comment="above 13.9">Very high</string>
|
||||||
|
<string name="below" comment="below "in range"">Below</string>
|
||||||
|
<string name="in_range">In range</string>
|
||||||
|
<string name="above" comment="above "in range"">Above</string>
|
||||||
|
<string name="hba1c">HbA1c: </string>
|
||||||
|
<string name="std_deviation">SD: %1$s</string>
|
||||||
|
<string name="detailed_14_days">Detailed 14 days</string>
|
||||||
|
<string name="day_tir">Day TIR</string>
|
||||||
|
<string name="night_tir">Night TIR</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
<string name="not_inserted">Not inserted</string>
|
<string name="not_inserted">Not inserted</string>
|
||||||
<string name="tdd_bolus">TDD Bolus</string>
|
<string name="tdd_bolus">TDD Bolus</string>
|
||||||
<string name="tdd_basal">TDD Basal</string>
|
<string name="tdd_basal">TDD Basal</string>
|
||||||
<string name="tdd_total">TDD Total</string>
|
|
||||||
<string name="tbr_formatter">%1$d%% for %2$d / %3$d min</string>
|
<string name="tbr_formatter">%1$d%% for %2$d / %3$d min</string>
|
||||||
<string name="multiwave_bolus">Multiwave bolus</string>
|
<string name="multiwave_bolus">Multiwave bolus</string>
|
||||||
<string name="eb_formatter">%1$.2f / %2$.2f U for %3$d min</string>
|
<string name="eb_formatter">%1$.2f / %2$.2f U for %3$d min</string>
|
||||||
|
|
|
@ -35,6 +35,14 @@
|
||||||
android:name=".activities.ErrorHelperActivity"
|
android:name=".activities.ErrorHelperActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:theme="@style/Theme.MaterialComponents.Translucent" />
|
android:theme="@style/Theme.MaterialComponents.Translucent" />
|
||||||
|
<activity
|
||||||
|
android:name=".activities.SurveyActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:theme="@style/AppTheme" />
|
||||||
|
<activity
|
||||||
|
android:name=".activities.StatsActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:theme="@style/AppTheme" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
package info.nightscout.androidaps.activities
|
package info.nightscout.ui.activities
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
||||||
import info.nightscout.androidaps.databinding.ActivityStatsBinding
|
import info.nightscout.androidaps.interfaces.stats.DexcomTirCalculator
|
||||||
|
import info.nightscout.androidaps.interfaces.stats.TddCalculator
|
||||||
|
import info.nightscout.androidaps.interfaces.stats.TirCalculator
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.utils.ActivityMonitor
|
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.androidaps.utils.stats.DexcomTirCalculator
|
import info.nightscout.ui.R
|
||||||
import info.nightscout.androidaps.utils.stats.TddCalculator
|
import info.nightscout.ui.databinding.ActivityStatsBinding
|
||||||
import info.nightscout.androidaps.utils.stats.TirCalculator
|
import info.nightscout.ui.utils.ActivityMonitor
|
||||||
import io.reactivex.rxjava3.core.Single
|
import io.reactivex.rxjava3.core.Single
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
|
@ -41,7 +42,7 @@ class StatsActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
binding.tdds.addView(TextView(this).apply { text = getString(R.string.tdd) + ": " + rh.gs(R.string.calculation_in_progress) })
|
binding.tdds.addView(TextView(this).apply { text = getString(R.string.tdd) + ": " + rh.gs(R.string.calculation_in_progress) })
|
||||||
binding.tir.addView(TextView(this).apply { text = getString(R.string.tir) + ": " + rh.gs(R.string.calculation_in_progress) })
|
binding.tir.addView(TextView(this).apply { text = getString(R.string.tir) + ": " + rh.gs(R.string.calculation_in_progress) })
|
||||||
binding.activity.addView(TextView(this).apply { text = getString(R.string.activitymonitor) + ": " + rh.gs(R.string.calculation_in_progress) })
|
binding.activity.addView(TextView(this).apply { text = getString(R.string.activity_monitor) + ": " + rh.gs(R.string.calculation_in_progress) })
|
||||||
|
|
||||||
disposable += Single.fromCallable { tddCalculator.stats(this) }
|
disposable += Single.fromCallable { tddCalculator.stats(this) }
|
||||||
.subscribeOn(aapsSchedulers.io)
|
.subscribeOn(aapsSchedulers.io)
|
||||||
|
@ -74,7 +75,7 @@ class StatsActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
binding.ok.setOnClickListener { finish() }
|
binding.ok.setOnClickListener { finish() }
|
||||||
binding.reset.setOnClickListener {
|
binding.reset.setOnClickListener {
|
||||||
OKDialog.showConfirmation(this, rh.gs(R.string.doyouwantresetstats)) {
|
OKDialog.showConfirmation(this, rh.gs(R.string.do_you_want_reset_stats)) {
|
||||||
uel.log(Action.STAT_RESET, Sources.Stats)
|
uel.log(Action.STAT_RESET, Sources.Stats)
|
||||||
activityMonitor.reset()
|
activityMonitor.reset()
|
||||||
recreate()
|
recreate()
|
|
@ -1,32 +1,29 @@
|
||||||
package info.nightscout.androidaps.activities
|
package info.nightscout.ui.activities
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import com.google.firebase.auth.FirebaseAuth
|
import com.google.firebase.auth.FirebaseAuth
|
||||||
import com.google.firebase.database.FirebaseDatabase
|
import com.google.firebase.database.FirebaseDatabase
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
|
||||||
import info.nightscout.androidaps.databinding.ActivitySurveyBinding
|
|
||||||
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
|
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.androidaps.utils.ActivityMonitor
|
import info.nightscout.androidaps.interfaces.stats.TddCalculator
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.InstanceId
|
import info.nightscout.androidaps.utils.InstanceId
|
||||||
import info.nightscout.androidaps.utils.ToastUtils
|
import info.nightscout.androidaps.utils.ToastUtils
|
||||||
import info.nightscout.androidaps.utils.defaultProfile.DefaultProfile
|
|
||||||
import info.nightscout.androidaps.utils.stats.TddCalculator
|
|
||||||
import info.nightscout.androidaps.utils.stats.TirCalculator
|
|
||||||
import info.nightscout.shared.SafeParse
|
import info.nightscout.shared.SafeParse
|
||||||
import info.nightscout.shared.logging.LTag
|
import info.nightscout.shared.logging.LTag
|
||||||
|
import info.nightscout.ui.R
|
||||||
|
import info.nightscout.ui.databinding.ActivitySurveyBinding
|
||||||
|
import info.nightscout.ui.defaultProfile.DefaultProfile
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class SurveyActivity : NoSplashAppCompatActivity() {
|
class SurveyActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
@Inject lateinit var activePlugin: ActivePlugin
|
@Inject lateinit var activePlugin: ActivePlugin
|
||||||
@Inject lateinit var tddCalculator: TddCalculator
|
@Inject lateinit var tddCalculator: TddCalculator
|
||||||
@Inject lateinit var tirCalculator: TirCalculator
|
|
||||||
@Inject lateinit var profileFunction: ProfileFunction
|
@Inject lateinit var profileFunction: ProfileFunction
|
||||||
@Inject lateinit var activityMonitor: ActivityMonitor
|
|
||||||
@Inject lateinit var defaultProfile: DefaultProfile
|
@Inject lateinit var defaultProfile: DefaultProfile
|
||||||
@Inject lateinit var dateUtil: DateUtil
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
|
|
||||||
|
@ -43,24 +40,20 @@ class SurveyActivity : NoSplashAppCompatActivity() {
|
||||||
val profileList = profileStore?.getProfileList() ?: return
|
val profileList = profileStore?.getProfileList() ?: return
|
||||||
binding.spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList)
|
binding.spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList)
|
||||||
|
|
||||||
//binding.tdds.text = tddCalculator.stats()
|
|
||||||
//binding.tir.text = tirCalculator.stats()
|
|
||||||
//binding.activity.text = activityMonitor.stats()
|
|
||||||
|
|
||||||
binding.profile.setOnClickListener {
|
binding.profile.setOnClickListener {
|
||||||
val age = SafeParse.stringToDouble(binding.age.text.toString())
|
val age = SafeParse.stringToDouble(binding.age.text.toString())
|
||||||
val weight = SafeParse.stringToDouble(binding.weight.text.toString())
|
val weight = SafeParse.stringToDouble(binding.weight.text.toString())
|
||||||
val tdd = SafeParse.stringToDouble(binding.tdd.text.toString())
|
val tdd = SafeParse.stringToDouble(binding.tdd.text.toString())
|
||||||
if (age < 1 || age > 120) {
|
if (age < 1 || age > 120) {
|
||||||
ToastUtils.warnToast(this, R.string.invalidage)
|
ToastUtils.warnToast(this, R.string.invalid_age)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
if ((weight < 5 || weight > 150) && tdd == 0.0) {
|
if ((weight < 5 || weight > 150) && tdd == 0.0) {
|
||||||
ToastUtils.warnToast(this, R.string.invalidweight)
|
ToastUtils.warnToast(this, R.string.invalid_weight)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
if ((tdd < 5 || tdd > 150) && weight == 0.0) {
|
if ((tdd < 5 || tdd > 150) && weight == 0.0) {
|
||||||
ToastUtils.warnToast(this, R.string.invalidweight)
|
ToastUtils.warnToast(this, R.string.invalid_weight)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
profileFunction.getProfile()?.let { runningProfile ->
|
profileFunction.getProfile()?.let { runningProfile ->
|
||||||
|
@ -84,11 +77,11 @@ class SurveyActivity : NoSplashAppCompatActivity() {
|
||||||
r.age = SafeParse.stringToInt(binding.age.text.toString())
|
r.age = SafeParse.stringToInt(binding.age.text.toString())
|
||||||
r.weight = SafeParse.stringToInt(binding.weight.text.toString())
|
r.weight = SafeParse.stringToInt(binding.weight.text.toString())
|
||||||
if (r.age < 1 || r.age > 120) {
|
if (r.age < 1 || r.age > 120) {
|
||||||
ToastUtils.warnToast(this, R.string.invalidage)
|
ToastUtils.warnToast(this, R.string.invalid_age)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
if (r.weight < 5 || r.weight > 150) {
|
if (r.weight < 5 || r.weight > 150) {
|
||||||
ToastUtils.warnToast(this, R.string.invalidweight)
|
ToastUtils.warnToast(this, R.string.invalid_weight)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package info.nightscout.androidaps.utils.defaultProfile
|
package info.nightscout.ui.defaultProfile
|
||||||
|
|
||||||
import info.nightscout.androidaps.data.PureProfile
|
import info.nightscout.androidaps.data.PureProfile
|
||||||
import info.nightscout.androidaps.extensions.pureProfileFromJson
|
import info.nightscout.androidaps.extensions.pureProfileFromJson
|
||||||
|
@ -13,31 +13,32 @@ import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
@Suppress("LocalVariableName")
|
||||||
@Singleton
|
@Singleton
|
||||||
class DefaultProfile @Inject constructor(val dateUtil: DateUtil) {
|
class DefaultProfile @Inject constructor(val dateUtil: DateUtil) {
|
||||||
|
|
||||||
var oneToFive: TreeMap<Double, Array<Double>> = TreeMap()
|
private var oneToFive: TreeMap<Double, Array<Double>> = TreeMap()
|
||||||
var sixToEleven: TreeMap<Double, Array<Double>> = TreeMap()
|
private var sixToEleven: TreeMap<Double, Array<Double>> = TreeMap()
|
||||||
var twelveToSeventeen: TreeMap<Double, Array<Double>> = TreeMap()
|
private var twelveToSeventeen: TreeMap<Double, Array<Double>> = TreeMap()
|
||||||
var eighteenToTwentyFour: TreeMap<Double, Array<Double>> = TreeMap()
|
@Suppress("unused") var eighteenToTwentyFour: TreeMap<Double, Array<Double>> = TreeMap()
|
||||||
|
|
||||||
fun profile(age: Double, tdd: Double, weight: Double, units: GlucoseUnit): PureProfile? {
|
fun profile(age: Double, tdd: Double, weight: Double, units: GlucoseUnit): PureProfile? {
|
||||||
val profile = JSONObject()
|
val profile = JSONObject()
|
||||||
if (age >= 1 && age < 6) {
|
if (age in 1.0..5.0) {
|
||||||
val _tdd = if (tdd == 0.0) 0.6 * weight else tdd
|
val _tdd = if (tdd == 0.0) 0.6 * weight else tdd
|
||||||
closest(oneToFive, _tdd * 0.3)?.let { array -> profile.put("basal", arrayToJson(array)) }
|
closest(oneToFive, _tdd * 0.3)?.let { array -> profile.put("basal", arrayToJson(array)) }
|
||||||
val ic = Round.roundTo(250.0 / _tdd, 1.0)
|
val ic = Round.roundTo(250.0 / _tdd, 1.0)
|
||||||
profile.put("carbratio", singleValueArray(ic, arrayOf(0.0, -4.0, -1.0, -2.0, -4.0, 0.0, -4.0)))
|
profile.put("carbratio", singleValueArray(ic, arrayOf(0.0, -4.0, -1.0, -2.0, -4.0, 0.0, -4.0)))
|
||||||
val isf = Round.roundTo(200.0 / _tdd, 0.1)
|
val isf = Round.roundTo(200.0 / _tdd, 0.1)
|
||||||
profile.put("sens", singleValueArrayFromMmolToUnits(isf, arrayOf(0.0, -2.0, -0.0, -0.0, -2.0, 0.0, -2.0),units))
|
profile.put("sens", singleValueArrayFromMmolToUnits(isf, arrayOf(0.0, -2.0, -0.0, -0.0, -2.0, 0.0, -2.0),units))
|
||||||
} else if (age >= 6 && age < 12) {
|
} else if (age in 6.0..11.0) {
|
||||||
val _tdd = if (tdd == 0.0) 0.8 * weight else tdd
|
val _tdd = if (tdd == 0.0) 0.8 * weight else tdd
|
||||||
closest(sixToEleven, _tdd * 0.4)?.let { array -> profile.put("basal", arrayToJson(array)) }
|
closest(sixToEleven, _tdd * 0.4)?.let { array -> profile.put("basal", arrayToJson(array)) }
|
||||||
val ic = Round.roundTo(375.0 / _tdd, 1.0)
|
val ic = Round.roundTo(375.0 / _tdd, 1.0)
|
||||||
profile.put("carbratio", singleValueArray(ic, arrayOf(0.0, -3.0, 0.0, -1.0, -3.0, 0.0, -2.0)))
|
profile.put("carbratio", singleValueArray(ic, arrayOf(0.0, -3.0, 0.0, -1.0, -3.0, 0.0, -2.0)))
|
||||||
val isf = Round.roundTo(170.0 / _tdd, 0.1)
|
val isf = Round.roundTo(170.0 / _tdd, 0.1)
|
||||||
profile.put("sens", singleValueArrayFromMmolToUnits(isf, arrayOf(0.0, -1.0, -0.0, -0.0, -1.0, 0.0, -1.0),units))
|
profile.put("sens", singleValueArrayFromMmolToUnits(isf, arrayOf(0.0, -1.0, -0.0, -0.0, -1.0, 0.0, -1.0),units))
|
||||||
} else if (age >= 12 && age <= 18) {
|
} else if (age in 12.0..18.0) {
|
||||||
val _tdd = if (tdd == 0.0) 1.0 * weight else tdd
|
val _tdd = if (tdd == 0.0) 1.0 * weight else tdd
|
||||||
closest(twelveToSeventeen, _tdd * 0.5)?.let { array -> profile.put("basal", arrayToJson(array)) }
|
closest(twelveToSeventeen, _tdd * 0.5)?.let { array -> profile.put("basal", arrayToJson(array)) }
|
||||||
val ic = Round.roundTo(500.0 / _tdd, 1.0)
|
val ic = Round.roundTo(500.0 / _tdd, 1.0)
|
|
@ -1,4 +1,4 @@
|
||||||
package info.nightscout.androidaps.utils.defaultProfile
|
package info.nightscout.ui.defaultProfile
|
||||||
|
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.data.PureProfile
|
import info.nightscout.androidaps.data.PureProfile
|
||||||
|
@ -15,22 +15,22 @@ import javax.inject.Singleton
|
||||||
@Singleton
|
@Singleton
|
||||||
class DefaultProfileDPV @Inject constructor(val injector: HasAndroidInjector, val dateUtil: DateUtil) {
|
class DefaultProfileDPV @Inject constructor(val injector: HasAndroidInjector, val dateUtil: DateUtil) {
|
||||||
|
|
||||||
var oneToFive = arrayOf(3.97, 3.61, 3.46, 3.70, 3.76, 3.87, 4.18, 4.01, 3.76, 3.54, 3.15, 2.80, 2.86, 3.21, 3.61, 3.97, 4.43, 4.96, 5.10, 5.50, 5.81, 6.14, 5.52, 5.10)
|
private var oneToFive = arrayOf(3.97, 3.61, 3.46, 3.70, 3.76, 3.87, 4.18, 4.01, 3.76, 3.54, 3.15, 2.80, 2.86, 3.21, 3.61, 3.97, 4.43, 4.96, 5.10, 5.50, 5.81, 6.14, 5.52, 5.10)
|
||||||
var sixToEleven = arrayOf(4.20, 4.27, 4.41, 4.62, 4.92, 5.09, 5.01, 4.47, 3.89, 3.33, 3.10, 2.91, 2.97, 3.08, 3.36, 3.93, 4.52, 4.76, 4.69, 4.63, 4.63, 4.47, 4.47, 4.31)
|
private var sixToEleven = arrayOf(4.20, 4.27, 4.41, 4.62, 4.92, 5.09, 5.01, 4.47, 3.89, 3.33, 3.10, 2.91, 2.97, 3.08, 3.36, 3.93, 4.52, 4.76, 4.69, 4.63, 4.63, 4.47, 4.47, 4.31)
|
||||||
var twelveToEighteen = arrayOf(3.47, 3.80, 4.31, 4.95, 5.59, 6.11, 5.89, 5.11, 4.31, 3.78, 3.55, 3.39, 3.35, 3.39, 3.64, 3.97, 4.53, 4.59, 4.50, 4.00, 3.69, 3.39, 3.35, 3.35)
|
private var twelveToEighteen = arrayOf(3.47, 3.80, 4.31, 4.95, 5.59, 6.11, 5.89, 5.11, 4.31, 3.78, 3.55, 3.39, 3.35, 3.39, 3.64, 3.97, 4.53, 4.59, 4.50, 4.00, 3.69, 3.39, 3.35, 3.35)
|
||||||
|
|
||||||
fun profile(age: Double, tdd: Double, basalSumPct: Double, units: GlucoseUnit): PureProfile? {
|
fun profile(age: Double, tdd: Double, basalSumPct: Double, units: GlucoseUnit): PureProfile? {
|
||||||
val basalSum = tdd * basalSumPct
|
val basalSum = tdd * basalSumPct
|
||||||
val profile = JSONObject()
|
val profile = JSONObject()
|
||||||
if (age >= 1 && age < 6) {
|
if (age in 1.0..5.0) {
|
||||||
profile.put("basal", arrayToJson(oneToFive, basalSum))
|
profile.put("basal", arrayToJson(oneToFive, basalSum))
|
||||||
profile.put("carbratio", singleValueArray(0.0))
|
profile.put("carbratio", singleValueArray(0.0))
|
||||||
profile.put("sens", singleValueArrayFromMmolToUnits(0.0, units))
|
profile.put("sens", singleValueArrayFromMmolToUnits(0.0, units))
|
||||||
} else if (age >= 6 && age < 12) {
|
} else if (age in 6.0..11.0) {
|
||||||
profile.put("basal", arrayToJson(sixToEleven, basalSum))
|
profile.put("basal", arrayToJson(sixToEleven, basalSum))
|
||||||
profile.put("carbratio", singleValueArray(0.0))
|
profile.put("carbratio", singleValueArray(0.0))
|
||||||
profile.put("sens", singleValueArrayFromMmolToUnits(0.0, units))
|
profile.put("sens", singleValueArrayFromMmolToUnits(0.0, units))
|
||||||
} else if (age >= 12 && age <= 18) {
|
} else if (age in 12.0..18.0) {
|
||||||
profile.put("basal", arrayToJson(twelveToEighteen, basalSum))
|
profile.put("basal", arrayToJson(twelveToEighteen, basalSum))
|
||||||
profile.put("carbratio", singleValueArray(0.0))
|
profile.put("carbratio", singleValueArray(0.0))
|
||||||
profile.put("sens", singleValueArrayFromMmolToUnits(0.0, units))
|
profile.put("sens", singleValueArrayFromMmolToUnits(0.0, units))
|
||||||
|
@ -56,12 +56,14 @@ class DefaultProfileDPV @Inject constructor(val injector: HasAndroidInjector, va
|
||||||
return basals
|
return basals
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("SameParameterValue")
|
||||||
private fun singleValueArray(value: Double): JSONArray {
|
private fun singleValueArray(value: Double): JSONArray {
|
||||||
val array = JSONArray()
|
val array = JSONArray()
|
||||||
array.put(JSONObject().put("time", "00:00").put("value", value).put("timeAsSeconds", 0 * 3600))
|
array.put(JSONObject().put("time", "00:00").put("value", value).put("timeAsSeconds", 0 * 3600))
|
||||||
return array
|
return array
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("SameParameterValue")
|
||||||
private fun singleValueArrayFromMmolToUnits(value: Double, units: GlucoseUnit): JSONArray {
|
private fun singleValueArrayFromMmolToUnits(value: Double, units: GlucoseUnit): JSONArray {
|
||||||
val array = JSONArray()
|
val array = JSONArray()
|
||||||
array.put(JSONObject().put("time", "00:00").put("value", Profile.fromMmolToUnits(value, units)).put("timeAsSeconds", 0 * 3600))
|
array.put(JSONObject().put("time", "00:00").put("value", Profile.fromMmolToUnits(value, units)).put("timeAsSeconds", 0 * 3600))
|
|
@ -2,8 +2,10 @@ package info.nightscout.ui.di
|
||||||
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.android.ContributesAndroidInjector
|
import dagger.android.ContributesAndroidInjector
|
||||||
|
import info.nightscout.ui.activities.SurveyActivity
|
||||||
import info.nightscout.ui.activities.BolusProgressHelperActivity
|
import info.nightscout.ui.activities.BolusProgressHelperActivity
|
||||||
import info.nightscout.ui.activities.ErrorHelperActivity
|
import info.nightscout.ui.activities.ErrorHelperActivity
|
||||||
|
import info.nightscout.ui.activities.StatsActivity
|
||||||
import info.nightscout.ui.activities.TDDStatsActivity
|
import info.nightscout.ui.activities.TDDStatsActivity
|
||||||
import info.nightscout.ui.dialogs.CalibrationDialog
|
import info.nightscout.ui.dialogs.CalibrationDialog
|
||||||
import info.nightscout.ui.dialogs.CarbsDialog
|
import info.nightscout.ui.dialogs.CarbsDialog
|
||||||
|
@ -18,5 +20,7 @@ abstract class UiModule {
|
||||||
@ContributesAndroidInjector abstract fun contributesTDDStatsActivity(): TDDStatsActivity
|
@ContributesAndroidInjector abstract fun contributesTDDStatsActivity(): TDDStatsActivity
|
||||||
@ContributesAndroidInjector abstract fun contributeBolusProgressHelperActivity(): BolusProgressHelperActivity
|
@ContributesAndroidInjector abstract fun contributeBolusProgressHelperActivity(): BolusProgressHelperActivity
|
||||||
@ContributesAndroidInjector abstract fun contributeErrorHelperActivity(): ErrorHelperActivity
|
@ContributesAndroidInjector abstract fun contributeErrorHelperActivity(): ErrorHelperActivity
|
||||||
|
@ContributesAndroidInjector abstract fun contributesStatsActivity(): StatsActivity
|
||||||
|
@ContributesAndroidInjector abstract fun contributesSurveyActivity(): SurveyActivity
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package info.nightscout.androidaps.utils
|
package info.nightscout.ui.utils
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
@ -10,12 +10,14 @@ import android.view.ViewGroup
|
||||||
import android.widget.TableLayout
|
import android.widget.TableLayout
|
||||||
import android.widget.TableRow
|
import android.widget.TableRow
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import info.nightscout.androidaps.R
|
|
||||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.shared.SafeParse
|
import info.nightscout.shared.SafeParse
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.logging.LTag
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.ui.R
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@ -69,7 +71,7 @@ class ActivityMonitor @Inject constructor(
|
||||||
layout.layoutParams = TableLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)
|
layout.layoutParams = TableLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)
|
||||||
layout.addView(
|
layout.addView(
|
||||||
TextView(context).apply {
|
TextView(context).apply {
|
||||||
text = rh.gs(R.string.activitymonitor)
|
text = rh.gs(R.string.activity_monitor)
|
||||||
setTypeface(typeface, Typeface.BOLD)
|
setTypeface(typeface, Typeface.BOLD)
|
||||||
gravity = Gravity.CENTER_HORIZONTAL
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
setTextAppearance(android.R.style.TextAppearance_Material_Medium)
|
setTextAppearance(android.R.style.TextAppearance_Material_Medium)
|
|
@ -5,7 +5,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context=".activities.StatsActivity">
|
tools:context="info.nightscout.ui.activities.StatsActivity">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
|
@ -68,7 +68,7 @@
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/weigth_label"
|
android:id="@+id/weight_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
|
@ -124,7 +124,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="20dp"
|
||||||
android:text="@string/mostcommonprofile"
|
android:text="@string/most_common_profile"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 7 KiB After Width: | Height: | Size: 7 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
@ -19,4 +19,21 @@
|
||||||
<string name="configure">Configure opacity</string>
|
<string name="configure">Configure opacity</string>
|
||||||
<string name="widget_description">AAPS widget</string>
|
<string name="widget_description">AAPS widget</string>
|
||||||
|
|
||||||
|
<!-- Activities-->
|
||||||
|
<string name="activity_monitor">Activity monitor</string>
|
||||||
|
<string name="do_you_want_reset_stats">Do you want to reset activity stats?</string>
|
||||||
|
<string name="statistics">Statistics</string>
|
||||||
|
<string name="calculation_in_progress">Calculation in progress</string>
|
||||||
|
<string name="invalid_age">Invalid age entry</string>
|
||||||
|
<string name="invalid_weight">Invalid weight entry</string>
|
||||||
|
<string name="reset">reset</string>
|
||||||
|
<string name="id">ID:</string>
|
||||||
|
<string name="submit">Submit</string>
|
||||||
|
<string name="profile">Profile</string>
|
||||||
|
<string name="age">Age</string>
|
||||||
|
<string name="weight_label">Weight</string>
|
||||||
|
<string name="most_common_profile">Most common profile:</string>
|
||||||
|
<string name="survey_comment">Note: Only data visible on this screen will be anonymously uploaded. ID is assigned to this installation of AAPS. You can submit data again if your main profile get changed but let it running at least for a week to make result visible in time in range. Your help is appreciated.</string>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
39
ui/src/test/java/info/nightscout/androidaps/TestBase.kt
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package info.nightscout.androidaps
|
||||||
|
|
||||||
|
import info.nightscout.shared.logging.AAPSLoggerTest
|
||||||
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.androidaps.utils.rx.TestAapsSchedulers
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.mockito.Mockito
|
||||||
|
import org.mockito.junit.MockitoJUnit
|
||||||
|
import org.mockito.junit.MockitoRule
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
open class TestBase {
|
||||||
|
|
||||||
|
val aapsLogger = AAPSLoggerTest()
|
||||||
|
val aapsSchedulers: AapsSchedulers = TestAapsSchedulers()
|
||||||
|
|
||||||
|
// Add a JUnit rule that will setup the @Mock annotated vars and log.
|
||||||
|
// Another possibility would be to add `MockitoAnnotations.initMocks(this) to the setup method.
|
||||||
|
@get:Rule
|
||||||
|
val mockitoRule: MockitoRule = MockitoJUnit.rule()
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setupLocale() {
|
||||||
|
Locale.setDefault(Locale.ENGLISH)
|
||||||
|
System.setProperty("disableFirebase", "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Workaround for Kotlin nullability.
|
||||||
|
// https://medium.com/@elye.project/befriending-kotlin-and-mockito-1c2e7b0ef791
|
||||||
|
// https://stackoverflow.com/questions/30305217/is-it-possible-to-use-mockito-in-kotlin
|
||||||
|
fun <T> anyObject(): T {
|
||||||
|
Mockito.any<T>()
|
||||||
|
return uninitialized()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("Unchecked_Cast")
|
||||||
|
fun <T> uninitialized(): T = null as T
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
package info.nightscout.androidaps
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import dagger.android.AndroidInjector
|
||||||
|
import dagger.android.HasAndroidInjector
|
||||||
|
import info.nightscout.androidaps.data.ProfileSealed
|
||||||
|
import info.nightscout.androidaps.database.embedments.InsulinConfiguration
|
||||||
|
import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
|
||||||
|
import info.nightscout.androidaps.extensions.pureProfileFromJson
|
||||||
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
|
import info.nightscout.androidaps.interfaces.Config
|
||||||
|
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||||
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
|
import info.nightscout.androidaps.interfaces.ProfileStore
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
|
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||||
|
import org.json.JSONObject
|
||||||
|
import org.junit.Before
|
||||||
|
import org.mockito.ArgumentMatchers.anyDouble
|
||||||
|
import org.mockito.ArgumentMatchers.anyInt
|
||||||
|
import org.mockito.ArgumentMatchers.anyString
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito
|
||||||
|
import org.mockito.Mockito.`when`
|
||||||
|
import org.mockito.invocation.InvocationOnMock
|
||||||
|
|
||||||
|
@Suppress("SpellCheckingInspection")
|
||||||
|
open class TestBaseWithProfile : TestBase() {
|
||||||
|
|
||||||
|
@Mock lateinit var activePluginProvider: ActivePlugin
|
||||||
|
@Mock lateinit var rh: ResourceHelper
|
||||||
|
@Mock lateinit var iobCobCalculator: IobCobCalculator
|
||||||
|
@Mock lateinit var fabricPrivacy: FabricPrivacy
|
||||||
|
@Mock lateinit var profileFunction: ProfileFunction
|
||||||
|
@Mock lateinit var config: Config
|
||||||
|
@Mock lateinit var context: Context
|
||||||
|
|
||||||
|
lateinit var dateUtil: DateUtil
|
||||||
|
val rxBus = RxBus(aapsSchedulers, aapsLogger)
|
||||||
|
|
||||||
|
val profileInjector = HasAndroidInjector { AndroidInjector { } }
|
||||||
|
|
||||||
|
private lateinit var validProfileJSON: String
|
||||||
|
lateinit var validProfile: ProfileSealed.Pure
|
||||||
|
lateinit var effectiveProfileSwitch: EffectiveProfileSwitch
|
||||||
|
|
||||||
|
@Suppress("PropertyName") val TESTPROFILENAME = "someProfile"
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun prepareMock() {
|
||||||
|
validProfileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," +
|
||||||
|
"{\"time\":\"2:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}]," +
|
||||||
|
"\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
|
||||||
|
dateUtil = Mockito.spy(DateUtil(context))
|
||||||
|
`when`(dateUtil.now()).thenReturn(1656358822000)
|
||||||
|
validProfile = ProfileSealed.Pure(pureProfileFromJson(JSONObject(validProfileJSON), dateUtil)!!)
|
||||||
|
effectiveProfileSwitch = EffectiveProfileSwitch(
|
||||||
|
timestamp = dateUtil.now(),
|
||||||
|
basalBlocks = validProfile.basalBlocks,
|
||||||
|
isfBlocks = validProfile.isfBlocks,
|
||||||
|
icBlocks = validProfile.icBlocks,
|
||||||
|
targetBlocks = validProfile.targetBlocks,
|
||||||
|
glucoseUnit = EffectiveProfileSwitch.GlucoseUnit.MMOL,
|
||||||
|
originalProfileName = "",
|
||||||
|
originalCustomizedName = "",
|
||||||
|
originalTimeshift = 0,
|
||||||
|
originalPercentage = 100,
|
||||||
|
originalDuration = 0,
|
||||||
|
originalEnd = 0,
|
||||||
|
insulinConfiguration = InsulinConfiguration("", 0, 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
Mockito.doAnswer { invocation: InvocationOnMock ->
|
||||||
|
val string = invocation.getArgument<Int>(0)
|
||||||
|
val arg1 = invocation.getArgument<Int?>(1)
|
||||||
|
String.format(rh.gs(string), arg1)
|
||||||
|
}.`when`(rh).gs(anyInt(), anyInt())
|
||||||
|
|
||||||
|
Mockito.doAnswer { invocation: InvocationOnMock ->
|
||||||
|
val string = invocation.getArgument<Int>(0)
|
||||||
|
val arg1 = invocation.getArgument<Double?>(1)
|
||||||
|
String.format(rh.gs(string), arg1)
|
||||||
|
}.`when`(rh).gs(anyInt(), anyDouble())
|
||||||
|
|
||||||
|
Mockito.doAnswer { invocation: InvocationOnMock ->
|
||||||
|
val string = invocation.getArgument<Int>(0)
|
||||||
|
val arg1 = invocation.getArgument<String?>(1)
|
||||||
|
String.format(rh.gs(string), arg1)
|
||||||
|
}.`when`(rh).gs(anyInt(), anyString())
|
||||||
|
|
||||||
|
Mockito.doAnswer { invocation: InvocationOnMock ->
|
||||||
|
val string = invocation.getArgument<Int>(0)
|
||||||
|
val arg1 = invocation.getArgument<String?>(1)
|
||||||
|
val arg2 = invocation.getArgument<String?>(2)
|
||||||
|
String.format(rh.gs(string), arg1, arg2)
|
||||||
|
}.`when`(rh).gs(anyInt(), anyString(), anyString())
|
||||||
|
|
||||||
|
Mockito.doAnswer { invocation: InvocationOnMock ->
|
||||||
|
val string = invocation.getArgument<Int>(0)
|
||||||
|
val arg1 = invocation.getArgument<String?>(1)
|
||||||
|
val arg2 = invocation.getArgument<Int?>(2)
|
||||||
|
String.format(rh.gs(string), arg1, arg2)
|
||||||
|
}.`when`(rh).gs(anyInt(), anyString(), anyInt())
|
||||||
|
|
||||||
|
Mockito.doAnswer { invocation: InvocationOnMock ->
|
||||||
|
val string = invocation.getArgument<Int>(0)
|
||||||
|
val arg1 = invocation.getArgument<Double?>(1)
|
||||||
|
val arg2 = invocation.getArgument<String?>(2)
|
||||||
|
String.format(rh.gs(string), arg1, arg2)
|
||||||
|
}.`when`(rh).gs(anyInt(), anyDouble(), anyString())
|
||||||
|
|
||||||
|
Mockito.doAnswer { invocation: InvocationOnMock ->
|
||||||
|
val string = invocation.getArgument<Int>(0)
|
||||||
|
val arg1 = invocation.getArgument<Double?>(1)
|
||||||
|
val arg2 = invocation.getArgument<Int?>(2)
|
||||||
|
String.format(rh.gs(string), arg1, arg2)
|
||||||
|
}.`when`(rh).gs(anyInt(), anyDouble(), anyInt())
|
||||||
|
|
||||||
|
Mockito.doAnswer { invocation: InvocationOnMock ->
|
||||||
|
val string = invocation.getArgument<Int>(0)
|
||||||
|
val arg1 = invocation.getArgument<Int?>(1)
|
||||||
|
val arg2 = invocation.getArgument<Int?>(2)
|
||||||
|
String.format(rh.gs(string), arg1, arg2)
|
||||||
|
}.`when`(rh).gs(anyInt(), anyInt(), anyInt())
|
||||||
|
|
||||||
|
Mockito.doAnswer { invocation: InvocationOnMock ->
|
||||||
|
val string = invocation.getArgument<Int>(0)
|
||||||
|
val arg1 = invocation.getArgument<Int?>(1)
|
||||||
|
val arg2 = invocation.getArgument<String?>(2)
|
||||||
|
String.format(rh.gs(string), arg1, arg2)
|
||||||
|
}.`when`(rh).gs(anyInt(), anyInt(), anyString())
|
||||||
|
|
||||||
|
Mockito.doAnswer { invocation: InvocationOnMock ->
|
||||||
|
val string = invocation.getArgument<Int>(0)
|
||||||
|
val arg1 = invocation.getArgument<Int?>(1)
|
||||||
|
val arg2 = invocation.getArgument<Int?>(2)
|
||||||
|
val arg3 = invocation.getArgument<String?>(3)
|
||||||
|
String.format(rh.gs(string), arg1, arg2, arg3)
|
||||||
|
}.`when`(rh).gs(anyInt(), anyInt(), anyInt(), anyString())
|
||||||
|
|
||||||
|
Mockito.doAnswer { invocation: InvocationOnMock ->
|
||||||
|
val string = invocation.getArgument<Int>(0)
|
||||||
|
val arg1 = invocation.getArgument<Int?>(1)
|
||||||
|
val arg2 = invocation.getArgument<String?>(2)
|
||||||
|
val arg3 = invocation.getArgument<String?>(3)
|
||||||
|
String.format(rh.gs(string), arg1, arg2, arg3)
|
||||||
|
}.`when`(rh).gs(anyInt(), anyInt(), anyString(), anyString())
|
||||||
|
|
||||||
|
Mockito.doAnswer { invocation: InvocationOnMock ->
|
||||||
|
val string = invocation.getArgument<Int>(0)
|
||||||
|
val arg1 = invocation.getArgument<Double?>(1)
|
||||||
|
val arg2 = invocation.getArgument<Int?>(2)
|
||||||
|
val arg3 = invocation.getArgument<String?>(3)
|
||||||
|
String.format(rh.gs(string), arg1, arg2, arg3)
|
||||||
|
}.`when`(rh).gs(anyInt(), anyDouble(), anyInt(), anyString())
|
||||||
|
|
||||||
|
Mockito.doAnswer { invocation: InvocationOnMock ->
|
||||||
|
val string = invocation.getArgument<Int>(0)
|
||||||
|
val arg1 = invocation.getArgument<String?>(1)
|
||||||
|
val arg2 = invocation.getArgument<Int?>(2)
|
||||||
|
val arg3 = invocation.getArgument<String?>(3)
|
||||||
|
String.format(rh.gs(string), arg1, arg2, arg3)
|
||||||
|
}.`when`(rh).gs(anyInt(), anyString(), anyInt(), anyString())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getValidProfileStore(): ProfileStore {
|
||||||
|
val json = JSONObject()
|
||||||
|
val store = JSONObject()
|
||||||
|
store.put(TESTPROFILENAME, JSONObject(validProfileJSON))
|
||||||
|
json.put("defaultProfile", TESTPROFILENAME)
|
||||||
|
json.put("store", store)
|
||||||
|
return ProfileStore(profileInjector, json, dateUtil)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package info.nightscout.androidaps
|
||||||
|
|
||||||
|
import dagger.android.HasAndroidInjector
|
||||||
|
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||||
|
import info.nightscout.androidaps.interfaces.Profile
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult
|
||||||
|
import info.nightscout.androidaps.interfaces.PumpDescription
|
||||||
|
import info.nightscout.androidaps.interfaces.Pump
|
||||||
|
import info.nightscout.androidaps.interfaces.PumpSync
|
||||||
|
import info.nightscout.androidaps.plugins.common.ManufacturerType
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
|
||||||
|
import info.nightscout.androidaps.utils.TimeChangeType
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
class TestPumpPlugin(val injector: HasAndroidInjector) : Pump {
|
||||||
|
|
||||||
|
var connected = false
|
||||||
|
var isProfileSet = true
|
||||||
|
|
||||||
|
override fun isConnected() = connected
|
||||||
|
override fun isConnecting() = false
|
||||||
|
override fun isHandshakeInProgress() = false
|
||||||
|
val lastData = 0L
|
||||||
|
|
||||||
|
val baseBasal = 0.0
|
||||||
|
override val pumpDescription = PumpDescription()
|
||||||
|
|
||||||
|
override fun isInitialized(): Boolean = true
|
||||||
|
override fun isSuspended(): Boolean = false
|
||||||
|
override fun isBusy(): Boolean = false
|
||||||
|
override fun connect(reason: String) {
|
||||||
|
connected = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun disconnect(reason: String) {
|
||||||
|
connected = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun stopConnecting() {
|
||||||
|
connected = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun waitForDisconnectionInSeconds(): Int = 0
|
||||||
|
override fun getPumpStatus(reason: String) {}
|
||||||
|
override fun setNewBasalProfile(profile: Profile): PumpEnactResult = PumpEnactResult(injector)
|
||||||
|
override fun isThisProfileSet(profile: Profile): Boolean = isProfileSet
|
||||||
|
override fun lastDataTime(): Long = lastData
|
||||||
|
override val baseBasalRate: Double = baseBasal
|
||||||
|
override val reservoirLevel: Double = 0.0
|
||||||
|
override val batteryLevel: Int = 0
|
||||||
|
override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult = PumpEnactResult(injector).success(true)
|
||||||
|
override fun stopBolusDelivering() {}
|
||||||
|
override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult = PumpEnactResult(injector).success(true)
|
||||||
|
override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult = PumpEnactResult(injector).success(true)
|
||||||
|
override fun setExtendedBolus(insulin: Double, durationInMinutes: Int): PumpEnactResult = PumpEnactResult(injector).success(true)
|
||||||
|
override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true)
|
||||||
|
override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true)
|
||||||
|
override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject = JSONObject()
|
||||||
|
override fun manufacturer(): ManufacturerType = ManufacturerType.AAPS
|
||||||
|
override fun model(): PumpType = PumpType.GENERIC_AAPS
|
||||||
|
override fun serialNumber(): String = "1"
|
||||||
|
override fun shortStatus(veryShort: Boolean): String = ""
|
||||||
|
override val isFakingTempsByExtendedBoluses: Boolean = false
|
||||||
|
override fun loadTDDs(): PumpEnactResult = PumpEnactResult(injector).success(true)
|
||||||
|
override fun canHandleDST(): Boolean = true
|
||||||
|
override fun timezoneOrDSTChanged(timeChangeType: TimeChangeType) {}
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
package info.nightscout.androidaps.utils.defaultProfile
|
package info.nightscout.ui.defaultProfile
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.TestBaseWithProfile
|
||||||
import info.nightscout.androidaps.data.ProfileSealed
|
import info.nightscout.androidaps.data.ProfileSealed
|
||||||
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
||||||
import info.nightscout.androidaps.TestBaseWithProfile
|
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|