From ff93c5d9cba09436d9f01d957ba13de5b01832ae Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sat, 11 Jan 2020 02:54:46 +0000
Subject: [PATCH 001/152] Apply translations in sl_SI
translation completed for the source file '/app/src/main/res/values/strings.xml'
on the 'sl_SI' language.
---
app/src/main/res/values-sl_SI/strings.xml | 433 ++++++++++++++++++++++
1 file changed, 433 insertions(+)
create mode 100644 app/src/main/res/values-sl_SI/strings.xml
diff --git a/app/src/main/res/values-sl_SI/strings.xml b/app/src/main/res/values-sl_SI/strings.xml
new file mode 100644
index 00000000..c11143aa
--- /dev/null
+++ b/app/src/main/res/values-sl_SI/strings.xml
@@ -0,0 +1,433 @@
+
+
+
+ Različica %s
+ Nastavitve
+
+
+ %srastlin
+
+ Vse rastline
+
+ Vse
+ Dejanja dodana
+ Zapiski dodani
+ Zalivanje dodano
+ Vrt izbrisan
+
+ Ali ste prepričani, da želite izbrisati vrt <b>%s</b>? Dejanje ne bo izbrisalo rastlin
+ Voda
+ Dejanje
+
+ Pripomoček ni na voljo, ko je vključena nastavitev za šifriranje
+ Dodaj novo rastlino
+ Podrobnosti o rastlini
+ Statistika o rastlini
+
+ Iz fotoaparata
+
+ Iz galerije
+ Izberi možnost
+ izberi sliko
+ Uporabi za drugo rastlino
+ Izberi rastlino
+ Slika dodana
+ Zajami še eno
+
+ Urniki
+ Podrobnosti o urniku
+ Datum urnika
+ Ime
+ Rahlo hranjenje
+ Opis
+
+ Rahlo hranjene z 2 tedenskim izpiranjem
+
+ + Novo hranjenje
+ + Nov urnik
+ + Nov dodatek
+ Dodatki
+ Dodatek
+ Od datuma
+ Od faze
+ Do datuma
+ Do faze
+ Napolni iz urnika
+ Napolni iz prejšnjega
+ Ali ste prepričani?
+ Kopiranje izbranega urnika?
+ Brisanje izbranega urnika?
+ Urnik kopiran
+ Urnik izbrisan
+ Razveljavi
+ Urniki hranjenja
+ Urniki hranjenja
+ Aplikacija posodobljena
+ Aplikacija je bila posodobljena na različico %s
+ Preglej spremembe
+ Zavrzi
+
+
+ Zalivanje %s
+ Zalivanje več rastlin
+
+ Beležka
+ Podrobnosti o vodi
+ pH vode
+ ppm
+ Odtok
+ Količina (%s)
+ Temp. (º%s)
+ Datum in čas
+ Zdaj
+ Datum
+ Danes
+ Zori že %s dni
+
+ Zalivanja
+ Spremembe faz
+
+ Podvojeno
+ Kopiraj v
+ Uredi dejanje
+ Izbriši dejanje
+
+ Izberi rastline
+ Vrtovi
+ Vse rastline
+ + Nov vrt
+ Dodatno
+ Nastavitve
+ Izbriši
+ Deli
+ Slika
+ Zadnje zalivanje
+ Zalij znova
+
+ Ime rastline
+ Nova rastlina
+ Sorta rastline
+ Lemon haze
+ Podrobnosti gojenja
+ Datum posaditve
+ Substrat
+
+ Podrobnosti substrata
+
+ Zemlja, Perlit, 50/50 mešanica
+ Iz potaknjenca?
+ Podrobnosti faze
+ Faza rastline
+ Preglej slike
+ Preglej zgodovino
+ Preglej statistiko
+ Slike
+ Zgodovina
+ Statistika
+ Filter
+ Posajeno
+ Kalitev
+ Potaknjenec
+ Vegetacija
+ Cvetenje
+ Sušenje
+ Zorenje
+ Požeto
+
+ Požeto pred %s
+ Izvozi vrt
+ Uredi vrt
+ Izbriši vrt
+ Izvozi
+
+ Celoten čas:
+ Skupno zalivanja:
+ Skupno izpiranja:
+ Povp. čas med zalivanji:
+ Dodatki filtra
+ pH
+
+ Min:
+ Max:
+ Povp.:
+ Temperatura
+ Splošno
+ Neuspešno nalaganje rastline
+ Fuck I Missed (FIM)
+ Izpiranje
+ Foliarno hranjenje
+ Low Stress Training
+ Lizika
+ Aplikacija pesticida
+ Vršičkano
+ Presajeno
+ Obrezano
+ ScrOG tlačenje
+
+ Zalito
+ Zapisek
+ Izbriši ta dogodek?
+ Ali ste prepričani, da želite izbrisati?
+ Ali ste prepričani, da želite izbrisati <b>%s</b> slike ? Teh ne boste mogli več obnoviti.
+ Uredi
+ Faza
+ Nastavi
+ Spremeni
+ Dodaj
+ Prekliči
+ Dejanje
+ Ok
+ Polje je potrebno
+ Napaka - nepravilno geslo
+ Uredi zalivanje
+ Dodano
+ Podvojeno dejanje
+ Več rastlin
+ Dejanje dodano k
+ Zapisek posodobljen
+ Posodobljeno
+ Faza posodobljena
+ Dogodek izbrisan
+ Končano
+ Vrt
+ Izberi vse
+ Ne izberi nobenega
+ Sprejmi
+ Omogoči
+ Zavrni
+ Sadika
+ Sadika
+
+ Oh ne
+ Izgleda, da je od zadnje uporabe aplikacije prišlo do sesutja.
+Ali bi želeli poslati ta anonimna poročila? Ta poročila bodo poslana na <a href=\"https://github.com/7LPdWcaW/GrowTracker-Android/issues\">github.com/7LPdWcaW/GrowTracker-Android/issues</a>, priloženih ne bo nič osebnih podatkov. Poljubno lahko tudi objavite ta poročila na <a href=\"https://reddit.com/r/growutils\">reddit.com/r/growutils</a> ročno, če želite. Poročila so shranjena v <i>%s<i>
+ Da
+ Ne
+
+ Vnesite svoje geslo
+ Vnesite geslo
+ Znova vnesite svoje geslo
+ Napaka - geslo se ne ujema
+
+ Nastala je usodna napaka pri shranjevanju podatkov o vrtu, prosimo naredite varnostno kopijo teh podatkov
+ Vzeto
+ Pred %s
+ Zalito pred <b>%s</b>
+ Zadnje zalivanje pred <b>%s</b>
+ Posajeno pred <b>%s</b>
+
+ Za shranjevanje fotografij je potreben dostop do zunanje shrambe. Nobeni drugi podatki niso potrebni.
+
+ Zalivanja dodana
+ Izbrisali boste <b>%s</b> in vse slike povezane s tem, ste prepričani ? To ne more biti razveljavljeno.
+ Brisanje rastline...
+
+ Podvojena rastlina
+ Odpri
+
+ Izvažanje dnevnika gojenja...
+ Izvažanje dnevnika gojenja vrta...
+ %s dodano
+ Ime ne more biti prazno
+ Izvažanje %s
+
+ Zemlja
+ Hidroponika
+ Substrat iz kokosa
+ Aeroponika
+ Skrij slike
+ Prikaži slike
+
+ Privzet vrt za prikaz ob odprtju, trenutno: <b>%s</b>
+ Izberi stil kartic, trenutno: %s
+ Uporaba privzetih enot merjenja, trenutno: <b>%s</b>
+ Uporaba privzetih enot merjenja dodatkov, trenutno: <b>%s</b>
+ Uporaba privzetih enot merjenja temperature, trenutno: <b>%s</b>
+ Trenutno: <b>%s MiB</b> / Uporabljate <b>%s</b>
+ Vnesite to geslo med fazo dešifriranja, da preprečite nalaganje podatkov
+ Opozorilo
+ To je osnovna oblika AES šifriranja, ki temelji na podanem geslu. To ni garantirana oblika zaščite pred organi pregona.
+ Varnostna kopija omogočena, kopije bodo shranjene v %s
+ Obnovitev v %s končana
+ Obnovitev varnostne kopije iz %s je spodletela. Datoteka je morda %s
+ Šifrirano
+ Nešifrirano
+
+ Izberi mersko enoto
+ Izberi temperaturo
+ Izberi vrt
+ Izberi varnostno kopijo
+ Da obnovite to varnostno kopijo, morate imeti omogočen način šifracije z enakim geslom
+
+ Kopirano do
+ Ni varnostnih kopij iz katerih bi lahko obnovili podatke
+ Vse/Nič
+
+ Vnesi pH
+ pH odtočne vode
+ Povprečen pH
+
+ Slike rastline
+
+ Vhodni pH:
+ Izhodni pH:
+ Količina:
+ Temp.:
+ Dodatki:
+ EC:
+ ppm:
+
+ Izberi urnik
+ Dejanja
+ Vsili temno temo
+ Vsili aplikaciji, da uporabi temno temo, ne glede na sistemske nastavitve dnevne-temne teme
+ Skrij požeto
+ Skrij vse požete rastline
+ Obrni vrstni red rastlin
+ Pokaže rastline v obratnem vrstnem redu. (Potreben je ponovni zagon aplikacije)
+ Privzet vrt
+
+ Enote
+ Enota dostave
+ Merska enota
+ Temperaturska enota
+ TDS enota
+ Privzeta uporaba TDS, trenutno: <b>%s</b>
+ Upravljanje podatkov
+ Samodejna varnostna kopija
+ Samodejno naredi varnostno kopijo vsakih 24 ur
+ Naredi varnostno kopijo zdaj
+ Omejitev velikosti varnostne kopije
+ Velikost v MiB
+ Omejena velikost varnostne kopije (MiB)
+ Obnovi iz varnostne kopije
+ Šifriraj podatke
+ Doda zaklepanje aplikacije s pin kodo in zašifrira vse podatke/slike
+ Varovalni mehanizem
+ Nastavi geslo varnostnega mehanizma da preprečiš dostop do podatkov
+ Dodatki
+ O aplikaciji
+ Preberi
+ Izvozi podatke
+ Stil kartic
+ Ni rastlin za prikaz
+ Ni urnikov
+ Ni slik za prikaz
+ Pretekla dejanja
+ Prikaži/skrij kolendar
+
+ %d izbrano
+ Hvala vam do slednjega
+ Prevodi
+ Pomagaj pri prevodu
+ Šifriranje podatkov in slik
+ Dešifriram podatke in slike, to lahko vzame nekaj časa...
+
+
+ 1 sekunda
+ s
+ min.
+ h
+ dni
+ ted.
+ mes.
+ l
+
+ Podrobnosti
+
+
+ - sekunda
+ - sekundi
+ - sekund
+ - sekunde
+
+
+
+ - minuta
+ - minuti
+ - minut
+ - minute
+
+
+
+ - ura
+ - uri
+ - ur
+ - ure
+
+
+
+ - dan
+ - dneva
+ - dni
+ - dnevi
+
+
+
+ - teden
+ - tedna
+ - tednov
+ - tedni
+
+
+
+ - mesec
+ - meseca
+ - mesecev
+ - meseci
+
+
+
+ - leto
+ - leti
+ - let
+ - leta
+
+
+
+ - Izvirno
+ - Kompaktno
+ - Ekstremno
+
+
+ Izgubili boste kakršnekoli neshranjene spremembe
+ Končaj
+ Rastline
+ Vlažnost
+ Trenutna temp.:
+ Trenutna vlažnost:
+ Urnik osvetljave
+ Izbriši ta predmet?
+ Ali ste prepričani da želite izbrisati <b>%s</b>?
+ Pokaži
+ Skrij
+ Vključene luči
+ Izključene luči
+
+ Zadnja varnostna kopija: <b>%s</b>
+ Mesto shrambe za slike, trenutno <b>%s</b>
+ Neuspešna nastavitev mesta slike
+ Mesto shrambe slik
+ Počisti predpomnilnik slik
+ Shramba slik in spomin prepomnilnika počiščena
+ Uvažanje slik, to lahko traja nekaj časa...
+ Opravilo podatkov
+ Opravilo končano
+ Ni dejanj za prikaz
+
+ Izvažanje dnevnika gojenja za %s
+ Izvoz %s končan
+ Izvoženo %s v %s
+ Izvoz končan
+ Vključim slike?
+ Podatki niso na voljo
+
+ Za zajem slik je potreben dostop do fotoaparata
+ Uprabljanje varnostnih kopij
+ Mesto shrambe varnostnih kopij
+ Mesto shrambe varnostnih kopij, trenutno <b>%s</b>
+ Neuspešna nastavitev mesta varnostne kopije
+ Neuspešen uvoz rastlin iz datoteke
+ Uvozi rastline iz datoteke
+ Uspešen uvoz rastlin iz datoteke
+
From 61c8c402a0d1fac34e60423210e3f8591875fdc9 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 19 Jan 2020 20:08:32 +0000
Subject: [PATCH 002/152] Adds no media file to import task
---
app/src/main/java/me/anon/lib/task/ImportTask.java | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/app/src/main/java/me/anon/lib/task/ImportTask.java b/app/src/main/java/me/anon/lib/task/ImportTask.java
index 593bf66e..a4e76e06 100644
--- a/app/src/main/java/me/anon/lib/task/ImportTask.java
+++ b/app/src/main/java/me/anon/lib/task/ImportTask.java
@@ -15,6 +15,7 @@
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
@@ -84,6 +85,11 @@ public ImportTask(Context appContext, AsyncCallback callback)
if (!to.exists())
{
to.mkdirs();
+ try
+ {
+ new File(to, ".nomedia").createNewFile();
+ }
+ catch (IOException e){}
}
ArrayList imagesToAdd = new ArrayList<>();
From fbf1b8aeb19a76b0e3437e520a00c745749113ed Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 19 Jan 2020 20:16:57 +0000
Subject: [PATCH 003/152] Tidies up translators. Closes #183
---
README.md | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/README.md b/README.md
index 65a5e402..e46ab4bd 100644
--- a/README.md
+++ b/README.md
@@ -277,16 +277,14 @@ You can decrypt your files using your passphrase either by writing a script that
Translations provided by;
-- Alex (Noxmiles) - de 
-- Basti B (Weltenesche) - de 
-- Heimen Stoffels (Vistaus) - nl 
-- EmmanuelMess - es 
-- Maxtille - fr 
-- Patrick B (EukalyptusX) - de 
-- Sascha Zenglein (szenglein) - de 
-- Vexatos - de 
-- W Q (williq) - de 
-- 9YbQiuEohUu1 - ru/uk  
+- German - ; Acrylic Boy, Alex (Noxmiles), Basti B (Weltenesche), Patrick B (EukalyptusX), Sascha Zenglein (szenglein), Vexatos, W Q (williq)
+- Dutch - ; Heimen Stoffels (Vistaus)
+- French - ; Maxtille
+- Norwegian Bokmål - ; Syver Stensholt (SuperPotato)
+- Slovenian - ; Klemen Skerbiš (aha999)
+- Spanish - ; EmmanuelMess
+- Ukranian - ; 9YbQiuEohUu1
+- Russian - ; 9YbQiuEohUu1
See [more](https://github.com/7LPdWcaW/GrowTracker-Android/issues/116) about translating GrowTracker
From 964a09598d352e515500e7eda778f63c14dd7ec2 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 19 Jan 2020 20:30:00 +0000
Subject: [PATCH 004/152] Refactor progress
---
.../anon/grow/fragment/StatisticsFragment2.kt | 40 +++++++++++++++++++
1 file changed, 40 insertions(+)
create mode 100644 app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
new file mode 100644
index 00000000..b631128c
--- /dev/null
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -0,0 +1,40 @@
+package me.anon.grow.fragment
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import me.anon.grow.R
+import me.anon.lib.TdsUnit
+import me.anon.lib.TdsUnit.Companion.getSelectedTdsUnit
+import me.anon.lib.Unit
+import me.anon.lib.ext.inflate
+import me.anon.model.Plant
+
+/**
+ * // TODO: Add class description
+ */
+class StatisticsFragment2 : Fragment()
+{
+ companion object
+ {
+ @JvmStatic
+ public fun newInstance(args: Bundle) = StatisticsFragment().apply {
+ this.arguments = args
+ }
+ }
+
+ private lateinit var plant: Plant
+ private val selectedTdsUnit by lazy { TdsUnit.getSelectedTdsUnit(activity!!) }
+ private val selectedDeliveryUnit by lazy { Unit.getSelectedDeliveryUnit(activity!!) }
+ private val selectedMeasurementUnit by lazy { Unit.getSelectedMeasurementUnit(activity!!) }
+ private val checkedAdditives = setOf()
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = inflater.inflate(R.layout.statistics_view, container, false)
+
+ override fun onActivityCreated(savedInstanceState: Bundle?)
+ {
+ super.onActivityCreated(savedInstanceState)
+ }
+}
From 3a80e4be4eceb344a6719003feebdabe59a10c5f Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Fri, 14 Feb 2020 13:14:51 +0000
Subject: [PATCH 005/152] Updates dependencies and adds multidex
---
app/build.gradle | 8 +++++---
app/src/main/java/me/anon/grow/MainApplication.java | 12 ++----------
build.gradle | 2 +-
gradle/wrapper/gradle-wrapper.properties | 4 ++--
4 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/app/build.gradle b/app/build.gradle
index 326212d3..9236fb8f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -32,6 +32,7 @@ android {
versionCode 1370//getCommitCountTotal()
versionName "2.6.1"
versionNameSuffix (travis ? "-alpha" : "")
+ multiDexEnabled true
compileOptions {
sourceCompatibility 1.8
@@ -115,19 +116,20 @@ android {
}
dependencies {
+ implementation 'androidx.multidex:multidex:2.0.1'
implementation 'androidx.core:core:1.1.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.preference:preference:1.1.0'
- implementation 'androidx.recyclerview:recyclerview:1.0.0'
+ implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.cardview:cardview:1.0.0'
- implementation 'androidx.exifinterface:exifinterface:1.0.0'
+ implementation 'androidx.exifinterface:exifinterface:1.1.0'
implementation 'androidx.documentfile:documentfile:1.0.1'
implementation 'com.github.prolificinteractive:material-calendarview:2.0.0'
implementation 'com.jakewharton.threetenabp:threetenabp:1.1.1'
- implementation 'com.google.android.material:material:1.2.0-alpha01'
+ implementation 'com.google.android.material:material:1.2.0-alpha04'
implementation 'com.google.android:flexbox:1.1.0'
implementation 'com.esotericsoftware:kryo:3.0.3'
implementation 'com.squareup.moshi:moshi-kotlin:1.8.0'
diff --git a/app/src/main/java/me/anon/grow/MainApplication.java b/app/src/main/java/me/anon/grow/MainApplication.java
index d56d5b30..9344c7ba 100644
--- a/app/src/main/java/me/anon/grow/MainApplication.java
+++ b/app/src/main/java/me/anon/grow/MainApplication.java
@@ -1,9 +1,7 @@
package me.anon.grow;
import android.app.AlarmManager;
-import android.app.Application;
import android.app.PendingIntent;
-import android.app.backup.BackupManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -34,6 +32,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
+import androidx.multidex.MultiDexApplication;
import me.anon.controller.receiver.BackupService;
import me.anon.lib.handler.ExceptionHandler;
import me.anon.lib.helper.BackupHelper;
@@ -44,14 +43,7 @@
import me.anon.lib.stream.DecryptInputStream;
import me.anon.lib.stream.EncryptOutputStream;
-/**
- * // TODO: Add class description
- *
- * @author 7LPdWcaW
- * @documentation // TODO Reference flow doc
- * @project GrowTracker
- */
-public class MainApplication extends Application
+public class MainApplication extends MultiDexApplication
{
private static DisplayImageOptions displayImageOptions;
private static boolean encrypted = false;
diff --git a/build.gradle b/build.gradle
index 4475281b..e55432de 100644
--- a/build.gradle
+++ b/build.gradle
@@ -9,7 +9,7 @@ buildscript {
dependencies {
- classpath 'com.android.tools.build:gradle:3.4.2'
+ classpath 'com.android.tools.build:gradle:3.5.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.41"
// NOTE: Do not place your application dependencies here; they belong
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index b4c566b9..a89f7e94 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Fri Aug 09 12:48:32 BST 2019
+#Fri Feb 14 12:54:10 GMT 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
From cd0279288a1bf07a45a99acd080c217426366291 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 16 Feb 2020 16:41:50 +0000
Subject: [PATCH 006/152] Initial general stats refactor
---
app/build.gradle | 1 +
app/src/main/AndroidManifest.xml | 2 +-
.../java/me/anon/grow/StatisticsActivity.kt | 16 ++-
.../anon/grow/fragment/StatisticsFragment2.kt | 107 +++++++++++++++++-
app/src/main/res/layout/statistics2_view.xml | 50 ++++++++
5 files changed, 164 insertions(+), 12 deletions(-)
create mode 100644 app/src/main/res/layout/statistics2_view.xml
diff --git a/app/build.gradle b/app/build.gradle
index 9236fb8f..7b5e01c9 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -118,6 +118,7 @@ android {
dependencies {
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'androidx.core:core:1.1.0'
+ implementation 'androidx.core:core-ktx:1.1.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.preference:preference:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5193da2d..7f8f5ee0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -66,7 +66,7 @@
-
+
diff --git a/app/src/main/java/me/anon/grow/StatisticsActivity.kt b/app/src/main/java/me/anon/grow/StatisticsActivity.kt
index 4d65b25b..e15e8a13 100644
--- a/app/src/main/java/me/anon/grow/StatisticsActivity.kt
+++ b/app/src/main/java/me/anon/grow/StatisticsActivity.kt
@@ -3,6 +3,8 @@ package me.anon.grow
import android.os.Bundle
import kotlinx.android.synthetic.main.fragment_holder.*
import me.anon.grow.fragment.StatisticsFragment
+import me.anon.grow.fragment.StatisticsFragment2
+import me.anon.lib.manager.PlantManager
class StatisticsActivity : BaseActivity()
{
@@ -13,16 +15,18 @@ class StatisticsActivity : BaseActivity()
setContentView(R.layout.fragment_holder)
setSupportActionBar(toolbar)
- if (intent.extras == null || !intent.hasExtra("plant"))
- {
- finish()
- return
- }
+// if (intent.extras == null || !intent.hasExtra("plant"))
+// {
+// finish()
+// return
+// }
+
+ intent.putExtra("plant", PlantManager.instance.plants[0])
if (supportFragmentManager.findFragmentByTag("fragment") == null)
{
supportFragmentManager.beginTransaction()
- .replace(R.id.coordinator, StatisticsFragment.newInstance(intent.extras), "fragment")
+ .replace(R.id.coordinator, StatisticsFragment2.newInstance(intent.extras!!), "fragment")
.commit()
}
}
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index b631128c..047ab0dd 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -4,13 +4,19 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.TextView
+import androidx.core.view.plusAssign
import androidx.fragment.app.Fragment
+import kotlinx.android.synthetic.main.data_label_stub.view.*
+import kotlinx.android.synthetic.main.statistics2_view.*
import me.anon.grow.R
import me.anon.lib.TdsUnit
-import me.anon.lib.TdsUnit.Companion.getSelectedTdsUnit
import me.anon.lib.Unit
-import me.anon.lib.ext.inflate
-import me.anon.model.Plant
+import me.anon.lib.ext.formatWhole
+import me.anon.lib.helper.TimeHelper
+import me.anon.model.*
+import java.lang.Math.abs
+import kotlin.math.ceil
/**
* // TODO: Add class description
@@ -20,7 +26,7 @@ class StatisticsFragment2 : Fragment()
companion object
{
@JvmStatic
- public fun newInstance(args: Bundle) = StatisticsFragment().apply {
+ public fun newInstance(args: Bundle) = StatisticsFragment2().apply {
this.arguments = args
}
}
@@ -31,10 +37,101 @@ class StatisticsFragment2 : Fragment()
private val selectedMeasurementUnit by lazy { Unit.getSelectedMeasurementUnit(activity!!) }
private val checkedAdditives = setOf()
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = inflater.inflate(R.layout.statistics_view, container, false)
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
+ = inflater.inflate(R.layout.statistics2_view, container, false)
override fun onActivityCreated(savedInstanceState: Bundle?)
{
super.onActivityCreated(savedInstanceState)
+
+ (savedInstanceState ?: arguments)?.let {
+ plant = it.getParcelable("plant") as Plant
+ }
+
+ if (!::plant.isInitialized) return
+
+ populateGeneralStats()
+ }
+
+ private fun populateGeneralStats()
+ {
+ class template(val label: String, val data: String)
+ val statTemplates = arrayListOf()
+
+ stats_container.removeAllViews()
+ val plantStages = plant.calculateStageTime()
+ plantStages.remove(PlantStage.HARVESTED)
+ PlantStage.values().forEach { stage ->
+ if (plantStages.containsKey(stage))
+ {
+ plantStages[stage]?.let { time ->
+ statTemplates += template(
+ label = "${getString(stage.printString)}:",
+ data = "${TimeHelper.toDays(time).toInt()} ${resources.getQuantityString(R.plurals.time_day, TimeHelper.toDays(time).toInt())}"
+ )
+ }
+ }
+ }
+
+ val startDate = plant.plantDate
+ var endDate = System.currentTimeMillis()
+ var waterDifference = 0L
+ var lastWater = 0L
+ var totalWater = 0
+ var totalFlush = 0
+
+ plant.actions?.forEach { action ->
+ when (action)
+ {
+ is StageChange -> {
+ if (action.newStage == PlantStage.HARVESTED) endDate = action.date
+ }
+
+ is Water -> {
+ if (lastWater != 0L) waterDifference += abs(action.date - lastWater)
+ totalWater++
+ lastWater = action.date
+ }
+
+ is EmptyAction -> {
+ if (action.action == Action.ActionName.FLUSH) totalFlush++
+ }
+ }
+ }
+
+ val days = ((endDate - startDate) / 1000.0) * 0.0000115741
+
+ // total time
+ statTemplates += template(
+ label = getString(R.string.total_time_label),
+ data = "${days.formatWhole()} ${resources.getQuantityString(R.plurals.time_day, days.toInt())}"
+ )
+
+ // total waters
+ statTemplates += template(
+ label = getString(R.string.total_waters_label),
+ data = "${totalWater.formatWhole()}"
+ )
+
+ // total flushes
+ statTemplates += template(
+ label = getString(R.string.total_flushes_label),
+ data = "${totalFlush.formatWhole()}"
+ )
+
+ // ave time between water
+ statTemplates += template(
+ label = getString(R.string.ave_time_between_water_label),
+ data = (TimeHelper.toDays(waterDifference) / totalWater).let { d ->
+ "${d.formatWhole()} ${resources.getQuantityString(R.plurals.time_day, ceil(d).toInt())}"
+ }
+ )
+
+ statTemplates.forEach {
+ val dataView = LayoutInflater.from(activity).inflate(R.layout.data_label_stub, stats_container, false)
+ dataView.label.text = it.label
+ dataView.data.text = it.data
+ stats_container += dataView
+ }
}
}
diff --git a/app/src/main/res/layout/statistics2_view.xml b/app/src/main/res/layout/statistics2_view.xml
new file mode 100644
index 00000000..84640d07
--- /dev/null
+++ b/app/src/main/res/layout/statistics2_view.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
From adae29132e6b6a4ef7abf7fc04e9da970992691e Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 16 Feb 2020 17:39:31 +0000
Subject: [PATCH 007/152] Adds average watering between stages functionality
---
.../anon/grow/fragment/StatisticsFragment2.kt | 26 +++++++++++++++++++
app/src/main/res/values/strings.xml | 1 +
2 files changed, 27 insertions(+)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index 047ab0dd..7171ad2f 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -7,6 +7,7 @@ import android.view.ViewGroup
import android.widget.TextView
import androidx.core.view.plusAssign
import androidx.fragment.app.Fragment
+import kotlinx.android.synthetic.main.action_buttons_stub.*
import kotlinx.android.synthetic.main.data_label_stub.view.*
import kotlinx.android.synthetic.main.statistics2_view.*
import me.anon.grow.R
@@ -73,6 +74,13 @@ class StatisticsFragment2 : Fragment()
}
}
+ val aveStageWaters = LinkedHashMap>()
+ aveStageWaters.putAll(plantStages.keys.map { it }.associateWith { arrayListOf() })
+ val stageChanges = plant.getStages()
+ stageChanges.toSortedMap(Comparator { first, second ->
+ (stageChanges[first]?.date ?: 0).compareTo(stageChanges[second]?.date ?: 0)
+ })
+
val startDate = plant.plantDate
var endDate = System.currentTimeMillis()
var waterDifference = 0L
@@ -91,6 +99,10 @@ class StatisticsFragment2 : Fragment()
if (lastWater != 0L) waterDifference += abs(action.date - lastWater)
totalWater++
lastWater = action.date
+
+ // find the stage change where the date is older than the watering
+ val stage = stageChanges.filterValues { it.date <= action.date }.toSortedMap().lastKey()
+ aveStageWaters.getOrPut(stage, { arrayListOf() }).add(action.date)
}
is EmptyAction -> {
@@ -127,6 +139,20 @@ class StatisticsFragment2 : Fragment()
}
)
+ // ave water time between stages
+ aveStageWaters.forEach { (stage, dates) ->
+ if (dates.isNotEmpty())
+ {
+ var dateDifference = dates.last() - dates.first()
+ statTemplates += template(
+ label = getString(R.string.ave_time_stage_label, stage.enString),
+ data = (TimeHelper.toDays(dateDifference) / dates.size).let { d ->
+ "${d.formatWhole()} ${resources.getQuantityString(R.plurals.time_day, ceil(d).toInt())}"
+ }
+ )
+ }
+ }
+
statTemplates.forEach {
val dataView = LayoutInflater.from(activity).inflate(R.layout.data_label_stub, stats_container, false)
dataView.label.text = it.label
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 765f15b8..4920a56e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -144,6 +144,7 @@
Total waters:
Total flushes:
Ave. time between water:
+ Ave. %s water:
Filter additives
pH
From 80d650fe04d875f39e68e34caa3085222904cfb9 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Wed, 26 Feb 2020 09:50:15 +0000
Subject: [PATCH 008/152] Sorts average times by stage ordinal
---
.../anon/grow/fragment/StatisticsFragment2.kt | 24 ++++++++++---------
1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index 7171ad2f..3f47ba95 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -140,18 +140,20 @@ class StatisticsFragment2 : Fragment()
)
// ave water time between stages
- aveStageWaters.forEach { (stage, dates) ->
- if (dates.isNotEmpty())
- {
- var dateDifference = dates.last() - dates.first()
- statTemplates += template(
- label = getString(R.string.ave_time_stage_label, stage.enString),
- data = (TimeHelper.toDays(dateDifference) / dates.size).let { d ->
- "${d.formatWhole()} ${resources.getQuantityString(R.plurals.time_day, ceil(d).toInt())}"
- }
- )
+ aveStageWaters
+ .toSortedMap(Comparator { first, second -> first.ordinal.compareTo(second.ordinal) })
+ .forEach { (stage, dates) ->
+ if (dates.isNotEmpty())
+ {
+ var dateDifference = dates.last() - dates.first()
+ statTemplates += template(
+ label = getString(R.string.ave_time_stage_label, stage.enString),
+ data = (TimeHelper.toDays(dateDifference) / dates.size).let { d ->
+ "${d.formatWhole()} ${resources.getQuantityString(R.plurals.time_day, ceil(d).toInt())}"
+ }
+ )
+ }
}
- }
statTemplates.forEach {
val dataView = LayoutInflater.from(activity).inflate(R.layout.data_label_stub, stats_container, false)
From 6854aa40efaedf98eed9cbf4a843ef6cdd9afe06 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Wed, 26 Feb 2020 10:11:03 +0000
Subject: [PATCH 009/152] Adds total water amount stat
---
.../anon/grow/fragment/StatisticsFragment2.kt | 52 +++++++++++++++----
app/src/main/java/me/anon/lib/Unit.java | 2 +-
app/src/main/res/layout/subtitle_stub.xml | 10 ++++
app/src/main/res/values/dimens.xml | 1 +
app/src/main/res/values/strings.xml | 1 +
5 files changed, 54 insertions(+), 12 deletions(-)
create mode 100644 app/src/main/res/layout/subtitle_stub.xml
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index 3f47ba95..83bd6d6e 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -56,7 +56,10 @@ class StatisticsFragment2 : Fragment()
private fun populateGeneralStats()
{
- class template(val label: String, val data: String)
+ open class template()
+ open class header(var label: String) : template()
+ open class data(label: String, val data: String) : header(label)
+
val statTemplates = arrayListOf()
stats_container.removeAllViews()
@@ -66,7 +69,7 @@ class StatisticsFragment2 : Fragment()
if (plantStages.containsKey(stage))
{
plantStages[stage]?.let { time ->
- statTemplates += template(
+ statTemplates += data(
label = "${getString(stage.printString)}:",
data = "${TimeHelper.toDays(time).toInt()} ${resources.getQuantityString(R.plurals.time_day, TimeHelper.toDays(time).toInt())}"
)
@@ -86,6 +89,7 @@ class StatisticsFragment2 : Fragment()
var waterDifference = 0L
var lastWater = 0L
var totalWater = 0
+ var totalWaterAmount = 0.0
var totalFlush = 0
plant.actions?.forEach { action ->
@@ -98,6 +102,7 @@ class StatisticsFragment2 : Fragment()
is Water -> {
if (lastWater != 0L) waterDifference += abs(action.date - lastWater)
totalWater++
+ totalWaterAmount += action.amount ?: 0.0
lastWater = action.date
// find the stage change where the date is older than the watering
@@ -114,25 +119,33 @@ class StatisticsFragment2 : Fragment()
val days = ((endDate - startDate) / 1000.0) * 0.0000115741
// total time
- statTemplates += template(
+ statTemplates += data(
label = getString(R.string.total_time_label),
data = "${days.formatWhole()} ${resources.getQuantityString(R.plurals.time_day, days.toInt())}"
)
+ statTemplates += header("Water stats")
+
// total waters
- statTemplates += template(
+ statTemplates += data(
label = getString(R.string.total_waters_label),
data = "${totalWater.formatWhole()}"
)
// total flushes
- statTemplates += template(
+ statTemplates += data(
label = getString(R.string.total_flushes_label),
data = "${totalFlush.formatWhole()}"
)
+ // total water amount
+ statTemplates += data(
+ label = getString(R.string.total_water_amount_label),
+ data = "${Unit.ML.to(selectedDeliveryUnit, totalWaterAmount).formatWhole()} ${selectedDeliveryUnit.label}"
+ )
+
// ave time between water
- statTemplates += template(
+ statTemplates += data(
label = getString(R.string.ave_time_between_water_label),
data = (TimeHelper.toDays(waterDifference) / totalWater).let { d ->
"${d.formatWhole()} ${resources.getQuantityString(R.plurals.time_day, ceil(d).toInt())}"
@@ -146,7 +159,7 @@ class StatisticsFragment2 : Fragment()
if (dates.isNotEmpty())
{
var dateDifference = dates.last() - dates.first()
- statTemplates += template(
+ statTemplates += data(
label = getString(R.string.ave_time_stage_label, stage.enString),
data = (TimeHelper.toDays(dateDifference) / dates.size).let { d ->
"${d.formatWhole()} ${resources.getQuantityString(R.plurals.time_day, ceil(d).toInt())}"
@@ -155,10 +168,27 @@ class StatisticsFragment2 : Fragment()
}
}
- statTemplates.forEach {
- val dataView = LayoutInflater.from(activity).inflate(R.layout.data_label_stub, stats_container, false)
- dataView.label.text = it.label
- dataView.data.text = it.data
+ statTemplates.forEach { template ->
+ var dataView = when (template)
+ {
+ is data -> {
+ LayoutInflater.from(activity).inflate(R.layout.data_label_stub, stats_container, false).also {
+ it.label.text = template.label
+ it.data.text = template.data
+ }
+ }
+
+ is header -> {
+ LayoutInflater.from(activity).inflate(R.layout.subtitle_stub, stats_container, false).also {
+ (it as TextView).text = template.label
+ it.setPadding(0, resources.getDimension(R.dimen.padding_16dp).toInt(), 0, 0)
+ }
+ }
+
+ else -> null
+ }
+
+ dataView ?: return
stats_container += dataView
}
}
diff --git a/app/src/main/java/me/anon/lib/Unit.java b/app/src/main/java/me/anon/lib/Unit.java
index e794ee65..b87535eb 100644
--- a/app/src/main/java/me/anon/lib/Unit.java
+++ b/app/src/main/java/me/anon/lib/Unit.java
@@ -30,7 +30,7 @@ public enum Unit
}
},
- L("l")
+ L("L")
{
@Override public double to(Unit to, double fromValue)
{
diff --git a/app/src/main/res/layout/subtitle_stub.xml b/app/src/main/res/layout/subtitle_stub.xml
new file mode 100644
index 00000000..45b4d6dc
--- /dev/null
+++ b/app/src/main/res/layout/subtitle_stub.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 73bfbd84..7f98f8e2 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -2,6 +2,7 @@
8dp
+ 16dp
4dp
190dp
256dp
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 4920a56e..ad4bf8f0 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -143,6 +143,7 @@
Total time:
Total waters:
Total flushes:
+ Total water used:
Ave. time between water:
Ave. %s water:
Filter additives
From 8a3bc9d22072d1bd49ec653a5cd230c8dfe2dcb9 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Wed, 26 Feb 2020 10:13:55 +0000
Subject: [PATCH 010/152] Adds average watering amount
---
.../main/java/me/anon/grow/fragment/StatisticsFragment2.kt | 6 ++++++
app/src/main/res/values/strings.xml | 1 +
2 files changed, 7 insertions(+)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index 83bd6d6e..7b7372d8 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -144,6 +144,12 @@ class StatisticsFragment2 : Fragment()
data = "${Unit.ML.to(selectedDeliveryUnit, totalWaterAmount).formatWhole()} ${selectedDeliveryUnit.label}"
)
+ // average water amount
+ statTemplates += data(
+ label = getString(R.string.ave_water_amount_label),
+ data = "${Unit.ML.to(selectedDeliveryUnit, (totalWaterAmount / totalWater.toDouble())).formatWhole()} ${selectedDeliveryUnit.label}"
+ )
+
// ave time between water
statTemplates += data(
label = getString(R.string.ave_time_between_water_label),
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index ad4bf8f0..63870f8f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -144,6 +144,7 @@
Total waters:
Total flushes:
Total water used:
+ Ave. water used:
Ave. time between water:
Ave. %s water:
Filter additives
From 8a89ffe9e82f30e9dd58024e89cf3a037e794206 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Wed, 26 Feb 2020 12:36:00 +0000
Subject: [PATCH 011/152] Adds data and stylises stage chart
---
app/build.gradle | 4 +-
.../grow/fragment/GardenTrackerFragment.kt | 196 +--
.../grow/fragment/StatisticsFragment.java | 177 ++-
.../anon/grow/fragment/StatisticsFragment2.kt | 78 ++
.../java/me/anon/lib/helper/StatsHelper.java | 1143 ++++++++---------
app/src/main/res/layout/statistics2_view.xml | 7 +
app/src/main/res/values/arrays.xml | 3 +-
7 files changed, 846 insertions(+), 762 deletions(-)
diff --git a/app/build.gradle b/app/build.gradle
index 7b5e01c9..966e3e61 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -135,11 +135,13 @@ dependencies {
implementation 'com.esotericsoftware:kryo:3.0.3'
implementation 'com.squareup.moshi:moshi-kotlin:1.8.0'
implementation 'com.squareup:otto:1.3.8'
- implementation 'com.github.PhilJay:MPAndroidChart:v2.1.6'
+// api 'com.github.PhilJay:MPAndroidChart:v2.1.6'
implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.6.0'
implementation 'net.lingala.zip4j:zip4j:1.3.2'
+ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
+
api "org.jetbrains.kotlin:kotlin-reflect:1.3.41"
api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.41"
diff --git a/app/src/main/java/me/anon/grow/fragment/GardenTrackerFragment.kt b/app/src/main/java/me/anon/grow/fragment/GardenTrackerFragment.kt
index 7ed6ccd0..01d8c1e5 100644
--- a/app/src/main/java/me/anon/grow/fragment/GardenTrackerFragment.kt
+++ b/app/src/main/java/me/anon/grow/fragment/GardenTrackerFragment.kt
@@ -303,29 +303,29 @@ class GardenTrackerFragment : Fragment()
if (data_container.findViewById(R.id.stats_temp) == null) data_container.addView(view)
}
StatsHelper.setTempData(garden, activity!!, temp, tempAdditional)
- temp.markerView = object : MarkerView(context, R.layout.chart_marker)
- {
- override fun refreshContent(e: Entry, highlight: Highlight)
- {
- val timeFormat = android.text.format.DateFormat.getTimeFormat(context)
- val action = e.data as Action
- var date = ""
-
- if (action != null) date = "\n" + timeFormat.format(Date(action.date))
-
- (findViewById(R.id.content) as TextView).text = e.getVal().formatWhole() + "°" + tempUnit.label + date
- }
-
- override fun getXOffset(xpos: Float): Int
- {
- return -(width / 2)
- }
-
- override fun getYOffset(ypos: Float): Int
- {
- return -height
- }
- }
+// temp.markerView = object : MarkerView(context, R.layout.chart_marker)
+// {
+// override fun refreshContent(e: Entry, highlight: Highlight)
+// {
+// val timeFormat = android.text.format.DateFormat.getTimeFormat(context)
+// val action = e.data as Action
+// var date = ""
+//
+// if (action != null) date = "\n" + timeFormat.format(Date(action.date))
+//
+// (findViewById(R.id.content) as TextView).text = e.getVal().formatWhole() + "°" + tempUnit.label + date
+// }
+//
+// override fun getXOffset(xpos: Float): Int
+// {
+// return -(width / 2)
+// }
+//
+// override fun getYOffset(ypos: Float): Int
+// {
+// return -height
+// }
+// }
temp.notifyDataSetChanged()
temp.postInvalidate()
min_temp.text = if (tempAdditional[0] == "100") "-" else "${tempAdditional[0]}°${tempUnit.label}"
@@ -342,87 +342,87 @@ class GardenTrackerFragment : Fragment()
if (data_container.findViewById(R.id.stats_humidity) == null) data_container.addView(view)
}
StatsHelper.setHumidityData(garden, activity!!, humidity, humidityAdditional)
- humidity.markerView = object : MarkerView(context, R.layout.chart_marker)
- {
- override fun refreshContent(e: Entry, highlight: Highlight)
- {
- val timeFormat = android.text.format.DateFormat.getTimeFormat(context)
- val action = e.data as Action
- var date = ""
-
- if (action != null) date = "\n" + timeFormat.format(Date(action.date))
- (findViewById(R.id.content) as TextView).text = e.getVal().toInt().toString() + "%" + date
- }
-
- override fun getXOffset(xpos: Float): Int
- {
- return -(width / 2)
- }
-
- override fun getYOffset(ypos: Float): Int
- {
- return -height
- }
- }
+// humidity.markerView = object : MarkerView(context, R.layout.chart_marker)
+// {
+// override fun refreshContent(e: Entry, highlight: Highlight)
+// {
+// val timeFormat = android.text.format.DateFormat.getTimeFormat(context)
+// val action = e.data as Action
+// var date = ""
+//
+// if (action != null) date = "\n" + timeFormat.format(Date(action.date))
+// (findViewById(R.id.content) as TextView).text = e.getVal().toInt().toString() + "%" + date
+// }
+//
+// override fun getXOffset(xpos: Float): Int
+// {
+// return -(width / 2)
+// }
+//
+// override fun getYOffset(ypos: Float): Int
+// {
+// return -height
+// }
+// }
humidity.notifyDataSetChanged()
humidity.postInvalidate()
min_humidity.text = if (humidityAdditional[0] == "100") "-" else "${humidityAdditional[0]}%"
max_humidity.text = if (humidityAdditional[1] == "-100") "-" else "${humidityAdditional[1]}%"
ave_humidity.text = "${humidityAdditional[2]}%"
- humidity.setOnChartValueSelectedListener(object : OnChartValueSelectedListener
- {
- override fun onNothingSelected()
- {
- edit_humidity.visibility = View.GONE
- delete_humidity.visibility = View.GONE
- }
-
- override fun onValueSelected(e: Entry?, dataSetIndex: Int, h: Highlight?)
- {
- edit_humidity.visibility = View.VISIBLE
- delete_humidity.visibility = View.VISIBLE
-
- edit_humidity.setOnClickListener {
- (e?.data as HumidityChange?)?.let { current ->
- editAction(current)
- }
- }
-
- delete_humidity.setOnClickListener {
- (e?.data as Action?)?.let {
- deleteAction(it)
- }
- }
- }
- })
-
- temp.setOnChartValueSelectedListener(object : OnChartValueSelectedListener
- {
- override fun onNothingSelected()
- {
- edit_temp.visibility = View.GONE
- delete_temp.visibility = View.GONE
- }
-
- override fun onValueSelected(e: Entry?, dataSetIndex: Int, h: Highlight?)
- {
- edit_temp.visibility = View.VISIBLE
- delete_temp.visibility = View.VISIBLE
-
- edit_temp.setOnClickListener {
- (e?.data as TemperatureChange?)?.let { current ->
- editAction(current)
- }
- }
-
- delete_temp.setOnClickListener {
- (e?.data as Action?)?.let { current ->
- deleteAction(current)
- }
- }
- }
- })
+// humidity.setOnChartValueSelectedListener(object : OnChartValueSelectedListener
+// {
+// override fun onNothingSelected()
+// {
+// edit_humidity.visibility = View.GONE
+// delete_humidity.visibility = View.GONE
+// }
+//
+// override fun onValueSelected(e: Entry?, dataSetIndex: Int, h: Highlight?)
+// {
+// edit_humidity.visibility = View.VISIBLE
+// delete_humidity.visibility = View.VISIBLE
+//
+// edit_humidity.setOnClickListener {
+// (e?.data as HumidityChange?)?.let { current ->
+// editAction(current)
+// }
+// }
+//
+// delete_humidity.setOnClickListener {
+// (e?.data as Action?)?.let {
+// deleteAction(it)
+// }
+// }
+// }
+// })
+//
+// temp.setOnChartValueSelectedListener(object : OnChartValueSelectedListener
+// {
+// override fun onNothingSelected()
+// {
+// edit_temp.visibility = View.GONE
+// delete_temp.visibility = View.GONE
+// }
+//
+// override fun onValueSelected(e: Entry?, dataSetIndex: Int, h: Highlight?)
+// {
+// edit_temp.visibility = View.VISIBLE
+// delete_temp.visibility = View.VISIBLE
+//
+// edit_temp.setOnClickListener {
+// (e?.data as TemperatureChange?)?.let { current ->
+// editAction(current)
+// }
+// }
+//
+// delete_temp.setOnClickListener {
+// (e?.data as Action?)?.let { current ->
+// deleteAction(current)
+// }
+// }
+// }
+// })
general_title.visibility = if (data_container.childCount > 0) View.VISIBLE else View.GONE
data_container.visibility = if (data_container.childCount > 0) View.VISIBLE else View.GONE
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment.java b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment.java
index e50b6c8b..7575a663 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment.java
@@ -19,7 +19,6 @@
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.formatter.ValueFormatter;
-import com.github.mikephil.charting.formatter.YAxisValueFormatter;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.utils.ViewPortHandler;
import com.google.android.flexbox.FlexboxLayout;
@@ -181,26 +180,26 @@ private void setTdsStats()
String[] tdsAdditional = new String[3];
StatsHelper.setTdsData(plant, getActivity(), tds, tdsAdditional, selectedTdsUnit);
- tds.setMarkerView(new MarkerView(getActivity(), R.layout.chart_marker)
- {
- @Override
- public void refreshContent(Entry e, Highlight highlight)
- {
- String val = NumberUtilsKt.formatWhole(e.getVal());
-
- ((TextView)findViewById(R.id.content)).setText(val);
- }
-
- @Override public int getXOffset(float xpos)
- {
- return -(getWidth() / 2);
- }
-
- @Override public int getYOffset(float ypos)
- {
- return -getHeight();
- }
- });
+// tds.setMarkerView(new MarkerView(getActivity(), R.layout.chart_marker)
+// {
+// @Override
+// public void refreshContent(Entry e, Highlight highlight)
+// {
+// String val = NumberUtilsKt.formatWhole(e.getVal());
+//
+// ((TextView)findViewById(R.id.content)).setText(val);
+// }
+//
+// @Override public int getXOffset(float xpos)
+// {
+// return -(getWidth() / 2);
+// }
+//
+// @Override public int getYOffset(float ypos)
+// {
+// return -getHeight();
+// }
+// });
tds.notifyDataSetChanged();
tds.postInvalidate();
mintds.setText(tdsAdditional[0].equals(String.valueOf(Long.MAX_VALUE)) ? "0" : tdsAdditional[0]);
@@ -234,34 +233,34 @@ private void setAdditiveStats()
final Unit measurement = Unit.getSelectedMeasurementUnit(getActivity());
final Unit delivery = Unit.getSelectedDeliveryUnit(getActivity());
- additives.setMarkerView(new MarkerView(getActivity(), R.layout.chart_marker)
- {
- @Override
- public void refreshContent(Entry e, Highlight highlight)
- {
- String val = NumberUtilsKt.formatWhole(e.getVal());
-
- ((TextView)findViewById(R.id.content)).setText(val + measurement.getLabel() + "/" + delivery.getLabel());
-
- int color = IntUtilsKt.resolveColor(R.attr.colorPrimary, getActivity());
- if (e.getData() instanceof Integer)
- {
- color = (int)e.getData();
- }
-
- ((TextView)findViewById(R.id.content)).setTextColor(color);
- }
-
- @Override public int getXOffset(float xpos)
- {
- return -(getWidth() / 2);
- }
-
- @Override public int getYOffset(float ypos)
- {
- return -getHeight();
- }
- });
+// additives.setMarkerView(new MarkerView(getActivity(), R.layout.chart_marker)
+// {
+// @Override
+// public void refreshContent(Entry e, Highlight highlight)
+// {
+// String val = NumberUtilsKt.formatWhole(e.getVal());
+//
+// ((TextView)findViewById(R.id.content)).setText(val + measurement.getLabel() + "/" + delivery.getLabel());
+//
+// int color = IntUtilsKt.resolveColor(R.attr.colorPrimary, getActivity());
+// if (e.getData() instanceof Integer)
+// {
+// color = (int)e.getData();
+// }
+//
+// ((TextView)findViewById(R.id.content)).setTextColor(color);
+// }
+//
+// @Override public int getXOffset(float xpos)
+// {
+// return -(getWidth() / 2);
+// }
+//
+// @Override public int getYOffset(float ypos)
+// {
+// return -getHeight();
+// }
+// });
additives.notifyDataSetChanged();
additives.postInvalidate();
@@ -407,45 +406,45 @@ private void setStatistics()
labels[index--] = getString(plantStage.getPrintString());
}
- entry.add(new BarEntry(yVals, 0));
-
- BarDataSet set = new BarDataSet(entry, "");
- set.setColors(statsColours);
- set.setStackLabels(labels);
- set.setValueTextSize(12.0f);
- set.setValueTextColor(IntUtilsKt.resolveColor(R.attr.chart_label, getActivity()));
- set.setHighlightEnabled(false);
-
- BarData data = new BarData(new String[] { "" }, set);
- data.setValueFormatter(new ValueFormatter()
- {
- @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler)
- {
- return (int)value + getString(R.string.day_abbr);
- }
- });
-
- StatsHelper.styleGraph(stagesChart);
-
- stagesChart.getXAxis().setLabelsToSkip(0);
- stagesChart.getAxisLeft().setValueFormatter(new YAxisValueFormatter()
- {
- @Override public String getFormattedValue(float value, YAxis yAxis)
- {
- return "" + (int)value;
- }
- });
- stagesChart.getAxisRight().setValueFormatter(new YAxisValueFormatter()
- {
- @Override public String getFormattedValue(float value, YAxis yAxis)
- {
- return "" + (int)value;
- }
- });
-
- stagesChart.setMarkerView(null);
- stagesChart.setHighlightPerTapEnabled(false);
- stagesChart.getAxisLeft().setStartAtZero(true);
- stagesChart.setData(data);
+// entry.add(new BarEntry(yVals, 0));
+//
+// BarDataSet set = new BarDataSet(entry, "");
+// set.setColors(statsColours);
+// set.setStackLabels(labels);
+// set.setValueTextSize(12.0f);
+// set.setValueTextColor(IntUtilsKt.resolveColor(R.attr.chart_label, getActivity()));
+// set.setHighlightEnabled(false);
+//
+// BarData data = new BarData(new String[] { "" }, set);
+// data.setValueFormatter(new ValueFormatter()
+// {
+// @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler)
+// {
+// return (int)value + getString(R.string.day_abbr);
+// }
+// });
+//
+// StatsHelper.styleGraph(stagesChart);
+//
+// stagesChart.getXAxis().setLabelsToSkip(0);
+// stagesChart.getAxisLeft().setValueFormatter(new YAxisValueFormatter()
+// {
+// @Override public String getFormattedValue(float value, YAxis yAxis)
+// {
+// return "" + (int)value;
+// }
+// });
+// stagesChart.getAxisRight().setValueFormatter(new YAxisValueFormatter()
+// {
+// @Override public String getFormattedValue(float value, YAxis yAxis)
+// {
+// return "" + (int)value;
+// }
+// });
+//
+// stagesChart.setMarkerView(null);
+// stagesChart.setHighlightPerTapEnabled(false);
+// stagesChart.getAxisLeft().setStartAtZero(true);
+// stagesChart.setData(data);
}
}
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index 7b7372d8..d2103ace 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -1,5 +1,6 @@
package me.anon.grow.fragment
+import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -7,6 +8,13 @@ import android.view.ViewGroup
import android.widget.TextView
import androidx.core.view.plusAssign
import androidx.fragment.app.Fragment
+import com.github.mikephil.charting.components.AxisBase
+import com.github.mikephil.charting.data.BarData
+import com.github.mikephil.charting.data.BarDataSet
+import com.github.mikephil.charting.data.BarEntry
+import com.github.mikephil.charting.data.Entry
+import com.github.mikephil.charting.formatter.ValueFormatter
+import com.github.mikephil.charting.utils.ViewPortHandler
import kotlinx.android.synthetic.main.action_buttons_stub.*
import kotlinx.android.synthetic.main.data_label_stub.view.*
import kotlinx.android.synthetic.main.statistics2_view.*
@@ -18,6 +26,8 @@ import me.anon.lib.helper.TimeHelper
import me.anon.model.*
import java.lang.Math.abs
import kotlin.math.ceil
+import kotlin.math.max
+import kotlin.math.roundToInt
/**
* // TODO: Add class description
@@ -197,5 +207,73 @@ class StatisticsFragment2 : Fragment()
dataView ?: return
stats_container += dataView
}
+
+ // stage chart
+ val entry = arrayListOf()
+ val labels = arrayOfNulls(plantStages.size)
+ val yVals = FloatArray(plantStages.size)
+
+ val statsColours = resources.getStringArray(R.array.stats_colours).map {
+ Color.parseColor(it)
+ }
+
+ var index = plantStages.size - 1
+ for (plantStage in plantStages.keys)
+ {
+ yVals[index] = max(TimeHelper.toDays(plantStages[plantStage] ?: 0).toFloat(), 1f)
+ labels[index--] = getString(plantStage.printString)
+ }
+
+ val stageEntries = arrayListOf()
+ stageEntries += BarEntry(0f, yVals, plantStages.keys.toList().asReversed())
+
+ val stageData = BarDataSet(stageEntries, "")
+ stageData.isHighlightEnabled = false
+ stageData.stackLabels = labels
+ stageData.setColors(statsColours)
+ stageData.valueFormatter = object : ValueFormatter()
+ {
+ override fun getBarStackedLabel(value: Float, stackedEntry: BarEntry?): String
+ {
+ stackedEntry?.let {
+ (it.data as? List)?.let { stages ->
+ val stageIndex = it.yVals.indexOf(value)
+ return "${value.toInt()}${getString(stages[stageIndex].printString)[0].toLowerCase()}"
+ }
+ }
+
+ return super.getBarStackedLabel(value, stackedEntry)
+ }
+ }
+
+ val barData = BarData(stageData)
+
+ stage_chart.data = barData
+ stage_chart.setDrawGridBackground(false)
+ stage_chart.description = null
+ stage_chart.isScaleYEnabled = false
+ stage_chart.setDrawBorders(false)
+ stage_chart.setDrawValueAboveBar(false)
+
+ stage_chart.axisLeft.setDrawGridLines(false)
+ stage_chart.axisLeft.axisMinimum = 0f
+ stage_chart.axisLeft.textColor = 0xffffffff.toInt()
+ stage_chart.axisLeft.valueFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return "${value.toInt()}${getString(R.string.day_abbr)}"
+ }
+ }
+
+ stage_chart.axisRight.setDrawLabels(false)
+ stage_chart.axisRight.setDrawGridLines(false)
+
+ stage_chart.xAxis.setDrawGridLines(false)
+ stage_chart.xAxis.setDrawAxisLine(false)
+ stage_chart.xAxis.setDrawLabels(false)
+
+ stage_chart.legend.textColor = 0xffffffff.toInt()
+ stage_chart.legend.isWordWrapEnabled = true
}
}
diff --git a/app/src/main/java/me/anon/lib/helper/StatsHelper.java b/app/src/main/java/me/anon/lib/helper/StatsHelper.java
index 8ac06f37..84fbcb4b 100644
--- a/app/src/main/java/me/anon/lib/helper/StatsHelper.java
+++ b/app/src/main/java/me/anon/lib/helper/StatsHelper.java
@@ -13,7 +13,6 @@
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.ValueFormatter;
-import com.github.mikephil.charting.formatter.YAxisValueFormatter;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.utils.ColorTemplate;
import com.github.mikephil.charting.utils.ViewPortHandler;
@@ -67,177 +66,177 @@ public class StatsHelper
public static void styleGraph(BarLineChartBase chart)
{
- Context context = new ContextThemeWrapper(chart.getContext(), R.style.AppTheme);
- chart.setDrawGridBackground(false);
- chart.setGridBackgroundColor(0x00ffffff);
- chart.getAxisLeft().setDrawGridLines(false);
- chart.getXAxis().setDrawGridLines(false);
- chart.getLegend().setTextColor(IntUtilsKt.resolveColor(R.attr.colorAccent, context));
- chart.getLegend().setTextSize(12f);
- chart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);
- chart.getXAxis().setTextColor(IntUtilsKt.resolveColor(R.attr.colorAccent, context));
- chart.getXAxis().setTextSize(12f);
- chart.getAxisRight().setEnabled(false);
- chart.getAxisLeft().setTextColor(IntUtilsKt.resolveColor(R.attr.colorAccent, context));
- chart.getAxisLeft().setTextSize(12f);
- chart.getAxisLeft().setValueFormatter(new YAxisValueFormatter()
- {
- @Override public String getFormattedValue(float value, YAxis yAxis)
- {
- return NumberUtilsKt.formatWhole(value);
- }
- });
- chart.getAxisLeft().setStartAtZero(false);
- chart.getAxisRight().setValueFormatter(new YAxisValueFormatter()
- {
- @Override public String getFormattedValue(float value, YAxis yAxis)
- {
- return NumberUtilsKt.formatWhole(value);
- }
- });
- chart.setScaleYEnabled(false);
- chart.setDescription("");
- chart.getAxisLeft().setXOffset(8.0f);
- chart.getLegend().setWordWrapEnabled(true);
- chart.setTouchEnabled(true);
- chart.setHighlightPerTapEnabled(true);
- chart.setNoDataText(context.getString(R.string.no_data));
- chart.setMarkerView(new MarkerView(context, R.layout.chart_marker)
- {
- @Override
- public void refreshContent(Entry e, Highlight highlight)
- {
- ((TextView)findViewById(R.id.content)).setText("" + e.getVal());
- }
-
- @Override public int getXOffset(float xpos)
- {
- return -(getWidth() / 2);
- }
-
- @Override public int getYOffset(float ypos)
- {
- return -getHeight();
- }
- });
+// Context context = new ContextThemeWrapper(chart.getContext(), R.style.AppTheme);
+// chart.setDrawGridBackground(false);
+// chart.setGridBackgroundColor(0x00ffffff);
+// chart.getAxisLeft().setDrawGridLines(false);
+// chart.getXAxis().setDrawGridLines(false);
+// chart.getLegend().setTextColor(IntUtilsKt.resolveColor(R.attr.colorAccent, context));
+// chart.getLegend().setTextSize(12f);
+// chart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);
+// chart.getXAxis().setTextColor(IntUtilsKt.resolveColor(R.attr.colorAccent, context));
+// chart.getXAxis().setTextSize(12f);
+// chart.getAxisRight().setEnabled(false);
+// chart.getAxisLeft().setTextColor(IntUtilsKt.resolveColor(R.attr.colorAccent, context));
+// chart.getAxisLeft().setTextSize(12f);
+// chart.getAxisLeft().setValueFormatter(new YAxisValueFormatter()
+// {
+// @Override public String getFormattedValue(float value, YAxis yAxis)
+// {
+// return NumberUtilsKt.formatWhole(value);
+// }
+// });
+// chart.getAxisLeft().setStartAtZero(false);
+// chart.getAxisRight().setValueFormatter(new YAxisValueFormatter()
+// {
+// @Override public String getFormattedValue(float value, YAxis yAxis)
+// {
+// return NumberUtilsKt.formatWhole(value);
+// }
+// });
+// chart.setScaleYEnabled(false);
+// chart.setDescription("");
+// chart.getAxisLeft().setXOffset(8.0f);
+// chart.getLegend().setWordWrapEnabled(true);
+// chart.setTouchEnabled(true);
+// chart.setHighlightPerTapEnabled(true);
+// chart.setNoDataText(context.getString(R.string.no_data));
+// chart.setMarkerView(new MarkerView(context, R.layout.chart_marker)
+// {
+// @Override
+// public void refreshContent(Entry e, Highlight highlight)
+// {
+// ((TextView)findViewById(R.id.content)).setText("" + e.getVal());
+// }
+//
+// @Override public int getXOffset(float xpos)
+// {
+// return -(getWidth() / 2);
+// }
+//
+// @Override public int getYOffset(float ypos)
+// {
+// return -getHeight();
+// }
+// });
}
public static void styleDataset(Context context, LineDataSet data, int colour)
{
- context = new ContextThemeWrapper(context, R.style.AppTheme);
- data.setValueTextColor(IntUtilsKt.resolveColor(R.attr.colorAccent, context));
- data.setCircleColor(IntUtilsKt.resolveColor(R.attr.colorAccent, context));
- data.setDrawCubic(true);
- data.setCubicIntensity(0.05f);
- data.setLineWidth(2.0f);
- data.setDrawCircleHole(true);
- data.setColor(colour);
- data.setCircleColor(colour);
- data.setCircleSize(4.0f);
- data.setDrawHighlightIndicators(true);
- data.setHighlightEnabled(true);
- data.setHighlightLineWidth(2f);
- data.setHighLightColor(ColorUtils.setAlphaComponent(colour, 96));
- data.setDrawValues(false);
- data.setValueFormatter(formatter);
+// context = new ContextThemeWrapper(context, R.style.AppTheme);
+// data.setValueTextColor(IntUtilsKt.resolveColor(R.attr.colorAccent, context));
+// data.setCircleColor(IntUtilsKt.resolveColor(R.attr.colorAccent, context));
+// data.setDrawCubic(true);
+// data.setCubicIntensity(0.05f);
+// data.setLineWidth(2.0f);
+// data.setDrawCircleHole(true);
+// data.setColor(colour);
+// data.setCircleColor(colour);
+// data.setCircleSize(4.0f);
+// data.setDrawHighlightIndicators(true);
+// data.setHighlightEnabled(true);
+// data.setHighlightLineWidth(2f);
+// data.setHighLightColor(ColorUtils.setAlphaComponent(colour, 96));
+// data.setDrawValues(false);
+// data.setValueFormatter(formatter);
}
public static void setAdditiveData(Plant plant, @NonNull Context context, @Nullable LineChart chart, @NonNull Set checkedAdditives)
{
- final Unit measurement = Unit.getSelectedMeasurementUnit(context);
- final Unit delivery = Unit.getSelectedDeliveryUnit(context);
-
- ArrayList actions = plant.getActions();
- ArrayList>> vals = new ArrayList<>();
- ArrayList xVals = new ArrayList<>();
- final Set additiveNames = new HashSet<>();
- LineData data = new LineData();
- LinkedHashMap stageTimes = plant.getStages();
- double min = Double.MAX_VALUE;
- double max = Double.MIN_VALUE;
-
- for (Action action : actions)
- {
- if (action instanceof Water)
- {
- List actionAdditives = ((Water)action).getAdditives();
- for (Additive additive : actionAdditives)
- {
- double amount = Unit.ML.to(measurement, additive.getAmount());
- additiveNames.add(additive.getDescription());
- min = Math.min(min, amount);
- max = Math.max(max, amount);
- }
-
- PlantStage stage = null;
- long changeDate = 0;
- ListIterator iterator = new ArrayList(stageTimes.keySet()).listIterator(stageTimes.size());
- while (iterator.hasPrevious())
- {
- PlantStage key = iterator.previous();
- Action changeAction = stageTimes.get(key);
- if (action.getDate() > changeAction.getDate())
- {
- stage = key;
- changeDate = changeAction.getDate();
- }
- }
-
- long difference = action.getDate() - changeDate;
- if (stage != null)
- {
- xVals.add(((int)TimeHelper.toDays(difference) + "" + context.getString(stage.getPrintString()).charAt(0)).toLowerCase());
- }
- else
- {
- xVals.add("");
- }
- }
- }
-
- ArrayList namesList = new ArrayList<>(additiveNames);
- ArrayList dataSets = new ArrayList<>();
- final String[] colours = chart.getResources().getStringArray(R.array.stats_colours);
- for (String additiveName : checkedAdditives)
- {
- int index = 0;
- int color = dataSets.size() < colours.length ? Color.parseColor(colours[namesList.indexOf(additiveName)]) : (additiveName.hashCode() + new Random().nextInt(0xffffff));
- ArrayList additiveValues = new ArrayList<>();
- for (Action action : actions)
- {
- if (action instanceof Water)
- {
- for (Additive additive : ((Water)action).getAdditives())
- {
- if (additiveName.equals(additive.getDescription()))
- {
- double amount = Unit.ML.to(measurement, additive.getAmount());
-
- Entry entry = new Entry((float)amount, index);
- entry.setData(color);
- additiveValues.add(entry);
- }
- }
-
- index++;
- }
- }
-
- LineDataSet dataSet = new LineDataSet(additiveValues, additiveName);
-
- StatsHelper.styleDataset(context, dataSet, color);
-
- dataSet.setValueFormatter(StatsHelper.formatter);
- dataSets.add(dataSet);
- }
-
- LineData lineData = new LineData(xVals, dataSets);
- lineData.setValueFormatter(StatsHelper.formatter);
- lineData.setValueTextColor(IntUtilsKt.resolveColor(android.R.attr.textColorSecondary, context));
-
- styleGraph(chart);
-
- chart.setData(lineData);
+// final Unit measurement = Unit.getSelectedMeasurementUnit(context);
+// final Unit delivery = Unit.getSelectedDeliveryUnit(context);
+//
+// ArrayList actions = plant.getActions();
+// ArrayList>> vals = new ArrayList<>();
+// ArrayList xVals = new ArrayList<>();
+// final Set additiveNames = new HashSet<>();
+// LineData data = new LineData();
+// LinkedHashMap stageTimes = plant.getStages();
+// double min = Double.MAX_VALUE;
+// double max = Double.MIN_VALUE;
+//
+// for (Action action : actions)
+// {
+// if (action instanceof Water)
+// {
+// List actionAdditives = ((Water)action).getAdditives();
+// for (Additive additive : actionAdditives)
+// {
+// double amount = Unit.ML.to(measurement, additive.getAmount());
+// additiveNames.add(additive.getDescription());
+// min = Math.min(min, amount);
+// max = Math.max(max, amount);
+// }
+//
+// PlantStage stage = null;
+// long changeDate = 0;
+// ListIterator iterator = new ArrayList(stageTimes.keySet()).listIterator(stageTimes.size());
+// while (iterator.hasPrevious())
+// {
+// PlantStage key = iterator.previous();
+// Action changeAction = stageTimes.get(key);
+// if (action.getDate() > changeAction.getDate())
+// {
+// stage = key;
+// changeDate = changeAction.getDate();
+// }
+// }
+//
+// long difference = action.getDate() - changeDate;
+// if (stage != null)
+// {
+// xVals.add(((int)TimeHelper.toDays(difference) + "" + context.getString(stage.getPrintString()).charAt(0)).toLowerCase());
+// }
+// else
+// {
+// xVals.add("");
+// }
+// }
+// }
+//
+// ArrayList namesList = new ArrayList<>(additiveNames);
+// ArrayList dataSets = new ArrayList<>();
+// final String[] colours = chart.getResources().getStringArray(R.array.stats_colours);
+// for (String additiveName : checkedAdditives)
+// {
+// int index = 0;
+// int color = dataSets.size() < colours.length ? Color.parseColor(colours[namesList.indexOf(additiveName)]) : (additiveName.hashCode() + new Random().nextInt(0xffffff));
+// ArrayList additiveValues = new ArrayList<>();
+// for (Action action : actions)
+// {
+// if (action instanceof Water)
+// {
+// for (Additive additive : ((Water)action).getAdditives())
+// {
+// if (additiveName.equals(additive.getDescription()))
+// {
+// double amount = Unit.ML.to(measurement, additive.getAmount());
+//
+// Entry entry = new Entry((float)amount, index);
+// entry.setData(color);
+// additiveValues.add(entry);
+// }
+// }
+//
+// index++;
+// }
+// }
+//
+// LineDataSet dataSet = new LineDataSet(additiveValues, additiveName);
+//
+// StatsHelper.styleDataset(context, dataSet, color);
+//
+// dataSet.setValueFormatter(StatsHelper.formatter);
+// dataSets.add(dataSet);
+// }
+//
+// LineData lineData = new LineData(xVals, dataSets);
+// lineData.setValueFormatter(StatsHelper.formatter);
+// lineData.setValueTextColor(IntUtilsKt.resolveColor(android.R.attr.textColorSecondary, context));
+//
+// styleGraph(chart);
+//
+// chart.setData(lineData);
}
/**
@@ -249,97 +248,97 @@ public static void setAdditiveData(Plant plant, @NonNull Context context, @Nulla
*/
public static void setInputData(Plant plant, @Nullable Context context, @Nullable LineChart chart, String[] additionalRef)
{
- ArrayList inputVals = new ArrayList<>();
- ArrayList runoffVals = new ArrayList<>();
- ArrayList averageVals = new ArrayList<>();
- ArrayList xVals = new ArrayList<>();
- LineData data = new LineData();
- LinkedHashMap stageTimes = plant.getStages();
- float min = Float.MAX_VALUE;
- float max = Float.MIN_VALUE;
- float totalIn = 0;
-
- int index = 0;
- for (Action action : plant.getActions())
- {
- if (action instanceof Water)
- {
- if (((Water)action).getPh() != null)
- {
- inputVals.add(new Entry(((Water)action).getPh().floatValue(), index));
- min = Math.min(min, ((Water)action).getPh().floatValue());
- max = Math.max(max, ((Water)action).getPh().floatValue());
-
- totalIn += ((Water)action).getPh().floatValue();
- }
-
- if (((Water)action).getRunoff() != null)
- {
- runoffVals.add(new Entry(((Water)action).getRunoff().floatValue(), index));
- min = Math.min(min, ((Water)action).getRunoff().floatValue());
- max = Math.max(max, ((Water)action).getRunoff().floatValue());
- }
-
- PlantStage stage = null;
- long changeDate = 0;
- ListIterator iterator = new ArrayList(stageTimes.keySet()).listIterator(stageTimes.size());
- while (iterator.hasPrevious())
- {
- PlantStage key = iterator.previous();
- Action changeAction = stageTimes.get(key);
- if (action.getDate() > changeAction.getDate())
- {
- stage = key;
- changeDate = changeAction.getDate();
- }
- }
-
- long difference = action.getDate() - changeDate;
- if (stage != null)
- {
- xVals.add(((int)TimeHelper.toDays(difference) + "" + (context != null ? context.getString(stage.getPrintString()) : stage.getEnString()).charAt(0)).toLowerCase());
- }
- else
- {
- xVals.add("");
- }
-
- index++;
- }
- }
-
- if (chart != null && context != null)
- {
- LineDataSet dataSet = new LineDataSet(inputVals, context.getString(R.string.stat_input_ph));
- styleDataset(context, dataSet, ColorTemplate.COLORFUL_COLORS[0]);
-
- LineDataSet runoffDataSet = new LineDataSet(runoffVals, context.getString(R.string.stat_runoff_ph));
- styleDataset(context, dataSet, ColorTemplate.COLORFUL_COLORS[1]);
-
- LineDataSet averageDataSet = new LineDataSet(averageVals, context.getString(R.string.stat_average_ph));
- styleDataset(context, dataSet, ColorTemplate.COLORFUL_COLORS[2]);
- averageDataSet.setValueFormatter(null);
-
- ArrayList dataSets = new ArrayList();
- dataSets.add(dataSet);
- dataSets.add(runoffDataSet);
-
- LineData lineData = new LineData(xVals, dataSets);
- lineData.setValueFormatter(formatter);
-
- styleGraph(chart);
- chart.getAxisLeft().setAxisMinValue(min - 0.5f);
- chart.getAxisLeft().setAxisMaxValue(max + 0.5f);
-
- chart.setData(lineData);
- }
-
- if (additionalRef != null)
- {
- additionalRef[0] = min == Float.MAX_VALUE ? "-" : NumberUtilsKt.formatWhole(min);
- additionalRef[1] = max == Float.MIN_VALUE ? "-" : NumberUtilsKt.formatWhole(max);
- additionalRef[2] = NumberUtilsKt.formatWhole(totalIn / (double)inputVals.size());
- }
+// ArrayList inputVals = new ArrayList<>();
+// ArrayList runoffVals = new ArrayList<>();
+// ArrayList averageVals = new ArrayList<>();
+// ArrayList xVals = new ArrayList<>();
+// LineData data = new LineData();
+// LinkedHashMap stageTimes = plant.getStages();
+// float min = Float.MAX_VALUE;
+// float max = Float.MIN_VALUE;
+// float totalIn = 0;
+//
+// int index = 0;
+// for (Action action : plant.getActions())
+// {
+// if (action instanceof Water)
+// {
+// if (((Water)action).getPh() != null)
+// {
+// inputVals.add(new Entry(((Water)action).getPh().floatValue(), index));
+// min = Math.min(min, ((Water)action).getPh().floatValue());
+// max = Math.max(max, ((Water)action).getPh().floatValue());
+//
+// totalIn += ((Water)action).getPh().floatValue();
+// }
+//
+// if (((Water)action).getRunoff() != null)
+// {
+// runoffVals.add(new Entry(((Water)action).getRunoff().floatValue(), index));
+// min = Math.min(min, ((Water)action).getRunoff().floatValue());
+// max = Math.max(max, ((Water)action).getRunoff().floatValue());
+// }
+//
+// PlantStage stage = null;
+// long changeDate = 0;
+// ListIterator iterator = new ArrayList(stageTimes.keySet()).listIterator(stageTimes.size());
+// while (iterator.hasPrevious())
+// {
+// PlantStage key = iterator.previous();
+// Action changeAction = stageTimes.get(key);
+// if (action.getDate() > changeAction.getDate())
+// {
+// stage = key;
+// changeDate = changeAction.getDate();
+// }
+// }
+//
+// long difference = action.getDate() - changeDate;
+// if (stage != null)
+// {
+// xVals.add(((int)TimeHelper.toDays(difference) + "" + (context != null ? context.getString(stage.getPrintString()) : stage.getEnString()).charAt(0)).toLowerCase());
+// }
+// else
+// {
+// xVals.add("");
+// }
+//
+// index++;
+// }
+// }
+//
+// if (chart != null && context != null)
+// {
+// LineDataSet dataSet = new LineDataSet(inputVals, context.getString(R.string.stat_input_ph));
+// styleDataset(context, dataSet, ColorTemplate.COLORFUL_COLORS[0]);
+//
+// LineDataSet runoffDataSet = new LineDataSet(runoffVals, context.getString(R.string.stat_runoff_ph));
+// styleDataset(context, dataSet, ColorTemplate.COLORFUL_COLORS[1]);
+//
+// LineDataSet averageDataSet = new LineDataSet(averageVals, context.getString(R.string.stat_average_ph));
+// styleDataset(context, dataSet, ColorTemplate.COLORFUL_COLORS[2]);
+// averageDataSet.setValueFormatter(null);
+//
+// ArrayList dataSets = new ArrayList();
+// dataSets.add(dataSet);
+// dataSets.add(runoffDataSet);
+//
+// LineData lineData = new LineData(xVals, dataSets);
+// lineData.setValueFormatter(formatter);
+//
+// styleGraph(chart);
+// chart.getAxisLeft().setAxisMinValue(min - 0.5f);
+// chart.getAxisLeft().setAxisMaxValue(max + 0.5f);
+//
+// chart.setData(lineData);
+// }
+//
+// if (additionalRef != null)
+// {
+// additionalRef[0] = min == Float.MAX_VALUE ? "-" : NumberUtilsKt.formatWhole(min);
+// additionalRef[1] = max == Float.MIN_VALUE ? "-" : NumberUtilsKt.formatWhole(max);
+// additionalRef[2] = NumberUtilsKt.formatWhole(totalIn / (double)inputVals.size());
+// }
}
/**
@@ -351,83 +350,83 @@ public static void setInputData(Plant plant, @Nullable Context context, @Nullabl
*/
public static void setTdsData(Plant plant, @Nullable Context context, @Nullable LineChart chart, String[] additionalRef, TdsUnit selectedUnit)
{
- ArrayList vals = new ArrayList<>();
- ArrayList xVals = new ArrayList<>();
- LineData data = new LineData();
- LinkedHashMap stageTimes = plant.getStages();
-
- float min = Float.MAX_VALUE;
- float max = Float.MIN_VALUE;
- float total = 0f;
-
- int index = 0;
- for (Action action : plant.getActions())
- {
- if (action instanceof Water && ((Water)action).getTds() != null && ((Water)action).getTds().getType() == selectedUnit)
- {
- float value = ((Water)action).getTds().getAmount().floatValue();
-
- vals.add(new Entry(value, index++));
- PlantStage stage = null;
- long changeDate = 0;
- ListIterator iterator = new ArrayList(stageTimes.keySet()).listIterator(stageTimes.size());
- while (iterator.hasPrevious())
- {
- PlantStage key = iterator.previous();
- Action changeAction = stageTimes.get(key);
- if (action.getDate() > changeAction.getDate())
- {
- stage = key;
- changeDate = changeAction.getDate();
- }
- }
-
- long difference = action.getDate() - changeDate;
- if (stage != null)
- {
- xVals.add(((int)TimeHelper.toDays(difference) + "" + (context != null ? context.getString(stage.getPrintString()) : stage.getEnString()).charAt(0)).toLowerCase());
- }
- else
- {
- xVals.add("");
- }
-
- min = Math.min(min, value);
- max = Math.max(max, value);
- total += value;
- }
- }
-
- if (chart != null && context != null)
- {
- LineDataSet dataSet = new LineDataSet(vals, selectedUnit.getLabel());
- styleDataset(context, dataSet, Color.parseColor(context.getResources().getStringArray(R.array.stats_colours)[0]));
- styleGraph(chart);
-
- chart.getAxisLeft().setValueFormatter(new YAxisValueFormatter()
- {
- @Override public String getFormattedValue(float value, YAxis yAxis)
- {
- return NumberUtilsKt.formatWhole(value);
- }
- });
- dataSet.setValueFormatter(new ValueFormatter()
- {
- @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler)
- {
- return NumberUtilsKt.formatWhole(value);
- }
- });
-
- chart.setData(new LineData(xVals, dataSet));
- }
-
- if (additionalRef != null)
- {
- additionalRef[0] = min == Float.MAX_VALUE ? "-" : NumberUtilsKt.formatWhole(min);
- additionalRef[1] = max == Float.MIN_VALUE ? "-" : NumberUtilsKt.formatWhole(max);
- additionalRef[2] = NumberUtilsKt.formatWhole(total / (double)vals.size());
- }
+// ArrayList vals = new ArrayList<>();
+// ArrayList xVals = new ArrayList<>();
+// LineData data = new LineData();
+// LinkedHashMap stageTimes = plant.getStages();
+//
+// float min = Float.MAX_VALUE;
+// float max = Float.MIN_VALUE;
+// float total = 0f;
+//
+// int index = 0;
+// for (Action action : plant.getActions())
+// {
+// if (action instanceof Water && ((Water)action).getTds() != null && ((Water)action).getTds().getType() == selectedUnit)
+// {
+// float value = ((Water)action).getTds().getAmount().floatValue();
+//
+// vals.add(new Entry(value, index++));
+// PlantStage stage = null;
+// long changeDate = 0;
+// ListIterator iterator = new ArrayList(stageTimes.keySet()).listIterator(stageTimes.size());
+// while (iterator.hasPrevious())
+// {
+// PlantStage key = iterator.previous();
+// Action changeAction = stageTimes.get(key);
+// if (action.getDate() > changeAction.getDate())
+// {
+// stage = key;
+// changeDate = changeAction.getDate();
+// }
+// }
+//
+// long difference = action.getDate() - changeDate;
+// if (stage != null)
+// {
+// xVals.add(((int)TimeHelper.toDays(difference) + "" + (context != null ? context.getString(stage.getPrintString()) : stage.getEnString()).charAt(0)).toLowerCase());
+// }
+// else
+// {
+// xVals.add("");
+// }
+//
+// min = Math.min(min, value);
+// max = Math.max(max, value);
+// total += value;
+// }
+// }
+//
+// if (chart != null && context != null)
+// {
+// LineDataSet dataSet = new LineDataSet(vals, selectedUnit.getLabel());
+// styleDataset(context, dataSet, Color.parseColor(context.getResources().getStringArray(R.array.stats_colours)[0]));
+// styleGraph(chart);
+//
+// chart.getAxisLeft().setValueFormatter(new YAxisValueFormatter()
+// {
+// @Override public String getFormattedValue(float value, YAxis yAxis)
+// {
+// return NumberUtilsKt.formatWhole(value);
+// }
+// });
+// dataSet.setValueFormatter(new ValueFormatter()
+// {
+// @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler)
+// {
+// return NumberUtilsKt.formatWhole(value);
+// }
+// });
+//
+// chart.setData(new LineData(xVals, dataSet));
+// }
+//
+// if (additionalRef != null)
+// {
+// additionalRef[0] = min == Float.MAX_VALUE ? "-" : NumberUtilsKt.formatWhole(min);
+// additionalRef[1] = max == Float.MIN_VALUE ? "-" : NumberUtilsKt.formatWhole(max);
+// additionalRef[2] = NumberUtilsKt.formatWhole(total / (double)vals.size());
+// }
}
/**
@@ -445,72 +444,72 @@ public static void setTempData(Plant plant, @NonNull Context context, @Nullable
public static void setTempData(Plant plant, @Nullable Context context, TempUnit tempUnit, @Nullable LineChart chart, String[] additionalRef)
{
- ArrayList vals = new ArrayList<>();
- ArrayList xVals = new ArrayList<>();
- LineData data = new LineData();
- LinkedHashMap stageTimes = plant.getStages();
- float min = Float.MAX_VALUE;
- float max = Float.MIN_VALUE;
- float total = 0;
-
- int index = 0;
- for (Action action : plant.getActions())
- {
- if (action instanceof Water && ((Water)action).getTemp() != null)
- {
- float temperature = (float)TempUnit.CELCIUS.to(tempUnit, ((Water)action).getTemp());
-
- vals.add(new Entry(temperature, index++));
- PlantStage stage = null;
- long changeDate = 0;
- ListIterator iterator = new ArrayList(stageTimes.keySet()).listIterator(stageTimes.size());
- while (iterator.hasPrevious())
- {
- PlantStage key = iterator.previous();
- Action changeAction = stageTimes.get(key);
- if (action.getDate() > changeAction.getDate())
- {
- stage = key;
- changeDate = changeAction.getDate();
- }
- }
-
- long difference = action.getDate() - changeDate;
- if (stage != null)
- {
- xVals.add(((int)TimeHelper.toDays(difference) + "" + (context != null ? context.getString(stage.getPrintString()) : stage.getEnString()).charAt(0)).toLowerCase());
- }
- else
- {
- xVals.add("");
- }
-
- min = Math.min(min, temperature);
- max = Math.max(max, temperature);
- total += temperature;
- }
- }
-
- if (chart != null)
- {
- LineDataSet dataSet = new LineDataSet(vals, context.getString(R.string.stat_temerature));
- styleDataset(context, dataSet, Color.parseColor(context.getResources().getStringArray(R.array.stats_colours)[0]));
-
- LineData lineData = new LineData(xVals, dataSet);
- lineData.setValueFormatter(formatter);
-
- chart.getAxisLeft().setAxisMinValue(min - 5f);
- chart.getAxisLeft().setAxisMaxValue(max + 5f);
- styleGraph(chart);
- chart.setData(lineData);
- }
-
- if (additionalRef != null)
- {
- additionalRef[0] = min == Float.MAX_VALUE ? "-" : NumberUtilsKt.formatWhole((int)min);
- additionalRef[1] = max == Float.MIN_VALUE ? "-" : NumberUtilsKt.formatWhole((int)max);
- additionalRef[2] = NumberUtilsKt.formatWhole((int)(total / (double)vals.size()));
- }
+// ArrayList vals = new ArrayList<>();
+// ArrayList xVals = new ArrayList<>();
+// LineData data = new LineData();
+// LinkedHashMap stageTimes = plant.getStages();
+// float min = Float.MAX_VALUE;
+// float max = Float.MIN_VALUE;
+// float total = 0;
+//
+// int index = 0;
+// for (Action action : plant.getActions())
+// {
+// if (action instanceof Water && ((Water)action).getTemp() != null)
+// {
+// float temperature = (float)TempUnit.CELCIUS.to(tempUnit, ((Water)action).getTemp());
+//
+// vals.add(new Entry(temperature, index++));
+// PlantStage stage = null;
+// long changeDate = 0;
+// ListIterator iterator = new ArrayList(stageTimes.keySet()).listIterator(stageTimes.size());
+// while (iterator.hasPrevious())
+// {
+// PlantStage key = iterator.previous();
+// Action changeAction = stageTimes.get(key);
+// if (action.getDate() > changeAction.getDate())
+// {
+// stage = key;
+// changeDate = changeAction.getDate();
+// }
+// }
+//
+// long difference = action.getDate() - changeDate;
+// if (stage != null)
+// {
+// xVals.add(((int)TimeHelper.toDays(difference) + "" + (context != null ? context.getString(stage.getPrintString()) : stage.getEnString()).charAt(0)).toLowerCase());
+// }
+// else
+// {
+// xVals.add("");
+// }
+//
+// min = Math.min(min, temperature);
+// max = Math.max(max, temperature);
+// total += temperature;
+// }
+// }
+//
+// if (chart != null)
+// {
+// LineDataSet dataSet = new LineDataSet(vals, context.getString(R.string.stat_temerature));
+// styleDataset(context, dataSet, Color.parseColor(context.getResources().getStringArray(R.array.stats_colours)[0]));
+//
+// LineData lineData = new LineData(xVals, dataSet);
+// lineData.setValueFormatter(formatter);
+//
+// chart.getAxisLeft().setAxisMinValue(min - 5f);
+// chart.getAxisLeft().setAxisMaxValue(max + 5f);
+// styleGraph(chart);
+// chart.setData(lineData);
+// }
+//
+// if (additionalRef != null)
+// {
+// additionalRef[0] = min == Float.MAX_VALUE ? "-" : NumberUtilsKt.formatWhole((int)min);
+// additionalRef[1] = max == Float.MIN_VALUE ? "-" : NumberUtilsKt.formatWhole((int)max);
+// additionalRef[2] = NumberUtilsKt.formatWhole((int)(total / (double)vals.size()));
+// }
}
/**
@@ -535,93 +534,93 @@ public static void setTempData(Garden garden, @NonNull Context context, @Nullabl
*/
public static void setTempData(Garden garden, @Nullable Context context, TempUnit tempUnit, @Nullable LineChart chart, String[] additionalRef)
{
- ArrayList vals = new ArrayList<>();
- ArrayList xVals = new ArrayList<>();
- LineData data = new LineData();
- float min = Float.MAX_VALUE;
- float max = Float.MIN_VALUE;
- float total = 0;
-
- int index = 0;
- DateFormat dateFormat = null;
-
- if (context != null)
- {
- dateFormat = android.text.format.DateFormat.getDateFormat(context);
- }
-
- for (Action action : garden.getActions())
- {
- if (action instanceof TemperatureChange)
- {
- String date = "";
-
- if (dateFormat != null)
- {
- date = dateFormat.format(new Date(action.getDate()));
- }
- else
- {
- date = DateTimeUtils.toLocalDateTime(new Timestamp(action.getDate())).format(DateTimeFormatter.ofPattern("yyyy/mm/dd"));
- }
-
- double temperature = TempUnit.CELCIUS.to(tempUnit, ((TemperatureChange)action).getTemp());
-
- Entry entry = new Entry((float)temperature, index++);
- entry.setData(action);
- vals.add(entry);
- xVals.add(date);
-
- min = (float)Math.min(min, temperature);
- max = (float)Math.max(max, temperature);
- total += temperature;
- }
- }
-
- if (chart != null)
- {
- LineDataSet dataSet = new LineDataSet(vals, context.getString(R.string.stat_temerature));
- styleDataset(context, dataSet, Color.parseColor(context.getResources().getStringArray(R.array.stats_colours)[0]));
-
- LineData lineData = new LineData(xVals, dataSet);
- lineData.setValueFormatter(new ValueFormatter()
- {
- @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler)
- {
- return formatter.getFormattedValue(value, entry, dataSetIndex, viewPortHandler) + "°" + tempUnit.getLabel();
- }
- });
-
- chart.getAxisLeft().setAxisMinValue(min - 5f);
- chart.getAxisLeft().setAxisMaxValue(max + 5f);
- styleGraph(chart);
- chart.setData(lineData);
- chart.getAxisLeft().setValueFormatter(new YAxisValueFormatter()
- {
- @Override public String getFormattedValue(float value, YAxis yAxis)
- {
- return String.format("%s°%s", NumberUtilsKt.formatWhole(value), tempUnit.getLabel());
- }
- });
-
- chart.getAxisRight().setValueFormatter(new YAxisValueFormatter()
- {
- @Override public String getFormattedValue(float value, YAxis yAxis)
- {
- return String.format("%s°%s", NumberUtilsKt.formatWhole(value), tempUnit.getLabel());
- }
- });
-
- chart.getXAxis().setYOffset(15.0f);
- chart.setExtraOffsets(0, 0, 30, 0);
- }
-
- if (additionalRef != null)
- {
- additionalRef[0] = min == Float.MAX_VALUE ? "-" : NumberUtilsKt.formatWhole(min);
- additionalRef[1] = max == Float.MIN_VALUE ? "-" : NumberUtilsKt.formatWhole(max);
- additionalRef[2] = NumberUtilsKt.formatWhole(total / (double)vals.size());
- }
+// ArrayList vals = new ArrayList<>();
+// ArrayList xVals = new ArrayList<>();
+// LineData data = new LineData();
+// float min = Float.MAX_VALUE;
+// float max = Float.MIN_VALUE;
+// float total = 0;
+//
+// int index = 0;
+// DateFormat dateFormat = null;
+//
+// if (context != null)
+// {
+// dateFormat = android.text.format.DateFormat.getDateFormat(context);
+// }
+//
+// for (Action action : garden.getActions())
+// {
+// if (action instanceof TemperatureChange)
+// {
+// String date = "";
+//
+// if (dateFormat != null)
+// {
+// date = dateFormat.format(new Date(action.getDate()));
+// }
+// else
+// {
+// date = DateTimeUtils.toLocalDateTime(new Timestamp(action.getDate())).format(DateTimeFormatter.ofPattern("yyyy/mm/dd"));
+// }
+//
+// double temperature = TempUnit.CELCIUS.to(tempUnit, ((TemperatureChange)action).getTemp());
+//
+// Entry entry = new Entry((float)temperature, index++);
+// entry.setData(action);
+// vals.add(entry);
+// xVals.add(date);
+//
+// min = (float)Math.min(min, temperature);
+// max = (float)Math.max(max, temperature);
+// total += temperature;
+// }
+// }
+//
+// if (chart != null)
+// {
+// LineDataSet dataSet = new LineDataSet(vals, context.getString(R.string.stat_temerature));
+// styleDataset(context, dataSet, Color.parseColor(context.getResources().getStringArray(R.array.stats_colours)[0]));
+//
+// LineData lineData = new LineData(xVals, dataSet);
+// lineData.setValueFormatter(new ValueFormatter()
+// {
+// @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler)
+// {
+// return formatter.getFormattedValue(value, entry, dataSetIndex, viewPortHandler) + "°" + tempUnit.getLabel();
+// }
+// });
+//
+// chart.getAxisLeft().setAxisMinValue(min - 5f);
+// chart.getAxisLeft().setAxisMaxValue(max + 5f);
+// styleGraph(chart);
+// chart.setData(lineData);
+// chart.getAxisLeft().setValueFormatter(new YAxisValueFormatter()
+// {
+// @Override public String getFormattedValue(float value, YAxis yAxis)
+// {
+// return String.format("%s°%s", NumberUtilsKt.formatWhole(value), tempUnit.getLabel());
+// }
+// });
+//
+// chart.getAxisRight().setValueFormatter(new YAxisValueFormatter()
+// {
+// @Override public String getFormattedValue(float value, YAxis yAxis)
+// {
+// return String.format("%s°%s", NumberUtilsKt.formatWhole(value), tempUnit.getLabel());
+// }
+// });
+//
+// chart.getXAxis().setYOffset(15.0f);
+// chart.setExtraOffsets(0, 0, 30, 0);
+// }
+//
+// if (additionalRef != null)
+// {
+// additionalRef[0] = min == Float.MAX_VALUE ? "-" : NumberUtilsKt.formatWhole(min);
+// additionalRef[1] = max == Float.MIN_VALUE ? "-" : NumberUtilsKt.formatWhole(max);
+// additionalRef[2] = NumberUtilsKt.formatWhole(total / (double)vals.size());
+// }
}
/**
@@ -633,92 +632,92 @@ public static void setTempData(Garden garden, @Nullable Context context, TempUni
*/
public static void setHumidityData(Garden garden, @Nullable Context context, @Nullable LineChart chart, String[] additionalRef)
{
- ArrayList vals = new ArrayList<>();
- ArrayList xVals = new ArrayList<>();
- LineData data = new LineData();
- float min = Float.MAX_VALUE;
- float max = Float.MIN_VALUE;
- float total = 0;
-
- int index = 0;
- DateFormat dateFormat = null;
-
- if (context != null)
- {
- dateFormat = android.text.format.DateFormat.getDateFormat(context);
- }
-
- for (Action action : garden.getActions())
- {
- if (action instanceof HumidityChange)
- {
- String date = "";
-
- if (dateFormat != null)
- {
- date = dateFormat.format(new Date(action.getDate()));
- }
- else
- {
- date = DateTimeUtils.toLocalDateTime(new Timestamp(action.getDate())).format(DateTimeFormatter.ofPattern("yyyy/mm/dd"));
- }
-
- double humidity = ((HumidityChange)action).getHumidity();
-
- Entry entry = new Entry((float)humidity, index++);
- entry.setData(action);
- vals.add(entry);
- xVals.add(date);
-
- min = (float)Math.min(min, humidity);
- max = (float)Math.max(max, humidity);
- total += humidity;
- }
- }
-
- if (chart != null && context != null)
- {
- LineDataSet dataSet = new LineDataSet(vals, "%");
- styleDataset(context, dataSet, Color.parseColor(context.getResources().getStringArray(R.array.stats_colours)[2]));
-
- LineData lineData = new LineData(xVals, dataSet);
- lineData.setValueFormatter(new ValueFormatter()
- {
- @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler)
- {
- return formatter.getFormattedValue(value, entry, dataSetIndex, viewPortHandler) + "%";
- }
- });
-
- chart.getAxisLeft().setAxisMinValue(min - 5f);
- chart.getAxisLeft().setAxisMaxValue(max + 5f);
- styleGraph(chart);
- chart.setData(lineData);
- chart.getAxisLeft().setValueFormatter(new YAxisValueFormatter()
- {
- @Override public String getFormattedValue(float value, YAxis yAxis)
- {
- return (int)value + "%";
- }
- });
-
- chart.getAxisRight().setValueFormatter(new YAxisValueFormatter()
- {
- @Override public String getFormattedValue(float value, YAxis yAxis)
- {
- return (int)value + "%";
- }
- });
-
- chart.getXAxis().setYOffset(15.0f);
- chart.setExtraOffsets(0, 0, 30, 0);
- }
-
- if (additionalRef != null)
- {
- additionalRef[0] = min == Float.MAX_VALUE ? "-" : NumberUtilsKt.formatWhole((int)min);
- additionalRef[1] = max == Float.MIN_VALUE ? "-" : NumberUtilsKt.formatWhole((int)max);
- additionalRef[2] = NumberUtilsKt.formatWhole((int)(total / (double)vals.size()));
- }
+// ArrayList vals = new ArrayList<>();
+// ArrayList xVals = new ArrayList<>();
+// LineData data = new LineData();
+// float min = Float.MAX_VALUE;
+// float max = Float.MIN_VALUE;
+// float total = 0;
+//
+// int index = 0;
+// DateFormat dateFormat = null;
+//
+// if (context != null)
+// {
+// dateFormat = android.text.format.DateFormat.getDateFormat(context);
+// }
+//
+// for (Action action : garden.getActions())
+// {
+// if (action instanceof HumidityChange)
+// {
+// String date = "";
+//
+// if (dateFormat != null)
+// {
+// date = dateFormat.format(new Date(action.getDate()));
+// }
+// else
+// {
+// date = DateTimeUtils.toLocalDateTime(new Timestamp(action.getDate())).format(DateTimeFormatter.ofPattern("yyyy/mm/dd"));
+// }
+//
+// double humidity = ((HumidityChange)action).getHumidity();
+//
+// Entry entry = new Entry((float)humidity, index++);
+// entry.setData(action);
+// vals.add(entry);
+// xVals.add(date);
+//
+// min = (float)Math.min(min, humidity);
+// max = (float)Math.max(max, humidity);
+// total += humidity;
+// }
+// }
+//
+// if (chart != null && context != null)
+// {
+// LineDataSet dataSet = new LineDataSet(vals, "%");
+// styleDataset(context, dataSet, Color.parseColor(context.getResources().getStringArray(R.array.stats_colours)[2]));
+//
+// LineData lineData = new LineData(xVals, dataSet);
+// lineData.setValueFormatter(new ValueFormatter()
+// {
+// @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler)
+// {
+// return formatter.getFormattedValue(value, entry, dataSetIndex, viewPortHandler) + "%";
+// }
+// });
+//
+// chart.getAxisLeft().setAxisMinValue(min - 5f);
+// chart.getAxisLeft().setAxisMaxValue(max + 5f);
+// styleGraph(chart);
+// chart.setData(lineData);
+// chart.getAxisLeft().setValueFormatter(new YAxisValueFormatter()
+// {
+// @Override public String getFormattedValue(float value, YAxis yAxis)
+// {
+// return (int)value + "%";
+// }
+// });
+//
+// chart.getAxisRight().setValueFormatter(new YAxisValueFormatter()
+// {
+// @Override public String getFormattedValue(float value, YAxis yAxis)
+// {
+// return (int)value + "%";
+// }
+// });
+//
+// chart.getXAxis().setYOffset(15.0f);
+// chart.setExtraOffsets(0, 0, 30, 0);
+// }
+//
+// if (additionalRef != null)
+// {
+// additionalRef[0] = min == Float.MAX_VALUE ? "-" : NumberUtilsKt.formatWhole((int)min);
+// additionalRef[1] = max == Float.MIN_VALUE ? "-" : NumberUtilsKt.formatWhole((int)max);
+// additionalRef[2] = NumberUtilsKt.formatWhole((int)(total / (double)vals.size()));
+// }
}
}
diff --git a/app/src/main/res/layout/statistics2_view.xml b/app/src/main/res/layout/statistics2_view.xml
index 84640d07..1a68e262 100644
--- a/app/src/main/res/layout/statistics2_view.xml
+++ b/app/src/main/res/layout/statistics2_view.xml
@@ -44,6 +44,13 @@
app:dividerDrawableVertical="@drawable/divider_8dp"
/>
+
+
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index 69471845..40be6fff 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -14,12 +14,11 @@
- #469990
- #e6beff
- #9A6324
- - #fffac8
- #800000
- #aaffc3
- #808000
- #ffd8b1
- - #000075
+ - #2222A5
From 5938a97210480f5508b6c1b93f3f279147dc48dc Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Wed, 26 Feb 2020 12:45:50 +0000
Subject: [PATCH 012/152] Tidies up and adds themed styling for labels
---
.../anon/grow/fragment/StatisticsFragment2.kt | 19 ++++++++++++-------
app/src/main/java/me/anon/lib/ext/IntUtils.kt | 10 ++++++----
2 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index d2103ace..3a90deef 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -1,6 +1,7 @@
package me.anon.grow.fragment
import android.graphics.Color
+import android.graphics.Typeface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -22,6 +23,8 @@ import me.anon.grow.R
import me.anon.lib.TdsUnit
import me.anon.lib.Unit
import me.anon.lib.ext.formatWhole
+import me.anon.lib.ext.resolveColor
+import me.anon.lib.ext.resolveDimen
import me.anon.lib.helper.TimeHelper
import me.anon.model.*
import java.lang.Math.abs
@@ -47,6 +50,11 @@ class StatisticsFragment2 : Fragment()
private val selectedDeliveryUnit by lazy { Unit.getSelectedDeliveryUnit(activity!!) }
private val selectedMeasurementUnit by lazy { Unit.getSelectedMeasurementUnit(activity!!) }
private val checkedAdditives = setOf()
+ private val statsColours by lazy {
+ resources.getStringArray(R.array.stats_colours).map {
+ Color.parseColor(it)
+ }
+ }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
= inflater.inflate(R.layout.statistics2_view, container, false)
@@ -209,14 +217,9 @@ class StatisticsFragment2 : Fragment()
}
// stage chart
- val entry = arrayListOf()
val labels = arrayOfNulls(plantStages.size)
val yVals = FloatArray(plantStages.size)
- val statsColours = resources.getStringArray(R.array.stats_colours).map {
- Color.parseColor(it)
- }
-
var index = plantStages.size - 1
for (plantStage in plantStages.keys)
{
@@ -231,6 +234,8 @@ class StatisticsFragment2 : Fragment()
stageData.isHighlightEnabled = false
stageData.stackLabels = labels
stageData.setColors(statsColours)
+ stageData.valueTypeface = Typeface.DEFAULT_BOLD
+ stageData.valueTextSize = 10f
stageData.valueFormatter = object : ValueFormatter()
{
override fun getBarStackedLabel(value: Float, stackedEntry: BarEntry?): String
@@ -257,7 +262,7 @@ class StatisticsFragment2 : Fragment()
stage_chart.axisLeft.setDrawGridLines(false)
stage_chart.axisLeft.axisMinimum = 0f
- stage_chart.axisLeft.textColor = 0xffffffff.toInt()
+ stage_chart.axisLeft.textColor = R.attr.colorOnSurface.resolveColor(context!!)
stage_chart.axisLeft.valueFormatter = object : ValueFormatter()
{
override fun getAxisLabel(value: Float, axis: AxisBase?): String
@@ -273,7 +278,7 @@ class StatisticsFragment2 : Fragment()
stage_chart.xAxis.setDrawAxisLine(false)
stage_chart.xAxis.setDrawLabels(false)
- stage_chart.legend.textColor = 0xffffffff.toInt()
+ stage_chart.legend.textColor = R.attr.colorOnSurface.resolveColor(context!!).toInt()
stage_chart.legend.isWordWrapEnabled = true
}
}
diff --git a/app/src/main/java/me/anon/lib/ext/IntUtils.kt b/app/src/main/java/me/anon/lib/ext/IntUtils.kt
index 66099eac..63a4edc7 100644
--- a/app/src/main/java/me/anon/lib/ext/IntUtils.kt
+++ b/app/src/main/java/me/anon/lib/ext/IntUtils.kt
@@ -3,10 +3,7 @@ package me.anon.lib.ext
import android.content.Context
import android.graphics.drawable.Drawable
import android.util.TypedValue
-import androidx.annotation.AttrRes
-import androidx.annotation.ColorInt
-import androidx.annotation.ColorRes
-import androidx.annotation.DrawableRes
+import androidx.annotation.*
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
@@ -62,6 +59,11 @@ public fun @receiver:ColorRes Int.getColor(themedContext: Context): Int
return ContextCompat.getColor(themedContext, this)
}
+/**
+ * Resolves a colour int from an attr res. Will only work for attr type color/reference (to color res)
+ */
+public fun @receiver:AttrRes Int.resolveDimen(themedContext: Context?): Float = themedContext?.resources?.getDimension(this) ?: 0f
+
/**
* Resolves a drawable object from a drawable res
*/
From 5cd676cf7683eb4e3c202147c896c81a2eec9cf0 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Wed, 26 Feb 2020 13:07:38 +0000
Subject: [PATCH 013/152] Moves common stats code out of local methods and adds
additive chips
---
.../anon/grow/fragment/StatisticsFragment2.kt | 170 +++++++++++-------
app/src/main/res/layout/statistics2_view.xml | 32 ++++
2 files changed, 142 insertions(+), 60 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index 3a90deef..69048444 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -16,8 +16,10 @@ import com.github.mikephil.charting.data.BarEntry
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.formatter.ValueFormatter
import com.github.mikephil.charting.utils.ViewPortHandler
+import com.google.android.material.chip.Chip
import kotlinx.android.synthetic.main.action_buttons_stub.*
import kotlinx.android.synthetic.main.data_label_stub.view.*
+import kotlinx.android.synthetic.main.garden_action_buttons_stub.*
import kotlinx.android.synthetic.main.statistics2_view.*
import me.anon.grow.R
import me.anon.lib.TdsUnit
@@ -37,6 +39,10 @@ import kotlin.math.roundToInt
*/
class StatisticsFragment2 : Fragment()
{
+ open class template()
+ open class header(var label: String) : template()
+ open class data(label: String, val data: String) : header(label)
+
companion object
{
@JvmStatic
@@ -56,6 +62,35 @@ class StatisticsFragment2 : Fragment()
}
}
+ // stat variables
+ val stageChanges by lazy {
+ plant.getStages().also {
+ it.toSortedMap(Comparator { first, second ->
+ (it[first]?.date ?: 0).compareTo(it[second]?.date ?: 0)
+ })
+ }
+ }
+
+ val plantStages by lazy {
+ plant.calculateStageTime().also {
+ it.remove(PlantStage.HARVESTED)
+ }
+ }
+
+ val aveStageWaters by lazy {
+ LinkedHashMap>().also { waters ->
+ waters.putAll(plantStages.keys.map { it }.associateWith { arrayListOf() })
+ }
+ }
+
+ val additives = arrayListOf()
+ var endDate = System.currentTimeMillis()
+ var waterDifference = 0L
+ var lastWater = 0L
+ var totalWater = 0
+ var totalWaterAmount = 0.0
+ var totalFlush = 0
+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
= inflater.inflate(R.layout.statistics2_view, container, false)
@@ -69,47 +104,13 @@ class StatisticsFragment2 : Fragment()
if (!::plant.isInitialized) return
+ calculateStats()
populateGeneralStats()
+ populateAdditiveStates()
}
- private fun populateGeneralStats()
+ private fun calculateStats()
{
- open class template()
- open class header(var label: String) : template()
- open class data(label: String, val data: String) : header(label)
-
- val statTemplates = arrayListOf()
-
- stats_container.removeAllViews()
- val plantStages = plant.calculateStageTime()
- plantStages.remove(PlantStage.HARVESTED)
- PlantStage.values().forEach { stage ->
- if (plantStages.containsKey(stage))
- {
- plantStages[stage]?.let { time ->
- statTemplates += data(
- label = "${getString(stage.printString)}:",
- data = "${TimeHelper.toDays(time).toInt()} ${resources.getQuantityString(R.plurals.time_day, TimeHelper.toDays(time).toInt())}"
- )
- }
- }
- }
-
- val aveStageWaters = LinkedHashMap>()
- aveStageWaters.putAll(plantStages.keys.map { it }.associateWith { arrayListOf() })
- val stageChanges = plant.getStages()
- stageChanges.toSortedMap(Comparator { first, second ->
- (stageChanges[first]?.date ?: 0).compareTo(stageChanges[second]?.date ?: 0)
- })
-
- val startDate = plant.plantDate
- var endDate = System.currentTimeMillis()
- var waterDifference = 0L
- var lastWater = 0L
- var totalWater = 0
- var totalWaterAmount = 0.0
- var totalFlush = 0
-
plant.actions?.forEach { action ->
when (action)
{
@@ -126,6 +127,8 @@ class StatisticsFragment2 : Fragment()
// find the stage change where the date is older than the watering
val stage = stageChanges.filterValues { it.date <= action.date }.toSortedMap().lastKey()
aveStageWaters.getOrPut(stage, { arrayListOf() }).add(action.date)
+
+ additives.addAll(action.additives)
}
is EmptyAction -> {
@@ -133,7 +136,27 @@ class StatisticsFragment2 : Fragment()
}
}
}
+ }
+
+ private fun populateGeneralStats()
+ {
+ val statTemplates = arrayListOf()
+
+ stats_container.removeAllViews()
+
+ PlantStage.values().forEach { stage ->
+ if (plantStages.containsKey(stage))
+ {
+ plantStages[stage]?.let { time ->
+ statTemplates += data(
+ label = "${getString(stage.printString)}:",
+ data = "${TimeHelper.toDays(time).toInt()} ${resources.getQuantityString(R.plurals.time_day, TimeHelper.toDays(time).toInt())}"
+ )
+ }
+ }
+ }
+ val startDate = plant.plantDate
val days = ((endDate - startDate) / 1000.0) * 0.0000115741
// total time
@@ -192,29 +215,7 @@ class StatisticsFragment2 : Fragment()
}
}
- statTemplates.forEach { template ->
- var dataView = when (template)
- {
- is data -> {
- LayoutInflater.from(activity).inflate(R.layout.data_label_stub, stats_container, false).also {
- it.label.text = template.label
- it.data.text = template.data
- }
- }
-
- is header -> {
- LayoutInflater.from(activity).inflate(R.layout.subtitle_stub, stats_container, false).also {
- (it as TextView).text = template.label
- it.setPadding(0, resources.getDimension(R.dimen.padding_16dp).toInt(), 0, 0)
- }
- }
-
- else -> null
- }
-
- dataView ?: return
- stats_container += dataView
- }
+ renderStats(stats_container, statTemplates)
// stage chart
val labels = arrayOfNulls(plantStages.size)
@@ -281,4 +282,53 @@ class StatisticsFragment2 : Fragment()
stage_chart.legend.textColor = R.attr.colorOnSurface.resolveColor(context!!).toInt()
stage_chart.legend.isWordWrapEnabled = true
}
+
+ private fun populateAdditiveStates()
+ {
+ class additiveStat(var total: Double = 0.0, var count: Int = 0)
+
+ val names = HashMap()
+ additives.forEach { additive ->
+ additive.description?.let { key ->
+ names.getOrPut(key, { additiveStat() }).apply {
+ total += additive.amount ?: 0.0
+ count++
+ }
+ }
+ }
+
+ names.forEach { (k, v) ->
+ val chip = Chip(context!!)
+ chip.text = k
+
+ additive_chips_container += chip
+ }
+ }
+
+ private fun renderStats(container: ViewGroup, templates: ArrayList)
+ {
+ templates.forEach { template ->
+ var dataView = when (template)
+ {
+ is data -> {
+ LayoutInflater.from(activity).inflate(R.layout.data_label_stub, stats_container, false).also {
+ it.label.text = template.label
+ it.data.text = template.data
+ }
+ }
+
+ is header -> {
+ LayoutInflater.from(activity).inflate(R.layout.subtitle_stub, stats_container, false).also {
+ (it as TextView).text = template.label
+ it.setPadding(0, resources.getDimension(R.dimen.padding_16dp).toInt(), 0, 0)
+ }
+ }
+
+ else -> null
+ }
+
+ dataView ?: return
+ container += dataView
+ }
+ }
}
diff --git a/app/src/main/res/layout/statistics2_view.xml b/app/src/main/res/layout/statistics2_view.xml
index 1a68e262..f2fd5471 100644
--- a/app/src/main/res/layout/statistics2_view.xml
+++ b/app/src/main/res/layout/statistics2_view.xml
@@ -52,6 +52,38 @@
android:layout_marginBottom="16dp"
/>
+
+
+
+
+
+
+
+
From 685fdb99d53b5f367cb4bddd384503119d930161 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sat, 29 Feb 2020 11:19:08 +0000
Subject: [PATCH 014/152] Adds chips
---
.../anon/grow/fragment/StatisticsFragment2.kt | 30 +++++++++++++++++--
app/src/main/res/layout/filter_chip_stub.xml | 10 +++++++
app/src/main/res/layout/statistics2_view.xml | 22 +++++++++++++-
app/src/main/res/values/strings.xml | 4 +++
4 files changed, 62 insertions(+), 4 deletions(-)
create mode 100644 app/src/main/res/layout/filter_chip_stub.xml
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index 69048444..bc868e8b 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -8,6 +8,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.view.plusAssign
+import androidx.core.view.setMargins
import androidx.fragment.app.Fragment
import com.github.mikephil.charting.components.AxisBase
import com.github.mikephil.charting.data.BarData
@@ -24,6 +25,7 @@ import kotlinx.android.synthetic.main.statistics2_view.*
import me.anon.grow.R
import me.anon.lib.TdsUnit
import me.anon.lib.Unit
+import me.anon.lib.ext.T
import me.anon.lib.ext.formatWhole
import me.anon.lib.ext.resolveColor
import me.anon.lib.ext.resolveDimen
@@ -32,6 +34,7 @@ import me.anon.model.*
import java.lang.Math.abs
import kotlin.math.ceil
import kotlin.math.max
+import kotlin.math.min
import kotlin.math.roundToInt
/**
@@ -285,22 +288,43 @@ class StatisticsFragment2 : Fragment()
private fun populateAdditiveStates()
{
- class additiveStat(var total: Double = 0.0, var count: Int = 0)
+ class additiveStat(var total: Double = 0.0, var count: Int = 0, var min: Double = Double.NaN, var max: Double = Double.NaN)
+
+ fun displayStats(name: String, stat: additiveStat)
+ {
+ val stats = arrayListOf()
+ stats += header(getString(R.string.additive_stat_header, name))
+ stats += data(
+ label = getString(R.string.additive_average_usage_label),
+ data = "${Unit.ML.to(selectedMeasurementUnit, stat.total / stat.count.toDouble()).formatWhole()} ${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ )
+ stats += data(
+ label = getString(R.string.additive_total_usage_label),
+ data = "${Unit.ML.to(selectedMeasurementUnit, stat.total).formatWhole()} ${selectedMeasurementUnit.label}"
+ )
+
+ additives_stats_container.removeAllViews()
+ renderStats(additives_stats_container, stats)
+ }
val names = HashMap()
additives.forEach { additive ->
additive.description?.let { key ->
names.getOrPut(key, { additiveStat() }).apply {
total += additive.amount ?: 0.0
+ min = max(min.isNaN() T Double.MIN_VALUE ?: min, additive.amount ?: 0.0)
+ max = min(max.isNaN() T Double.MIN_VALUE ?: max, additive.amount ?: 0.0)
count++
}
}
}
names.forEach { (k, v) ->
- val chip = Chip(context!!)
+ val chip = LayoutInflater.from(context!!).inflate(R.layout.filter_chip_stub, additive_chips_container, false) as Chip
chip.text = k
-
+ chip.setOnCheckedChangeListener { buttonView, isChecked ->
+ //displayStats(k, v)
+ }
additive_chips_container += chip
}
}
diff --git a/app/src/main/res/layout/filter_chip_stub.xml b/app/src/main/res/layout/filter_chip_stub.xml
new file mode 100644
index 00000000..d2a8156b
--- /dev/null
+++ b/app/src/main/res/layout/filter_chip_stub.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/layout/statistics2_view.xml b/app/src/main/res/layout/statistics2_view.xml
index f2fd5471..3d99a468 100644
--- a/app/src/main/res/layout/statistics2_view.xml
+++ b/app/src/main/res/layout/statistics2_view.xml
@@ -74,15 +74,35 @@
android:padding="16dp"
android:orientation="vertical"
>
-
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 63870f8f..d331327c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -436,4 +436,8 @@
Failed to import plants from file
Import plants from file
Plants successfully imported from file
+
+ %s stats
+ Ave. each feeding:
+ Total amount:
From 001c312e3e31d76973d91fc97e56ed7c0be2fb39 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sat, 29 Feb 2020 11:23:45 +0000
Subject: [PATCH 015/152] Downgrade target SDK because of SAF bullshit
---
app/build.gradle | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/build.gradle b/app/build.gradle
index 9236fb8f..21286bc9 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -28,7 +28,7 @@ android {
defaultConfig {
applicationId "me.anon.grow"
minSdkVersion 17
- targetSdkVersion 29
+ targetSdkVersion 28
versionCode 1370//getCommitCountTotal()
versionName "2.6.1"
versionNameSuffix (travis ? "-alpha" : "")
From 0bdcad66a95586ac17fa31563667b4dc247187d7 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sat, 29 Feb 2020 16:00:14 +0000
Subject: [PATCH 016/152] Adds images to markdown generator
---
.../java/me/anon/lib/export/ExportHelper.kt | 32 ++++++++++++++++---
.../me/anon/lib/export/ExportProcessor.kt | 3 +-
.../java/me/anon/lib/export/HtmlProcessor.kt | 3 +-
.../me/anon/lib/export/MarkdownProcessor.kt | 15 +++++++--
4 files changed, 45 insertions(+), 8 deletions(-)
diff --git a/app/src/main/java/me/anon/lib/export/ExportHelper.kt b/app/src/main/java/me/anon/lib/export/ExportHelper.kt
index 88bd064a..1c875dd6 100644
--- a/app/src/main/java/me/anon/lib/export/ExportHelper.kt
+++ b/app/src/main/java/me/anon/lib/export/ExportHelper.kt
@@ -18,6 +18,7 @@ import me.anon.lib.TdsUnit
import me.anon.lib.TempUnit
import me.anon.lib.helper.NotificationHelper
import me.anon.lib.helper.StatsHelper
+import me.anon.lib.helper.TimeHelper
import me.anon.model.*
import net.lingala.zip4j.core.ZipFile
import net.lingala.zip4j.model.ZipParameters
@@ -26,6 +27,8 @@ import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileInputStream
+import java.text.SimpleDateFormat
+import java.time.format.DateTimeFormatter
import java.util.*
import kotlin.collections.ArrayList
@@ -137,7 +140,8 @@ class ExportHelper(
processor.printPlantStats(plant)
processor.printPlantActions(plant)
- val imagePaths = arrayListOf()
+ val imagePaths = sortedMapOf>()
+ val stages = plant.getStages()
for (filePath in plant.images!!)
{
try
@@ -150,7 +154,28 @@ class ExportHelper(
fileDate = currentImage.lastModified()
}
- imagePaths.add(zipPathPrefix + "images/" + dateFolder(context, fileDate) + "/" + fileDate + ".jpg")
+ val totalDays = TimeHelper.toDays(Math.abs(fileDate - plant.plantDate)).toInt()
+ var stageChange: StageChange? = null
+ with (stages.keys.iterator())
+ {
+ while (this.hasNext())
+ {
+ val k = next()
+ stages[k]?.let { action ->
+ if (action.date <= fileDate && stageChange == null)
+ {
+ stageChange = action as? StageChange
+ }
+ }
+ }
+ }
+
+ var dateSuffix = ""
+ stageChange?.let { change ->
+ dateSuffix = " ${totalDays}/" + TimeHelper.toDays(fileDate - change.date).toInt() + context.getString(change.newStage.printString)[0].toLowerCase()
+ }
+
+ imagePaths.getOrPut(dateFolder(context, fileDate) + dateSuffix) { arrayListOf() }.add(zipPathPrefix + "images/" + dateFolder(context, fileDate) + "/" + fileDate + ".jpg")
}
catch (e: java.lang.Exception)
{
@@ -586,8 +611,7 @@ class ExportHelper(
@JvmStatic
fun dateFolder(context: Context, timestamp: Long): String
{
- val dateFormat = android.text.format.DateFormat.getDateFormat(context)
- return dateFormat.format(Date(timestamp)).replace("[^0-9]".toRegex(), "-")
+ return SimpleDateFormat("yyyy-MM-dd").format(Date(timestamp)).replace("[^0-9]".toRegex(), "-")
}
}
}
diff --git a/app/src/main/java/me/anon/lib/export/ExportProcessor.kt b/app/src/main/java/me/anon/lib/export/ExportProcessor.kt
index 527b444e..546ca975 100644
--- a/app/src/main/java/me/anon/lib/export/ExportProcessor.kt
+++ b/app/src/main/java/me/anon/lib/export/ExportProcessor.kt
@@ -6,6 +6,7 @@ import me.anon.lib.Unit
import me.anon.model.Garden
import me.anon.model.Plant
import net.lingala.zip4j.core.ZipFile
+import java.util.*
/**
* Defines methods to interact with when processing the export data
@@ -24,7 +25,7 @@ open abstract class ExportProcessor
open abstract fun printPlantStages(plant: Plant)
open abstract fun printPlantStats(plant: Plant)
open abstract fun printPlantActions(plant: Plant)
- open abstract fun printPlantImages(arrayList: ArrayList)
+ open abstract fun printPlantImages(map: SortedMap>)
open abstract fun printGardenDetails(garden: Garden)
open abstract fun printGardenStats(garden: Garden)
diff --git a/app/src/main/java/me/anon/lib/export/HtmlProcessor.kt b/app/src/main/java/me/anon/lib/export/HtmlProcessor.kt
index 37c14887..bb0e426d 100644
--- a/app/src/main/java/me/anon/lib/export/HtmlProcessor.kt
+++ b/app/src/main/java/me/anon/lib/export/HtmlProcessor.kt
@@ -3,6 +3,7 @@ package me.anon.lib.export
import me.anon.model.Garden
import me.anon.model.Plant
import net.lingala.zip4j.core.ZipFile
+import java.util.*
/**
* // TODO: Add class description
@@ -39,7 +40,7 @@ class HtmlProcessor : ExportProcessor()
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
- override fun printPlantImages(arrayList: ArrayList)
+ override fun printPlantImages(map: SortedMap>)
{
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
diff --git a/app/src/main/java/me/anon/lib/export/MarkdownProcessor.kt b/app/src/main/java/me/anon/lib/export/MarkdownProcessor.kt
index d9818299..fc59eb5f 100644
--- a/app/src/main/java/me/anon/lib/export/MarkdownProcessor.kt
+++ b/app/src/main/java/me/anon/lib/export/MarkdownProcessor.kt
@@ -311,7 +311,7 @@ class MarkdownProcessor : ExportProcessor()
if (action.additives.isNotEmpty())
{
documentBuilder.append(" / ")
- action.additives.forEach { additive ->
+ action.additives.sortedBy { it.description ?: "" }.forEach { additive ->
documentBuilder.append("**${additive.description ?: ""}:** ").append(Unit.ML.to(selectedMeasurement, additive.amount ?: 0.0).formatWhole()).append(selectedMeasurement!!.label).append("/").append(selectedDelivery!!.label)
if (action.additives.last() != additive) documentBuilder.append(" – ")
}
@@ -337,8 +337,19 @@ class MarkdownProcessor : ExportProcessor()
documentBuilder.append(NEW_LINE)
}
- override fun printPlantImages(arrayList: ArrayList)
+ override fun printPlantImages(map: SortedMap>)
{
+ documentBuilder.append("## Images")
+ documentBuilder.append(NEW_LINE + NEW_LINE)
+
+ map.forEach { (k, items) ->
+ documentBuilder.append("### $k")
+ documentBuilder.append(NEW_LINE + NEW_LINE)
+ items.forEach { item ->
+ documentBuilder.append("")
+ documentBuilder.append(NEW_LINE + NEW_LINE)
+ }
+ }
}
override fun printGardenDetails(garden: Garden)
From e00df893a93c1b3a28f4c23abb1c2e44bfd8f222 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sat, 29 Feb 2020 16:00:33 +0000
Subject: [PATCH 017/152] Fixes incorrect bolding for colon
---
.../me/anon/lib/export/MarkdownProcessor.kt | 26 +++++++++----------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/app/src/main/java/me/anon/lib/export/MarkdownProcessor.kt b/app/src/main/java/me/anon/lib/export/MarkdownProcessor.kt
index fc59eb5f..7fe66411 100644
--- a/app/src/main/java/me/anon/lib/export/MarkdownProcessor.kt
+++ b/app/src/main/java/me/anon/lib/export/MarkdownProcessor.kt
@@ -238,18 +238,18 @@ class MarkdownProcessor : ExportProcessor()
val tdsArr = arrayOfNulls(3)
StatsHelper.setTdsData(plant, null, null, tdsArr, tds)
- documentBuilder.append(" - **Minimum input ${tds.enStr}**: ").append(tdsArr[0]).append(tds.label).append(NEW_LINE)
- documentBuilder.append(" - **Maximum input ${tds.enStr}**: ").append(tdsArr[1]).append(tds.label).append(NEW_LINE)
- documentBuilder.append(" - **Average input ${tds.enStr}**: ").append(tdsArr[2]).append(tds.label).append(NEW_LINE + NEW_LINE)
+ documentBuilder.append(" - **Minimum input ${tds.enStr}:** ").append(tdsArr[0]).append(tds.label).append(NEW_LINE)
+ documentBuilder.append(" - **Maximum input ${tds.enStr}:** ").append(tdsArr[1]).append(tds.label).append(NEW_LINE)
+ documentBuilder.append(" - **Average input ${tds.enStr}:** ").append(tdsArr[2]).append(tds.label).append(NEW_LINE + NEW_LINE)
documentBuilder.append("").append(NEW_LINE + NEW_LINE)
}
val aveTemp = arrayOfNulls(3)
StatsHelper.setTempData(plant, null, selectedTemp, null, aveTemp)
documentBuilder.append("### Temperature (°${selectedTemp!!.label})").append(NEW_LINE + NEW_LINE)
- documentBuilder.append(" - **Minimum input temperature**: ").append(aveTemp[0]).append("°${selectedTemp!!.label}").append(NEW_LINE)
- documentBuilder.append(" - **Maximum input temperature**: ").append(aveTemp[1]).append("°${selectedTemp!!.label}").append(NEW_LINE)
- documentBuilder.append(" - **Average input temperature**: ").append(aveTemp[2]).append("°${selectedTemp!!.label}").append(NEW_LINE + NEW_LINE)
+ documentBuilder.append(" - **Minimum input temperature:** ").append(aveTemp[0]).append("°${selectedTemp!!.label}").append(NEW_LINE)
+ documentBuilder.append(" - **Maximum input temperature:** ").append(aveTemp[1]).append("°${selectedTemp!!.label}").append(NEW_LINE)
+ documentBuilder.append(" - **Average input temperature:** ").append(aveTemp[2]).append("°${selectedTemp!!.label}").append(NEW_LINE + NEW_LINE)
documentBuilder.append("").append(NEW_LINE + NEW_LINE)
}
@@ -366,17 +366,17 @@ class MarkdownProcessor : ExportProcessor()
val aveTemp = arrayOfNulls(3)
StatsHelper.setTempData(garden, null, selectedTemp, null, aveTemp)
documentBuilder.append("### Temperature (°${selectedTemp!!.label})").append(NEW_LINE + NEW_LINE)
- documentBuilder.append(" - **Minimum temperature**: ").append(aveTemp[0]).append("°${selectedTemp!!.label}").append(NEW_LINE)
- documentBuilder.append(" - **Maximum temperature**: ").append(aveTemp[1]).append("°${selectedTemp!!.label}").append(NEW_LINE)
- documentBuilder.append(" - **Average temperature**: ").append(aveTemp[2]).append("°${selectedTemp!!.label}").append(NEW_LINE + NEW_LINE)
+ documentBuilder.append(" - **Minimum temperature:** ").append(aveTemp[0]).append("°${selectedTemp!!.label}").append(NEW_LINE)
+ documentBuilder.append(" - **Maximum temperature:** ").append(aveTemp[1]).append("°${selectedTemp!!.label}").append(NEW_LINE)
+ documentBuilder.append(" - **Average temperature:** ").append(aveTemp[2]).append("°${selectedTemp!!.label}").append(NEW_LINE + NEW_LINE)
documentBuilder.append("").append(NEW_LINE + NEW_LINE)
val aveHumidity = arrayOfNulls(3)
StatsHelper.setHumidityData(garden, null, null, aveHumidity)
documentBuilder.append("### Humidity").append(NEW_LINE + NEW_LINE)
- documentBuilder.append(" - **Minimum humidity**: ").append(aveHumidity[0]).append("%").append(NEW_LINE)
- documentBuilder.append(" - **Maximum humidity**: ").append(aveHumidity[1]).append("%").append(NEW_LINE)
- documentBuilder.append(" - **Average humidity**: ").append(aveHumidity[2]).append("%").append(NEW_LINE + NEW_LINE)
+ documentBuilder.append(" - **Minimum humidity:** ").append(aveHumidity[0]).append("%").append(NEW_LINE)
+ documentBuilder.append(" - **Maximum humidity:** ").append(aveHumidity[1]).append("%").append(NEW_LINE)
+ documentBuilder.append(" - **Average humidity:** ").append(aveHumidity[2]).append("%").append(NEW_LINE + NEW_LINE)
documentBuilder.append("").append(NEW_LINE + NEW_LINE)
}
@@ -408,7 +408,7 @@ class MarkdownProcessor : ExportProcessor()
}
is LightingChange -> {
- documentBuilder.append("**Lights on:** ").append(action.on).append(" **Lights off:**: ").append(action.off)
+ documentBuilder.append("**Lights on:** ").append(action.on).append(" **Lights off::** ").append(action.off)
}
else -> documentBuilder.append(" ")
From 88ece8815e244992aac57205366a38ed606b403a Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sat, 29 Feb 2020 16:14:36 +0000
Subject: [PATCH 018/152] Adds garden to water activity
---
.../java/me/anon/grow/AddWateringActivity.kt | 3 +-
.../java/me/anon/grow/EditWateringActivity.kt | 2 +-
.../me/anon/grow/fragment/GardenFragment.java | 1 +
.../anon/grow/fragment/WateringFragment.java | 39 +++++++++++++++++--
4 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/AddWateringActivity.kt b/app/src/main/java/me/anon/grow/AddWateringActivity.kt
index 8aa07508..efa5a40e 100644
--- a/app/src/main/java/me/anon/grow/AddWateringActivity.kt
+++ b/app/src/main/java/me/anon/grow/AddWateringActivity.kt
@@ -15,6 +15,7 @@ class AddWateringActivity : BaseActivity()
setSupportActionBar(toolbar)
var plantIndex: IntArray? = intent.extras?.getIntArray("plant_index") ?: intArrayOf(-1)
+ var gardenIndex: Int = intent.extras?.getInt("garden_index") ?: -1
if (plantIndex == null || plantIndex.size == 0)
{
@@ -24,7 +25,7 @@ class AddWateringActivity : BaseActivity()
if (supportFragmentManager.findFragmentByTag(TAG_FRAGMENT) == null)
{
- supportFragmentManager.beginTransaction().replace(R.id.coordinator, WateringFragment.newInstance(plantIndex, -1), TAG_FRAGMENT).commit()
+ supportFragmentManager.beginTransaction().replace(R.id.coordinator, WateringFragment.newInstance(plantIndex, -1, gardenIndex), TAG_FRAGMENT).commit()
}
}
diff --git a/app/src/main/java/me/anon/grow/EditWateringActivity.kt b/app/src/main/java/me/anon/grow/EditWateringActivity.kt
index cb14639d..caa12977 100644
--- a/app/src/main/java/me/anon/grow/EditWateringActivity.kt
+++ b/app/src/main/java/me/anon/grow/EditWateringActivity.kt
@@ -38,7 +38,7 @@ class EditWateringActivity : BaseActivity()
if (supportFragmentManager.findFragmentByTag("fragment") == null)
{
supportFragmentManager.beginTransaction()
- .replace(R.id.coordinator, WateringFragment.newInstance(intArrayOf(plantIndex), feedingIndex), "fragment")
+ .replace(R.id.coordinator, WateringFragment.newInstance(intArrayOf(plantIndex), feedingIndex, -1), "fragment")
.commit()
}
}
diff --git a/app/src/main/java/me/anon/grow/fragment/GardenFragment.java b/app/src/main/java/me/anon/grow/fragment/GardenFragment.java
index cb961293..2c6b811b 100644
--- a/app/src/main/java/me/anon/grow/fragment/GardenFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/GardenFragment.java
@@ -295,6 +295,7 @@ private synchronized void saveCurrentState()
Intent feed = new Intent(getActivity(), AddWateringActivity.class);
feed.putExtra("plant_index", plants);
+ feed.putExtra("garden_index", GardenManager.getInstance().getGardens().indexOf(garden));
startActivityForResult(feed, 2);
}
diff --git a/app/src/main/java/me/anon/grow/fragment/WateringFragment.java b/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
index 79d8f4e6..e4ed4dd6 100644
--- a/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
@@ -36,18 +36,21 @@
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import me.anon.controller.provider.PlantWidgetProvider;
+import me.anon.grow.BaseActivity;
import me.anon.grow.R;
import me.anon.lib.TdsUnit;
import me.anon.lib.TempUnit;
import me.anon.lib.Unit;
import me.anon.lib.Views;
import me.anon.lib.ext.NumberUtilsKt;
+import me.anon.lib.manager.GardenManager;
import me.anon.lib.manager.PlantManager;
import me.anon.lib.manager.ScheduleManager;
import me.anon.model.Action;
import me.anon.model.Additive;
import me.anon.model.FeedingSchedule;
import me.anon.model.FeedingScheduleDate;
+import me.anon.model.Garden;
import me.anon.model.Plant;
import me.anon.model.Tds;
import me.anon.model.Water;
@@ -79,6 +82,7 @@ public class WateringFragment extends Fragment
@Views.InjectView(R.id.notes) private EditText notes;
private int[] plantIndex = {-1};
+ private int gardenIndex = -1;
private int actionIndex = -1;
private ArrayList plants = new ArrayList<>();
private Water water;
@@ -100,10 +104,11 @@ public class WateringFragment extends Fragment
* @param plantIndex If -1, assume new plant
* @return Instantiated details fragment
*/
- public static WateringFragment newInstance(int[] plantIndex, int feedingIndex)
+ public static WateringFragment newInstance(int[] plantIndex, int feedingIndex, int gardenIndex)
{
Bundle args = new Bundle();
args.putIntArray("plant_index", plantIndex);
+ args.putInt("garden_index", gardenIndex);
args.putInt("action_index", feedingIndex);
WateringFragment fragment = new WateringFragment();
@@ -138,12 +143,14 @@ public static WateringFragment newInstance(int[] plantIndex, int feedingIndex)
if (savedInstanceState != null)
{
plantIndex = savedInstanceState.getIntArray("plant_index");
+ gardenIndex = savedInstanceState.getInt("garden_index");
actionIndex = savedInstanceState.getInt("action_index");
water = savedInstanceState.getParcelable("water");
}
else if (getArguments() != null)
{
plantIndex = getArguments().getIntArray("plant_index");
+ gardenIndex = getArguments().getInt("garden_index");
actionIndex = getArguments().getInt("action_index");
if (actionIndex > -1 && plantIndex.length == 1)
@@ -176,6 +183,33 @@ else if (getArguments() != null)
return;
}
+ if (getActivity() instanceof BaseActivity)
+ {
+ Garden garden = null;
+ if (gardenIndex > -1)
+ {
+ garden = GardenManager.getInstance().getGardens().get(gardenIndex);
+ }
+
+ if (plants.size() == 1)
+ {
+ getActivity().setTitle(getString(R.string.feeding_single_title, plants.get(0).getName()));
+ }
+ else
+ {
+ getActivity().setTitle(getString(R.string.feeding_single_title, garden == null ? "" : garden.getName()));
+ String subtitle = "";
+ for (Plant plant : plants)
+ {
+ if (subtitle.length() > 0) subtitle += ", ";
+ subtitle += plant.getName();
+ }
+
+ ((BaseActivity)getActivity()).getSupportActionBar().setSubtitle(subtitle);
+ }
+ }
+
+
setUi();
setHints();
}
@@ -183,6 +217,7 @@ else if (getArguments() != null)
@Override public void onSaveInstanceState(@NonNull Bundle outState)
{
outState.putIntArray("plant_index", plantIndex);
+ outState.putInt("garden_index", actionIndex);
outState.putInt("action_index", actionIndex);
outState.putParcelable("water", water);
@@ -421,8 +456,6 @@ private void setUi()
date.setText("");
notes.setText("");
- getActivity().setTitle(plants.size() == 1 ? getString(R.string.feeding_single_title, plants.get(0).getName()) : getString(R.string.feeding_multiple_title));
-
Calendar date = Calendar.getInstance();
date.setTimeInMillis(water.getDate());
From 5dab5dbcfbce64a5293ed66471d6029b1590a503 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sat, 29 Feb 2020 16:21:25 +0000
Subject: [PATCH 019/152] Adds plant name to subtitle
---
app/src/main/java/me/anon/grow/PlantDetailsActivity.kt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/app/src/main/java/me/anon/grow/PlantDetailsActivity.kt b/app/src/main/java/me/anon/grow/PlantDetailsActivity.kt
index 9e653417..5a7a3738 100644
--- a/app/src/main/java/me/anon/grow/PlantDetailsActivity.kt
+++ b/app/src/main/java/me/anon/grow/PlantDetailsActivity.kt
@@ -80,6 +80,8 @@ class PlantDetailsActivity : BaseActivity()
return@setOnNavigationItemSelectedListener true
}
+
+ supportActionBar?.subtitle = plant.name
}
}
}
From 891df735ca35c42b7ecad8f13070746257625fde Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sat, 29 Feb 2020 16:30:29 +0000
Subject: [PATCH 020/152] Adds budding and ripening as stages
---
app/src/main/java/me/anon/model/Models.kt | 2 ++
app/src/main/res/values/strings.xml | 2 ++
2 files changed, 4 insertions(+)
diff --git a/app/src/main/java/me/anon/model/Models.kt b/app/src/main/java/me/anon/model/Models.kt
index ae08287e..e9948327 100644
--- a/app/src/main/java/me/anon/model/Models.kt
+++ b/app/src/main/java/me/anon/model/Models.kt
@@ -450,7 +450,9 @@ enum class PlantStage private constructor(val printString: Int, val enString: St
SEEDLING(R.string.seedling, "Seedling"),
CUTTING(R.string.cutting, "Cutting"),
VEGETATION(R.string.vegetation, "Vegetation"),
+ BUDDING(R.string.budding, "Budding"),
FLOWER(R.string.flowering, "Flowering"),
+ RIPENING(R.string.ripening, "Ripening"),
DRYING(R.string.drying, "Drying"),
CURING(R.string.curing, "Curing"),
HARVESTED(R.string.harvested, "Harvested");
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 765f15b8..b4aa80bb 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -129,7 +129,9 @@
Germination
Cutting
Vegetation
+ Budding
Flowering
+ Ripening
Drying
Curing
Harvested
From 531ff1b8cc49d93fc8e0e716e1c2a77d88a4d4bd Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sat, 29 Feb 2020 16:45:49 +0000
Subject: [PATCH 021/152] Fixes issue with filtering
---
.../me/anon/grow/fragment/PlantListFragment.java | 14 +++++++++++++-
app/src/main/res/menu/plant_list_menu.xml | 14 +++++++++++++-
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/PlantListFragment.java b/app/src/main/java/me/anon/grow/fragment/PlantListFragment.java
index 1d63774e..d3892acb 100644
--- a/app/src/main/java/me/anon/grow/fragment/PlantListFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/PlantListFragment.java
@@ -419,7 +419,19 @@ private synchronized void saveCurrentState()
saveCurrentState();
}
- int[] ids = {R.id.filter_planted, R.id.filter_germination, R.id.filter_seedling, R.id.filter_cutting, R.id.filter_vegetation, R.id.filter_flowering, R.id.filter_drying, R.id.filter_curing, R.id.filter_harvested};
+ int[] ids = {
+ R.id.filter_planted,
+ R.id.filter_germination,
+ R.id.filter_seedling,
+ R.id.filter_cutting,
+ R.id.filter_vegetation,
+ R.id.filter_budding,
+ R.id.filter_flowering,
+ R.id.filter_ripening,
+ R.id.filter_drying,
+ R.id.filter_curing,
+ R.id.filter_harvested
+ };
PlantStage[] stages = PlantStage.values();
for (int index = 0; index < ids.length; index++)
diff --git a/app/src/main/res/menu/plant_list_menu.xml b/app/src/main/res/menu/plant_list_menu.xml
index cca61b4b..f73f0874 100644
--- a/app/src/main/res/menu/plant_list_menu.xml
+++ b/app/src/main/res/menu/plant_list_menu.xml
@@ -42,12 +42,24 @@
android:checked="true"
/>
+
+
+
+
-
+
-
Date: Sat, 29 Feb 2020 18:44:12 +0000
Subject: [PATCH 022/152] Apply translations in nl_NL
translation completed for the source file '/app/src/main/res/values/strings.xml'
on the 'nl_NL' language.
---
app/src/main/res/values-nl_NL/strings.xml | 420 ++++++++++++++++++++++
1 file changed, 420 insertions(+)
create mode 100644 app/src/main/res/values-nl_NL/strings.xml
diff --git a/app/src/main/res/values-nl_NL/strings.xml b/app/src/main/res/values-nl_NL/strings.xml
new file mode 100644
index 00000000..fc554216
--- /dev/null
+++ b/app/src/main/res/values-nl_NL/strings.xml
@@ -0,0 +1,420 @@
+
+
+
+ Versie %s
+ Instellingen
+
+
+ %s planten
+
+ Alle planten
+
+ Alle
+ Acties toegevoegd
+ Aantekeningen toegevoegd
+ Water geven toegevoegd
+ Tuin verwijderd
+
+ Weet je zeker dat je de tuin <b>\'%s\'</b> wilt verwijderen? De planten worden niet verwijderd.
+ Water geven
+ Actie
+
+ De widget is niet beschikbaar zolang versleuteling is ingeschakeld
+ Plant toevoegen
+ Plantinformatie
+ Plantstatistieken
+
+ Foto maken
+
+ Kiezen uit fotogalerij
+ Kies een optie
+ Afbeelding kiezen
+ Toepassen op andere plant
+ Plant kiezen
+ Afbeelding toegevoegd
+ Nóg één maken
+
+ Schema\'s
+ Schema-informatie
+ Schemadatum
+ Naam
+ Licht voeden
+ Omschrijving
+
+ Elke 2 weken licht voeden
+
+ + Voeding toevoegen
+ + Schema toevoegen
+ + Toevoeging toevoegen
+ Toevoegingen
+ Toevoeging
+ Vanaf datum
+ Vanaf fase
+ Tot datum
+ Tot fase
+ Samenstellen uit schema
+ Samenstellen uit vorige
+ Weet je het zeker?
+ Wil je het geselecteerde schema kopiëren?
+ Wil je het geselecteerde schema verwijderen?
+ Schema gekopieerd
+ Schema verwijderd
+ Ongedaan maken
+ Voederschema\'s
+ Voederschema
+ App is bijgewerkt
+ De app is geüpdatet naar versie %s
+ Wijzigingslog bekijken
+ Verwerpen
+
+
+ %s water geven
+ Meerdere planten water geven
+
+ Aantekeningen
+ Waterinformatie
+ pH-waarde
+ PPM
+ Afvoer
+ Hoeveelheid (%s)
+ Temperatuur (º%s)
+ Datum en tijd
+ Nu
+ Datum
+ Vandaag
+ %s dagen genezen
+
+ Water geven
+ Fase-aanpassingen
+
+ Klonen
+ Kopiëren naar
+ Actie bewerken
+ Actie verwijderen
+
+ Planten selecteren
+ Tuinen
+ Alle planten
+ + Tuin toevoegen
+ Aanvullend
+ Instellingen
+ Verwijderen
+ Delen
+ Foto
+ Water gegeven op
+ Opnieuw water geven
+
+ Plantnaam
+ Plant toevoegen
+ Plantensoort
+ Citroengras
+ Groei-informatie
+ Geplant op
+ Gemiddeld
+
+ Gemiddelde informatie
+
+ Aarde en perliet (half-om-half)
+ Uit kloon?
+ Fase-informatie
+ Plantfase
+ Foto\'s bekijken
+ Geschiedenis tonen
+ Statistieken tonen
+ Foto\'s
+ Geschiedenis
+ Statistieken
+ Filter
+ Geplant
+ Ontkiemd
+ Gewied
+ Groeiende
+ Ontkieming
+ Bloeiende
+ Rijping
+ Drogende
+ Genezende
+ Geplukt
+
+ %s geleden geplukt
+ Tuin exporteren
+ Tuin aanpassen
+ Tuin verwijderen
+ Exporteren
+
+ Totaaltijd:
+ Totaal water gegeven:
+ Totaal bijgesteld:
+ Gem. tijd tussen water geven:
+ Toevoegingen filteren
+ pH-waarde
+
+ Min.:
+ Max.:
+ Gem.:
+ Temperatuur
+ Algemeen
+ Kan plant niet laden
+ Oeps, vergeten! (OV)
+ Bijstellen
+ Bladvoeding
+ Lagestresstraining
+ Lolly
+ Bestrijdingsmiddel
+ Afgedekt
+ Verpot
+ Bijsnijden
+ ScrOG Tuck
+
+ Water gegeven
+ Aantekening
+ Item verwijderen?
+ Weet je zeker dat je het volgende wilt verwijderen:
+ Weet je zeker dat je <b>%s</b> foto\'s wilt verwijderen? Je kunt dit niet ongedaan maken.
+ Bewerken
+ fase
+ Instellen
+ Aanpassen
+ Toevoegen
+ Annuleren
+ actie
+ Oké
+ Veld is vereist
+ Fout: onjuiste toegangscode
+ Water geven aanpassen
+ toegevoegd
+ Actie gekloond
+ meerdere planten
+ Actie toegevoegd aan
+ Aantekening bijgewerkt
+ bijgewerkt
+ Fase bijgewerkt
+ Gebeurtenis verwijderd
+ Klaar
+ Tuin
+ Alles selecteren
+ Niets selecteren
+ Toestaan
+ Inschakelen
+ Afwijzen
+ Kiemplant:
+ Kiemplant
+
+ Oeps
+ Het lijkt erop dat de app vorige keer gecrasht is. Wil je deze anonieme logbestanden versturen? Ze worden verstuurd naar <a href=\"https://github.com/7LPdWcaW/GrowTracker-Android/issues\">github.com/7LPdWcaW/GrowTracker-Android/issues</a> - er worden geen persoonlijke gegevens meegestuurd. Je kunt de bestanden ook handmatig plaatsen op <a href=\"https://reddit.com/r/growutils\">reddit.com/r/growutils</a>. De logbestanden worden opgeslagen in <i>%s<i>
+ Ja
+ Nee
+
+ Voer je toegangscode in
+ Voer een toegangscode in
+ Voer nogmaals je toegangscode in
+ Fout: de toegangscodes komen niet overeen
+
+ Er is een fatale fout opgetreden tijdens het opslaan van de tuingegevens. Maak hier een back-up van.
+ In gebruik
+ %s geleden
+ Water gegeven: <b>%s</b> geleden
+ Water gegeven: <b>%s</b> geleden
+ Geplant: <b>%s</b> geleden
+
+ GrowTracker heeft toegang nodig tot je externe opslag om foto\'s op te slaan. Er worden geen andere gegevens uitgelezen.
+
+ Water geven toegevoegd
+ Weet je zeker dat je <b>%s</b> en alle bijbehorende foto\'s wilt verwijderen? Je kunt dit niet ongedaan maken.
+ Bezig met verwijderen van plant...
+
+ Plant gekloond
+ Openen
+
+ Bezig met exporteren van groeilog...
+ Bezig met exporteren van groeilog...
+ %s toegevoegd
+ Voer een naam in
+ Bezig met exporteren van %s...
+
+ Aarde
+ Hydrocultuur
+ Kokosvezel
+ Luchtcultuur
+ Afbeeldingen verbergen
+ Afbeeldingen tonen
+
+ De te tonen tuin na het openen van de app - momenteel: <b>%s</b>
+ Kaartstijl kiezen - momenteel: %s
+ De standaard maateenheid - momenteel: <b>%s</b>
+ De standaard maateenheid bij toevoegingen - momenteel: <b>%s</b>
+ De standaard temperatuureenheid - momenteel: <b>%s</b>
+ Momenteel: <b>%s MiB</b> / Verbruik: <b>%s</b>
+ Voer dit wachtvoord in tijdens het ontgrendelen om te voorkomen dat er informatie wordt geladen
+ Waarschuwing
+ Dit is een basale vorm van AES-versleuteling gebaseerd op de opgegeven toegangscode. Dit is geen gegarandeerde vorm van bescherming tegen handhaving.
+ Back-ups ingeschakeld. Back-ups worden opgeslagen in %s
+ Herstellen van %s voltooid
+ De back-up, %s, kan niet worden hersteld. Het bestand is mogelijk %s.
+ versleuteld
+ onversleuteld
+
+ Maat kiezen
+ Temperatuur kiezen
+ Tuin kiezen
+ Back-up kiezen
+ Je kunt deze back-up alleen herstellen als je versleuteling hebt ingeschakeld en hetzelfde wachtwoord opgeeft
+
+ Gebackupt naar
+ Er zijn geen te herstellen back-ups
+ Alles/Niets
+
+ Toevoer-pH-waarde
+ Afvoer-pH-waarde
+ Gemiddelde pH-waarde
+
+ Plantenfoto\'s
+
+ Toev.-pH:
+ Afv.-pH:
+ Hoeveelheid:
+ Temp.:
+ Toevoegingen:
+ EC:
+ PPM:
+
+ Schema kiezen
+ Acties
+ Donker thema gebruiken
+ Stelt het donkere thema in in de app, ongeacht de systeeminstelling voor dag- en nachtthema\'s
+ Geplukte items verbergen
+ Verberg alle planten die reeds geplukt zijn
+ Plantvolgorde omdraaien
+ Toont de planten in omgekeerde volgorde. (herstart vereist)
+ Standaardtuin
+
+ Eenheden
+ Toevoereenheid
+ Maateenheid
+ Temperatuureenheid
+ TDS-eenheid
+ De standaard tds-eenheid - momenteel: <b>%s</b>
+ Gegevensbeheer
+ Automatisch back-uppen
+ Plantinformatie elke 24 uur automatisch back-uppen
+ Nu back-uppen
+ Back-upgrootte
+ Grootte (in MiB)
+ Back-uplimiet (MiB)
+ Herstellen uit back-up
+ Gegevens versleutelen
+ Voegt een pincode toe aan de app en versleutelt alle gegevens/afbeeldingen
+ Noodwachtwoord
+ Stel een noodwachtwoord in waarmee je informatietoegang voorkomt
+ Uitbreidingen
+ Over
+ Leesmij
+ Informatie exporteren
+ Kaartstijl
+ Je hebt geen planten
+ Je hebt geen schema\'s
+ Je hebt geen foto\'s
+ Eerdere acties
+ Kalender tonen/verbergen
+
+ %d geselecteerd
+ Met dank aan
+ Vertaald door
+ Helpen met vertalen
+ Bezig met versleutelen; even geduld...
+ Bezig met ontsleutelen; even geduld...
+
+
+ 1s
+ s
+ m
+ u
+ d
+ w
+ ma
+ j
+
+ Informatie
+
+
+
- seconde
+ - seconden
+
+
+
+ - minuut
+ - minuten
+
+
+
+ - uur
+ - uur
+
+
+
+ - dag
+ - dagen
+
+
+
+ - week
+ - weken
+
+
+
+ - maand
+ - maanden
+
+
+
+ - jaar
+ - jaar
+
+
+
+ - Origineel
+ - Compact
+ - Extreem
+
+
+ Alle niet-opgeslagen aanpassingen gaan verloren
+ Afsluiten
+ Planten
+ Luchtvochtigheid
+ Huidige temperatuur:
+ Huidige luchtvochtigheid:
+ Lichtschema
+ Item verwijderen?
+ Weet je zeker dat je <b>\'%s\'</b> wilt verwijderen?
+ Tonen
+ Verbergen
+ Lichten aan
+ Lichten uit
+
+ Gebackupt: <b>%s</b>
+ Opslaglocatie van afbeeldingen - momenteel: <b>%s</b>
+ Kan afbeeldingslocatie niet instellen
+ Opslaglocatie voor afbeeldingen
+ Afbeeldingscache wissen
+ Afbeeldings- en geheugencache gewist
+ Bezig met importeren; even geduld...
+ Gegevenstaak
+ Taak volbracht
+ Er zijn geen acties
+
+ Bezig met exporteren van groeilog van %s...
+ %s is geëxporteerd
+ %s is geëxporteerd naar %s
+ Exporteren voltooid
+ Afbeeldingen bijvoegen?
+ Er in geen informatie beschikbaar
+
+ Cameramachtiging vereist om foto\'s te maken
+ Back-upbeheer
+ Opslaglocatie
+ Opslaglocatie van back-ups - momenteel: <b>%s</b>
+ Kan back-uplocatie niet instellen
+ Kan planten niet importeren uit bestand
+ Planten importeren uit bestand
+ De planten zijn geïmporteerd
+
From 52ea0de3c9a7b8f74546c29c46947a0ec14bd154 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Thu, 5 Mar 2020 11:59:33 +0000
Subject: [PATCH 023/152] Fixes issue with filtering again for real this time
---
.../me/anon/grow/fragment/GardenFragment.java | 39 +++++++++++++++----
.../anon/grow/fragment/PlantListFragment.java | 26 +++++++++----
2 files changed, 49 insertions(+), 16 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/GardenFragment.java b/app/src/main/java/me/anon/grow/fragment/GardenFragment.java
index 2c6b811b..4a9d5fa1 100644
--- a/app/src/main/java/me/anon/grow/fragment/GardenFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/GardenFragment.java
@@ -207,7 +207,7 @@ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, Recycle
if (filterList == null)
{
filterList = new ArrayList<>();
- Set prefsList = androidx.preference.PreferenceManager.getDefaultSharedPreferences(getActivity()).getStringSet("filter_list", null);
+ Set prefsList = androidx.preference.PreferenceManager.getDefaultSharedPreferences(getActivity()).getStringSet("new_filter_list", null);
if (prefsList == null)
{
filterList.addAll(Arrays.asList(PlantStage.values()));
@@ -218,8 +218,7 @@ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, Recycle
{
try
{
- int ordinal = IntUtilsKt.toSafeInt(s);
- filterList.add(PlantStage.values()[ordinal]);
+ filterList.add(PlantStage.valueOf(s));
}
catch (Exception e)
{
@@ -441,8 +440,20 @@ private synchronized void saveCurrentState()
menu.findItem(R.id.export_garden).setVisible(true);
menu.findItem(R.id.delete_garden).setVisible(true);
- int[] ids = {R.id.filter_germination, R.id.filter_vegetation, R.id.filter_seedling, R.id.filter_cutting, R.id.filter_flowering, R.id.filter_drying, R.id.filter_curing, R.id.filter_harvested, R.id.filter_planted};
- PlantStage[] stages = {PlantStage.GERMINATION, PlantStage.VEGETATION, PlantStage.SEEDLING, PlantStage.CUTTING, PlantStage.FLOWER, PlantStage.DRYING, PlantStage.CURING, PlantStage.HARVESTED, PlantStage.PLANTED};
+ int[] ids = {
+ R.id.filter_planted,
+ R.id.filter_germination,
+ R.id.filter_seedling,
+ R.id.filter_cutting,
+ R.id.filter_vegetation,
+ R.id.filter_budding,
+ R.id.filter_flowering,
+ R.id.filter_ripening,
+ R.id.filter_drying,
+ R.id.filter_curing,
+ R.id.filter_harvested
+ };
+ PlantStage[] stages = PlantStage.values();
for (int index = 0; index < ids.length; index++)
{
@@ -549,7 +560,19 @@ else if (item.getItemId() == R.id.delete_garden)
saveCurrentState();
}
- int[] ids = {R.id.filter_planted, R.id.filter_germination, R.id.filter_seedling, R.id.filter_cutting, R.id.filter_vegetation, R.id.filter_flowering, R.id.filter_drying, R.id.filter_curing, R.id.filter_harvested};
+ int[] ids = {
+ R.id.filter_planted,
+ R.id.filter_germination,
+ R.id.filter_seedling,
+ R.id.filter_cutting,
+ R.id.filter_vegetation,
+ R.id.filter_budding,
+ R.id.filter_flowering,
+ R.id.filter_ripening,
+ R.id.filter_drying,
+ R.id.filter_curing,
+ R.id.filter_harvested
+ };
PlantStage[] stages = PlantStage.values();
for (int index = 0; index < ids.length; index++)
@@ -573,10 +596,10 @@ else if (item.getItemId() == R.id.delete_garden)
Set stageOrdinals = new LinkedHashSet<>();
for (PlantStage plantStage : filterList)
{
- stageOrdinals.add(plantStage.ordinal() + "");
+ stageOrdinals.add(plantStage.name());
}
androidx.preference.PreferenceManager.getDefaultSharedPreferences(getActivity()).edit()
- .putStringSet("filter_list", stageOrdinals)
+ .putStringSet("new_filter_list", stageOrdinals)
.apply();
if (filter)
diff --git a/app/src/main/java/me/anon/grow/fragment/PlantListFragment.java b/app/src/main/java/me/anon/grow/fragment/PlantListFragment.java
index d3892acb..b2df3541 100644
--- a/app/src/main/java/me/anon/grow/fragment/PlantListFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/PlantListFragment.java
@@ -175,7 +175,7 @@ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, Recycle
if (filterList == null)
{
filterList = new ArrayList<>();
- Set prefsList = androidx.preference.PreferenceManager.getDefaultSharedPreferences(getActivity()).getStringSet("filter_list", null);
+ Set prefsList = androidx.preference.PreferenceManager.getDefaultSharedPreferences(getActivity()).getStringSet("new_filter_list", null);
if (prefsList == null)
{
filterList.addAll(Arrays.asList(PlantStage.values()));
@@ -186,8 +186,7 @@ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, Recycle
{
try
{
- int ordinal = IntUtilsKt.toSafeInt(s);
- filterList.add(PlantStage.values()[ordinal]);
+ filterList.add(PlantStage.valueOf(s));
}
catch (Exception e)
{
@@ -390,8 +389,20 @@ private synchronized void saveCurrentState()
{
inflater.inflate(R.menu.plant_list_menu, menu);
- int[] ids = {R.id.filter_germination, R.id.filter_vegetation, R.id.filter_seedling, R.id.filter_cutting, R.id.filter_flowering, R.id.filter_drying, R.id.filter_curing, R.id.filter_harvested, R.id.filter_planted};
- PlantStage[] stages = {PlantStage.GERMINATION, PlantStage.VEGETATION, PlantStage.SEEDLING, PlantStage.CUTTING, PlantStage.FLOWER, PlantStage.DRYING, PlantStage.CURING, PlantStage.HARVESTED, PlantStage.PLANTED};
+ int[] ids = {
+ R.id.filter_planted,
+ R.id.filter_germination,
+ R.id.filter_seedling,
+ R.id.filter_cutting,
+ R.id.filter_vegetation,
+ R.id.filter_budding,
+ R.id.filter_flowering,
+ R.id.filter_ripening,
+ R.id.filter_drying,
+ R.id.filter_curing,
+ R.id.filter_harvested
+ };
+ PlantStage[] stages = PlantStage.values();
for (int index = 0; index < ids.length; index++)
{
@@ -455,11 +466,11 @@ private synchronized void saveCurrentState()
Set stageOrdinals = new LinkedHashSet<>();
for (PlantStage plantStage : filterList)
{
- stageOrdinals.add(plantStage.ordinal() + "");
+ stageOrdinals.add(plantStage.name() + "");
}
PreferenceManager.getDefaultSharedPreferences(getActivity()).edit()
- .putStringSet("filter_list", stageOrdinals)
+ .putStringSet("new_filter_list", stageOrdinals)
.apply();
if (filter)
@@ -472,7 +483,6 @@ private synchronized void saveCurrentState()
private void filter()
{
- Log.e("TEST", "filtering");
ArrayList plantList = PlantManager.getInstance().getSortedPlantList(null);
if (reverse)
{
From 96e98eec6df42bdcd19f5f64f93df9c697315369 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Thu, 5 Mar 2020 12:55:33 +0000
Subject: [PATCH 024/152] Fixes NL locale
---
app/src/main/res/values-nl-rNL/strings.xml | 2 +
app/src/main/res/values-nl_NL/strings.xml | 420 ---------------------
2 files changed, 2 insertions(+), 420 deletions(-)
delete mode 100644 app/src/main/res/values-nl_NL/strings.xml
diff --git a/app/src/main/res/values-nl-rNL/strings.xml b/app/src/main/res/values-nl-rNL/strings.xml
index d8f79ab7..fc554216 100644
--- a/app/src/main/res/values-nl-rNL/strings.xml
+++ b/app/src/main/res/values-nl-rNL/strings.xml
@@ -129,7 +129,9 @@
Ontkiemd
Gewied
Groeiende
+ Ontkieming
Bloeiende
+ Rijping
Drogende
Genezende
Geplukt
diff --git a/app/src/main/res/values-nl_NL/strings.xml b/app/src/main/res/values-nl_NL/strings.xml
deleted file mode 100644
index fc554216..00000000
--- a/app/src/main/res/values-nl_NL/strings.xml
+++ /dev/null
@@ -1,420 +0,0 @@
-
-
-
- Versie %s
- Instellingen
-
-
- %s planten
-
- Alle planten
-
- Alle
- Acties toegevoegd
- Aantekeningen toegevoegd
- Water geven toegevoegd
- Tuin verwijderd
-
- Weet je zeker dat je de tuin <b>\'%s\'</b> wilt verwijderen? De planten worden niet verwijderd.
- Water geven
- Actie
-
- De widget is niet beschikbaar zolang versleuteling is ingeschakeld
- Plant toevoegen
- Plantinformatie
- Plantstatistieken
-
- Foto maken
-
- Kiezen uit fotogalerij
- Kies een optie
- Afbeelding kiezen
- Toepassen op andere plant
- Plant kiezen
- Afbeelding toegevoegd
- Nóg één maken
-
- Schema\'s
- Schema-informatie
- Schemadatum
- Naam
- Licht voeden
- Omschrijving
-
- Elke 2 weken licht voeden
-
- + Voeding toevoegen
- + Schema toevoegen
- + Toevoeging toevoegen
- Toevoegingen
- Toevoeging
- Vanaf datum
- Vanaf fase
- Tot datum
- Tot fase
- Samenstellen uit schema
- Samenstellen uit vorige
- Weet je het zeker?
- Wil je het geselecteerde schema kopiëren?
- Wil je het geselecteerde schema verwijderen?
- Schema gekopieerd
- Schema verwijderd
- Ongedaan maken
- Voederschema\'s
- Voederschema
- App is bijgewerkt
- De app is geüpdatet naar versie %s
- Wijzigingslog bekijken
- Verwerpen
-
-
- %s water geven
- Meerdere planten water geven
-
- Aantekeningen
- Waterinformatie
- pH-waarde
- PPM
- Afvoer
- Hoeveelheid (%s)
- Temperatuur (º%s)
- Datum en tijd
- Nu
- Datum
- Vandaag
- %s dagen genezen
-
- Water geven
- Fase-aanpassingen
-
- Klonen
- Kopiëren naar
- Actie bewerken
- Actie verwijderen
-
- Planten selecteren
- Tuinen
- Alle planten
- + Tuin toevoegen
- Aanvullend
- Instellingen
- Verwijderen
- Delen
- Foto
- Water gegeven op
- Opnieuw water geven
-
- Plantnaam
- Plant toevoegen
- Plantensoort
- Citroengras
- Groei-informatie
- Geplant op
- Gemiddeld
-
- Gemiddelde informatie
-
- Aarde en perliet (half-om-half)
- Uit kloon?
- Fase-informatie
- Plantfase
- Foto\'s bekijken
- Geschiedenis tonen
- Statistieken tonen
- Foto\'s
- Geschiedenis
- Statistieken
- Filter
- Geplant
- Ontkiemd
- Gewied
- Groeiende
- Ontkieming
- Bloeiende
- Rijping
- Drogende
- Genezende
- Geplukt
-
- %s geleden geplukt
- Tuin exporteren
- Tuin aanpassen
- Tuin verwijderen
- Exporteren
-
- Totaaltijd:
- Totaal water gegeven:
- Totaal bijgesteld:
- Gem. tijd tussen water geven:
- Toevoegingen filteren
- pH-waarde
-
- Min.:
- Max.:
- Gem.:
- Temperatuur
- Algemeen
- Kan plant niet laden
- Oeps, vergeten! (OV)
- Bijstellen
- Bladvoeding
- Lagestresstraining
- Lolly
- Bestrijdingsmiddel
- Afgedekt
- Verpot
- Bijsnijden
- ScrOG Tuck
-
- Water gegeven
- Aantekening
- Item verwijderen?
- Weet je zeker dat je het volgende wilt verwijderen:
- Weet je zeker dat je <b>%s</b> foto\'s wilt verwijderen? Je kunt dit niet ongedaan maken.
- Bewerken
- fase
- Instellen
- Aanpassen
- Toevoegen
- Annuleren
- actie
- Oké
- Veld is vereist
- Fout: onjuiste toegangscode
- Water geven aanpassen
- toegevoegd
- Actie gekloond
- meerdere planten
- Actie toegevoegd aan
- Aantekening bijgewerkt
- bijgewerkt
- Fase bijgewerkt
- Gebeurtenis verwijderd
- Klaar
- Tuin
- Alles selecteren
- Niets selecteren
- Toestaan
- Inschakelen
- Afwijzen
- Kiemplant:
- Kiemplant
-
- Oeps
- Het lijkt erop dat de app vorige keer gecrasht is. Wil je deze anonieme logbestanden versturen? Ze worden verstuurd naar <a href=\"https://github.com/7LPdWcaW/GrowTracker-Android/issues\">github.com/7LPdWcaW/GrowTracker-Android/issues</a> - er worden geen persoonlijke gegevens meegestuurd. Je kunt de bestanden ook handmatig plaatsen op <a href=\"https://reddit.com/r/growutils\">reddit.com/r/growutils</a>. De logbestanden worden opgeslagen in <i>%s<i>
- Ja
- Nee
-
- Voer je toegangscode in
- Voer een toegangscode in
- Voer nogmaals je toegangscode in
- Fout: de toegangscodes komen niet overeen
-
- Er is een fatale fout opgetreden tijdens het opslaan van de tuingegevens. Maak hier een back-up van.
- In gebruik
- %s geleden
- Water gegeven: <b>%s</b> geleden
- Water gegeven: <b>%s</b> geleden
- Geplant: <b>%s</b> geleden
-
- GrowTracker heeft toegang nodig tot je externe opslag om foto\'s op te slaan. Er worden geen andere gegevens uitgelezen.
-
- Water geven toegevoegd
- Weet je zeker dat je <b>%s</b> en alle bijbehorende foto\'s wilt verwijderen? Je kunt dit niet ongedaan maken.
- Bezig met verwijderen van plant...
-
- Plant gekloond
- Openen
-
- Bezig met exporteren van groeilog...
- Bezig met exporteren van groeilog...
- %s toegevoegd
- Voer een naam in
- Bezig met exporteren van %s...
-
- Aarde
- Hydrocultuur
- Kokosvezel
- Luchtcultuur
- Afbeeldingen verbergen
- Afbeeldingen tonen
-
- De te tonen tuin na het openen van de app - momenteel: <b>%s</b>
- Kaartstijl kiezen - momenteel: %s
- De standaard maateenheid - momenteel: <b>%s</b>
- De standaard maateenheid bij toevoegingen - momenteel: <b>%s</b>
- De standaard temperatuureenheid - momenteel: <b>%s</b>
- Momenteel: <b>%s MiB</b> / Verbruik: <b>%s</b>
- Voer dit wachtvoord in tijdens het ontgrendelen om te voorkomen dat er informatie wordt geladen
- Waarschuwing
- Dit is een basale vorm van AES-versleuteling gebaseerd op de opgegeven toegangscode. Dit is geen gegarandeerde vorm van bescherming tegen handhaving.
- Back-ups ingeschakeld. Back-ups worden opgeslagen in %s
- Herstellen van %s voltooid
- De back-up, %s, kan niet worden hersteld. Het bestand is mogelijk %s.
- versleuteld
- onversleuteld
-
- Maat kiezen
- Temperatuur kiezen
- Tuin kiezen
- Back-up kiezen
- Je kunt deze back-up alleen herstellen als je versleuteling hebt ingeschakeld en hetzelfde wachtwoord opgeeft
-
- Gebackupt naar
- Er zijn geen te herstellen back-ups
- Alles/Niets
-
- Toevoer-pH-waarde
- Afvoer-pH-waarde
- Gemiddelde pH-waarde
-
- Plantenfoto\'s
-
- Toev.-pH:
- Afv.-pH:
- Hoeveelheid:
- Temp.:
- Toevoegingen:
- EC:
- PPM:
-
- Schema kiezen
- Acties
- Donker thema gebruiken
- Stelt het donkere thema in in de app, ongeacht de systeeminstelling voor dag- en nachtthema\'s
- Geplukte items verbergen
- Verberg alle planten die reeds geplukt zijn
- Plantvolgorde omdraaien
- Toont de planten in omgekeerde volgorde. (herstart vereist)
- Standaardtuin
-
- Eenheden
- Toevoereenheid
- Maateenheid
- Temperatuureenheid
- TDS-eenheid
- De standaard tds-eenheid - momenteel: <b>%s</b>
- Gegevensbeheer
- Automatisch back-uppen
- Plantinformatie elke 24 uur automatisch back-uppen
- Nu back-uppen
- Back-upgrootte
- Grootte (in MiB)
- Back-uplimiet (MiB)
- Herstellen uit back-up
- Gegevens versleutelen
- Voegt een pincode toe aan de app en versleutelt alle gegevens/afbeeldingen
- Noodwachtwoord
- Stel een noodwachtwoord in waarmee je informatietoegang voorkomt
- Uitbreidingen
- Over
- Leesmij
- Informatie exporteren
- Kaartstijl
- Je hebt geen planten
- Je hebt geen schema\'s
- Je hebt geen foto\'s
- Eerdere acties
- Kalender tonen/verbergen
-
- %d geselecteerd
- Met dank aan
- Vertaald door
- Helpen met vertalen
- Bezig met versleutelen; even geduld...
- Bezig met ontsleutelen; even geduld...
-
-
- 1s
- s
- m
- u
- d
- w
- ma
- j
-
- Informatie
-
-
- - seconde
- - seconden
-
-
-
- - minuut
- - minuten
-
-
-
- - uur
- - uur
-
-
-
- - dag
- - dagen
-
-
-
- - week
- - weken
-
-
-
- - maand
- - maanden
-
-
-
- - jaar
- - jaar
-
-
-
- - Origineel
- - Compact
- - Extreem
-
-
- Alle niet-opgeslagen aanpassingen gaan verloren
- Afsluiten
- Planten
- Luchtvochtigheid
- Huidige temperatuur:
- Huidige luchtvochtigheid:
- Lichtschema
- Item verwijderen?
- Weet je zeker dat je <b>\'%s\'</b> wilt verwijderen?
- Tonen
- Verbergen
- Lichten aan
- Lichten uit
-
- Gebackupt: <b>%s</b>
- Opslaglocatie van afbeeldingen - momenteel: <b>%s</b>
- Kan afbeeldingslocatie niet instellen
- Opslaglocatie voor afbeeldingen
- Afbeeldingscache wissen
- Afbeeldings- en geheugencache gewist
- Bezig met importeren; even geduld...
- Gegevenstaak
- Taak volbracht
- Er zijn geen acties
-
- Bezig met exporteren van groeilog van %s...
- %s is geëxporteerd
- %s is geëxporteerd naar %s
- Exporteren voltooid
- Afbeeldingen bijvoegen?
- Er in geen informatie beschikbaar
-
- Cameramachtiging vereist om foto\'s te maken
- Back-upbeheer
- Opslaglocatie
- Opslaglocatie van back-ups - momenteel: <b>%s</b>
- Kan back-uplocatie niet instellen
- Kan planten niet importeren uit bestand
- Planten importeren uit bestand
- De planten zijn geïmporteerd
-
From b2692cef82ba665e63ff5c2ba925a31587a8651c Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Thu, 5 Mar 2020 13:39:14 +0000
Subject: [PATCH 025/152] Fixes SI
---
app/src/main/res/{values-sl_SI => values-sl-rSI}/strings.xml | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename app/src/main/res/{values-sl_SI => values-sl-rSI}/strings.xml (100%)
diff --git a/app/src/main/res/values-sl_SI/strings.xml b/app/src/main/res/values-sl-rSI/strings.xml
similarity index 100%
rename from app/src/main/res/values-sl_SI/strings.xml
rename to app/src/main/res/values-sl-rSI/strings.xml
From 03cca366f2086d9ec7b4a7637ae1f1822a2e3458 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Fri, 13 Mar 2020 12:53:25 +0000
Subject: [PATCH 026/152] Fixes issue with non existent photos not being
deleted/removed correctly
---
.../grow/fragment/ViewPhotosFragment.java | 92 ++++++++++---------
1 file changed, 49 insertions(+), 43 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/ViewPhotosFragment.java b/app/src/main/java/me/anon/grow/fragment/ViewPhotosFragment.java
index beb0e637..d7eb82d8 100644
--- a/app/src/main/java/me/anon/grow/fragment/ViewPhotosFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/ViewPhotosFragment.java
@@ -71,6 +71,8 @@ public class ViewPhotosFragment extends Fragment
private Plant plant;
+ private String tempImagePath = "";
+
public static ViewPhotosFragment newInstance(Bundle arguments)
{
ViewPhotosFragment fragment = new ViewPhotosFragment();
@@ -90,6 +92,7 @@ public static ViewPhotosFragment newInstance(Bundle arguments)
@Override public void onSaveInstanceState(@NonNull Bundle outState)
{
outState.putParcelable("plant", plant);
+ outState.putString("temp_image", tempImagePath);
super.onSaveInstanceState(outState);
}
@@ -106,6 +109,7 @@ public static ViewPhotosFragment newInstance(Bundle arguments)
else if (savedInstanceState != null)
{
plant = savedInstanceState.getParcelable("plant");
+ tempImagePath = savedInstanceState.getString("temp_image", "");
}
if (plant == null)
@@ -190,7 +194,7 @@ else if (item.getItemId() == R.id.delete)
File imageFile = new File(image);
folders.add(imageFile.getParentFile().getPath());
- if (imageFile.delete())
+ if (!imageFile.exists() || imageFile.delete())
{
plant.getImages().remove(image);
}
@@ -198,23 +202,7 @@ else if (item.getItemId() == R.id.delete)
for (String folder : folders)
{
- File folderFile = new File(folder);
- if (folderFile.isDirectory())
- {
- String[] list = folderFile.list();
- if (list != null)
- {
- if (list.length == 1 && ".nomedia".equals(list[0]))
- {
- new File(folderFile, ".nomedia").delete();
- }
-
- if (folderFile.list() == null || folderFile.list().length == 0)
- {
- folderFile.delete();
- }
- }
- }
+ cleanupFolder(new File(folder));
}
PlantManager.getInstance().upsert(plant);
@@ -411,7 +399,8 @@ private void setEmpty()
File out = new File(path, System.currentTimeMillis() + ".jpg");
Uri photoURI = FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID + ".provider", out);
- plant.getImages().add(out.getAbsolutePath());
+ tempImagePath = out.getAbsolutePath();
+ plant.getImages().add(tempImagePath);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(intent, 1);
@@ -447,47 +436,62 @@ private void setEmpty()
.show();
}
+ private void cleanupFolder(@Nullable File folderPath)
+ {
+ if (folderPath != null)
+ {
+ String[] list = folderPath.list();
+ if (list != null)
+ {
+ if (list.length == 1 && ".nomedia".equals(list[0]))
+ {
+ new File(folderPath, ".nomedia").delete();
+ }
+
+ if (folderPath.list() == null || folderPath.list().length == 0)
+ {
+ folderPath.delete();
+ }
+ }
+ else
+ {
+ folderPath.delete();
+ }
+ }
+ }
+
@Override public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == 1)
{
if (resultCode == Activity.RESULT_CANCELED)
{
- File imageFile = new File(plant.getImages().get(plant.getImages().size() - 1));
+ File imageFile = new File(tempImagePath);
- if (imageFile.delete())
+ if (!imageFile.exists() || imageFile.delete())
{
plant.getImages().remove(plant.getImages().size() - 1);
}
- File folderFile = imageFile.getParentFile();
- String[] list = folderFile.list();
- if (list != null)
+ cleanupFolder(imageFile.getParentFile());
+ }
+ else
+ {
+ File imageFile = new File(tempImagePath);
+ if (imageFile.exists() && imageFile.length() > 0)
{
- if (list.length == 1 && ".nomedia".equals(list[0]))
- {
- new File(folderFile, ".nomedia").delete();
- }
+ PlantManager.getInstance().upsert(plant);
- if (folderFile.list() == null || folderFile.list().length == 0)
- {
- folderFile.delete();
- }
+ setAdapter();
+ adapter.notifyDataSetChanged();
+
+ finishPhotoIntent();
}
else
{
- folderFile.delete();
+ cleanupFolder(imageFile.getParentFile());
}
}
- else
- {
- PlantManager.getInstance().upsert(plant);
-
- setAdapter();
- adapter.notifyDataSetChanged();
-
- finishPhotoIntent();
- }
}
else if (requestCode == 3) // choose image from gallery
{
@@ -549,6 +553,8 @@ else if (requestCode == 3) // choose image from gallery
private void finishPhotoIntent()
{
+ tempImagePath = "";
+
Intent intent = new Intent();
intent.putExtra("plant", plant);
getActivity().setIntent(intent);
@@ -572,7 +578,7 @@ private void finishPhotoIntent()
@Override public void onSnackBarAction(View v)
{
- onFabPhotoClick(null);
+ onFabPhotoClick(v);
}
});
}
From 111c43d63d3ac2c19927b5c848f6bea010f5a901 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Fri, 13 Mar 2020 13:05:28 +0000
Subject: [PATCH 027/152] Adds new actions
---
app/src/main/java/me/anon/model/Models.kt | 4 +++-
app/src/main/res/values/strings.xml | 2 ++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/me/anon/model/Models.kt b/app/src/main/java/me/anon/model/Models.kt
index e9948327..7190df30 100644
--- a/app/src/main/java/me/anon/model/Models.kt
+++ b/app/src/main/java/me/anon/model/Models.kt
@@ -77,7 +77,9 @@ abstract class Action(
TOP(R.string.action_topped, -0x6543555c, "Topped"),
TRANSPLANTED(R.string.action_transplanted, -0x65000073, "Transplanted"),
TRIM(R.string.action_trim, -0x6500546f, "Trim"),
- TUCK(R.string.action_tuck, -0x65800046, "ScrOG Tuck");
+ TUCK(R.string.action_tuck, -0x65800046, "ScrOG Tuck"),
+ SUPERCROP(R.string.action_supercrop, 0xFF72C7D6.toInt(), "Supercrop"),
+ MONSTERCROP(R.string.action_monstercrop, 0xFFFF7681.toInt(), "Monstercrop");
companion object
{
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b4aa80bb..4cb1f594 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -165,6 +165,8 @@
Transplanted
Trim
ScrOG Tuck
+ Supercrop
+ Monstercrop
Watered
Note
From b35d86ac90f4a35e86cd56f0f7c60dffbc6974dd Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Fri, 13 Mar 2020 13:08:01 +0000
Subject: [PATCH 028/152] Fixes snacker string when updating action
---
.../main/java/me/anon/grow/fragment/ActionsListFragment.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/ActionsListFragment.java b/app/src/main/java/me/anon/grow/fragment/ActionsListFragment.java
index 2501a543..264c1ab7 100644
--- a/app/src/main/java/me/anon/grow/fragment/ActionsListFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/ActionsListFragment.java
@@ -437,7 +437,7 @@ else if (action instanceof EmptyAction)
setActions();
adapter.notifyDataSetChanged();
- SnackBar.show(getActivity(), action.getAction().getPrintString() + " " + getString(R.string.updated), getString(R.string.undo), new SnackBarListener()
+ SnackBar.show(getActivity(), getString(action.getAction().getPrintString()) + " " + getString(R.string.updated), getString(R.string.undo), new SnackBarListener()
{
@Override public void onSnackBarStarted(Object o){}
@Override public void onSnackBarFinished(Object o){}
From 6a673b60874253d048277291a33c0378d10eab2c Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 15 Mar 2020 12:25:50 +0000
Subject: [PATCH 029/152] Adds calendar view into adapter
---
.../controller/adapter/ActionAdapter.java | 73 +++++++++++++++++--
.../grow/fragment/ActionsListFragment.java | 38 ++--------
app/src/main/res/layout/actions_list_view.xml | 18 +----
app/src/main/res/layout/calendar_item.xml | 14 ++++
4 files changed, 88 insertions(+), 55 deletions(-)
create mode 100644 app/src/main/res/layout/calendar_item.xml
diff --git a/app/src/main/java/me/anon/controller/adapter/ActionAdapter.java b/app/src/main/java/me/anon/controller/adapter/ActionAdapter.java
index 82246251..a8760a29 100644
--- a/app/src/main/java/me/anon/controller/adapter/ActionAdapter.java
+++ b/app/src/main/java/me/anon/controller/adapter/ActionAdapter.java
@@ -15,6 +15,11 @@
import com.esotericsoftware.kryo.Kryo;
import com.prolificinteractive.materialcalendarview.CalendarDay;
+import com.prolificinteractive.materialcalendarview.DayViewDecorator;
+import com.prolificinteractive.materialcalendarview.DayViewFacade;
+import com.prolificinteractive.materialcalendarview.MaterialCalendarView;
+import com.prolificinteractive.materialcalendarview.OnDateSelectedListener;
+import com.prolificinteractive.materialcalendarview.spans.DotSpan;
import org.jetbrains.annotations.NotNull;
import org.threeten.bp.Instant;
@@ -75,6 +80,7 @@ public interface OnItemSelectCallback
public void onItemSelected(Action action);
}
+ private OnDateSelectedListener onDateSelectedListener;
private OnItemSelectCallback onItemSelectCallback;
private OnActionSelectListener onActionSelectListener;
@Nullable private Plant plant;
@@ -83,6 +89,7 @@ public interface OnItemSelectCallback
private TempUnit tempUnit;
private boolean showDate = true;
private boolean showActions = true;
+ public boolean showCalendar = false;
private CalendarDay selectedFilterDate = null;
public void setFilterDate(CalendarDay selectedFilterDate)
@@ -90,6 +97,11 @@ public void setFilterDate(CalendarDay selectedFilterDate)
this.selectedFilterDate = selectedFilterDate;
}
+ public void setOnDateChangedListener(OnDateSelectedListener onDateSelectedListener)
+ {
+ this.onDateSelectedListener = onDateSelectedListener;
+ }
+
/**
* Dummy image action placeholder class
*/
@@ -268,6 +280,13 @@ private static long getImageDate(String image)
@Override public int getItemViewType(int position)
{
+ if (showCalendar && position == 0)
+ {
+ return 3;
+ }
+
+ position = position - (showCalendar ? 1 : 0);
+
if (selectedFilterDate != null)
{
LocalDate actionDate = CalendarDay.from(LocalDate.from(Instant.ofEpochMilli(actions.get(position).getDate()).atZone(ZoneId.systemDefault()))).getDate();
@@ -284,7 +303,11 @@ private static long getImageDate(String image)
@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType)
{
- if (viewType == 0)
+ if (viewType == 3)
+ {
+ return new RecyclerView.ViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.calendar_item, viewGroup, false)){};
+ }
+ else if (viewType == 0)
{
return new RecyclerView.ViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.empty, viewGroup, false)){};
}
@@ -300,7 +323,41 @@ else if (viewType == 2)
{
if (getItemViewType(index) == 0) return;
- final Action action = actions.get(index);
+ if (getItemViewType(index) == 3)
+ {
+ final MaterialCalendarView calendar = (MaterialCalendarView)vh.itemView;
+ calendar.removeDecorators();
+ calendar.addDecorator(new DayViewDecorator()
+ {
+ @Override public boolean shouldDecorate(CalendarDay calendarDay)
+ {
+ // find an action that is on this day
+ for (Action action : plant.getActions())
+ {
+ LocalDate actionDate = CalendarDay.from(LocalDate.from(Instant.ofEpochMilli(action.getDate()).atZone(ZoneId.systemDefault()))).getDate();
+ if (calendarDay.getDate().equals(actionDate))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override public void decorate(DayViewFacade dayViewFacade)
+ {
+ dayViewFacade.addSpan(new DotSpan(6.0f, IntUtilsKt.resolveColor(R.attr.colorAccent, calendar.getContext())));
+ }
+ });
+ calendar.setOnDateChangedListener(onDateSelectedListener);
+ calendar.setSelectedDate(selectedFilterDate);
+ calendar.setCurrentDate(selectedFilterDate);
+
+ return;
+ }
+
+ final int actionIndex = index - (showCalendar ? 1 : 0);
+ final Action action = actions.get(actionIndex);
DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(vh.itemView.getContext());
DateFormat timeFormat = android.text.format.DateFormat.getTimeFormat(vh.itemView.getContext());
TextView dateDay = null;
@@ -343,9 +400,9 @@ else if (vh instanceof ActionHolder)
String fullDateStr = dateFormat.format(actionDate) + " " + timeFormat.format(actionDate);
String dateStr = vh.itemView.getContext().getString(R.string.ago, "" + new DateRenderer(viewHolder.itemView.getContext()).timeAgo(action.getDate()).formattedDate + "");
- if (index > 0)
+ if (actionIndex > 0)
{
- long difference = actions.get(index - 1).getDate() - action.getDate();
+ long difference = actions.get(actionIndex - 1).getDate() - action.getDate();
int days = (int)Math.round(((double)difference / 60d / 60d / 24d / 1000d));
dateStr += " (-" + days + vh.itemView.getContext().getString(R.string.day_abbr) + ")";
@@ -503,13 +560,13 @@ else if (item.getItemId() == R.id.delete)
StageChange lastChange = null;
long currentChangeDate = action.getDate();
- for (int actionIndex = index; actionIndex < actions.size(); actionIndex++)
+ for (int aIndex = index; aIndex < actions.size(); aIndex++)
{
- if (actions.get(actionIndex) instanceof StageChange)
+ if (actions.get(aIndex) instanceof StageChange)
{
if (lastChange == null)
{
- lastChange = (StageChange)actions.get(actionIndex);
+ lastChange = (StageChange)actions.get(aIndex);
break;
}
}
@@ -564,7 +621,7 @@ else if (item.getItemId() == R.id.delete)
@Override public int getItemCount()
{
- return actions.size();
+ return actions.size() + (showCalendar ? 1 : 0);
}
@Override public void onItemMove(int fromPosition, int toPosition)
diff --git a/app/src/main/java/me/anon/grow/fragment/ActionsListFragment.java b/app/src/main/java/me/anon/grow/fragment/ActionsListFragment.java
index 264c1ab7..ecffce99 100644
--- a/app/src/main/java/me/anon/grow/fragment/ActionsListFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/ActionsListFragment.java
@@ -62,7 +62,6 @@ public class ActionsListFragment extends Fragment implements ActionAdapter.OnAct
@Views.InjectView(R.id.fab_add) private View fabAdd;
@Views.InjectView(R.id.recycler_view) private RecyclerView recycler;
- @Views.InjectView(R.id.calendar) private MaterialCalendarView calendar;
@Views.InjectView(R.id.empty) private View empty;
private Plant plant;
@@ -126,31 +125,10 @@ else if (getArguments() != null)
adapter.setOnActionSelectListener(this);
if (plant.getActions() != null && plant.getActions().size() > 0)
{
- calendar.addDecorator(new DayViewDecorator()
- {
- @Override public boolean shouldDecorate(CalendarDay calendarDay)
- {
- // find an action that is on this day
- for (Action action : plant.getActions())
- {
- LocalDate actionDate = CalendarDay.from(LocalDate.from(Instant.ofEpochMilli(action.getDate()).atZone(ZoneId.systemDefault()))).getDate();
- if (calendarDay.getDate().equals(actionDate))
- {
- return true;
- }
- }
-
- return false;
- }
-
- @Override public void decorate(DayViewFacade dayViewFacade)
- {
- dayViewFacade.addSpan(new DotSpan(6.0f, IntUtilsKt.resolveColor(R.attr.colorAccent, getActivity())));
- }
- });
+// calendar.
}
- calendar.setOnDateChangedListener(new OnDateSelectedListener()
+ adapter.setOnDateChangedListener(new OnDateSelectedListener()
{
@Override public void onDateSelected(@NonNull MaterialCalendarView materialCalendarView, @NonNull CalendarDay calendarDay, boolean b)
{
@@ -159,8 +137,8 @@ else if (getArguments() != null)
adapter.notifyDataSetChanged();
}
});
- calendar.setCurrentDate(CalendarDay.today());
- calendar.setVisibility(filtered && getResources().getBoolean(R.bool.is_portrait) ? View.VISIBLE : View.GONE);
+
+ adapter.showCalendar = filtered;
adapter.setFilterDate(selectedFilterDate);
setActions();
@@ -552,16 +530,16 @@ private void setResult()
if (item.getItemId() == R.id.menu_calendar)
{
- calendar.setVisibility(calendar.getVisibility() == View.GONE ? View.VISIBLE : View.GONE);
- filtered = calendar.getVisibility() == View.VISIBLE;
+ adapter.showCalendar = !adapter.showCalendar;
+ filtered = adapter.showCalendar;
selectedFilterDate = null;
fabAdd.setVisibility(View.VISIBLE);
if (filtered)
{
fabAdd.setVisibility(View.GONE);
- selectedFilterDate = CalendarDay.today();
- calendar.setSelectedDate(selectedFilterDate);
+ Action lastAction = plant.getActions().get(plant.getActions().size() - 1);
+ selectedFilterDate = CalendarDay.from(LocalDate.from(Instant.ofEpochMilli(lastAction.getDate()).atZone(ZoneId.systemDefault())));
}
adapter.setFilterDate(selectedFilterDate);
diff --git a/app/src/main/res/layout/actions_list_view.xml b/app/src/main/res/layout/actions_list_view.xml
index a65ff46f..a6265f5d 100644
--- a/app/src/main/res/layout/actions_list_view.xml
+++ b/app/src/main/res/layout/actions_list_view.xml
@@ -11,22 +11,6 @@
android:layout_height="match_parent"
android:orientation="vertical"
>
-
-
+
+
From b6a5640277264c2f1c72d04d6394c06169da1308 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 15 Mar 2020 12:28:03 +0000
Subject: [PATCH 030/152] Fixes issue with day dates not showing
---
.../main/java/me/anon/controller/adapter/ActionAdapter.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/src/main/java/me/anon/controller/adapter/ActionAdapter.java b/app/src/main/java/me/anon/controller/adapter/ActionAdapter.java
index a8760a29..e762cfc5 100644
--- a/app/src/main/java/me/anon/controller/adapter/ActionAdapter.java
+++ b/app/src/main/java/me/anon/controller/adapter/ActionAdapter.java
@@ -543,9 +543,9 @@ else if (item.getItemId() == R.id.delete)
{
String lastDateStr = "";
- if (index - 1 >= 0)
+ if (actionIndex - 1 >= 0)
{
- Date lastActionDate = new Date(actions.get(index - 1).getDate());
+ Date lastActionDate = new Date(actions.get(actionIndex - 1).getDate());
Calendar lastActionCalendar = GregorianCalendar.getInstance();
lastActionCalendar.setTime(lastActionDate);
lastDateStr = lastActionCalendar.get(Calendar.DAY_OF_MONTH) + " " + lastActionCalendar.getDisplayName(Calendar.MONTH, Calendar.SHORT, Locale.getDefault());
@@ -560,7 +560,7 @@ else if (item.getItemId() == R.id.delete)
StageChange lastChange = null;
long currentChangeDate = action.getDate();
- for (int aIndex = index; aIndex < actions.size(); aIndex++)
+ for (int aIndex = actionIndex; aIndex < actions.size(); aIndex++)
{
if (actions.get(aIndex) instanceof StageChange)
{
From 2d972f1f5c3c2ad8c39e1b553c86af49d86b7ad0 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 15 Mar 2020 12:31:33 +0000
Subject: [PATCH 031/152] Tightens up calendar view
---
app/src/main/res/layout/calendar_item.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/src/main/res/layout/calendar_item.xml b/app/src/main/res/layout/calendar_item.xml
index 061addce..de077972 100644
--- a/app/src/main/res/layout/calendar_item.xml
+++ b/app/src/main/res/layout/calendar_item.xml
@@ -4,9 +4,9 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
- android:layout_height="300dp"
+ android:layout_height="256dp"
+ android:paddingBottom="12dp"
android:id="@+id/calendar"
- android:layout_marginBottom="12dp"
app:mcv_tileWidth="match_parent"
app:mcv_showOtherDates="other_months"
app:mcv_calendarMode="month"
From 488fda344cb588a8b487e49678b4aa33a6de46ed Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 15 Mar 2020 13:02:36 +0000
Subject: [PATCH 032/152] Replaces layout structure to allow for layout
behaviour of FAB
---
.../java/me/anon/grow/PlantDetailsActivity.kt | 8 +--
app/src/main/java/me/anon/lib/SnackBar.kt | 2 +-
app/src/main/res/layout/image_grid_view.xml | 69 +++++++++++--------
.../res/layout/tabbed_fragment_holder.xml | 6 +-
4 files changed, 47 insertions(+), 38 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/PlantDetailsActivity.kt b/app/src/main/java/me/anon/grow/PlantDetailsActivity.kt
index 5a7a3738..42273f95 100644
--- a/app/src/main/java/me/anon/grow/PlantDetailsActivity.kt
+++ b/app/src/main/java/me/anon/grow/PlantDetailsActivity.kt
@@ -48,7 +48,7 @@ class PlantDetailsActivity : BaseActivity()
}
else -> PlantDetailsFragment.newInstance(intent.extras)
}
- supportFragmentManager.beginTransaction().replace(R.id.coordinator, fragment, TAG_FRAGMENT).commit()
+ supportFragmentManager.beginTransaction().replace(R.id.fragment_holder, fragment, TAG_FRAGMENT).commit()
}
tabs.visibility = View.GONE
@@ -58,7 +58,7 @@ class PlantDetailsActivity : BaseActivity()
tabs.visibility = View.VISIBLE
tabs.setOnNavigationItemSelectedListener {
plant = intent.extras?.get("plant") as Plant
- val fragment = supportFragmentManager.findFragmentById(R.id.coordinator)
+ val fragment = supportFragmentManager.findFragmentById(R.id.fragment_holder)
if (fragment is PlantDetailsFragment)
{
@@ -68,7 +68,7 @@ class PlantDetailsActivity : BaseActivity()
toolbarLayout.removeViews(1, toolbarLayout.childCount - 1)
supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.fade_in, R.anim.fade_out)
- .replace(R.id.coordinator, when (it.itemId)
+ .replace(R.id.fragment_holder, when (it.itemId)
{
R.id.view_details -> PlantDetailsFragment.newInstance(intent.extras)
R.id.view_history -> ActionsListFragment.newInstance(intent.extras)
@@ -98,7 +98,7 @@ class PlantDetailsActivity : BaseActivity()
{
if (item.itemId == android.R.id.home)
{
- val fragment = supportFragmentManager.findFragmentById(R.id.coordinator)
+ val fragment = supportFragmentManager.findFragmentById(R.id.fragment_holder)
if (fragment is PlantDetailsFragment)
{
diff --git a/app/src/main/java/me/anon/lib/SnackBar.kt b/app/src/main/java/me/anon/lib/SnackBar.kt
index 645d2610..fa8dd229 100644
--- a/app/src/main/java/me/anon/lib/SnackBar.kt
+++ b/app/src/main/java/me/anon/lib/SnackBar.kt
@@ -97,7 +97,7 @@ class SnackBar
action: (View) -> kotlin.Unit = {}
)
{
- val snackbar = Snackbar.make(context.findViewById(R.id.coordinator), message, length)
+ val snackbar = Snackbar.make(context.findViewById(R.id.coordinator) ?: context.findViewById(R.id.fragment_holder) , message, length)
var actionText = actionText
var action = action
diff --git a/app/src/main/res/layout/image_grid_view.xml b/app/src/main/res/layout/image_grid_view.xml
index b5b4a656..51b55ed0 100644
--- a/app/src/main/res/layout/image_grid_view.xml
+++ b/app/src/main/res/layout/image_grid_view.xml
@@ -1,46 +1,52 @@
-
-
-
-
-
-
-
+ android:id="@+id/empty"
+ android:layout_gravity="center"
+ android:orientation="vertical"
+ android:visibility="gone"
+ >
+
+
+
+
+
-
+
diff --git a/app/src/main/res/layout/tabbed_fragment_holder.xml b/app/src/main/res/layout/tabbed_fragment_holder.xml
index e91a3dde..4b80d807 100644
--- a/app/src/main/res/layout/tabbed_fragment_holder.xml
+++ b/app/src/main/res/layout/tabbed_fragment_holder.xml
@@ -25,10 +25,10 @@
/>
-
@@ -38,7 +38,7 @@
-
+
Date: Sun, 15 Mar 2020 13:43:28 +0000
Subject: [PATCH 033/152] Replaces other fragment instance layouts with updated
layout to provide for FAB layout behaviour
---
.../main/java/me/anon/grow/ActionsActivity.kt | 2 +-
.../java/me/anon/grow/AddWateringActivity.kt | 2 +-
.../me/anon/grow/FeedingScheduleActivity.kt | 2 +-
.../grow/FeedingScheduleDetailsActivity.kt | 2 +-
.../main/java/me/anon/grow/MainActivity.java | 8 +-
.../anon/grow/ScheduleDateDetailsActivity.kt | 2 +-
.../java/me/anon/grow/StatisticsActivity.kt | 2 +-
.../java/me/anon/grow/ViewPhotosActivity.kt | 2 +-
.../FeedingScheduleDetailsFragment.kt | 13 +-
.../fragment/FeedingScheduleListFragment.kt | 13 +-
.../me/anon/grow/fragment/GardenFragment.java | 71 +-----
.../anon/grow/fragment/GardenHostFragment.kt | 6 +-
.../grow/fragment/PlantDetailsFragment.java | 71 +-----
.../anon/grow/fragment/PlantListFragment.java | 71 +-----
.../java/me/anon/lib/helper/FabAnimator.java | 27 ---
.../res/layout-land/actions_list_view.xml | 87 -------
app/src/main/res/layout/actions_list_view.xml | 8 +-
app/src/main/res/layout/fragment_holder.xml | 4 +-
.../res/layout/garden_fragment_holder.xml | 13 +-
app/src/main/res/layout/garden_view.xml | 88 ++++---
app/src/main/res/layout/plant_list_view.xml | 87 ++++---
.../main/res/layout/schedule_details_view.xml | 229 +++++++++---------
.../main/res/layout/schedule_list_view.xml | 75 +++---
23 files changed, 290 insertions(+), 595 deletions(-)
delete mode 100644 app/src/main/java/me/anon/lib/helper/FabAnimator.java
delete mode 100644 app/src/main/res/layout-land/actions_list_view.xml
diff --git a/app/src/main/java/me/anon/grow/ActionsActivity.kt b/app/src/main/java/me/anon/grow/ActionsActivity.kt
index 2483cf25..f6ebbb06 100644
--- a/app/src/main/java/me/anon/grow/ActionsActivity.kt
+++ b/app/src/main/java/me/anon/grow/ActionsActivity.kt
@@ -22,7 +22,7 @@ class ActionsActivity : BaseActivity()
if (supportFragmentManager.findFragmentByTag("fragment") == null)
{
supportFragmentManager.beginTransaction()
- .replace(R.id.coordinator, ActionsListFragment.newInstance(intent.extras), "fragment")
+ .replace(R.id.fragment_holder, ActionsListFragment.newInstance(intent.extras), "fragment")
.commit()
}
}
diff --git a/app/src/main/java/me/anon/grow/AddWateringActivity.kt b/app/src/main/java/me/anon/grow/AddWateringActivity.kt
index efa5a40e..15227f80 100644
--- a/app/src/main/java/me/anon/grow/AddWateringActivity.kt
+++ b/app/src/main/java/me/anon/grow/AddWateringActivity.kt
@@ -25,7 +25,7 @@ class AddWateringActivity : BaseActivity()
if (supportFragmentManager.findFragmentByTag(TAG_FRAGMENT) == null)
{
- supportFragmentManager.beginTransaction().replace(R.id.coordinator, WateringFragment.newInstance(plantIndex, -1, gardenIndex), TAG_FRAGMENT).commit()
+ supportFragmentManager.beginTransaction().replace(R.id.fragment_holder, WateringFragment.newInstance(plantIndex, -1, gardenIndex), TAG_FRAGMENT).commit()
}
}
diff --git a/app/src/main/java/me/anon/grow/FeedingScheduleActivity.kt b/app/src/main/java/me/anon/grow/FeedingScheduleActivity.kt
index 34beb918..db581dda 100644
--- a/app/src/main/java/me/anon/grow/FeedingScheduleActivity.kt
+++ b/app/src/main/java/me/anon/grow/FeedingScheduleActivity.kt
@@ -24,7 +24,7 @@ class FeedingScheduleActivity : BaseActivity()
if (supportFragmentManager.findFragmentByTag(TAG_FRAGMENT) == null)
{
- supportFragmentManager.beginTransaction().replace(R.id.coordinator, FeedingScheduleListFragment(), TAG_FRAGMENT).commit()
+ supportFragmentManager.beginTransaction().replace(R.id.fragment_holder, FeedingScheduleListFragment(), TAG_FRAGMENT).commit()
}
}
}
diff --git a/app/src/main/java/me/anon/grow/FeedingScheduleDetailsActivity.kt b/app/src/main/java/me/anon/grow/FeedingScheduleDetailsActivity.kt
index ebda56de..213a3fcf 100644
--- a/app/src/main/java/me/anon/grow/FeedingScheduleDetailsActivity.kt
+++ b/app/src/main/java/me/anon/grow/FeedingScheduleDetailsActivity.kt
@@ -24,7 +24,7 @@ class FeedingScheduleDetailsActivity : BaseActivity()
if (supportFragmentManager.findFragmentByTag(TAG_FRAGMENT) == null)
{
- supportFragmentManager.beginTransaction().replace(R.id.coordinator, FeedingScheduleDetailsFragment.newInstance(intent.extras), TAG_FRAGMENT).commit()
+ supportFragmentManager.beginTransaction().replace(R.id.fragment_holder, FeedingScheduleDetailsFragment.newInstance(intent.extras), TAG_FRAGMENT).commit()
}
}
diff --git a/app/src/main/java/me/anon/grow/MainActivity.java b/app/src/main/java/me/anon/grow/MainActivity.java
index e9bd89e0..abd01165 100644
--- a/app/src/main/java/me/anon/grow/MainActivity.java
+++ b/app/src/main/java/me/anon/grow/MainActivity.java
@@ -123,13 +123,13 @@ public NavigationView getNavigation()
{
if (navigation.getMenu().findItem(selectedItem).isCheckable())
{
- getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentById(R.id.coordinator)).commit();
+ getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentById(R.id.fragment_holder)).commit();
navigation.getMenu().findItem(selectedItem).setChecked(true);
onNavigationItemSelected(navigation.getMenu().findItem(selectedItem));
}
}
- getSupportFragmentManager().findFragmentById(R.id.coordinator).onActivityResult(requestCode, resultCode, data);
+ getSupportFragmentManager().findFragmentById(R.id.fragment_holder).onActivityResult(requestCode, resultCode, data);
}
@Override protected void onResume()
@@ -334,7 +334,7 @@ else if (item.getItemId() == R.id.all)
navigation.getMenu().findItem(R.id.garden_menu).getSubMenu().findItem(R.id.all).setChecked(true);
selectedItem = item.getItemId();
- getSupportFragmentManager().beginTransaction().replace(R.id.coordinator, PlantListFragment.newInstance(), TAG_FRAGMENT).commit();
+ getSupportFragmentManager().beginTransaction().replace(R.id.fragment_holder, PlantListFragment.newInstance(), TAG_FRAGMENT).commit();
}
else if (item.getItemId() >= 100 && item.getItemId() < Integer.MAX_VALUE)
{
@@ -349,7 +349,7 @@ else if (item.getItemId() >= 100 && item.getItemId() < Integer.MAX_VALUE)
selectedItem = item.getItemId();
item.setChecked(true);
int gardenIndex = item.getItemId() - 100;
- getSupportFragmentManager().beginTransaction().replace(R.id.coordinator, GardenHostFragment.newInstance(GardenManager.getInstance().getGardens().get(gardenIndex)), TAG_FRAGMENT).commit();
+ getSupportFragmentManager().beginTransaction().replace(R.id.fragment_holder, GardenHostFragment.newInstance(GardenManager.getInstance().getGardens().get(gardenIndex)), TAG_FRAGMENT).commit();
}
if (drawer != null)
diff --git a/app/src/main/java/me/anon/grow/ScheduleDateDetailsActivity.kt b/app/src/main/java/me/anon/grow/ScheduleDateDetailsActivity.kt
index 28603a8a..527d0801 100644
--- a/app/src/main/java/me/anon/grow/ScheduleDateDetailsActivity.kt
+++ b/app/src/main/java/me/anon/grow/ScheduleDateDetailsActivity.kt
@@ -25,7 +25,7 @@ class ScheduleDateDetailsActivity : BaseActivity()
if (supportFragmentManager.findFragmentByTag(TAG_FRAGMENT) == null)
{
supportFragmentManager.beginTransaction().replace(
- R.id.coordinator,
+ R.id.fragment_holder,
ScheduleDateDetailsFragment.newInstance(intent.extras!!),
TAG_FRAGMENT
).commit()
diff --git a/app/src/main/java/me/anon/grow/StatisticsActivity.kt b/app/src/main/java/me/anon/grow/StatisticsActivity.kt
index 4d65b25b..b685fbc1 100644
--- a/app/src/main/java/me/anon/grow/StatisticsActivity.kt
+++ b/app/src/main/java/me/anon/grow/StatisticsActivity.kt
@@ -22,7 +22,7 @@ class StatisticsActivity : BaseActivity()
if (supportFragmentManager.findFragmentByTag("fragment") == null)
{
supportFragmentManager.beginTransaction()
- .replace(R.id.coordinator, StatisticsFragment.newInstance(intent.extras), "fragment")
+ .replace(R.id.fragment_holder, StatisticsFragment.newInstance(intent.extras), "fragment")
.commit()
}
}
diff --git a/app/src/main/java/me/anon/grow/ViewPhotosActivity.kt b/app/src/main/java/me/anon/grow/ViewPhotosActivity.kt
index 0f66ae56..351430eb 100644
--- a/app/src/main/java/me/anon/grow/ViewPhotosActivity.kt
+++ b/app/src/main/java/me/anon/grow/ViewPhotosActivity.kt
@@ -22,7 +22,7 @@ class ViewPhotosActivity : BaseActivity()
if (supportFragmentManager.findFragmentByTag("fragment") == null)
{
supportFragmentManager.beginTransaction()
- .replace(R.id.coordinator, ViewPhotosFragment.newInstance(intent.extras), "fragment")
+ .replace(R.id.fragment_holder, ViewPhotosFragment.newInstance(intent.extras), "fragment")
.commit()
}
}
diff --git a/app/src/main/java/me/anon/grow/fragment/FeedingScheduleDetailsFragment.kt b/app/src/main/java/me/anon/grow/fragment/FeedingScheduleDetailsFragment.kt
index ce366fc1..b48e3da1 100644
--- a/app/src/main/java/me/anon/grow/fragment/FeedingScheduleDetailsFragment.kt
+++ b/app/src/main/java/me/anon/grow/fragment/FeedingScheduleDetailsFragment.kt
@@ -18,7 +18,6 @@ import me.anon.grow.ScheduleDateDetailsActivity
import me.anon.lib.SnackBar
import me.anon.lib.Unit
import me.anon.lib.ext.T
-import me.anon.lib.helper.FabAnimator
import me.anon.lib.manager.ScheduleManager
import me.anon.model.FeedingSchedule
import me.anon.model.FeedingScheduleDate
@@ -154,11 +153,7 @@ class FeedingScheduleDetailsFragment : Fragment()
scheduleDates.remove(date)
populateScheduleDates()
- SnackBar().show(activity as AppCompatActivity, R.string.schedule_deleted, R.string.undo, {
- FabAnimator.animateUp(fab_complete)
- }, {
- FabAnimator.animateDown(fab_complete)
- }, {
+ SnackBar().show(activity as AppCompatActivity, R.string.schedule_deleted, R.string.undo, action = {
scheduleDates.add(index, date)
populateScheduleDates()
})
@@ -174,11 +169,7 @@ class FeedingScheduleDetailsFragment : Fragment()
scheduleDates.add((index < 0) T scheduleDates.size - 1 ?: index, newSchedule)
populateScheduleDates()
- SnackBar().show(activity!!, R.string.schedule_copied, R.string.undo, {
- FabAnimator.animateUp(fab_complete)
- }, {
- FabAnimator.animateDown(fab_complete)
- }, {
+ SnackBar().show(activity!!, R.string.schedule_copied, R.string.undo, action = {
scheduleDates.remove(newSchedule)
populateScheduleDates()
})
diff --git a/app/src/main/java/me/anon/grow/fragment/FeedingScheduleListFragment.kt b/app/src/main/java/me/anon/grow/fragment/FeedingScheduleListFragment.kt
index da4a451e..767f2f95 100644
--- a/app/src/main/java/me/anon/grow/fragment/FeedingScheduleListFragment.kt
+++ b/app/src/main/java/me/anon/grow/fragment/FeedingScheduleListFragment.kt
@@ -16,7 +16,6 @@ import me.anon.controller.adapter.FeedingScheduleAdapter
import me.anon.grow.FeedingScheduleDetailsActivity
import me.anon.grow.R
import me.anon.lib.SnackBar
-import me.anon.lib.helper.FabAnimator
import me.anon.lib.manager.ScheduleManager
import java.util.*
@@ -47,11 +46,7 @@ class FeedingScheduleListFragment : Fragment()
adapter.notifyDataSetChanged()
checkAdapter()
- SnackBar().show(activity as AppCompatActivity, R.string.schedule_deleted, R.string.undo, {
- FabAnimator.animateUp(fab_add)
- }, {
- FabAnimator.animateDown(fab_add)
- }, {
+ SnackBar().show(activity as AppCompatActivity, R.string.schedule_deleted, R.string.undo, action = {
ScheduleManager.instance.schedules.add(index, schedule)
ScheduleManager.instance.save()
adapter.items = ScheduleManager.instance.schedules
@@ -69,11 +64,7 @@ class FeedingScheduleListFragment : Fragment()
adapter.notifyDataSetChanged()
checkAdapter()
- SnackBar().show(activity as AppCompatActivity, R.string.schedule_copied, R.string.undo, {
- FabAnimator.animateUp(fab_add)
- }, {
- FabAnimator.animateDown(fab_add)
- }, {
+ SnackBar().show(activity as AppCompatActivity, R.string.schedule_copied, R.string.undo, action = {
ScheduleManager.instance.schedules.remove(newSchedule)
ScheduleManager.instance.save()
adapter.items = ScheduleManager.instance.schedules
diff --git a/app/src/main/java/me/anon/grow/fragment/GardenFragment.java b/app/src/main/java/me/anon/grow/fragment/GardenFragment.java
index 4a9d5fa1..ff7d4c3e 100644
--- a/app/src/main/java/me/anon/grow/fragment/GardenFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/GardenFragment.java
@@ -51,7 +51,6 @@
import me.anon.lib.export.ExportProcessor;
import me.anon.lib.ext.IntUtilsKt;
import me.anon.lib.helper.BusHelper;
-import me.anon.lib.helper.FabAnimator;
import me.anon.lib.manager.GardenManager;
import me.anon.lib.manager.PlantManager;
import me.anon.model.EmptyAction;
@@ -312,28 +311,7 @@ private synchronized void saveCurrentState()
saveCurrentState();
- SnackBar.show(getActivity(), getString(R.string.snackbar_action_add), new SnackBarListener()
- {
- @Override public void onSnackBarStarted(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateUp(getView().findViewById(R.id.fab_add));
- }
- }
-
- @Override public void onSnackBarFinished(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateDown(getView().findViewById(R.id.fab_add));
- }
- }
-
- @Override public void onSnackBarAction(View v)
- {
- }
- });
+ SnackBar.show(getActivity(), getString(R.string.snackbar_action_add), null);
}
});
dialogFragment.show(getFragmentManager(), null);
@@ -354,28 +332,7 @@ private synchronized void saveCurrentState()
saveCurrentState();
- SnackBar.show(getActivity(), getString(R.string.snackbar_note_add), new SnackBarListener()
- {
- @Override public void onSnackBarStarted(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateUp(getView().findViewById(R.id.fab_add));
- }
- }
-
- @Override public void onSnackBarFinished(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateDown(getView().findViewById(R.id.fab_add));
- }
- }
-
- @Override public void onSnackBarAction(View v)
- {
- }
- });
+ SnackBar.show(getActivity(), getString(R.string.snackbar_note_add), null);
}
});
dialogFragment.show(getFragmentManager(), null);
@@ -404,29 +361,7 @@ private synchronized void saveCurrentState()
{
adapter.notifyDataSetChanged();
saveCurrentState();
- SnackBar.show(getActivity(), getString(R.string.snackbar_watering_add), new SnackBarListener()
- {
- @Override public void onSnackBarStarted(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateUp(getView().findViewById(R.id.fab_add));
- }
- }
-
- @Override public void onSnackBarAction(View v)
- {
-
- }
-
- @Override public void onSnackBarFinished(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateDown(getView().findViewById(R.id.fab_add));
- }
- }
- });
+ SnackBar.show(getActivity(), getString(R.string.snackbar_watering_add), null);
}
}
diff --git a/app/src/main/java/me/anon/grow/fragment/GardenHostFragment.kt b/app/src/main/java/me/anon/grow/fragment/GardenHostFragment.kt
index 592f4746..e18d81df 100644
--- a/app/src/main/java/me/anon/grow/fragment/GardenHostFragment.kt
+++ b/app/src/main/java/me/anon/grow/fragment/GardenHostFragment.kt
@@ -28,13 +28,13 @@ class GardenHostFragment : Fragment()
}
childFragmentManager.findFragmentByTag("child_fragment") ?: let {
- childFragmentManager.beginTransaction().replace(R.id.child_fragment_holder, GardenFragment.newInstance(garden), "child_fragment").commit()
+ childFragmentManager.beginTransaction().replace(R.id.fragment_holder, GardenFragment.newInstance(garden), "child_fragment").commit()
}
tabs.setOnNavigationItemSelectedListener {
childFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.fade_in, R.anim.fade_out)
- .replace(R.id.child_fragment_holder, when (it.itemId)
+ .replace(R.id.fragment_holder, when (it.itemId)
{
R.id.view_plants -> GardenFragment.newInstance(garden)
R.id.view_history -> GardenTrackerFragment.newInstance(garden)
@@ -49,7 +49,7 @@ class GardenHostFragment : Fragment()
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)
{
super.onActivityResult(requestCode, resultCode, data)
- childFragmentManager.findFragmentById(R.id.child_fragment_holder)?.onActivityResult(requestCode, resultCode, data)
+ childFragmentManager.findFragmentById(R.id.fragment_holder)?.onActivityResult(requestCode, resultCode, data)
}
override fun onSaveInstanceState(outState: Bundle)
diff --git a/app/src/main/java/me/anon/grow/fragment/PlantDetailsFragment.java b/app/src/main/java/me/anon/grow/fragment/PlantDetailsFragment.java
index 583cd952..d06defbe 100644
--- a/app/src/main/java/me/anon/grow/fragment/PlantDetailsFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/PlantDetailsFragment.java
@@ -71,7 +71,6 @@
import me.anon.lib.Views;
import me.anon.lib.export.ExportHelper;
import me.anon.lib.export.ExportProcessor;
-import me.anon.lib.helper.FabAnimator;
import me.anon.lib.helper.NotificationHelper;
import me.anon.lib.helper.PermissionHelper;
import me.anon.lib.manager.FileManager;
@@ -388,17 +387,12 @@ private void setUi()
{
@Override public void onSnackBarStarted(Object o)
{
- if (getView() != null)
- {
- FabAnimator.animateUp(getView().findViewById(R.id.fab_complete));
- }
}
@Override public void onSnackBarFinished(Object o)
{
if (getView() != null)
{
- FabAnimator.animateDown(getView().findViewById(R.id.fab_complete));
PlantWidgetProvider.triggerUpdateAll(getView().getContext());
}
}
@@ -565,18 +559,10 @@ else if (requestCode == ACTIVITY_REQUEST_FEEDING)
{
@Override public void onSnackBarStarted(Object o)
{
- if (getView() != null)
- {
- FabAnimator.animateUp(getView().findViewById(R.id.fab_complete));
- }
}
@Override public void onSnackBarFinished(Object o)
{
- if (getView() != null)
- {
- FabAnimator.animateDown(getView().findViewById(R.id.fab_complete));
- }
}
@Override public void onSnackBarAction(View v)
@@ -595,32 +581,7 @@ else if (requestCode == ACTIVITY_REQUEST_FEEDING)
PlantManager.getInstance().getPlants().get(index).getActions().add(copy);
}
- SnackBar.show(getActivity(), R.string.waterings_added, new SnackBarListener()
- {
- @Override public void onSnackBarStarted(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateUp(getView().findViewById(R.id.fab_complete));
- }
- }
-
- @Override public void onSnackBarFinished(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateDown(getView().findViewById(R.id.fab_complete));
- }
- }
-
- @Override public void onSnackBarAction(@NotNull View o)
- {
- if (getView() != null)
- {
- FabAnimator.animateUp(getView().findViewById(R.id.fab_complete));
- }
- }
- });
+ SnackBar.show(getActivity(), R.string.waterings_added, null);
}
});
dialog.show(getFragmentManager(), "plant-select");
@@ -697,19 +658,12 @@ else if (requestCode == ACTIVITY_REQUEST_LAST_WATER)
SnackBar.show(getActivity(), R.string.snackbar_image_added, R.string.snackbar_action_take_another, new SnackBarListener()
{
- @Override public void onSnackBarStarted(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateUp(getView().findViewById(R.id.fab_complete));
- }
- }
+ @Override public void onSnackBarStarted(Object o){}
@Override public void onSnackBarFinished(Object o)
{
if (getView() != null)
{
- FabAnimator.animateDown(getView().findViewById(R.id.fab_complete));
PlantWidgetProvider.triggerUpdateAll(getView().getContext());
}
}
@@ -828,18 +782,10 @@ else if (item.getItemId() == R.id.duplicate)
{
@Override public void onSnackBarStarted(Object o)
{
- if (getView() != null)
- {
- FabAnimator.animateUp(getView().findViewById(R.id.fab_complete));
- }
}
@Override public void onSnackBarFinished(Object o)
{
- if (getView() != null)
- {
- FabAnimator.animateDown(getView().findViewById(R.id.fab_complete));
- }
}
@Override public void onSnackBarAction(View v)
@@ -882,17 +828,12 @@ else if (item.getItemId() == R.id.export)
{
@Override public void onSnackBarStarted(Object o)
{
- if (getView() != null)
- {
- FabAnimator.animateUp(getView().findViewById(R.id.fab_complete));
- }
}
@Override public void onSnackBarFinished(Object o)
{
if (getView() != null)
{
- FabAnimator.animateDown(getView().findViewById(R.id.fab_complete));
PlantWidgetProvider.triggerUpdateAll(getView().getContext());
}
}
@@ -955,18 +896,10 @@ else if (item.getItemId() == R.id.export)
{
@Override public void onSnackBarStarted(Object o)
{
- if (getView() != null)
- {
- FabAnimator.animateUp(getView().findViewById(R.id.fab_add));
- }
}
@Override public void onSnackBarFinished(Object o)
{
- if (getView() != null)
- {
- FabAnimator.animateDown(getView().findViewById(R.id.fab_add));
- }
}
@Override public void onSnackBarAction(View v)
diff --git a/app/src/main/java/me/anon/grow/fragment/PlantListFragment.java b/app/src/main/java/me/anon/grow/fragment/PlantListFragment.java
index b2df3541..0bd2c7df 100644
--- a/app/src/main/java/me/anon/grow/fragment/PlantListFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/PlantListFragment.java
@@ -42,7 +42,6 @@
import me.anon.lib.SnackBarListener;
import me.anon.lib.Views;
import me.anon.lib.ext.IntUtilsKt;
-import me.anon.lib.helper.FabAnimator;
import me.anon.lib.manager.PlantManager;
import me.anon.model.EmptyAction;
import me.anon.model.NoteAction;
@@ -272,28 +271,7 @@ private synchronized void saveCurrentState()
PlantManager.getInstance().save();
- SnackBar.show(getActivity(), R.string.snackbar_action_add, new SnackBarListener()
- {
- @Override public void onSnackBarStarted(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateUp(getView().findViewById(R.id.fab_add));
- }
- }
-
- @Override public void onSnackBarFinished(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateDown(getView().findViewById(R.id.fab_add));
- }
- }
-
- @Override public void onSnackBarAction(View v)
- {
- }
- });
+ SnackBar.show(getActivity(), R.string.snackbar_action_add, null);
}
});
dialogFragment.show(getChildFragmentManager(), null);
@@ -314,28 +292,7 @@ private synchronized void saveCurrentState()
PlantManager.getInstance().save();
- SnackBar.show(getActivity(), R.string.snackbar_note_add, new SnackBarListener()
- {
- @Override public void onSnackBarStarted(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateUp(getView().findViewById(R.id.fab_add));
- }
- }
-
- @Override public void onSnackBarFinished(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateDown(getView().findViewById(R.id.fab_add));
- }
- }
-
- @Override public void onSnackBarAction(View v)
- {
- }
- });
+ SnackBar.show(getActivity(), R.string.snackbar_note_add, null);
}
});
dialogFragment.show(getChildFragmentManager(), null);
@@ -356,29 +313,7 @@ private synchronized void saveCurrentState()
if (resultCode != Activity.RESULT_CANCELED)
{
adapter.notifyDataSetChanged();
- SnackBar.show(getActivity(), R.string.snackbar_watering_add, new SnackBarListener()
- {
- @Override public void onSnackBarStarted(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateUp(getView().findViewById(R.id.fab_add));
- }
- }
-
- @Override public void onSnackBarAction(View v)
- {
-
- }
-
- @Override public void onSnackBarFinished(Object o)
- {
- if (getView() != null)
- {
- FabAnimator.animateDown(getView().findViewById(R.id.fab_add));
- }
- }
- });
+ SnackBar.show(getActivity(), R.string.snackbar_watering_add, null);
}
}
diff --git a/app/src/main/java/me/anon/lib/helper/FabAnimator.java b/app/src/main/java/me/anon/lib/helper/FabAnimator.java
deleted file mode 100644
index 9e3cd5b9..00000000
--- a/app/src/main/java/me/anon/lib/helper/FabAnimator.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package me.anon.lib.helper;
-
-import android.view.View;
-
-/**
- * // TODO: Add class description
- *
- * @author 7LPdWcaW
- * @documentation // TODO Reference flow doc
- * @project GrowTracker
- */
-public class FabAnimator
-{
- public static void animateUp(View fab)
- {
- if (fab == null) return;
-
- fab.animate().translationYBy(-(fab.getHeight() * 0.85f)).setDuration(200).start();
- }
-
- public static void animateDown(View fab)
- {
- if (fab == null) return;
-
- fab.animate().translationYBy((fab.getHeight() * 0.85f)).setDuration(200).start();
- }
-}
diff --git a/app/src/main/res/layout-land/actions_list_view.xml b/app/src/main/res/layout-land/actions_list_view.xml
deleted file mode 100644
index 7e523d01..00000000
--- a/app/src/main/res/layout-land/actions_list_view.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/actions_list_view.xml b/app/src/main/res/layout/actions_list_view.xml
index a6265f5d..4ff34fb5 100644
--- a/app/src/main/res/layout/actions_list_view.xml
+++ b/app/src/main/res/layout/actions_list_view.xml
@@ -1,10 +1,11 @@
-
-
+
diff --git a/app/src/main/res/layout/fragment_holder.xml b/app/src/main/res/layout/fragment_holder.xml
index 19acf0fa..70a078a7 100644
--- a/app/src/main/res/layout/fragment_holder.xml
+++ b/app/src/main/res/layout/fragment_holder.xml
@@ -25,9 +25,9 @@
/>
-
diff --git a/app/src/main/res/layout/garden_fragment_holder.xml b/app/src/main/res/layout/garden_fragment_holder.xml
index 25a4ac36..753147c4 100644
--- a/app/src/main/res/layout/garden_fragment_holder.xml
+++ b/app/src/main/res/layout/garden_fragment_holder.xml
@@ -6,20 +6,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
>
-
-
-
+ />
-
-
-
+
+
-
-
-
-
-
-
-
-
+ android:gravity="center_horizontal"
+ android:text="@string/empty_plant_list"
+ android:textColor="?android:textColorTertiary"
+ android:layout_marginTop="12dp"
+ android:layout_gravity="center_horizontal"
+ />
+
+
-
+
diff --git a/app/src/main/res/layout/plant_list_view.xml b/app/src/main/res/layout/plant_list_view.xml
index 3b1163e5..10a0ac0b 100644
--- a/app/src/main/res/layout/plant_list_view.xml
+++ b/app/src/main/res/layout/plant_list_view.xml
@@ -1,59 +1,65 @@
-
-
-
-
-
-
-
-
-
+ android:id="@+id/empty"
+ android:layout_gravity="center"
+ android:orientation="vertical"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ >
+
+
+
+
+
+
-
+
diff --git a/app/src/main/res/layout/schedule_details_view.xml b/app/src/main/res/layout/schedule_details_view.xml
index 4fa08ada..c994c169 100644
--- a/app/src/main/res/layout/schedule_details_view.xml
+++ b/app/src/main/res/layout/schedule_details_view.xml
@@ -1,161 +1,167 @@
-
-
-
-
-
+
+
-
+
+
-
+
+
-
-
-
+
+
-
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
+
diff --git a/app/src/main/res/layout/schedule_list_view.xml b/app/src/main/res/layout/schedule_list_view.xml
index 489f334c..eb1f3b12 100644
--- a/app/src/main/res/layout/schedule_list_view.xml
+++ b/app/src/main/res/layout/schedule_list_view.xml
@@ -1,48 +1,56 @@
-
-
-
-
-
-
-
+ android:id="@+id/empty"
+ android:layout_gravity="center"
+ android:orientation="vertical"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ >
+
+
+
+
+
-
+
From b45d3573090969de75097e7a586bb4b4c7bb5e6c Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 15 Mar 2020 13:48:54 +0000
Subject: [PATCH 034/152] Fixes settings activity
---
app/src/main/java/me/anon/grow/SettingsActivity.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/me/anon/grow/SettingsActivity.java b/app/src/main/java/me/anon/grow/SettingsActivity.java
index cd687a04..b9a43448 100644
--- a/app/src/main/java/me/anon/grow/SettingsActivity.java
+++ b/app/src/main/java/me/anon/grow/SettingsActivity.java
@@ -20,7 +20,9 @@ public class SettingsActivity extends BaseActivity
if (getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT) == null)
{
- getSupportFragmentManager().beginTransaction().replace(R.id.coordinator, new SettingsFragment(), TAG_FRAGMENT).commit();
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.fragment_holder, new SettingsFragment(), TAG_FRAGMENT)
+ .commit();
}
}
}
From 1757cf05969e4e47235acd09ff306b712f4e197c Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 15 Mar 2020 13:51:37 +0000
Subject: [PATCH 035/152] Fixes issue with snacker overlaying bottom man in
details fragment
---
.../main/res/layout/plant_details_view.xml | 520 +++++++++---------
1 file changed, 263 insertions(+), 257 deletions(-)
diff --git a/app/src/main/res/layout/plant_details_view.xml b/app/src/main/res/layout/plant_details_view.xml
index 6ca1ec6b..d57a795f 100644
--- a/app/src/main/res/layout/plant_details_view.xml
+++ b/app/src/main/res/layout/plant_details_view.xml
@@ -1,349 +1,355 @@
-
-
-
-
-
-
+ android:paddingLeft="12dp"
+ >
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
+ android:text="@string/plant_details_title"
+ style="@style/SectionTitle"
+ />
-
+ android:orientation="vertical"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="16dp"
+ >
+
-
+
+
+
+ android:orientation="vertical"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp"
+ >
+
+
+
+
-
-
-
-
-
-
-
-
-
+ android:text="@string/grow_details_title"
+ style="@style/SectionTitle"
+ />
-
+ android:id="@+id/plant_date_container"
+ android:orientation="vertical"
+ android:padding="16dp"
+ android:background="?selectableItemBackground"
+ >
+
-
-
+
+
-
-
+ android:id="@+id/plant_medium_container"
+ android:orientation="vertical"
+ android:padding="16dp"
+ android:background="?selectableItemBackground"
+ >
+
-
+
+
+
-
+ android:id="@+id/plant_medium_details_container"
+ android:orientation="vertical"
+ android:padding="16dp"
+ >
+
-
-
+
+
-
+ android:orientation="horizontal"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:paddingTop="16dp"
+ android:paddingBottom="8dp"
+ >
+
+
+
+
-
-
-
-
+
+
-
+ android:orientation="vertical"
+ android:padding="16dp"
+ >
+
-
+
+
-
-
+
+
From ad696d7e5f82b4ccc47028dbb2057c16bfbc7282 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 15 Mar 2020 13:52:07 +0000
Subject: [PATCH 036/152] Updates land layout for detais
---
app/src/main/res/layout-land/plant_details_view.xml | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/app/src/main/res/layout-land/plant_details_view.xml b/app/src/main/res/layout-land/plant_details_view.xml
index 88cb3065..6981a917 100644
--- a/app/src/main/res/layout-land/plant_details_view.xml
+++ b/app/src/main/res/layout-land/plant_details_view.xml
@@ -1,10 +1,11 @@
-
-
+
From 4b7d1e12c1ec5681f731219b0210ca4d2bbbd496 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 15 Mar 2020 13:54:16 +0000
Subject: [PATCH 037/152] Force recreate activity after applying theme change
---
app/src/main/java/me/anon/grow/fragment/SettingsFragment.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/app/src/main/java/me/anon/grow/fragment/SettingsFragment.java b/app/src/main/java/me/anon/grow/fragment/SettingsFragment.java
index 7726cf3e..cb960c9b 100644
--- a/app/src/main/java/me/anon/grow/fragment/SettingsFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/SettingsFragment.java
@@ -307,6 +307,7 @@ private void populateAddons()
{
PreferenceManager.getDefaultSharedPreferences(getActivity()).edit().putBoolean("force_dark", (boolean)newValue).apply();
AppCompatDelegate.setDefaultNightMode((boolean)newValue ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
+ getActivity().recreate();
}
else if ("backup_size".equals(preference.getKey()))
{
From bab0c1086df5b55a5d1ed49cfd3091b68908f9d8 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 15 Mar 2020 14:17:44 +0000
Subject: [PATCH 038/152] Adds functionality for multiple feeding suggestions
---
.../controller/adapter/FeedingDateAdapter.kt | 14 +++++--
.../FeedingScheduleSelectDialogFragment.java | 37 ++++++++-----------
.../anon/grow/fragment/WateringFragment.java | 2 +-
.../java/me/anon/view/FeedingDateHolder.kt | 21 +++++++----
4 files changed, 40 insertions(+), 34 deletions(-)
diff --git a/app/src/main/java/me/anon/controller/adapter/FeedingDateAdapter.kt b/app/src/main/java/me/anon/controller/adapter/FeedingDateAdapter.kt
index e8f9e95a..12b753a1 100644
--- a/app/src/main/java/me/anon/controller/adapter/FeedingDateAdapter.kt
+++ b/app/src/main/java/me/anon/controller/adapter/FeedingDateAdapter.kt
@@ -9,6 +9,7 @@ import me.anon.model.Plant
import me.anon.model.PlantStage
import me.anon.view.FeedingDateHolder
import java.util.*
+import kotlin.collections.ArrayList
/**
* // TODO: Add class description
@@ -23,10 +24,17 @@ class FeedingDateAdapter : RecyclerView.Adapter()
items.addAll(value)
notifyDataSetChanged()
}
- public var plant: Plant = Plant()
- public val plantStages: SortedMap by lazy { plant.calculateStageTime() }
+ public var plants: ArrayList = arrayListOf()
+ public val plantStages: ArrayList> by lazy {
+ ArrayList(plants.map { it.calculateStageTime() })
+ }
- public fun getLastStage(): PlantStage = plantStages.toSortedMap().lastKey()
+ public fun getLastStages(): ArrayList
+ {
+ return ArrayList(plantStages.map {
+ it.toSortedMap().lastKey()
+ })
+ }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FeedingDateHolder
= FeedingDateHolder(this, LayoutInflater.from(parent.context).inflate(R.layout.feeding_date_stub, parent, false))
diff --git a/app/src/main/java/me/anon/grow/fragment/FeedingScheduleSelectDialogFragment.java b/app/src/main/java/me/anon/grow/fragment/FeedingScheduleSelectDialogFragment.java
index 3b0119c3..2591e757 100644
--- a/app/src/main/java/me/anon/grow/fragment/FeedingScheduleSelectDialogFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/FeedingScheduleSelectDialogFragment.java
@@ -1,6 +1,5 @@
package me.anon.grow.fragment;
-import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
@@ -9,6 +8,8 @@
import android.view.WindowManager;
import android.widget.LinearLayout;
+import java.util.ArrayList;
+
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.recyclerview.widget.DividerItemDecoration;
@@ -43,7 +44,7 @@ public interface OnFeedingSelectedListener
@Views.InjectView(R.id.recycler_view) private RecyclerView recyclerView;
private FeedingDateAdapter adapter;
private OnFeedingSelectedListener onFeedingSelected;
- private Plant plant;
+ private ArrayList plants;
private FeedingSchedule schedule;
public void setOnFeedingSelectedListener(OnFeedingSelectedListener onFeedingSelected)
@@ -51,15 +52,14 @@ public void setOnFeedingSelectedListener(OnFeedingSelectedListener onFeedingSele
this.onFeedingSelected = onFeedingSelected;
}
- @SuppressLint("ValidFragment")
- public FeedingScheduleSelectDialogFragment(FeedingSchedule schedule, Plant plant)
+ public static FeedingScheduleSelectDialogFragment newInstance(FeedingSchedule schedule, ArrayList plants)
{
- this.plant = plant;
- this.schedule = schedule;
+ FeedingScheduleSelectDialogFragment fragment = new FeedingScheduleSelectDialogFragment();
+ fragment.plants = new ArrayList(plants);
+ fragment.schedule = schedule;
+ return fragment;
}
-
- @SuppressLint("ValidFragment")
public FeedingScheduleSelectDialogFragment()
{
}
@@ -70,7 +70,7 @@ public FeedingScheduleSelectDialogFragment()
Views.inject(this, view);
adapter = new FeedingDateAdapter();
- adapter.setPlant(plant);
+ adapter.setPlants(plants);
adapter.setItems(schedule.getSchedules());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
@@ -101,25 +101,18 @@ public FeedingScheduleSelectDialogFragment()
{
@Override public void onShow(DialogInterface dialog)
{
- PlantStage lastStage = adapter.getLastStage();
- int days = (int)TimeHelper.toDays(adapter.getPlantStages().get(lastStage));
- int suggestedIndex = 0;
- for (FeedingScheduleDate feedingScheduleDate : adapter.getItems())
+ for (int index = 0; index < recyclerView.getAdapter().getItemCount(); index++)
{
- if (lastStage.ordinal() >= feedingScheduleDate.getStageRange()[0].ordinal())
+ recyclerView.scrollToPosition(index);
+ for (int childIndex = 0; childIndex < recyclerView.getChildCount(); childIndex++)
{
- if (days >= feedingScheduleDate.getDateRange()[0]
- && ((days <= feedingScheduleDate.getDateRange()[1] && lastStage.ordinal() == feedingScheduleDate.getStageRange()[0].ordinal())
- || (lastStage.ordinal() < feedingScheduleDate.getStageRange()[1].ordinal())))
+ if (recyclerView.getChildAt(childIndex).getTag() == Boolean.TRUE)
{
- break;
+ recyclerView.scrollToPosition(recyclerView.getChildAdapterPosition(recyclerView.getChildAt(childIndex)));
+ return;
}
}
-
- suggestedIndex++;
}
-
- recyclerView.scrollToPosition(suggestedIndex);
}
});
diff --git a/app/src/main/java/me/anon/grow/fragment/WateringFragment.java b/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
index e4ed4dd6..6e028489 100644
--- a/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
@@ -307,7 +307,7 @@ public int compare(Action o1, Action o2)
private void showScheduleDialog(FeedingSchedule schedule)
{
- FeedingScheduleSelectDialogFragment feedingScheduleSelectDialogFragment = new FeedingScheduleSelectDialogFragment(schedule, plants.get(0));
+ FeedingScheduleSelectDialogFragment feedingScheduleSelectDialogFragment = FeedingScheduleSelectDialogFragment.newInstance(schedule, plants);
feedingScheduleSelectDialogFragment.setOnFeedingSelectedListener(new FeedingScheduleSelectDialogFragment.OnFeedingSelectedListener()
{
@Override public void onFeedingSelected(FeedingScheduleDate date)
diff --git a/app/src/main/java/me/anon/view/FeedingDateHolder.kt b/app/src/main/java/me/anon/view/FeedingDateHolder.kt
index 0a66fb44..80394ee6 100644
--- a/app/src/main/java/me/anon/view/FeedingDateHolder.kt
+++ b/app/src/main/java/me/anon/view/FeedingDateHolder.kt
@@ -33,16 +33,21 @@ class FeedingDateHolder(val adapter: FeedingDateAdapter, itemView: View) : Recyc
copy.visibility = View.GONE
card.setCardBackgroundColor(R.attr.colorSurface.resolveColor(card.context))
- val lastStage = adapter.plantStages.toSortedMap().lastKey()
- val days = TimeHelper.toDays(adapter.plantStages[lastStage] ?: 0).toInt()
+ val lastStages = adapter.getLastStages()
- if (lastStage.ordinal >= feedingSchedule.stageRange[0].ordinal)
- {
- if (days >= feedingSchedule.dateRange[0]
- && ((days <= feedingSchedule.dateRange[1] && lastStage.ordinal == feedingSchedule.stageRange[0].ordinal)
- || (lastStage.ordinal < feedingSchedule.stageRange[1].ordinal)))
+ lastStages.forEachIndexed { index, lastStage ->
+ val days = TimeHelper.toDays(adapter.plantStages[index][lastStage] ?: 0).toInt()
+
+ if (lastStage.ordinal >= feedingSchedule.stageRange[0].ordinal)
{
- card.setCardBackgroundColor(android.R.attr.colorAccent.resolveColor(card.context))
+ if (days >= feedingSchedule.dateRange[0]
+ && ((days <= feedingSchedule.dateRange[1] && lastStage.ordinal == feedingSchedule.stageRange[0].ordinal)
+ || (lastStage.ordinal < feedingSchedule.stageRange[1].ordinal)))
+ {
+ itemView.tag = true
+ card.setCardBackgroundColor(android.R.attr.colorAccent.resolveColor(card.context))
+ return@forEachIndexed
+ }
}
}
From 6a259f02ea5cd082640a51a65e19f158e5aade16 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 15 Mar 2020 14:27:19 +0000
Subject: [PATCH 039/152] Fixes issue with dialog rotation causing crash
---
.../FeedingScheduleSelectDialogFragment.java | 14 ++++++++
.../anon/grow/fragment/WateringFragment.java | 36 ++++++++++++-------
2 files changed, 37 insertions(+), 13 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/FeedingScheduleSelectDialogFragment.java b/app/src/main/java/me/anon/grow/fragment/FeedingScheduleSelectDialogFragment.java
index 2591e757..2a504c56 100644
--- a/app/src/main/java/me/anon/grow/fragment/FeedingScheduleSelectDialogFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/FeedingScheduleSelectDialogFragment.java
@@ -10,6 +10,7 @@
import java.util.ArrayList;
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.recyclerview.widget.DividerItemDecoration;
@@ -64,11 +65,24 @@ public FeedingScheduleSelectDialogFragment()
{
}
+ @Override public void onSaveInstanceState(@NonNull Bundle outState)
+ {
+ outState.putParcelableArrayList("plants", plants);
+ outState.putParcelable("schedule", schedule);
+ super.onSaveInstanceState(outState);
+ }
+
@Override public Dialog onCreateDialog(Bundle savedInstanceState)
{
View view = getActivity().getLayoutInflater().inflate(R.layout.feeding_list_dialog_view, null, false);
Views.inject(this, view);
+ if (savedInstanceState != null)
+ {
+ plants = savedInstanceState.getParcelableArrayList("plants");
+ schedule = savedInstanceState.getParcelable("schedule");
+ }
+
adapter = new FeedingDateAdapter();
adapter.setPlants(plants);
adapter.setItems(schedule.getSchedules());
diff --git a/app/src/main/java/me/anon/grow/fragment/WateringFragment.java b/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
index 6e028489..0d5ac249 100644
--- a/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
@@ -28,6 +28,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
+import java.util.EnumSet;
import java.util.GregorianCalendar;
import androidx.annotation.NonNull;
@@ -209,7 +210,7 @@ else if (getArguments() != null)
}
}
-
+ reattachFeedingDialogListener();
setUi();
setHints();
}
@@ -308,22 +309,31 @@ public int compare(Action o1, Action o2)
private void showScheduleDialog(FeedingSchedule schedule)
{
FeedingScheduleSelectDialogFragment feedingScheduleSelectDialogFragment = FeedingScheduleSelectDialogFragment.newInstance(schedule, plants);
- feedingScheduleSelectDialogFragment.setOnFeedingSelectedListener(new FeedingScheduleSelectDialogFragment.OnFeedingSelectedListener()
+ feedingScheduleSelectDialogFragment.show(getFragmentManager(), "feeding");
+ reattachFeedingDialogListener();
+ }
+
+ private void reattachFeedingDialogListener()
+ {
+ FeedingScheduleSelectDialogFragment feedingScheduleSelectDialogFragment = (FeedingScheduleSelectDialogFragment)getFragmentManager().findFragmentByTag("feeding");
+ if (feedingScheduleSelectDialogFragment != null)
{
- @Override public void onFeedingSelected(FeedingScheduleDate date)
+ feedingScheduleSelectDialogFragment.setOnFeedingSelectedListener(new FeedingScheduleSelectDialogFragment.OnFeedingSelectedListener()
{
- ArrayList additives = new ArrayList<>();
-
- for (Additive additive : date.getAdditives())
+ @Override public void onFeedingSelected(FeedingScheduleDate date)
{
- additives.add(new Kryo().copy(additive));
- }
+ ArrayList additives = new ArrayList<>();
- water.setAdditives(additives);
- populateAdditives();
- }
- });
- feedingScheduleSelectDialogFragment.show(getFragmentManager(), "feeding");
+ for (Additive additive : date.getAdditives())
+ {
+ additives.add(new Kryo().copy(additive));
+ }
+
+ water.setAdditives(additives);
+ populateAdditives();
+ }
+ });
+ }
}
private void setHints()
From 7748921dad77858e58698754cc08c38a5a68e564 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 15 Mar 2020 14:33:51 +0000
Subject: [PATCH 040/152] Fixes issue with previous feed dialog rotation
---
.../fragment/ActionSelectDialogFragment.java | 49 +++++++++++++------
.../anon/grow/fragment/WateringFragment.java | 38 ++++++++------
2 files changed, 57 insertions(+), 30 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/ActionSelectDialogFragment.java b/app/src/main/java/me/anon/grow/fragment/ActionSelectDialogFragment.java
index ef9793a8..156576ab 100644
--- a/app/src/main/java/me/anon/grow/fragment/ActionSelectDialogFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/ActionSelectDialogFragment.java
@@ -10,6 +10,7 @@
import java.util.ArrayList;
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.recyclerview.widget.DividerItemDecoration;
@@ -38,26 +39,53 @@ public interface OnActionSelectedListener
}
@Views.InjectView(R.id.recycler_view) private RecyclerView recyclerView;
+ private ArrayList actions;
private ActionAdapter adapter;
private OnActionSelectedListener onActionSelected;
+ private ArrayList exclude = new ArrayList<>();
+ {
+ exclude.add(ImageActionHolder.class);
+ }
public void setOnActionSelectedListener(OnActionSelectedListener onActionSelected)
{
this.onActionSelected = onActionSelected;
}
- @SuppressLint("ValidFragment")
- public ActionSelectDialogFragment(ArrayList actions)
+ public static ActionSelectDialogFragment newInstance(ArrayList actions)
{
- ArrayList exclude = new ArrayList<>();
- exclude.add(ImageActionHolder.class);
+ ActionSelectDialogFragment fragment = new ActionSelectDialogFragment();
+ fragment.actions = actions;
+
+ return fragment;
+ }
+
+ public ActionSelectDialogFragment()
+ {
+ }
+
+ @Override public void onSaveInstanceState(@NonNull Bundle outState)
+ {
+ outState.putParcelableArrayList("actions", actions);
+ super.onSaveInstanceState(outState);
+ }
+
+ @Override public Dialog onCreateDialog(Bundle savedInstanceState)
+ {
+ View view = getActivity().getLayoutInflater().inflate(R.layout.action_list_dialog_view, null, false);
+ Views.inject(this, view);
+
+ if (savedInstanceState != null)
+ {
+ actions = savedInstanceState.getParcelableArrayList("actions");
+ }
adapter = new ActionAdapter()
{
@Override public void onBindViewHolder(RecyclerView.ViewHolder vh, int index)
{
super.onBindViewHolder(vh, index);
- int padding = (int)getResources().getDimension(R.dimen.padding_8dp);
+ int padding = (int)vh.itemView.getContext().getResources().getDimension(R.dimen.padding_8dp);
vh.itemView.setPadding(0, 0, 0, 0);
vh.itemView.findViewById(R.id.date_container).setVisibility(View.GONE);
((View)vh.itemView.findViewById(R.id.content_container).getParent()).setPadding(0, 0, 0, 0);
@@ -73,17 +101,6 @@ public ActionSelectDialogFragment(ArrayList actions)
adapter.setShowDate(false);
adapter.setShowActions(false);
adapter.setActions(null, actions, exclude);
- }
-
- @SuppressLint("ValidFragment")
- public ActionSelectDialogFragment()
- {
- }
-
- @Override public Dialog onCreateDialog(Bundle savedInstanceState)
- {
- View view = getActivity().getLayoutInflater().inflate(R.layout.action_list_dialog_view, null, false);
- Views.inject(this, view);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
diff --git a/app/src/main/java/me/anon/grow/fragment/WateringFragment.java b/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
index 0d5ac249..c7d54301 100644
--- a/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
@@ -211,6 +211,7 @@ else if (getArguments() != null)
}
reattachFeedingDialogListener();
+ reattachScheduleDialogListener();
setUi();
setHints();
}
@@ -290,17 +291,9 @@ public int compare(Action o1, Action o2)
}
});
- ActionSelectDialogFragment actionSelectDialogFragment = new ActionSelectDialogFragment(items);
- actionSelectDialogFragment.setOnActionSelectedListener(new ActionSelectDialogFragment.OnActionSelectedListener()
- {
- @Override public void onActionSelected(Action action)
- {
- water = (Water)new Kryo().copy(action);
- water.setDate(System.currentTimeMillis());
- setUi();
- }
- });
+ ActionSelectDialogFragment actionSelectDialogFragment = ActionSelectDialogFragment.newInstance(items);
actionSelectDialogFragment.show(getFragmentManager(), "actions");
+ reattachFeedingDialogListener();
}
return super.onOptionsItemSelected(item);
@@ -310,15 +303,32 @@ private void showScheduleDialog(FeedingSchedule schedule)
{
FeedingScheduleSelectDialogFragment feedingScheduleSelectDialogFragment = FeedingScheduleSelectDialogFragment.newInstance(schedule, plants);
feedingScheduleSelectDialogFragment.show(getFragmentManager(), "feeding");
- reattachFeedingDialogListener();
+ reattachScheduleDialogListener();
}
private void reattachFeedingDialogListener()
{
- FeedingScheduleSelectDialogFragment feedingScheduleSelectDialogFragment = (FeedingScheduleSelectDialogFragment)getFragmentManager().findFragmentByTag("feeding");
- if (feedingScheduleSelectDialogFragment != null)
+ ActionSelectDialogFragment fragment = (ActionSelectDialogFragment)getFragmentManager().findFragmentByTag("actions");
+ if (fragment != null)
+ {
+ fragment.setOnActionSelectedListener(new ActionSelectDialogFragment.OnActionSelectedListener()
+ {
+ @Override public void onActionSelected(Action action)
+ {
+ water = (Water)new Kryo().copy(action);
+ water.setDate(System.currentTimeMillis());
+ setUi();
+ }
+ });
+ }
+ }
+
+ private void reattachScheduleDialogListener()
+ {
+ FeedingScheduleSelectDialogFragment fragment = (FeedingScheduleSelectDialogFragment)getFragmentManager().findFragmentByTag("feeding");
+ if (fragment != null)
{
- feedingScheduleSelectDialogFragment.setOnFeedingSelectedListener(new FeedingScheduleSelectDialogFragment.OnFeedingSelectedListener()
+ fragment.setOnFeedingSelectedListener(new FeedingScheduleSelectDialogFragment.OnFeedingSelectedListener()
{
@Override public void onFeedingSelected(FeedingScheduleDate date)
{
From 5277a643079ea26653e799b6251306aeb07b8782 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 15 Mar 2020 14:43:28 +0000
Subject: [PATCH 041/152] Fixes date dialog orientation in water fragment
---
.../grow/fragment/ActionDialogFragment.java | 2 +-
.../grow/fragment/DateDialogFragment.java | 20 ++++++--
.../grow/fragment/HumidityDialogFragment.kt | 2 +-
.../grow/fragment/PlantDetailsFragment.java | 2 +-
.../grow/fragment/StageDialogFragment.java | 2 +-
.../fragment/TemperatureDialogFragment.kt | 2 +-
.../anon/grow/fragment/WateringFragment.java | 48 ++++++++++++-------
7 files changed, 51 insertions(+), 27 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/ActionDialogFragment.java b/app/src/main/java/me/anon/grow/fragment/ActionDialogFragment.java
index 5775c55d..2cf438c6 100644
--- a/app/src/main/java/me/anon/grow/fragment/ActionDialogFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/ActionDialogFragment.java
@@ -105,7 +105,7 @@ public ActionDialogFragment(){}
{
@Override public void onClick(View v)
{
- final DateDialogFragment fragment = new DateDialogFragment(action.getDate());
+ final DateDialogFragment fragment = DateDialogFragment.newInstance(action.getDate());
fragment.setOnDateSelected(new DateDialogFragment.OnDateSelectedListener()
{
@Override public void onDateSelected(Calendar date)
diff --git a/app/src/main/java/me/anon/grow/fragment/DateDialogFragment.java b/app/src/main/java/me/anon/grow/fragment/DateDialogFragment.java
index f14d7761..9fa61794 100644
--- a/app/src/main/java/me/anon/grow/fragment/DateDialogFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/DateDialogFragment.java
@@ -10,6 +10,7 @@
import java.util.Calendar;
+import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
public class DateDialogFragment extends Fragment
@@ -29,19 +30,30 @@ public void setOnDateSelected(OnDateSelectedListener onDateSelected)
this.onDateSelected = onDateSelected;
}
- @SuppressLint("ValidFragment")
public DateDialogFragment(){}
- @SuppressLint("ValidFragment")
- public DateDialogFragment(long time)
+ public static DateDialogFragment newInstance(long time)
{
- this.time = time;
+ DateDialogFragment fragment = new DateDialogFragment();
+ fragment.time = time;
+ return fragment;
+ }
+
+ @Override public void onSaveInstanceState(@NonNull Bundle outState)
+ {
+ outState.putLong("time", time);
+ super.onSaveInstanceState(outState);
}
@Override public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
+ if (savedInstanceState != null)
+ {
+ time = savedInstanceState.getLong("time");
+ }
+
final Calendar date = Calendar.getInstance();
date.setTimeInMillis(time);
diff --git a/app/src/main/java/me/anon/grow/fragment/HumidityDialogFragment.kt b/app/src/main/java/me/anon/grow/fragment/HumidityDialogFragment.kt
index 98539324..eb8bf6c8 100644
--- a/app/src/main/java/me/anon/grow/fragment/HumidityDialogFragment.kt
+++ b/app/src/main/java/me/anon/grow/fragment/HumidityDialogFragment.kt
@@ -59,7 +59,7 @@ class HumidityDialogFragment(var action: HumidityChange? = null, val callback: (
view.findViewById(R.id.date).text = dateStr
view.findViewById(R.id.date).setOnClickListener {
- val fragment = DateDialogFragment(action!!.date)
+ val fragment = DateDialogFragment.newInstance(action!!.date)
fragment.setOnDateSelected(object : DateDialogFragment.OnDateSelectedListener
{
override fun onDateSelected(date: Calendar)
diff --git a/app/src/main/java/me/anon/grow/fragment/PlantDetailsFragment.java b/app/src/main/java/me/anon/grow/fragment/PlantDetailsFragment.java
index d06defbe..1f3a8797 100644
--- a/app/src/main/java/me/anon/grow/fragment/PlantDetailsFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/PlantDetailsFragment.java
@@ -332,7 +332,7 @@ private void setUi()
{
@Override public void onClick(View v)
{
- final DateDialogFragment fragment = new DateDialogFragment(plant.getPlantDate());
+ final DateDialogFragment fragment = DateDialogFragment.newInstance(plant.getPlantDate());
fragment.setOnDateSelected(new DateDialogFragment.OnDateSelectedListener()
{
@Override public void onDateSelected(Calendar newDate)
diff --git a/app/src/main/java/me/anon/grow/fragment/StageDialogFragment.java b/app/src/main/java/me/anon/grow/fragment/StageDialogFragment.java
index 93e4eb65..333700d5 100644
--- a/app/src/main/java/me/anon/grow/fragment/StageDialogFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/StageDialogFragment.java
@@ -97,7 +97,7 @@ public StageDialogFragment(){}
{
@Override public void onClick(View v)
{
- final DateDialogFragment fragment = new DateDialogFragment(action.getDate());
+ final DateDialogFragment fragment = DateDialogFragment.newInstance(action.getDate());
fragment.setOnDateSelected(new DateDialogFragment.OnDateSelectedListener()
{
@Override public void onDateSelected(Calendar date)
diff --git a/app/src/main/java/me/anon/grow/fragment/TemperatureDialogFragment.kt b/app/src/main/java/me/anon/grow/fragment/TemperatureDialogFragment.kt
index ea2129d8..8ab6146f 100644
--- a/app/src/main/java/me/anon/grow/fragment/TemperatureDialogFragment.kt
+++ b/app/src/main/java/me/anon/grow/fragment/TemperatureDialogFragment.kt
@@ -61,7 +61,7 @@ class TemperatureDialogFragment(var action: TemperatureChange? = null, val callb
view.findViewById(R.id.date).text = dateStr
view.findViewById(R.id.date).setOnClickListener {
- val fragment = DateDialogFragment(action!!.date)
+ val fragment = DateDialogFragment.newInstance(action!!.date)
fragment.setOnDateSelected(object : DateDialogFragment.OnDateSelectedListener
{
override fun onDateSelected(date: Calendar)
diff --git a/app/src/main/java/me/anon/grow/fragment/WateringFragment.java b/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
index c7d54301..7ffaefe2 100644
--- a/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
@@ -28,7 +28,6 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
-import java.util.EnumSet;
import java.util.GregorianCalendar;
import androidx.annotation.NonNull;
@@ -212,6 +211,7 @@ else if (getArguments() != null)
reattachFeedingDialogListener();
reattachScheduleDialogListener();
+ reattachDateDialogListener();
setUi();
setHints();
}
@@ -323,6 +323,33 @@ private void reattachFeedingDialogListener()
}
}
+ private void reattachDateDialogListener()
+ {
+ DateDialogFragment fragment = (DateDialogFragment)getFragmentManager().findFragmentByTag("date");
+ if (fragment != null)
+ {
+ fragment.setOnDateSelected(new DateDialogFragment.OnDateSelectedListener()
+ {
+ @Override public void onDateSelected(Calendar date)
+ {
+ final DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(getActivity());
+ final DateFormat timeFormat = android.text.format.DateFormat.getTimeFormat(getActivity());
+
+ String dateStr = dateFormat.format(date.getTime()) + " " + timeFormat.format(date.getTime());
+ WateringFragment.this.date.setText(dateStr);
+
+ water.setDate(date.getTimeInMillis());
+ onCancelled();
+ }
+
+ @Override public void onCancelled()
+ {
+ getFragmentManager().beginTransaction().remove(fragment).commit();
+ }
+ });
+ }
+ }
+
private void reattachScheduleDialogListener()
{
FeedingScheduleSelectDialogFragment fragment = (FeedingScheduleSelectDialogFragment)getFragmentManager().findFragmentByTag("feeding");
@@ -489,24 +516,9 @@ private void setUi()
{
@Override public void onClick(View v)
{
- final DateDialogFragment fragment = new DateDialogFragment(water.getDate());
- fragment.setOnDateSelected(new DateDialogFragment.OnDateSelectedListener()
- {
- @Override public void onDateSelected(Calendar date)
- {
- String dateStr = dateFormat.format(date.getTime()) + " " + timeFormat.format(date.getTime());
- WateringFragment.this.date.setText(dateStr);
-
- water.setDate(date.getTimeInMillis());
- onCancelled();
- }
-
- @Override public void onCancelled()
- {
- getFragmentManager().beginTransaction().remove(fragment).commit();
- }
- });
+ final DateDialogFragment fragment = DateDialogFragment.newInstance(water.getDate());
getFragmentManager().beginTransaction().add(fragment, "date").commit();
+ reattachDateDialogListener();
}
});
From 3d41a2bb83befd15e088bc984953e831989ca23a Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 16:58:27 +0000
Subject: [PATCH 042/152] Apply translations in nl_NL
translation completed for the source file '/app/src/main/res/values/strings.xml'
on the 'nl_NL' language.
---
app/src/main/res/values-nl_NL/strings.xml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/app/src/main/res/values-nl_NL/strings.xml b/app/src/main/res/values-nl_NL/strings.xml
index fc554216..1d584291 100644
--- a/app/src/main/res/values-nl_NL/strings.xml
+++ b/app/src/main/res/values-nl_NL/strings.xml
@@ -165,6 +165,8 @@
Verpot
Bijsnijden
ScrOG Tuck
+ Supergroot gewas
+ Immens gewas
Water gegeven
Aantekening
From 8a33e5525624279725274a8d30e5422270cb474e Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 20:39:11 +0000
Subject: [PATCH 043/152] Apply translations in nl_NL
at least 99% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'nl_NL' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From fa48bd5f399109ff05c1f6724319b477c8009ed5 Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:13:36 +0000
Subject: [PATCH 044/152] Apply translations in nl_NL
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'nl_NL' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From d053d463b2b8b662a156a5f31d089fb90d4e29a9 Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:13:42 +0000
Subject: [PATCH 045/152] Apply translations in fr
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'fr' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
---
app/src/main/res/values-fr/strings.xml | 1 -
1 file changed, 1 deletion(-)
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index b8306f06..82ddceb7 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -163,7 +163,6 @@
Rempotage
Taillée
Tricotage ScrOG
-
Arrosée
Note
Supprimer cet événement ?
From 2a695bd02a726b6432c0b4a421e93e005e20f4b4 Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:13:47 +0000
Subject: [PATCH 046/152] Apply translations in de_DE
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'de_DE' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
---
app/src/main/res/values-de_DE/strings.xml | 338 ++++++++++++++++++++++
1 file changed, 338 insertions(+)
create mode 100644 app/src/main/res/values-de_DE/strings.xml
diff --git a/app/src/main/res/values-de_DE/strings.xml b/app/src/main/res/values-de_DE/strings.xml
new file mode 100644
index 00000000..b20a9578
--- /dev/null
+++ b/app/src/main/res/values-de_DE/strings.xml
@@ -0,0 +1,338 @@
+
+
+
+ Version %s
+ Einstellungen
+
+
+ %s Pflanzen
+
+ Alle Pflanzen
+
+ Alle
+ Maßnahme hinzugefügt
+ Notiz hinzugefügt
+ Bewässerung hinzugefügt
+ Garten gelöscht
+
+ Willst du Garten <b>\"%s\"</b> löschen? Dadurch werden die Pflanzen nicht gelöscht.
+ Gießen
+ Maßnahme
+
+ Widget ist nicht verfügbar, wenn die Verschlüsselung aktiviert ist
+ Neue Pflanze hinzufügen
+ Pflanzen Details
+ Pflanzen Statistik
+
+ Von der Kamera
+
+ Aus der Galerie
+ Option auswählen
+ Bild auswählen
+ Auf eine andere Pflanze anwenden
+ Pflanze auswählen
+ Bild hinzugefügt
+ Weiteres hinzufügen
+
+ Zeitpläne
+ Zeitplan Details
+ Plane ein Datum
+ Name
+ Geringfügiges Düngen
+ Beschreibung
+
+ Geringfügiges Düngen mit 2-wöchigem Ausspülen
+
+ + Neues Düngen
+ Neuer Zeitplan
+ + neuer Zusatzstoff
+ Zusatzstoffe
+ Zusatzstoff
+ Startzeitpunkt
+ Endzeitpunkt
+ Aus Zeitplan befüllen
+ Aus Vorigem füllen
+ Bist du sicher?
+ Ausgewählten Zeitplan kopieren?
+ Ausgewählten Zeitplan löschen?
+ Zeitplan kopiert
+ Zeitplan gelöscht
+ Rückgängig
+ Düngepläne
+ Düngeplan
+ App aktualisiert
+ App wurde auf Version %s aktualisiert
+ Änderungen ansehen
+ Ablehnen
+
+
+ Gieße %s
+ Gieße mehrere Pflanzen
+
+ Notizen
+ Wasser Details
+ Wasser pH
+ PPM
+ Abfluss
+ Menge (%s)
+ Temperatur (º%s)
+ Datum und Zeit
+ Jetzt
+ Darum
+ Heute
+ Gießen
+ Statusänderung
+
+ Duplizieren
+ Kopieren nach
+ Maßnahme bearbeiten
+ Maßnahme löschen
+
+ Pflanzen auswählen
+ Gärten
+ Alle Pflanzen
+ + Neuer Garten
+ Weitere
+ Einstellungen
+ Löschen
+ Teilen
+ Foto
+ Zuletzt gegossen
+ Nochmal gießen
+
+ Pflanzen Name
+ Neue Pflanze
+ Pflanzensorte
+ Lemon haze
+ Pflanzdetails
+ Pflanzzeitpunkt
+ Substrat
+
+ Substratdetails
+
+ Erde, Perlite Mischung 50/50
+ Aus Klon?
+ Statusinfo
+ Pflanzenstatus
+ Fotos ansehen
+ Verlauf ansehen
+ Statistik ansehen
+ Fotos
+ Verlauf
+ Statistik
+ Filter
+ Gepflanzt
+ Keimung
+ Schneiden
+ Vegetation
+ Blütezeit
+ Trocknen
+ Heilung
+ Geernetet
+
+ Vor %s geerntet
+ Garten exportieren
+ Garten bearbeiten
+ Garten löschen
+ Exportieren
+
+ Gesamtzeit:
+ Gesamt-Ausspülungen:
+ Mittlere Zeit zwischen dem Gießen:
+ Filter-Zusatzstoffe
+ PH
+
+ Min:
+ Max:
+ Ø:
+ Temperatur
+ Allgemein
+ Pflanze konnte nicht geladen werden
+ Verpasst
+ Ausspülen
+ Blattdüngung
+ Stressarmes Training
+ Lutscher
+ Pestizidanwendung
+ Oben
+ Verpflanzt
+ Trimmen
+ Gegossen
+ Notiz
+ Dieses Event löschen?
+ Möchtest du das wirklich löschen?
+ Bearbeiten
+ Status
+ Setzen
+ Ändern
+ Hinzufügen
+ Abbrechen
+ Maßnahme
+ OK
+ Feld muss ausgefüllt werden
+ Fehler - falsches Passwort
+ Bewässerung bearbeiten
+ hinzugefügt
+ Maßnahme dupliziert
+ mehrere Pflanzen
+ Notiz aktualisiert
+ aktualisiert
+ Status aktualisiert
+ Event gelöscht
+ Erledigt
+ Garten
+ Alles auswählen
+ Nichts auswählen
+ Akzeptieren
+ Aktivieren
+ Ablehnen
+ Sämling:
+ Sämling
+
+ Ups
+ Offenbar ist die App bei der letzten Nutzung gelöscht. Möchtest du einen anonymen Fehlerreport senden? Dieser Fehlerreport wird an <a href=\"https://github.com/7LPdWcaW/GrowTracker-Android/issues\">github.com/7LPdWcaW/GrowTracker-Android/issues</a> gesemdet und es werden keine persönlichen Informationen gesendet. Zusätzlich kannst du den Fehler hier melden: <a href=\"https://reddit.com/r/growutils\">reddit.com/r/growutils</a> auf Wunsch auch manuell. Die Fehlerreporte werden hier gespeichert: <i>%s<i>
+ Ja
+ Nein
+
+ Passwort eingeben
+ Ein Passwort eingeben
+ Passwort erneut eingeben
+ Fehler - Passwörter stimmen nicht überein
+
+ Der Garten konnte nicht gespeichert werden, bitte mach ein Backup deiner Daten.
+ Entnommen
+ Vor %s
+ Gegossen vor <b> %s </b>
+ Zuletzt gegossen vor <b> %s </b>
+ Gepflanzt vor <b> %s </b>
+
+ Für die Speicherung von Fotos ist der Zugriff auf den externen Speicher erforderlich. Es werden keine anderen Daten verwendet.
+
+ Bewässerungen hinzugefügt
+ Hiermit wird <b> %s </b> gelöscht, ebenso alle damit verknüpften Bilder, sind sie sicher? Dies kann nicht wieder rückgängig gemacht werden.
+ Lösche Pflanze...
+
+ Pflanze dupliziert
+ Öffnen
+
+ Exportiere Wachstumsprotokoll
+ %s hinzugefügt
+ Name kann nicht leer sein
+ Exportiere %s
+
+ Erde
+ Hydroponik
+ Kokosnussfasern
+ Aeroponik
+ Bild verstecken
+ Bild anzeigen
+
+ Gib das Passwort während der Entschlüsselungsphase an, um das Laden von Daten zu verhindern
+ Warnung
+ Dies ist eine Standart AES-Verschlüsselung auf der Grundlage einer bereitgestellten Passphrase. Es ist kein garantierter Schutz vor Strafverfolgungsbehörden.
+ Backup aktiviert, die Backups werden in %s
+ Wiederherstellen nach %s abgeschlossen
+ verschlüsselt
+ nicht verschlüsselt
+
+ Messung auswählen
+ Temperatur auswählen
+ Garten auswählen
+ Backup auswählen
+ Du musst den verschlüsselten Modus mit demselben Kennwort aktiviert haben, um dieses Backup wiederherzustellen
+
+ Gesichert nach
+ Es ist kein Backup vorhanden
+ Alle/Keine
+
+ Durchschnitts pH-Wert
+
+ Pflanzenfotos
+
+ Menge:
+ Temp:
+ Zusatzstoffe:
+ Zeitplan auswählen
+ Maßnahmen
+ Erzwinge Dark Theme
+ Erzwingt das Dark Theme unabhängig von der Systemeinstellung
+ Geerntete verstecken
+ Verstecke alle Pflanzen, die geernted wurden
+ Reihenfolge der Anlage umkehren
+ Zeigt Pflanzen in umgekehrter Reihenfolge. (Benötigt App-Neustart)
+ Standard-Garten
+
+ Einheiten
+ Lieferumfang
+ Maßeinheit
+ Temperatureinheiten
+ Datenmanagement
+ Automatisches Backup
+ Sichert Automatisch Ihre Daten alle 24 Stunden
+ Jetzt sichern
+ Begrenzung der Backup-Größe
+ Größe in MB
+ Backup-Limit (MB)
+ Wiederherstellen aus Backup
+ Daten verschlüsseln
+ Fügt eine PIN-Sperre hinzu und verschlüsselt alle Daten/Bilder
+ Setze ein sicheres Kennwort, um den Zugriff auf Daten zu verhindern
+ Erweiterungen
+ Über
+ Lies mich
+ Daten exportieren
+ Keine Pflanzen zum Anzeigen vorhanden
+ Es gibt keine Zeitpläne
+ Keine Fotos zum Anzeigen vorhanden
+ Kalender ein-/ausblenden
+ Vielen Dank an
+ Übersetzungen von
+ Hilf Übersetzen
+ Das Verschlüsseln von Daten und Bildern kann eine Weile dauern...
+ Das Entschlüsseln von Daten und Bildern kann eine Weile dauern...
+
+
+ 1s
+ s
+ m
+ h
+ d
+ w
+ mo
+ y
+
+ Details
+
+
+ - Original
+ - Kompakt
+ - Extreme
+
+
+ Du verlierst alle ungespeicherten Änderungen
+ Beenden
+ Pflanzen
+ Feuchtigkeit
+ Diesen Eintrag löschen?
+ Bildspeicherort konnte nicht festgelegt werden
+ Speicherort des Bildes
+ Bild-Cache löschen
+ Image-Festplatte und Speicher-Cache gelöscht
+ Das Importieren von Bildern kann eine Weile dauern...
+ Aufgabe erledigt
+ Es sind keine Aktionen zu zeigen
+
+ Exportiert %s nach %s
+ Export abgeschlossen
+ Bilder einbeziehen?
+ Es sind keine Daten verfügbar
+
+ Für das Fotografieren ist eine Genehmigung der Kamera erforderlich
+ Backup-Verwaltung
+ Backup-Speicherort
+ Backup-Speicherort, derzeit <b>%s</b>
+ Backup-Speicherort konnte nicht festgelegt werden
+ Import von Pflanzen aus Datei fehlgeschlagen
+ Pflanzen aus Datei importieren
+ Pflanzen erfolgreich aus Datei importiert
+
From 18c25c5b4efa5bf9b00eb5f3533cce1b0d93156d Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:13:52 +0000
Subject: [PATCH 047/152] Apply translations in nb
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'nb' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
---
app/src/main/res/values-nb/strings.xml | 268 +++++++++++++++++++++++++
1 file changed, 268 insertions(+)
create mode 100644 app/src/main/res/values-nb/strings.xml
diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml
new file mode 100644
index 00000000..12a2f187
--- /dev/null
+++ b/app/src/main/res/values-nb/strings.xml
@@ -0,0 +1,268 @@
+
+
+
+ Versjon %s
+ Innstillinger
+
+
+ %s planter
+
+ Alle planter
+
+ Alle
+ La til handlinger
+ La til notater
+ La til vanning
+ Slettet hagen
+
+ Er du sikker på at du vil slette hagen <b>\"%s\"</b>? Dette vil ikke slette plantene.
+ Vann
+ Handling
+
+ Widget er ikke tilgjengelig når kryptering er slått på
+ Legg til ny plante
+ Plantedetaljer
+ Plantestatistikker
+
+ Fra kamera
+
+ Fra galleri
+ Velg et alternativ
+ Velg bilde
+ Bruk på en annen plante
+ Velg plante
+ La til bilde
+ Ta et til
+
+ Tidsplaner
+ Tidsplandetaljer
+ Tidsplan-dato
+ Navn
+ Lett mating
+ Beskrivelse
+
+ Lett mating med 2 ukers flush
+
+ + Ny mating
+ + Ny tidsplan
+ + Ny additiv
+ Additiver
+ Additiv
+ Fra dato
+ Fra fase
+ Til dato
+ Til fase
+ Fyll ut ved hjelp av tidsplan
+ Fyll ut ved hjelp av forrige
+ Er du sikker?
+ Kopiere valgte tidsplan?
+ Slette valgt tidsplan?
+ Tidsplan kopiert
+ Tidsplan slettet
+ Angre
+ Tidsplaner for mating
+ Tidsplan for mating
+ App er oppdatert
+ Appen er blitt oppdatert til versjon %s
+ Se endringer
+ Avvis
+
+
+ Vanning %s
+ Vanning av flere planer
+
+ Notater
+ Vanndetaljer
+ Vann-pH
+ PPM
+ Dato og tid
+ Nå
+ Dato
+ I dag
+ Vanninger
+ Dupliser
+ Kopier til
+ Endre handling
+ Slett handling
+
+ Velg planter
+ Hager
+ Alle planter
+ + Ny hage
+ Innstillinger
+ Slett
+ Del
+ Bilde
+ Siste vanning
+ Vann igjen
+
+ Plantenavn
+ Ny plante
+ Voksedetaljer
+ Plantedato
+ Se bilder
+ Se historikk
+ Se statistikker
+ Bilder
+ Historikk
+ Statistikker
+ Filter
+ Plantet
+ Eksporter hage
+ Rediger hage
+ Slett hage
+ Eksporter
+
+ Min:
+ Max:
+ Gj.snitt:
+ Temperatur
+ Generelt
+ Kunne ikke laste plante
+ Fuck I Missed (FIM)
+ Slette denne hendelser?
+ Er du sikker på at du vil slette
+ Er du sikker på at du vil slette <b>%s</b> bilder? Du vil ikke kunne gjenopprette de.
+ Rediger
+ Angi
+ Endre
+ Legg til
+ Avbryt
+ handling
+ OK
+ Feltet er obligatorisk
+ Feil - Ukorrekt passord
+ Rediger vanning
+ lagt til
+ Dupliserte handlingen
+ flere planter
+ La handlingen til
+ Notat oppdatert
+ oppdatert
+ Ferdig
+ Hage
+ Velg alle
+ Velg ingen
+ Aksepter
+ Aktiver
+ Avslå
+ Oisann.
+ Ser ut som at det var en stopp i programmet sist gang du brukte appen. Vil du sende disse anonyme rapportene? Rapportene vil sendes til <a href=\"https://github.com/7LPdWcaW/GrowTracker-Android/issues\">github.com/7LPdWcaW/GrowTracker-Android/issues</a>, ingen personlig informasjon vil inkluderes. Du kan selv publisere disse rapportene på <a href=\"https://reddit.com/r/growutils\">reddit.com/r/growutils</a> manuelt hvis du vil. Rapporter lagres i <i>%s<i>
+ Ja
+ Nei
+
+ Angi passordet ditt
+ Angi et passord
+ Sletter plante...
+
+ Dupliserte plante
+ Åpne
+
+ La til %s
+ Navn kan ikke stå tomt
+ Eksporterer %s
+
+ kryptert
+ ukryptert
+
+ Handlinger
+ Tving mørkt tema
+ Tvinger appen til å bruke det mørke temaet, uavhengig av systemets innstillinger.
+ Enheter
+ Måleenhet
+ Temperaturenhet
+ Automatisk sikkerhetskopi
+ Sikkerhetskopier plantedataene dine hver 24 time
+ Sikkerhetskopier nå
+ Sikkerhetskopi-størrelsesbegrensning
+ Størrelse i MiB
+ Sikkerhetskopi-begrensning (MiB)
+ Gjenopprett fra sikkerhetskopi
+ Krypter data
+ En kodelås legges til appen og krypterer alt av data og bilder
+ Tillegg
+ Om
+ Les meg
+ Eksporter data
+ Kortstil
+ Det er ingen planter å vise
+ Det er ingen tidsplaner
+ Det er ingen bilder å vise
+ Tidligere handlinger
+ Vis/skjul kalender
+
+ %d valgt
+ Tusen takk til de følgende
+ Oversettelser av
+ Hjelp til med å oversette
+ Krypterer data og bilder. Dette kan ta en stund...
+ Dekrypterer data og bilder. Dette kan ta en stund...
+
+
+ 1s
+ s
+ m
+ t
+ d
+ u
+ m
+ å
+
+ Detaljer
+
+
+ - sekund
+ - sekunder
+
+
+
+ - minutt
+ - minutter
+
+
+
+ - time
+ - timer
+
+
+
+ - dag
+ - dager
+
+
+
+ - uke
+ - uker
+
+
+
+ - måned
+ - måneder
+
+
+
+ - år
+ - år
+
+
+
+ - Original
+ - Kompakt
+ - Ekstrem
+
+
+ Du vil miste ulagrede endringer
+ Gå ut
+ Planter
+ Fuktighet
+ Nåværende temperatur:
+ Nåværende fuktighet:
+ Slette dette elementet
+ Er du sikker på at du vil slette <b>%s</b>?
+ Vis
+ Skjul
+ Inkludere bilder?
+ Det er ingen data tilgjengelig
+
+ Kameratillatelse trengs for å ta bilder
+
From 95f4936149d6dfc715de44501285b7f6ffaada4b Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:13:58 +0000
Subject: [PATCH 048/152] Apply translations in ru
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'ru' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
---
app/src/main/res/values-ru/strings.xml | 1 -
1 file changed, 1 deletion(-)
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 0be65b56..2f0445df 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -163,7 +163,6 @@
Пересадка
Тримминг
Применение ScrOG
-
Полито
Заметка
Удалить событие?
From dfed6d85c55409d3c1ae4f71b2a7e187bc52c63e Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:14:03 +0000
Subject: [PATCH 049/152] Apply translations in sl_SI
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'sl_SI' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
---
app/src/main/res/values-sl_SI/strings.xml | 1 -
1 file changed, 1 deletion(-)
diff --git a/app/src/main/res/values-sl_SI/strings.xml b/app/src/main/res/values-sl_SI/strings.xml
index c11143aa..27631485 100644
--- a/app/src/main/res/values-sl_SI/strings.xml
+++ b/app/src/main/res/values-sl_SI/strings.xml
@@ -163,7 +163,6 @@
Presajeno
Obrezano
ScrOG tlačenje
-
Zalito
Zapisek
Izbriši ta dogodek?
From e79dbc6b32ada666769b14b17ba91b9db1268a2a Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:14:08 +0000
Subject: [PATCH 050/152] Apply translations in es
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'es' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
---
app/src/main/res/values-es/strings.xml | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 8541d2c8..b97c65c9 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -163,7 +163,6 @@
Transplantado
Recortar
Meter debajo de follaje preexistente
-
Regado
Nota
Eliminar este evento?
@@ -246,7 +245,7 @@
Provee esta contraseña durante la desencriptación para prevenir que la información se cargue
Alerta
Esta es una forma básica de encriptación AES, basado en una frase contraseña. Esto no es una defensa garantizada contra organismos de justicia.
- Copia de seguridad habilitada, copias se guardaran en /sdcard/backups/GrowTracker/
+ Copia de seguridad habilitada, copias se guardaran en /sdcard/backups/GrowTracker/
Restauración a %s completada
No se pudo restaurar desde la copia de seguridad %s. El archivo puede ser %s
encriptado
@@ -408,4 +407,4 @@
No hay ninguna información disponible
Para tomar fotos se necesita el permiso para la cámara
-
+
From 16eabab2e4ef68ba7848f54c8bd93692ecf7e68b Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:14:15 +0000
Subject: [PATCH 051/152] Apply translations in uk
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'uk' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
---
app/src/main/res/values-uk/strings.xml | 1 -
1 file changed, 1 deletion(-)
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index b6e3bfc0..a4ec8b38 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -163,7 +163,6 @@
Пересадка
Трімінг
Виконання ScrOG
-
Полито
Нотатка
Видалити подію?
From fa64301fd889c719e54e1702fea36533d92aaa9d Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:15:47 +0000
Subject: [PATCH 052/152] Apply translations in nl_NL
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'nl_NL' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From afd0b53ec7246926a3324bfcd4b27c050a87cc1f Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:15:52 +0000
Subject: [PATCH 053/152] Apply translations in fr
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'fr' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From 91ed2ec423d9a6b92c0a318a78ce863563369b0a Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:15:56 +0000
Subject: [PATCH 054/152] Apply translations in de_DE
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'de_DE' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
---
app/src/main/res/values-de-rDE/strings.xml | 338 +++++++++++++++++++++
1 file changed, 338 insertions(+)
create mode 100644 app/src/main/res/values-de-rDE/strings.xml
diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml
new file mode 100644
index 00000000..b20a9578
--- /dev/null
+++ b/app/src/main/res/values-de-rDE/strings.xml
@@ -0,0 +1,338 @@
+
+
+
+ Version %s
+ Einstellungen
+
+
+ %s Pflanzen
+
+ Alle Pflanzen
+
+ Alle
+ Maßnahme hinzugefügt
+ Notiz hinzugefügt
+ Bewässerung hinzugefügt
+ Garten gelöscht
+
+ Willst du Garten <b>\"%s\"</b> löschen? Dadurch werden die Pflanzen nicht gelöscht.
+ Gießen
+ Maßnahme
+
+ Widget ist nicht verfügbar, wenn die Verschlüsselung aktiviert ist
+ Neue Pflanze hinzufügen
+ Pflanzen Details
+ Pflanzen Statistik
+
+ Von der Kamera
+
+ Aus der Galerie
+ Option auswählen
+ Bild auswählen
+ Auf eine andere Pflanze anwenden
+ Pflanze auswählen
+ Bild hinzugefügt
+ Weiteres hinzufügen
+
+ Zeitpläne
+ Zeitplan Details
+ Plane ein Datum
+ Name
+ Geringfügiges Düngen
+ Beschreibung
+
+ Geringfügiges Düngen mit 2-wöchigem Ausspülen
+
+ + Neues Düngen
+ Neuer Zeitplan
+ + neuer Zusatzstoff
+ Zusatzstoffe
+ Zusatzstoff
+ Startzeitpunkt
+ Endzeitpunkt
+ Aus Zeitplan befüllen
+ Aus Vorigem füllen
+ Bist du sicher?
+ Ausgewählten Zeitplan kopieren?
+ Ausgewählten Zeitplan löschen?
+ Zeitplan kopiert
+ Zeitplan gelöscht
+ Rückgängig
+ Düngepläne
+ Düngeplan
+ App aktualisiert
+ App wurde auf Version %s aktualisiert
+ Änderungen ansehen
+ Ablehnen
+
+
+ Gieße %s
+ Gieße mehrere Pflanzen
+
+ Notizen
+ Wasser Details
+ Wasser pH
+ PPM
+ Abfluss
+ Menge (%s)
+ Temperatur (º%s)
+ Datum und Zeit
+ Jetzt
+ Darum
+ Heute
+ Gießen
+ Statusänderung
+
+ Duplizieren
+ Kopieren nach
+ Maßnahme bearbeiten
+ Maßnahme löschen
+
+ Pflanzen auswählen
+ Gärten
+ Alle Pflanzen
+ + Neuer Garten
+ Weitere
+ Einstellungen
+ Löschen
+ Teilen
+ Foto
+ Zuletzt gegossen
+ Nochmal gießen
+
+ Pflanzen Name
+ Neue Pflanze
+ Pflanzensorte
+ Lemon haze
+ Pflanzdetails
+ Pflanzzeitpunkt
+ Substrat
+
+ Substratdetails
+
+ Erde, Perlite Mischung 50/50
+ Aus Klon?
+ Statusinfo
+ Pflanzenstatus
+ Fotos ansehen
+ Verlauf ansehen
+ Statistik ansehen
+ Fotos
+ Verlauf
+ Statistik
+ Filter
+ Gepflanzt
+ Keimung
+ Schneiden
+ Vegetation
+ Blütezeit
+ Trocknen
+ Heilung
+ Geernetet
+
+ Vor %s geerntet
+ Garten exportieren
+ Garten bearbeiten
+ Garten löschen
+ Exportieren
+
+ Gesamtzeit:
+ Gesamt-Ausspülungen:
+ Mittlere Zeit zwischen dem Gießen:
+ Filter-Zusatzstoffe
+ PH
+
+ Min:
+ Max:
+ Ø:
+ Temperatur
+ Allgemein
+ Pflanze konnte nicht geladen werden
+ Verpasst
+ Ausspülen
+ Blattdüngung
+ Stressarmes Training
+ Lutscher
+ Pestizidanwendung
+ Oben
+ Verpflanzt
+ Trimmen
+ Gegossen
+ Notiz
+ Dieses Event löschen?
+ Möchtest du das wirklich löschen?
+ Bearbeiten
+ Status
+ Setzen
+ Ändern
+ Hinzufügen
+ Abbrechen
+ Maßnahme
+ OK
+ Feld muss ausgefüllt werden
+ Fehler - falsches Passwort
+ Bewässerung bearbeiten
+ hinzugefügt
+ Maßnahme dupliziert
+ mehrere Pflanzen
+ Notiz aktualisiert
+ aktualisiert
+ Status aktualisiert
+ Event gelöscht
+ Erledigt
+ Garten
+ Alles auswählen
+ Nichts auswählen
+ Akzeptieren
+ Aktivieren
+ Ablehnen
+ Sämling:
+ Sämling
+
+ Ups
+ Offenbar ist die App bei der letzten Nutzung gelöscht. Möchtest du einen anonymen Fehlerreport senden? Dieser Fehlerreport wird an <a href=\"https://github.com/7LPdWcaW/GrowTracker-Android/issues\">github.com/7LPdWcaW/GrowTracker-Android/issues</a> gesemdet und es werden keine persönlichen Informationen gesendet. Zusätzlich kannst du den Fehler hier melden: <a href=\"https://reddit.com/r/growutils\">reddit.com/r/growutils</a> auf Wunsch auch manuell. Die Fehlerreporte werden hier gespeichert: <i>%s<i>
+ Ja
+ Nein
+
+ Passwort eingeben
+ Ein Passwort eingeben
+ Passwort erneut eingeben
+ Fehler - Passwörter stimmen nicht überein
+
+ Der Garten konnte nicht gespeichert werden, bitte mach ein Backup deiner Daten.
+ Entnommen
+ Vor %s
+ Gegossen vor <b> %s </b>
+ Zuletzt gegossen vor <b> %s </b>
+ Gepflanzt vor <b> %s </b>
+
+ Für die Speicherung von Fotos ist der Zugriff auf den externen Speicher erforderlich. Es werden keine anderen Daten verwendet.
+
+ Bewässerungen hinzugefügt
+ Hiermit wird <b> %s </b> gelöscht, ebenso alle damit verknüpften Bilder, sind sie sicher? Dies kann nicht wieder rückgängig gemacht werden.
+ Lösche Pflanze...
+
+ Pflanze dupliziert
+ Öffnen
+
+ Exportiere Wachstumsprotokoll
+ %s hinzugefügt
+ Name kann nicht leer sein
+ Exportiere %s
+
+ Erde
+ Hydroponik
+ Kokosnussfasern
+ Aeroponik
+ Bild verstecken
+ Bild anzeigen
+
+ Gib das Passwort während der Entschlüsselungsphase an, um das Laden von Daten zu verhindern
+ Warnung
+ Dies ist eine Standart AES-Verschlüsselung auf der Grundlage einer bereitgestellten Passphrase. Es ist kein garantierter Schutz vor Strafverfolgungsbehörden.
+ Backup aktiviert, die Backups werden in %s
+ Wiederherstellen nach %s abgeschlossen
+ verschlüsselt
+ nicht verschlüsselt
+
+ Messung auswählen
+ Temperatur auswählen
+ Garten auswählen
+ Backup auswählen
+ Du musst den verschlüsselten Modus mit demselben Kennwort aktiviert haben, um dieses Backup wiederherzustellen
+
+ Gesichert nach
+ Es ist kein Backup vorhanden
+ Alle/Keine
+
+ Durchschnitts pH-Wert
+
+ Pflanzenfotos
+
+ Menge:
+ Temp:
+ Zusatzstoffe:
+ Zeitplan auswählen
+ Maßnahmen
+ Erzwinge Dark Theme
+ Erzwingt das Dark Theme unabhängig von der Systemeinstellung
+ Geerntete verstecken
+ Verstecke alle Pflanzen, die geernted wurden
+ Reihenfolge der Anlage umkehren
+ Zeigt Pflanzen in umgekehrter Reihenfolge. (Benötigt App-Neustart)
+ Standard-Garten
+
+ Einheiten
+ Lieferumfang
+ Maßeinheit
+ Temperatureinheiten
+ Datenmanagement
+ Automatisches Backup
+ Sichert Automatisch Ihre Daten alle 24 Stunden
+ Jetzt sichern
+ Begrenzung der Backup-Größe
+ Größe in MB
+ Backup-Limit (MB)
+ Wiederherstellen aus Backup
+ Daten verschlüsseln
+ Fügt eine PIN-Sperre hinzu und verschlüsselt alle Daten/Bilder
+ Setze ein sicheres Kennwort, um den Zugriff auf Daten zu verhindern
+ Erweiterungen
+ Über
+ Lies mich
+ Daten exportieren
+ Keine Pflanzen zum Anzeigen vorhanden
+ Es gibt keine Zeitpläne
+ Keine Fotos zum Anzeigen vorhanden
+ Kalender ein-/ausblenden
+ Vielen Dank an
+ Übersetzungen von
+ Hilf Übersetzen
+ Das Verschlüsseln von Daten und Bildern kann eine Weile dauern...
+ Das Entschlüsseln von Daten und Bildern kann eine Weile dauern...
+
+
+ 1s
+ s
+ m
+ h
+ d
+ w
+ mo
+ y
+
+ Details
+
+
+ - Original
+ - Kompakt
+ - Extreme
+
+
+ Du verlierst alle ungespeicherten Änderungen
+ Beenden
+ Pflanzen
+ Feuchtigkeit
+ Diesen Eintrag löschen?
+ Bildspeicherort konnte nicht festgelegt werden
+ Speicherort des Bildes
+ Bild-Cache löschen
+ Image-Festplatte und Speicher-Cache gelöscht
+ Das Importieren von Bildern kann eine Weile dauern...
+ Aufgabe erledigt
+ Es sind keine Aktionen zu zeigen
+
+ Exportiert %s nach %s
+ Export abgeschlossen
+ Bilder einbeziehen?
+ Es sind keine Daten verfügbar
+
+ Für das Fotografieren ist eine Genehmigung der Kamera erforderlich
+ Backup-Verwaltung
+ Backup-Speicherort
+ Backup-Speicherort, derzeit <b>%s</b>
+ Backup-Speicherort konnte nicht festgelegt werden
+ Import von Pflanzen aus Datei fehlgeschlagen
+ Pflanzen aus Datei importieren
+ Pflanzen erfolgreich aus Datei importiert
+
From 9d0d78978a088257e67529a1f3fe35a903e7687f Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:16:01 +0000
Subject: [PATCH 055/152] Apply translations in nb
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'nb' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From bd6830d42d46f756fcc1b7166063a0a5a00fbe50 Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:16:06 +0000
Subject: [PATCH 056/152] Apply translations in ru
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'ru' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From 00c5924356e26109429dded30bff190b63b5ecc8 Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:16:10 +0000
Subject: [PATCH 057/152] Apply translations in sl_SI
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'sl_SI' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From 2a95249883c474a93a6e6d7dee76e29843cb9fa0 Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:16:15 +0000
Subject: [PATCH 058/152] Apply translations in es
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'es' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From 0e7b071ad0e5d7e1953cbdf44ef82ec201c74d46 Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:16:20 +0000
Subject: [PATCH 059/152] Apply translations in uk
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'uk' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From 6c6a9857197e4af42c850c89eeb2446df76e7a4c Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:23:32 +0000
Subject: [PATCH 060/152] Apply translations in nl_NL
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'nl_NL' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
---
app/src/main/res/values-nl-rNL/strings.xml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/app/src/main/res/values-nl-rNL/strings.xml b/app/src/main/res/values-nl-rNL/strings.xml
index d8f79ab7..1d584291 100644
--- a/app/src/main/res/values-nl-rNL/strings.xml
+++ b/app/src/main/res/values-nl-rNL/strings.xml
@@ -129,7 +129,9 @@
Ontkiemd
Gewied
Groeiende
+ Ontkieming
Bloeiende
+ Rijping
Drogende
Genezende
Geplukt
@@ -163,6 +165,8 @@
Verpot
Bijsnijden
ScrOG Tuck
+ Supergroot gewas
+ Immens gewas
Water gegeven
Aantekening
From 1701aa2f38c2c1bcf14272d2b92369af1b58fe2a Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:23:41 +0000
Subject: [PATCH 061/152] Apply translations in fr
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'fr' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From cd028d524060e6d635c40fd01dbf31b5df2e2df8 Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:23:45 +0000
Subject: [PATCH 062/152] Apply translations in de_DE
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'de_DE' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From 94d9dd283f6f685d88cf10f6070b98b4e5458d18 Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:23:49 +0000
Subject: [PATCH 063/152] Apply translations in nb
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'nb' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From 7024f2e3b8f33a120b2e7b1393d5211a492f6cf7 Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:23:54 +0000
Subject: [PATCH 064/152] Apply translations in ru
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'ru' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From 1204f0fafe7434da6cbe3be0983effce758165d1 Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:23:58 +0000
Subject: [PATCH 065/152] Apply translations in sl_SI
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'sl_SI' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
---
app/src/main/res/values-sl-rSI/strings.xml | 432 +++++++++++++++++++++
1 file changed, 432 insertions(+)
create mode 100644 app/src/main/res/values-sl-rSI/strings.xml
diff --git a/app/src/main/res/values-sl-rSI/strings.xml b/app/src/main/res/values-sl-rSI/strings.xml
new file mode 100644
index 00000000..27631485
--- /dev/null
+++ b/app/src/main/res/values-sl-rSI/strings.xml
@@ -0,0 +1,432 @@
+
+
+
+ Različica %s
+ Nastavitve
+
+
+ %srastlin
+
+ Vse rastline
+
+ Vse
+ Dejanja dodana
+ Zapiski dodani
+ Zalivanje dodano
+ Vrt izbrisan
+
+ Ali ste prepričani, da želite izbrisati vrt <b>%s</b>? Dejanje ne bo izbrisalo rastlin
+ Voda
+ Dejanje
+
+ Pripomoček ni na voljo, ko je vključena nastavitev za šifriranje
+ Dodaj novo rastlino
+ Podrobnosti o rastlini
+ Statistika o rastlini
+
+ Iz fotoaparata
+
+ Iz galerije
+ Izberi možnost
+ izberi sliko
+ Uporabi za drugo rastlino
+ Izberi rastlino
+ Slika dodana
+ Zajami še eno
+
+ Urniki
+ Podrobnosti o urniku
+ Datum urnika
+ Ime
+ Rahlo hranjenje
+ Opis
+
+ Rahlo hranjene z 2 tedenskim izpiranjem
+
+ + Novo hranjenje
+ + Nov urnik
+ + Nov dodatek
+ Dodatki
+ Dodatek
+ Od datuma
+ Od faze
+ Do datuma
+ Do faze
+ Napolni iz urnika
+ Napolni iz prejšnjega
+ Ali ste prepričani?
+ Kopiranje izbranega urnika?
+ Brisanje izbranega urnika?
+ Urnik kopiran
+ Urnik izbrisan
+ Razveljavi
+ Urniki hranjenja
+ Urniki hranjenja
+ Aplikacija posodobljena
+ Aplikacija je bila posodobljena na različico %s
+ Preglej spremembe
+ Zavrzi
+
+
+ Zalivanje %s
+ Zalivanje več rastlin
+
+ Beležka
+ Podrobnosti o vodi
+ pH vode
+ ppm
+ Odtok
+ Količina (%s)
+ Temp. (º%s)
+ Datum in čas
+ Zdaj
+ Datum
+ Danes
+ Zori že %s dni
+
+ Zalivanja
+ Spremembe faz
+
+ Podvojeno
+ Kopiraj v
+ Uredi dejanje
+ Izbriši dejanje
+
+ Izberi rastline
+ Vrtovi
+ Vse rastline
+ + Nov vrt
+ Dodatno
+ Nastavitve
+ Izbriši
+ Deli
+ Slika
+ Zadnje zalivanje
+ Zalij znova
+
+ Ime rastline
+ Nova rastlina
+ Sorta rastline
+ Lemon haze
+ Podrobnosti gojenja
+ Datum posaditve
+ Substrat
+
+ Podrobnosti substrata
+
+ Zemlja, Perlit, 50/50 mešanica
+ Iz potaknjenca?
+ Podrobnosti faze
+ Faza rastline
+ Preglej slike
+ Preglej zgodovino
+ Preglej statistiko
+ Slike
+ Zgodovina
+ Statistika
+ Filter
+ Posajeno
+ Kalitev
+ Potaknjenec
+ Vegetacija
+ Cvetenje
+ Sušenje
+ Zorenje
+ Požeto
+
+ Požeto pred %s
+ Izvozi vrt
+ Uredi vrt
+ Izbriši vrt
+ Izvozi
+
+ Celoten čas:
+ Skupno zalivanja:
+ Skupno izpiranja:
+ Povp. čas med zalivanji:
+ Dodatki filtra
+ pH
+
+ Min:
+ Max:
+ Povp.:
+ Temperatura
+ Splošno
+ Neuspešno nalaganje rastline
+ Fuck I Missed (FIM)
+ Izpiranje
+ Foliarno hranjenje
+ Low Stress Training
+ Lizika
+ Aplikacija pesticida
+ Vršičkano
+ Presajeno
+ Obrezano
+ ScrOG tlačenje
+ Zalito
+ Zapisek
+ Izbriši ta dogodek?
+ Ali ste prepričani, da želite izbrisati?
+ Ali ste prepričani, da želite izbrisati <b>%s</b> slike ? Teh ne boste mogli več obnoviti.
+ Uredi
+ Faza
+ Nastavi
+ Spremeni
+ Dodaj
+ Prekliči
+ Dejanje
+ Ok
+ Polje je potrebno
+ Napaka - nepravilno geslo
+ Uredi zalivanje
+ Dodano
+ Podvojeno dejanje
+ Več rastlin
+ Dejanje dodano k
+ Zapisek posodobljen
+ Posodobljeno
+ Faza posodobljena
+ Dogodek izbrisan
+ Končano
+ Vrt
+ Izberi vse
+ Ne izberi nobenega
+ Sprejmi
+ Omogoči
+ Zavrni
+ Sadika
+ Sadika
+
+ Oh ne
+ Izgleda, da je od zadnje uporabe aplikacije prišlo do sesutja.
+Ali bi želeli poslati ta anonimna poročila? Ta poročila bodo poslana na <a href=\"https://github.com/7LPdWcaW/GrowTracker-Android/issues\">github.com/7LPdWcaW/GrowTracker-Android/issues</a>, priloženih ne bo nič osebnih podatkov. Poljubno lahko tudi objavite ta poročila na <a href=\"https://reddit.com/r/growutils\">reddit.com/r/growutils</a> ročno, če želite. Poročila so shranjena v <i>%s<i>
+ Da
+ Ne
+
+ Vnesite svoje geslo
+ Vnesite geslo
+ Znova vnesite svoje geslo
+ Napaka - geslo se ne ujema
+
+ Nastala je usodna napaka pri shranjevanju podatkov o vrtu, prosimo naredite varnostno kopijo teh podatkov
+ Vzeto
+ Pred %s
+ Zalito pred <b>%s</b>
+ Zadnje zalivanje pred <b>%s</b>
+ Posajeno pred <b>%s</b>
+
+ Za shranjevanje fotografij je potreben dostop do zunanje shrambe. Nobeni drugi podatki niso potrebni.
+
+ Zalivanja dodana
+ Izbrisali boste <b>%s</b> in vse slike povezane s tem, ste prepričani ? To ne more biti razveljavljeno.
+ Brisanje rastline...
+
+ Podvojena rastlina
+ Odpri
+
+ Izvažanje dnevnika gojenja...
+ Izvažanje dnevnika gojenja vrta...
+ %s dodano
+ Ime ne more biti prazno
+ Izvažanje %s
+
+ Zemlja
+ Hidroponika
+ Substrat iz kokosa
+ Aeroponika
+ Skrij slike
+ Prikaži slike
+
+ Privzet vrt za prikaz ob odprtju, trenutno: <b>%s</b>
+ Izberi stil kartic, trenutno: %s
+ Uporaba privzetih enot merjenja, trenutno: <b>%s</b>
+ Uporaba privzetih enot merjenja dodatkov, trenutno: <b>%s</b>
+ Uporaba privzetih enot merjenja temperature, trenutno: <b>%s</b>
+ Trenutno: <b>%s MiB</b> / Uporabljate <b>%s</b>
+ Vnesite to geslo med fazo dešifriranja, da preprečite nalaganje podatkov
+ Opozorilo
+ To je osnovna oblika AES šifriranja, ki temelji na podanem geslu. To ni garantirana oblika zaščite pred organi pregona.
+ Varnostna kopija omogočena, kopije bodo shranjene v %s
+ Obnovitev v %s končana
+ Obnovitev varnostne kopije iz %s je spodletela. Datoteka je morda %s
+ Šifrirano
+ Nešifrirano
+
+ Izberi mersko enoto
+ Izberi temperaturo
+ Izberi vrt
+ Izberi varnostno kopijo
+ Da obnovite to varnostno kopijo, morate imeti omogočen način šifracije z enakim geslom
+
+ Kopirano do
+ Ni varnostnih kopij iz katerih bi lahko obnovili podatke
+ Vse/Nič
+
+ Vnesi pH
+ pH odtočne vode
+ Povprečen pH
+
+ Slike rastline
+
+ Vhodni pH:
+ Izhodni pH:
+ Količina:
+ Temp.:
+ Dodatki:
+ EC:
+ ppm:
+
+ Izberi urnik
+ Dejanja
+ Vsili temno temo
+ Vsili aplikaciji, da uporabi temno temo, ne glede na sistemske nastavitve dnevne-temne teme
+ Skrij požeto
+ Skrij vse požete rastline
+ Obrni vrstni red rastlin
+ Pokaže rastline v obratnem vrstnem redu. (Potreben je ponovni zagon aplikacije)
+ Privzet vrt
+
+ Enote
+ Enota dostave
+ Merska enota
+ Temperaturska enota
+ TDS enota
+ Privzeta uporaba TDS, trenutno: <b>%s</b>
+ Upravljanje podatkov
+ Samodejna varnostna kopija
+ Samodejno naredi varnostno kopijo vsakih 24 ur
+ Naredi varnostno kopijo zdaj
+ Omejitev velikosti varnostne kopije
+ Velikost v MiB
+ Omejena velikost varnostne kopije (MiB)
+ Obnovi iz varnostne kopije
+ Šifriraj podatke
+ Doda zaklepanje aplikacije s pin kodo in zašifrira vse podatke/slike
+ Varovalni mehanizem
+ Nastavi geslo varnostnega mehanizma da preprečiš dostop do podatkov
+ Dodatki
+ O aplikaciji
+ Preberi
+ Izvozi podatke
+ Stil kartic
+ Ni rastlin za prikaz
+ Ni urnikov
+ Ni slik za prikaz
+ Pretekla dejanja
+ Prikaži/skrij kolendar
+
+ %d izbrano
+ Hvala vam do slednjega
+ Prevodi
+ Pomagaj pri prevodu
+ Šifriranje podatkov in slik
+ Dešifriram podatke in slike, to lahko vzame nekaj časa...
+
+
+ 1 sekunda
+ s
+ min.
+ h
+ dni
+ ted.
+ mes.
+ l
+
+ Podrobnosti
+
+
+ - sekunda
+ - sekundi
+ - sekund
+ - sekunde
+
+
+
+ - minuta
+ - minuti
+ - minut
+ - minute
+
+
+
+ - ura
+ - uri
+ - ur
+ - ure
+
+
+
+ - dan
+ - dneva
+ - dni
+ - dnevi
+
+
+
+ - teden
+ - tedna
+ - tednov
+ - tedni
+
+
+
+ - mesec
+ - meseca
+ - mesecev
+ - meseci
+
+
+
+ - leto
+ - leti
+ - let
+ - leta
+
+
+
+ - Izvirno
+ - Kompaktno
+ - Ekstremno
+
+
+ Izgubili boste kakršnekoli neshranjene spremembe
+ Končaj
+ Rastline
+ Vlažnost
+ Trenutna temp.:
+ Trenutna vlažnost:
+ Urnik osvetljave
+ Izbriši ta predmet?
+ Ali ste prepričani da želite izbrisati <b>%s</b>?
+ Pokaži
+ Skrij
+ Vključene luči
+ Izključene luči
+
+ Zadnja varnostna kopija: <b>%s</b>
+ Mesto shrambe za slike, trenutno <b>%s</b>
+ Neuspešna nastavitev mesta slike
+ Mesto shrambe slik
+ Počisti predpomnilnik slik
+ Shramba slik in spomin prepomnilnika počiščena
+ Uvažanje slik, to lahko traja nekaj časa...
+ Opravilo podatkov
+ Opravilo končano
+ Ni dejanj za prikaz
+
+ Izvažanje dnevnika gojenja za %s
+ Izvoz %s končan
+ Izvoženo %s v %s
+ Izvoz končan
+ Vključim slike?
+ Podatki niso na voljo
+
+ Za zajem slik je potreben dostop do fotoaparata
+ Uprabljanje varnostnih kopij
+ Mesto shrambe varnostnih kopij
+ Mesto shrambe varnostnih kopij, trenutno <b>%s</b>
+ Neuspešna nastavitev mesta varnostne kopije
+ Neuspešen uvoz rastlin iz datoteke
+ Uvozi rastline iz datoteke
+ Uspešen uvoz rastlin iz datoteke
+
From 6e33889c05321cfd5db16a836ca9d212fdb53c7b Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:24:03 +0000
Subject: [PATCH 066/152] Apply translations in es
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'es' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From 1247b50a7b012955a082980ea9b8580c63ab8a74 Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2020 21:24:08 +0000
Subject: [PATCH 067/152] Apply translations in uk
at least 50% translated for the source file '/app/src/main/res/values/strings.xml'
on the 'uk' language.
Manual sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format
From f1fcc4781c08d2fabacd8c4be94fbcc1031c906f Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Mon, 16 Mar 2020 20:58:11 +0000
Subject: [PATCH 068/152] Removes persistent uuid for feeding schedule date
---
.../grow/fragment/FeedingScheduleDetailsFragment.kt | 3 +--
app/src/main/java/me/anon/model/Models.kt | 12 +++---------
2 files changed, 4 insertions(+), 11 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/FeedingScheduleDetailsFragment.kt b/app/src/main/java/me/anon/grow/fragment/FeedingScheduleDetailsFragment.kt
index b48e3da1..38ae8e23 100644
--- a/app/src/main/java/me/anon/grow/fragment/FeedingScheduleDetailsFragment.kt
+++ b/app/src/main/java/me/anon/grow/fragment/FeedingScheduleDetailsFragment.kt
@@ -165,8 +165,7 @@ class FeedingScheduleDetailsFragment : Fragment()
feedingView.copy.setOnClickListener { view ->
val newSchedule = Kryo().copy(date)
newSchedule.id = UUID.randomUUID().toString()
- val index = schedule_dates_container.indexOfChild(feedingView)
- scheduleDates.add((index < 0) T scheduleDates.size - 1 ?: index, newSchedule)
+ scheduleDates.add(newSchedule)
populateScheduleDates()
SnackBar().show(activity!!, R.string.schedule_copied, R.string.undo, action = {
diff --git a/app/src/main/java/me/anon/model/Models.kt b/app/src/main/java/me/anon/model/Models.kt
index 7190df30..2ffedd1a 100644
--- a/app/src/main/java/me/anon/model/Models.kt
+++ b/app/src/main/java/me/anon/model/Models.kt
@@ -46,17 +46,11 @@ class FeedingSchedule(
@Parcelize
@JsonClass(generateAdapter = true)
class FeedingScheduleDate(
- var id: String = UUID.randomUUID().toString(),
- var dateRange: Array,
- var stageRange: Array,
+ @Transient var id: String = UUID.randomUUID().toString(),
+ var dateRange: Array = arrayOf(),
+ var stageRange: Array = arrayOf(),
var additives: ArrayList = arrayListOf()
) : Parcelable {
- constructor() : this(
- id = UUID.randomUUID().toString(),
- dateRange = arrayOf(),
- stageRange = arrayOf(),
- additives = arrayListOf()
- ){}
}
abstract class Action(
From e80a63d685d746645be6bc24cdd7f0e33064568a Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Wed, 18 Mar 2020 16:58:12 +0000
Subject: [PATCH 069/152] Apply translations in es
translation completed for the source file '/app/src/main/res/values/strings.xml'
on the 'es' language.
---
app/src/main/res/values-es/strings.xml | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index b97c65c9..6f95273f 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -129,7 +129,9 @@
Germinación
Esqueje
Vegetación
+ Cerniendo
Florecimiento
+ Madurado
Secado
Curando
Cosechado
@@ -163,6 +165,9 @@
Transplantado
Recortar
Meter debajo de follaje preexistente
+ Supercrop
+ Monstercrop
+
Regado
Nota
Eliminar este evento?
@@ -407,4 +412,11 @@
No hay ninguna información disponible
Para tomar fotos se necesita el permiso para la cámara
-
+ Manejo de copias de seguridad
+ Lugar de guardadado de la copia de seguridad
+ Ubicación de la copia de seguridad, actualmente <b>%s</b>
+ Falló en establecer ubicación de la copia de seguridad
+ Falló al importar plantas desde archivo
+ Importar plantas desde archivo
+ Plantas importadas de archivo correctamente
+
From 78ed42edb38b6fe503f23cf468bd38284d721458 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Thu, 19 Mar 2020 11:03:18 +0000
Subject: [PATCH 070/152] Additive chart progress
---
.../java/me/anon/grow/PlantDetailsActivity.kt | 9 +-
.../anon/grow/fragment/StatisticsFragment2.kt | 89 ++++++++++++++++++-
2 files changed, 88 insertions(+), 10 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/PlantDetailsActivity.kt b/app/src/main/java/me/anon/grow/PlantDetailsActivity.kt
index 42273f95..8e027094 100644
--- a/app/src/main/java/me/anon/grow/PlantDetailsActivity.kt
+++ b/app/src/main/java/me/anon/grow/PlantDetailsActivity.kt
@@ -9,10 +9,7 @@ import com.google.android.material.appbar.AppBarLayout
import kotlinx.android.synthetic.main.fragment_holder.toolbar
import kotlinx.android.synthetic.main.fragment_holder.toolbar_layout
import kotlinx.android.synthetic.main.tabbed_fragment_holder.*
-import me.anon.grow.fragment.ActionsListFragment
-import me.anon.grow.fragment.PlantDetailsFragment
-import me.anon.grow.fragment.StatisticsFragment
-import me.anon.grow.fragment.ViewPhotosFragment
+import me.anon.grow.fragment.*
import me.anon.model.Plant
class PlantDetailsActivity : BaseActivity()
@@ -44,7 +41,7 @@ class PlantDetailsActivity : BaseActivity()
}
"statistics" -> {
tabs.selectedItemId = R.id.view_statistics
- StatisticsFragment.newInstance(intent.extras)
+ StatisticsFragment2.newInstance(intent.extras!!)
}
else -> PlantDetailsFragment.newInstance(intent.extras)
}
@@ -73,7 +70,7 @@ class PlantDetailsActivity : BaseActivity()
R.id.view_details -> PlantDetailsFragment.newInstance(intent.extras)
R.id.view_history -> ActionsListFragment.newInstance(intent.extras)
R.id.view_photos -> ViewPhotosFragment.newInstance(intent.extras)
- R.id.view_statistics -> StatisticsFragment.newInstance(intent.extras)
+ R.id.view_statistics -> StatisticsFragment2.newInstance(intent.extras!!)
else -> Fragment()
}, TAG_FRAGMENT)
.commit()
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index bc868e8b..c4e96eb6 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -11,17 +11,18 @@ import androidx.core.view.plusAssign
import androidx.core.view.setMargins
import androidx.fragment.app.Fragment
import com.github.mikephil.charting.components.AxisBase
-import com.github.mikephil.charting.data.BarData
-import com.github.mikephil.charting.data.BarDataSet
-import com.github.mikephil.charting.data.BarEntry
-import com.github.mikephil.charting.data.Entry
+import com.github.mikephil.charting.data.*
import com.github.mikephil.charting.formatter.ValueFormatter
+import com.github.mikephil.charting.interfaces.datasets.ILineDataSet
import com.github.mikephil.charting.utils.ViewPortHandler
import com.google.android.material.chip.Chip
import kotlinx.android.synthetic.main.action_buttons_stub.*
import kotlinx.android.synthetic.main.data_label_stub.view.*
import kotlinx.android.synthetic.main.garden_action_buttons_stub.*
import kotlinx.android.synthetic.main.statistics2_view.*
+import kotlinx.android.synthetic.main.statistics2_view.stage_chart
+import kotlinx.android.synthetic.main.statistics2_view.stats_container
+import kotlinx.android.synthetic.main.statistics_view.*
import me.anon.grow.R
import me.anon.lib.TdsUnit
import me.anon.lib.Unit
@@ -87,6 +88,7 @@ class StatisticsFragment2 : Fragment()
}
val additives = arrayListOf()
+ val additiveValues = hashMapOf>()
var endDate = System.currentTimeMillis()
var waterDifference = 0L
var lastWater = 0L
@@ -114,6 +116,7 @@ class StatisticsFragment2 : Fragment()
private fun calculateStats()
{
+ var additiveIndex = 0
plant.actions?.forEach { action ->
when (action)
{
@@ -131,6 +134,18 @@ class StatisticsFragment2 : Fragment()
val stage = stageChanges.filterValues { it.date <= action.date }.toSortedMap().lastKey()
aveStageWaters.getOrPut(stage, { arrayListOf() }).add(action.date)
+ action.additives.forEach { additive ->
+ if (additive.description != null)
+ {
+ additive.amount?.let { amount ->
+ val amount = Unit.ML.to(selectedMeasurementUnit, amount)
+ val entry = Entry(additiveIndex.toFloat(), amount.toFloat())
+ additiveValues.getOrPut(additive.description!!, { arrayListOf() }).add(entry)
+ }
+ }
+ }
+
+ additiveIndex++
additives.addAll(action.additives)
}
@@ -288,6 +303,8 @@ class StatisticsFragment2 : Fragment()
private fun populateAdditiveStates()
{
+ val selectedAdditives = arrayListOf()
+
class additiveStat(var total: Double = 0.0, var count: Int = 0, var min: Double = Double.NaN, var max: Double = Double.NaN)
fun displayStats(name: String, stat: additiveStat)
@@ -307,6 +324,30 @@ class StatisticsFragment2 : Fragment()
renderStats(additives_stats_container, stats)
}
+ fun displayChart()
+ {
+ val dataSets = arrayListOf()
+ var index = 0
+ additiveValues.forEach { (k, v) ->
+ if (selectedAdditives.contains(k))
+ {
+ dataSets += LineDataSet(v, k).apply {
+ color = statsColours.get(index)
+ fillColor = color
+ setCircleColor(color)
+ }
+ }
+
+ index++
+ if (index >= statsColours.size) index = 0
+ }
+
+ val lineData = LineData(dataSets)
+ additives_chart.data = lineData
+ additives_chart.notifyDataSetChanged()
+ additives_chart.invalidate()
+ }
+
val names = HashMap()
additives.forEach { additive ->
additive.description?.let { key ->
@@ -322,11 +363,51 @@ class StatisticsFragment2 : Fragment()
names.forEach { (k, v) ->
val chip = LayoutInflater.from(context!!).inflate(R.layout.filter_chip_stub, additive_chips_container, false) as Chip
chip.text = k
+ chip.isChecked = true
chip.setOnCheckedChangeListener { buttonView, isChecked ->
//displayStats(k, v)
+ if (isChecked)
+ {
+ selectedAdditives += k
+ }
+ else
+ {
+ selectedAdditives -= k
+ }
+
+ displayChart()
}
+
+ selectedAdditives += k
additive_chips_container += chip
}
+
+ additives_chart.setDrawGridBackground(false)
+ additives_chart.description = null
+ additives_chart.isScaleYEnabled = false
+ additives_chart.setDrawBorders(false)
+
+ additives_chart.axisLeft.setDrawGridLines(false)
+ additives_chart.axisLeft.axisMinimum = 0f
+ additives_chart.axisLeft.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ additives_chart.axisLeft.valueFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return "${value.toInt()}${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ }
+ }
+
+ additives_chart.axisRight.setDrawLabels(false)
+ additives_chart.axisRight.setDrawGridLines(false)
+
+ additives_chart.xAxis.setDrawGridLines(false)
+ additives_chart.xAxis.setDrawAxisLine(false)
+ additives_chart.xAxis.setDrawLabels(false)
+
+ additives_chart.legend.textColor = R.attr.colorOnSurface.resolveColor(context!!).toInt()
+ additives_chart.legend.isWordWrapEnabled = true
+ displayChart()
}
private fun renderStats(container: ViewGroup, templates: ArrayList)
From 1efc72f8d1015c611e8ae14b6e74d19fc7fe85dd Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Thu, 19 Mar 2020 11:27:08 +0000
Subject: [PATCH 071/152] Fixes issue with listeners not attaching because
fragment manager show is asynchronous
---
.../anon/grow/fragment/WateringFragment.java | 21 ++++++++-----------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/WateringFragment.java b/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
index 7ffaefe2..3f3bed3a 100644
--- a/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
@@ -209,9 +209,9 @@ else if (getArguments() != null)
}
}
- reattachFeedingDialogListener();
- reattachScheduleDialogListener();
- reattachDateDialogListener();
+ reattachFeedingDialogListener((ActionSelectDialogFragment)getFragmentManager().findFragmentByTag("actions"));
+ reattachScheduleDialogListener((FeedingScheduleSelectDialogFragment)getFragmentManager().findFragmentByTag("feeding"));
+ reattachDateDialogListener((DateDialogFragment)getFragmentManager().findFragmentByTag("date"));
setUi();
setHints();
}
@@ -293,7 +293,7 @@ public int compare(Action o1, Action o2)
ActionSelectDialogFragment actionSelectDialogFragment = ActionSelectDialogFragment.newInstance(items);
actionSelectDialogFragment.show(getFragmentManager(), "actions");
- reattachFeedingDialogListener();
+ reattachFeedingDialogListener(actionSelectDialogFragment);
}
return super.onOptionsItemSelected(item);
@@ -303,12 +303,11 @@ private void showScheduleDialog(FeedingSchedule schedule)
{
FeedingScheduleSelectDialogFragment feedingScheduleSelectDialogFragment = FeedingScheduleSelectDialogFragment.newInstance(schedule, plants);
feedingScheduleSelectDialogFragment.show(getFragmentManager(), "feeding");
- reattachScheduleDialogListener();
+ reattachScheduleDialogListener(feedingScheduleSelectDialogFragment);
}
- private void reattachFeedingDialogListener()
+ private void reattachFeedingDialogListener(ActionSelectDialogFragment fragment)
{
- ActionSelectDialogFragment fragment = (ActionSelectDialogFragment)getFragmentManager().findFragmentByTag("actions");
if (fragment != null)
{
fragment.setOnActionSelectedListener(new ActionSelectDialogFragment.OnActionSelectedListener()
@@ -323,9 +322,8 @@ private void reattachFeedingDialogListener()
}
}
- private void reattachDateDialogListener()
+ private void reattachDateDialogListener(DateDialogFragment fragment)
{
- DateDialogFragment fragment = (DateDialogFragment)getFragmentManager().findFragmentByTag("date");
if (fragment != null)
{
fragment.setOnDateSelected(new DateDialogFragment.OnDateSelectedListener()
@@ -350,9 +348,8 @@ private void reattachDateDialogListener()
}
}
- private void reattachScheduleDialogListener()
+ private void reattachScheduleDialogListener(FeedingScheduleSelectDialogFragment fragment)
{
- FeedingScheduleSelectDialogFragment fragment = (FeedingScheduleSelectDialogFragment)getFragmentManager().findFragmentByTag("feeding");
if (fragment != null)
{
fragment.setOnFeedingSelectedListener(new FeedingScheduleSelectDialogFragment.OnFeedingSelectedListener()
@@ -518,7 +515,7 @@ private void setUi()
{
final DateDialogFragment fragment = DateDialogFragment.newInstance(water.getDate());
getFragmentManager().beginTransaction().add(fragment, "date").commit();
- reattachDateDialogListener();
+ reattachDateDialogListener(fragment);
}
});
From a1af1a8a4e928ab5b92a485d079573c82deda745 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Thu, 19 Mar 2020 11:48:01 +0000
Subject: [PATCH 072/152] Makes title required for feeding schedule
---
.../me/anon/grow/fragment/FeedingScheduleDetailsFragment.kt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/FeedingScheduleDetailsFragment.kt b/app/src/main/java/me/anon/grow/fragment/FeedingScheduleDetailsFragment.kt
index 38ae8e23..4b7663ca 100644
--- a/app/src/main/java/me/anon/grow/fragment/FeedingScheduleDetailsFragment.kt
+++ b/app/src/main/java/me/anon/grow/fragment/FeedingScheduleDetailsFragment.kt
@@ -63,7 +63,7 @@ class FeedingScheduleDetailsFragment : Fragment()
fab_complete.setOnClickListener {
title.error = null
- if (scheduleDates.isNotEmpty() && title.text.isEmpty())
+ if (title.text.isEmpty())
{
title.error = getString(R.string.field_required)
}
From 487ff108559056595b73dafdf3243e1c658c1cf4 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Fri, 20 Mar 2020 15:29:00 +0000
Subject: [PATCH 073/152] Fixes formatting of additive totals and hints
---
.../java/me/anon/grow/fragment/WateringFragment.java | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/WateringFragment.java b/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
index 3f3bed3a..4ca5157b 100644
--- a/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/WateringFragment.java
@@ -453,7 +453,7 @@ private void setHints()
if (!averagePh.isNaN())
{
- waterPh.setHint(String.valueOf(averagePh));
+ waterPh.setHint(NumberUtilsKt.formatWhole(averagePh));
}
if (!selectedTdsAverage.isNaN())
@@ -464,13 +464,13 @@ private void setHints()
}
else
{
- waterPpm.setHint(selectedTdsAverage + " " + selectedTdsUnit.getLabel());
+ waterPpm.setHint(NumberUtilsKt.formatWhole(selectedTdsAverage) + " " + selectedTdsUnit.getLabel());
}
}
if (!averageRunoff.isNaN())
{
- runoffPh.setHint(String.valueOf(averageRunoff));
+ runoffPh.setHint(NumberUtilsKt.formatWhole(averageRunoff));
}
if (!averageAmount.isNaN())
@@ -565,7 +565,7 @@ private void populateAdditives()
if (additive == null || additive.getAmount() == null) continue;
double converted = Unit.ML.to(selectedMeasurementUnit, additive.getAmount());
- String amountStr = converted == Math.floor(converted) ? String.valueOf((int)converted) : String.valueOf(converted);
+ String amountStr = NumberUtilsKt.formatWhole(converted);
amountStr = additive.getDescription() + " - " + amountStr + selectedMeasurementUnit.getLabel() + "/" + selectedDeliveryUnit.getLabel();
maxChars = Math.max(maxChars, amountStr.length());
}
@@ -601,7 +601,7 @@ private void populateAdditives()
totalDelivery = ML.to(selectedDeliveryUnit, totalDelivery);
Double additiveAmount = ML.to(selectedMeasurementUnit, additive.getAmount());
- amountStr = amountStr + " (" + Unit.toTwoDecimalPlaces(additiveAmount * totalDelivery) + selectedMeasurementUnit.getLabel() + " total)";
+ amountStr = amountStr + " (" + NumberUtilsKt.formatWhole(Unit.toTwoDecimalPlaces(additiveAmount * totalDelivery)) + selectedMeasurementUnit.getLabel() + " total)";
}
((TextView)additiveStub).setText(Html.fromHtml(amountStr));
From 8efdaac151429a214fffc14e5c199e5e459cd649 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Fri, 20 Mar 2020 15:51:05 +0000
Subject: [PATCH 074/152] Fixes issue with garden sorting not working correctly
---
.../main/java/me/anon/grow/fragment/GardenFragment.java | 4 +---
app/src/main/java/me/anon/lib/manager/PlantManager.kt | 8 +++++++-
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/GardenFragment.java b/app/src/main/java/me/anon/grow/fragment/GardenFragment.java
index ff7d4c3e..0edd0f10 100644
--- a/app/src/main/java/me/anon/grow/fragment/GardenFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/GardenFragment.java
@@ -179,7 +179,6 @@ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, Recycle
{
for (int index = fromPosition; index < toPosition; index++)
{
- Collections.swap(PlantManager.getInstance().getPlants(), index, index + 1);
Collections.swap(adapter.getPlants(), index, index + 1);
adapter.notifyItemChanged(index, Boolean.TRUE);
adapter.notifyItemChanged(index + 1, Boolean.TRUE);
@@ -189,7 +188,6 @@ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, Recycle
{
for (int index = fromPosition; index > toPosition; index--)
{
- Collections.swap(PlantManager.getInstance().getPlants(), index, index - 1);
Collections.swap(adapter.getPlants(), index, index - 1);
adapter.notifyItemChanged(index, Boolean.TRUE);
adapter.notifyItemChanged(index - 1, Boolean.TRUE);
@@ -267,7 +265,7 @@ private synchronized void saveCurrentState()
}
garden.setPlantIds(orderedPlantIds);
- GardenManager.getInstance().save();
+ GardenManager.getInstance().upsert(garden);
}
PlantManager.getInstance().upsert(plants);
diff --git a/app/src/main/java/me/anon/lib/manager/PlantManager.kt b/app/src/main/java/me/anon/lib/manager/PlantManager.kt
index 17c159d1..7dabacf3 100644
--- a/app/src/main/java/me/anon/lib/manager/PlantManager.kt
+++ b/app/src/main/java/me/anon/lib/manager/PlantManager.kt
@@ -59,7 +59,13 @@ class PlantManager private constructor()
}
synchronized(this.plants) {
- return ArrayList(plants.filterIndexed { index, plant -> garden?.plantIds?.contains(plant.id) ?: true })
+ val list = garden?.let {
+ ArrayList((garden?.plantIds ?: arrayListOf()).map { id ->
+ plants.firstOrNull { it.id == id }
+ }).filterNotNull() as ArrayList
+ } ?: plants
+
+ return list
}
}
From e6b7ec958c6d1dd2c3a9a21fe1f921e7d1340fa4 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Mon, 23 Mar 2020 10:00:31 +0000
Subject: [PATCH 075/152] Adds more method extensions
---
app/src/main/java/me/anon/lib/ext/ClassUtils.kt | 6 ++++++
app/src/main/java/me/anon/lib/ext/NumberUtils.kt | 9 +++++++++
2 files changed, 15 insertions(+)
create mode 100644 app/src/main/java/me/anon/lib/ext/ClassUtils.kt
diff --git a/app/src/main/java/me/anon/lib/ext/ClassUtils.kt b/app/src/main/java/me/anon/lib/ext/ClassUtils.kt
new file mode 100644
index 00000000..5ed10b23
--- /dev/null
+++ b/app/src/main/java/me/anon/lib/ext/ClassUtils.kt
@@ -0,0 +1,6 @@
+package me.anon.lib.ext
+
+/**
+ * Performs a transformation of an object type into another object type
+ */
+public inline fun T.transform(transformer: T.() -> O): O = transformer(this)
diff --git a/app/src/main/java/me/anon/lib/ext/NumberUtils.kt b/app/src/main/java/me/anon/lib/ext/NumberUtils.kt
index 802129a8..2dfe9e6d 100644
--- a/app/src/main/java/me/anon/lib/ext/NumberUtils.kt
+++ b/app/src/main/java/me/anon/lib/ext/NumberUtils.kt
@@ -1,5 +1,7 @@
package me.anon.lib.ext
+import android.content.Context
+import android.util.TypedValue
import kotlin.math.round
public fun Double.round(decimals: Int): Double
@@ -27,3 +29,10 @@ public fun Number?.formatWhole(): String
}
} ?: "0"
}
+
+public fun Long.toDays(): Double = (this / (1000.0 * 60.0 * 60.0 * 24.0))
+
+public fun Number.dip(context: Context): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), context.resources.displayMetrics)
+public fun Number.sp(context: Context): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, this.toFloat(), context.resources.displayMetrics)
+public fun Number.mm(context: Context): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, this.toFloat(), context.resources.displayMetrics)
+public fun Number.pt(context: Context): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PT, this.toFloat(), context.resources.displayMetrics)
From f3c230217f8eaaf623e6cb7ba54e22ce7414bd8a Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Mon, 23 Mar 2020 10:01:00 +0000
Subject: [PATCH 076/152] Adds basic additive stats functionality
---
.../anon/grow/fragment/StatisticsFragment2.kt | 134 ++++++++++++------
.../me/anon/lib/export/MarkdownProcessor.kt | 5 +-
app/src/main/res/layout/statistics2_view.xml | 22 +--
3 files changed, 101 insertions(+), 60 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index c4e96eb6..92d9876b 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -1,5 +1,6 @@
package me.anon.grow.fragment
+import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.os.Bundle
@@ -7,36 +8,31 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
+import androidx.appcompat.view.ContextThemeWrapper
+import androidx.core.graphics.ColorUtils
import androidx.core.view.plusAssign
-import androidx.core.view.setMargins
import androidx.fragment.app.Fragment
import com.github.mikephil.charting.components.AxisBase
+import com.github.mikephil.charting.components.XAxis
import com.github.mikephil.charting.data.*
import com.github.mikephil.charting.formatter.ValueFormatter
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet
-import com.github.mikephil.charting.utils.ViewPortHandler
import com.google.android.material.chip.Chip
-import kotlinx.android.synthetic.main.action_buttons_stub.*
import kotlinx.android.synthetic.main.data_label_stub.view.*
-import kotlinx.android.synthetic.main.garden_action_buttons_stub.*
import kotlinx.android.synthetic.main.statistics2_view.*
import kotlinx.android.synthetic.main.statistics2_view.stage_chart
import kotlinx.android.synthetic.main.statistics2_view.stats_container
-import kotlinx.android.synthetic.main.statistics_view.*
import me.anon.grow.R
import me.anon.lib.TdsUnit
import me.anon.lib.Unit
-import me.anon.lib.ext.T
-import me.anon.lib.ext.formatWhole
-import me.anon.lib.ext.resolveColor
-import me.anon.lib.ext.resolveDimen
+import me.anon.lib.ext.*
+import me.anon.lib.helper.StatsHelper.formatter
import me.anon.lib.helper.TimeHelper
import me.anon.model.*
import java.lang.Math.abs
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.min
-import kotlin.math.roundToInt
/**
* // TODO: Add class description
@@ -88,6 +84,7 @@ class StatisticsFragment2 : Fragment()
}
val additives = arrayListOf()
+ val additiveDates = arrayListOf()
val additiveValues = hashMapOf>()
var endDate = System.currentTimeMillis()
var waterDifference = 0L
@@ -131,9 +128,15 @@ class StatisticsFragment2 : Fragment()
lastWater = action.date
// find the stage change where the date is older than the watering
- val stage = stageChanges.filterValues { it.date <= action.date }.toSortedMap().lastKey()
+ val sortedStageChange = stageChanges.filterValues { it.date <= action.date }.toSortedMap()
+ val stage = sortedStageChange.lastKey()
+ val stageChangeDate = sortedStageChange[stage]?.date ?: 0
+ val waterDate = action.date
+ val stageLength = (waterDate - stageChangeDate).toDays().toInt()
aveStageWaters.getOrPut(stage, { arrayListOf() }).add(action.date)
+ additiveDates.add("${stageLength}${getString(stage.printString).toLowerCase()[0]}")
+ // add additives to pre calculated list
action.additives.forEach { additive ->
if (additive.description != null)
{
@@ -303,38 +306,53 @@ class StatisticsFragment2 : Fragment()
private fun populateAdditiveStates()
{
- val selectedAdditives = arrayListOf()
-
class additiveStat(var total: Double = 0.0, var count: Int = 0, var min: Double = Double.NaN, var max: Double = Double.NaN)
- fun displayStats(name: String, stat: additiveStat)
- {
- val stats = arrayListOf()
- stats += header(getString(R.string.additive_stat_header, name))
- stats += data(
- label = getString(R.string.additive_average_usage_label),
- data = "${Unit.ML.to(selectedMeasurementUnit, stat.total / stat.count.toDouble()).formatWhole()} ${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
- )
- stats += data(
- label = getString(R.string.additive_total_usage_label),
- data = "${Unit.ML.to(selectedMeasurementUnit, stat.total).formatWhole()} ${selectedMeasurementUnit.label}"
- )
+ val selectedAdditives = arrayListOf()
+ val additiveStats = LinkedHashMap()
+ fun displayStats()
+ {
additives_stats_container.removeAllViews()
- renderStats(additives_stats_container, stats)
+
+ selectedAdditives.forEach { name ->
+ additiveStats[name]?.let { stat ->
+ val stats = arrayListOf()
+ stats += header(getString(R.string.additive_stat_header, name))
+ stats += data(
+ label = getString(R.string.min),
+ data = "${Unit.ML.to(selectedMeasurementUnit, stat.min).formatWhole()} ${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ )
+ stats += data(
+ label = getString(R.string.max),
+ data = "${Unit.ML.to(selectedMeasurementUnit, stat.max).formatWhole()} ${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ )
+ stats += data(
+ label = getString(R.string.additive_average_usage_label),
+ data = "${Unit.ML.to(selectedMeasurementUnit, stat.total / stat.count.toDouble()).formatWhole()} ${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ )
+ stats += data(
+ label = getString(R.string.additive_total_usage_label),
+ data = "${Unit.ML.to(selectedMeasurementUnit, stat.total).formatWhole()} ${selectedMeasurementUnit.label}"
+ )
+
+ renderStats(additives_stats_container, stats)
+ }
+ }
}
fun displayChart()
{
val dataSets = arrayListOf()
var index = 0
- additiveValues.forEach { (k, v) ->
+ additiveValues.toSortedMap().forEach { (k, v) ->
if (selectedAdditives.contains(k))
{
dataSets += LineDataSet(v, k).apply {
color = statsColours.get(index)
fillColor = color
setCircleColor(color)
+ styleDataset(context!!, this, color)
}
}
@@ -348,34 +366,27 @@ class StatisticsFragment2 : Fragment()
additives_chart.invalidate()
}
- val names = HashMap()
- additives.forEach { additive ->
+ additives.sortedBy { it.description }.forEach { additive ->
additive.description?.let { key ->
- names.getOrPut(key, { additiveStat() }).apply {
+ additiveStats.getOrPut(key, { additiveStat() }).apply {
total += additive.amount ?: 0.0
- min = max(min.isNaN() T Double.MIN_VALUE ?: min, additive.amount ?: 0.0)
- max = min(max.isNaN() T Double.MIN_VALUE ?: max, additive.amount ?: 0.0)
+ min = min(min.isNaN() T Double.MAX_VALUE ?: min, additive.amount ?: 0.0)
+ max = max(max.isNaN() T Double.MIN_VALUE ?: max, additive.amount ?: 0.0)
count++
}
}
}
- names.forEach { (k, v) ->
+ additiveStats.forEach { (k, v) ->
val chip = LayoutInflater.from(context!!).inflate(R.layout.filter_chip_stub, additive_chips_container, false) as Chip
chip.text = k
chip.isChecked = true
chip.setOnCheckedChangeListener { buttonView, isChecked ->
- //displayStats(k, v)
- if (isChecked)
- {
- selectedAdditives += k
- }
- else
- {
- selectedAdditives -= k
- }
+ if (isChecked) selectedAdditives += k
+ else selectedAdditives -= k
displayChart()
+ displayStats()
}
selectedAdditives += k
@@ -387,27 +398,37 @@ class StatisticsFragment2 : Fragment()
additives_chart.isScaleYEnabled = false
additives_chart.setDrawBorders(false)
+ additives_chart.axisLeft.granularity = 1f
additives_chart.axisLeft.setDrawGridLines(false)
- additives_chart.axisLeft.axisMinimum = 0f
additives_chart.axisLeft.textColor = R.attr.colorOnSurface.resolveColor(context!!)
additives_chart.axisLeft.valueFormatter = object : ValueFormatter()
{
override fun getAxisLabel(value: Float, axis: AxisBase?): String
{
- return "${value.toInt()}${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ return "${value.formatWhole()}${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
}
}
additives_chart.axisRight.setDrawLabels(false)
additives_chart.axisRight.setDrawGridLines(false)
+ additives_chart.axisRight.setDrawAxisLine(false)
additives_chart.xAxis.setDrawGridLines(false)
- additives_chart.xAxis.setDrawAxisLine(false)
- additives_chart.xAxis.setDrawLabels(false)
+ additives_chart.xAxis.granularity = 1f
+ additives_chart.xAxis.position = XAxis.XAxisPosition.BOTTOM
+ additives_chart.xAxis.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ additives_chart.xAxis.valueFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return additiveDates.getOrElse(value.toInt(), { "" })
+ }
+ }
- additives_chart.legend.textColor = R.attr.colorOnSurface.resolveColor(context!!).toInt()
+ additives_chart.legend.textColor = R.attr.colorOnSurface.resolveColor(context!!)
additives_chart.legend.isWordWrapEnabled = true
displayChart()
+ displayStats()
}
private fun renderStats(container: ViewGroup, templates: ArrayList)
@@ -436,4 +457,23 @@ class StatisticsFragment2 : Fragment()
container += dataView
}
}
+
+ fun styleDataset(context: Context, data: LineDataSet, colour: Int)
+ {
+ val context = ContextThemeWrapper(context, R.style.AppTheme)
+ data.valueTextColor = R.attr.colorAccent.resolveColor(context)
+ data.setCircleColor(R.attr.colorAccent.resolveColor(context))
+ data.cubicIntensity = 0.2f
+ data.lineWidth = 2.0f
+ data.setDrawCircleHole(true)
+ data.color = colour
+ data.setCircleColor(colour)
+ data.circleRadius = 4.0f
+ data.setDrawHighlightIndicators(true)
+ data.isHighlightEnabled = true
+ data.highlightLineWidth = 2f
+ data.highLightColor = ColorUtils.setAlphaComponent(colour, 96)
+ data.setDrawValues(false)
+ data.valueFormatter = formatter
+ }
}
diff --git a/app/src/main/java/me/anon/lib/export/MarkdownProcessor.kt b/app/src/main/java/me/anon/lib/export/MarkdownProcessor.kt
index 7fe66411..3e259b06 100644
--- a/app/src/main/java/me/anon/lib/export/MarkdownProcessor.kt
+++ b/app/src/main/java/me/anon/lib/export/MarkdownProcessor.kt
@@ -311,9 +311,10 @@ class MarkdownProcessor : ExportProcessor()
if (action.additives.isNotEmpty())
{
documentBuilder.append(" / ")
- action.additives.sortedBy { it.description ?: "" }.forEach { additive ->
+ val additives = action.additives.sortedBy { it.description ?: "" }
+ additives.forEach { additive ->
documentBuilder.append("**${additive.description ?: ""}:** ").append(Unit.ML.to(selectedMeasurement, additive.amount ?: 0.0).formatWhole()).append(selectedMeasurement!!.label).append("/").append(selectedDelivery!!.label)
- if (action.additives.last() != additive) documentBuilder.append(" – ")
+ if (additives.last() != additive) documentBuilder.append(" – ")
}
}
}
diff --git a/app/src/main/res/layout/statistics2_view.xml b/app/src/main/res/layout/statistics2_view.xml
index 3d99a468..90d168d7 100644
--- a/app/src/main/res/layout/statistics2_view.xml
+++ b/app/src/main/res/layout/statistics2_view.xml
@@ -81,16 +81,6 @@
app:chipSpacing="4dp"
app:chipSpacingVertical="0dp"
/>
-
-
+
+
From 63031be3c0b596473116e6483fe4c2b537a55ef4 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Wed, 8 Apr 2020 17:07:36 +0100
Subject: [PATCH 077/152] Fixes edit watering activity crash
---
app/src/main/java/me/anon/grow/EditWateringActivity.kt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/src/main/java/me/anon/grow/EditWateringActivity.kt b/app/src/main/java/me/anon/grow/EditWateringActivity.kt
index caa12977..db8090db 100644
--- a/app/src/main/java/me/anon/grow/EditWateringActivity.kt
+++ b/app/src/main/java/me/anon/grow/EditWateringActivity.kt
@@ -38,7 +38,7 @@ class EditWateringActivity : BaseActivity()
if (supportFragmentManager.findFragmentByTag("fragment") == null)
{
supportFragmentManager.beginTransaction()
- .replace(R.id.coordinator, WateringFragment.newInstance(intArrayOf(plantIndex), feedingIndex, -1), "fragment")
+ .replace(R.id.fragment_holder, WateringFragment.newInstance(intArrayOf(plantIndex), feedingIndex, -1), "fragment")
.commit()
}
}
From 0441997918183807373547a36b79da1e57f19017 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sat, 18 Apr 2020 11:07:54 +0100
Subject: [PATCH 078/152] Adds total plant date into additives graph
---
.../me/anon/grow/fragment/StatisticsFragment2.kt | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index 92d9876b..fe247d3b 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -20,12 +20,13 @@ import com.github.mikephil.charting.interfaces.datasets.ILineDataSet
import com.google.android.material.chip.Chip
import kotlinx.android.synthetic.main.data_label_stub.view.*
import kotlinx.android.synthetic.main.statistics2_view.*
-import kotlinx.android.synthetic.main.statistics2_view.stage_chart
-import kotlinx.android.synthetic.main.statistics2_view.stats_container
import me.anon.grow.R
import me.anon.lib.TdsUnit
import me.anon.lib.Unit
-import me.anon.lib.ext.*
+import me.anon.lib.ext.T
+import me.anon.lib.ext.formatWhole
+import me.anon.lib.ext.resolveColor
+import me.anon.lib.ext.toDays
import me.anon.lib.helper.StatsHelper.formatter
import me.anon.lib.helper.TimeHelper
import me.anon.model.*
@@ -133,8 +134,9 @@ class StatisticsFragment2 : Fragment()
val stageChangeDate = sortedStageChange[stage]?.date ?: 0
val waterDate = action.date
val stageLength = (waterDate - stageChangeDate).toDays().toInt()
+ val totalDate = TimeHelper.toDays(action.date - plant.plantDate).toInt()
aveStageWaters.getOrPut(stage, { arrayListOf() }).add(action.date)
- additiveDates.add("${stageLength}${getString(stage.printString).toLowerCase()[0]}")
+ additiveDates.add("${totalDate}/${stageLength}${getString(stage.printString).toLowerCase()[0]}")
// add additives to pre calculated list
action.additives.forEach { additive ->
@@ -421,7 +423,7 @@ class StatisticsFragment2 : Fragment()
{
override fun getAxisLabel(value: Float, axis: AxisBase?): String
{
- return additiveDates.getOrElse(value.toInt(), { "" })
+ return additiveDates.getOrElse(value.toInt()) { "" }
}
}
From a5c356aa1e57c4438b8b9ebdfca59a55f8af960d Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sat, 18 Apr 2020 13:50:12 +0100
Subject: [PATCH 079/152] Adds last modified dates for imported images if they
exist
---
.../grow/fragment/PlantDetailsFragment.java | 32 ++++++++++++----
.../grow/fragment/ViewPhotosFragment.java | 38 ++++++++++++++++---
.../java/me/anon/lib/task/ImportTask.java | 18 ++++++---
3 files changed, 69 insertions(+), 19 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/PlantDetailsFragment.java b/app/src/main/java/me/anon/grow/fragment/PlantDetailsFragment.java
index 1f3a8797..5b397b21 100644
--- a/app/src/main/java/me/anon/grow/fragment/PlantDetailsFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/PlantDetailsFragment.java
@@ -7,11 +7,13 @@
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.database.Cursor;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
+import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.text.Html;
import android.text.TextUtils;
@@ -32,16 +34,14 @@
import com.esotericsoftware.kryo.Kryo;
-import org.jetbrains.annotations.NotNull;
-
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
-import java.util.Collections;
import java.util.Date;
+import java.util.HashMap;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
@@ -595,10 +595,10 @@ else if (requestCode == ACTIVITY_REQUEST_PHOTO_GALLERY) // choose image from gal
{
if (data == null) return;
- ArrayList images = new ArrayList<>();
+ HashMap images = new HashMap();
if (data.getData() != null)
{
- images.add(data.getData());
+ images.put(data.getData(), System.currentTimeMillis());
try
{
@@ -620,10 +620,28 @@ else if (requestCode == ACTIVITY_REQUEST_PHOTO_GALLERY) // choose image from gal
{
for (int index = 0; index < data.getClipData().getItemCount(); index++)
{
- images.add(data.getClipData().getItemAt(index).getUri());
+ images.put(data.getClipData().getItemAt(index).getUri(), System.currentTimeMillis());
+ }
+ }
+
+ for (Uri key : images.keySet())
+ {
+ try
+ {
+ Cursor query = getActivity().getContentResolver().query(key, null,
+ DocumentsContract.Document.COLUMN_DOCUMENT_ID + " = " + key.getPath(), null, null);
+ long modifiedDate = images.get(key);
+ int modifiedIndex = query.getColumnIndex(DocumentsContract.Document.COLUMN_LAST_MODIFIED);
+ while (query.moveToNext()) {
+ modifiedDate = query.getLong(modifiedIndex);
+ break;
+ }
+
+ images.put(key, modifiedDate == -1 ? images.get(key) : modifiedDate);
+ query.close();
}
+ catch (Exception e){}
}
- images.removeAll(Collections.singleton(null));
NotificationHelper.sendDataTaskNotification(getActivity(), getString(R.string.app_name), getString(R.string.import_progress_warning));
new ImportTask(getActivity(), new AsyncCallback()
diff --git a/app/src/main/java/me/anon/grow/fragment/ViewPhotosFragment.java b/app/src/main/java/me/anon/grow/fragment/ViewPhotosFragment.java
index d7eb82d8..4df2292b 100644
--- a/app/src/main/java/me/anon/grow/fragment/ViewPhotosFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/ViewPhotosFragment.java
@@ -6,10 +6,12 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
+import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
+import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.text.Html;
import android.view.ActionMode;
@@ -23,7 +25,7 @@
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -106,7 +108,8 @@ public static ViewPhotosFragment newInstance(Bundle arguments)
{
plant = getArguments().getParcelable("plant");
}
- else if (savedInstanceState != null)
+
+ if (savedInstanceState != null)
{
plant = savedInstanceState.getParcelable("plant");
tempImagePath = savedInstanceState.getString("temp_image", "");
@@ -480,6 +483,10 @@ private void cleanupFolder(@Nullable File folderPath)
File imageFile = new File(tempImagePath);
if (imageFile.exists() && imageFile.length() > 0)
{
+ if (!plant.getImages().contains(imageFile.getAbsolutePath()))
+ {
+ plant.getImages().add(imageFile.getAbsolutePath());
+ }
PlantManager.getInstance().upsert(plant);
setAdapter();
@@ -489,6 +496,7 @@ private void cleanupFolder(@Nullable File folderPath)
}
else
{
+ plant.getImages().remove(imageFile.getAbsolutePath());
cleanupFolder(imageFile.getParentFile());
}
}
@@ -499,10 +507,10 @@ else if (requestCode == 3) // choose image from gallery
{
if (data == null) return;
- ArrayList images = new ArrayList<>();
+ HashMap images = new HashMap();
if (data.getData() != null)
{
- images.add(data.getData());
+ images.put(data.getData(), System.currentTimeMillis());
try
{
@@ -524,10 +532,28 @@ else if (requestCode == 3) // choose image from gallery
{
for (int index = 0; index < data.getClipData().getItemCount(); index++)
{
- images.add(data.getClipData().getItemAt(index).getUri());
+ images.put(data.getClipData().getItemAt(index).getUri(), System.currentTimeMillis());
+ }
+ }
+
+ for (Uri key : images.keySet())
+ {
+ try
+ {
+ Cursor query = getActivity().getContentResolver().query(key, null,
+ DocumentsContract.Document.COLUMN_DOCUMENT_ID + " = " + key.getPath(), null, null);
+ long modifiedDate = images.get(key);
+ int modifiedIndex = query.getColumnIndex(DocumentsContract.Document.COLUMN_LAST_MODIFIED);
+ while (query.moveToNext()) {
+ modifiedDate = query.getLong(modifiedIndex);
+ break;
+ }
+
+ images.put(key, modifiedDate == -1 ? images.get(key) : modifiedDate);
+ query.close();
}
+ catch (Exception e){}
}
- images.removeAll(Collections.singleton(null));
NotificationHelper.sendDataTaskNotification(getActivity(), getString(R.string.app_name), getString(R.string.import_progress_warning));
new ImportTask(getActivity(), new AsyncCallback()
diff --git a/app/src/main/java/me/anon/lib/task/ImportTask.java b/app/src/main/java/me/anon/lib/task/ImportTask.java
index a4e76e06..5b60796d 100644
--- a/app/src/main/java/me/anon/lib/task/ImportTask.java
+++ b/app/src/main/java/me/anon/lib/task/ImportTask.java
@@ -19,6 +19,8 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
import javax.crypto.Cipher;
@@ -39,7 +41,7 @@
* @documentation // TODO Reference flow doc
* @project GrowTracker
*/
-public class ImportTask extends AsyncTask>, Integer, Void>
+public class ImportTask extends AsyncTask>, Integer, Void>
{
protected NotificationCompat.Builder notification;
protected NotificationManager notificationManager;
@@ -74,7 +76,7 @@ public ImportTask(Context appContext, AsyncCallback callback)
notificationManager.notify(1, notification.build());
}
- @Override protected Void doInBackground(Pair>... params)
+ @Override protected Void doInBackground(Pair>... params)
{
MainApplication.dataTaskRunning.set(true);
@@ -93,9 +95,9 @@ public ImportTask(Context appContext, AsyncCallback callback)
}
ArrayList imagesToAdd = new ArrayList<>();
- for (Uri filePath : params[0].getSecond())
+ for (Uri filePath : params[0].getSecond().keySet())
{
- File toPath = new File(to, System.currentTimeMillis() + ".jpg");
+ File toPath = new File(to, params[0].getSecond().get(filePath) + ".jpg");
copyImage(appContext, filePath, toPath);
if (toPath.exists())
@@ -109,11 +111,15 @@ public ImportTask(Context appContext, AsyncCallback callback)
Plant plant = PlantManager.getInstance().getPlant(params[0].getFirst());
if (plant != null)
{
- plant.getImages().addAll(imagesToAdd);
+ ArrayList images = plant.getImages();
+ images.addAll(imagesToAdd);
+ Collections.sort(images);
+ plant.setImages(images);
+
PlantManager.getInstance().save();
}
- for (Uri uri : params[0].getSecond())
+ for (Uri uri : params[0].getSecond().keySet())
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
From 8d38694df50c0df4c75ffdc9505403f53974c36b Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sat, 18 Apr 2020 16:37:04 +0100
Subject: [PATCH 080/152] Adds test bar overlay for stage in additives chart
---
.../anon/grow/fragment/StatisticsFragment2.kt | 69 ++++++++++++++-----
app/src/main/res/layout/statistics2_view.xml | 2 +-
2 files changed, 52 insertions(+), 19 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index fe247d3b..6d5c2bf8 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -12,10 +12,13 @@ import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.graphics.ColorUtils
import androidx.core.view.plusAssign
import androidx.fragment.app.Fragment
+import com.github.mikephil.charting.charts.CombinedChart.DrawOrder
import com.github.mikephil.charting.components.AxisBase
import com.github.mikephil.charting.components.XAxis
+import com.github.mikephil.charting.components.YAxis
import com.github.mikephil.charting.data.*
import com.github.mikephil.charting.formatter.ValueFormatter
+import com.github.mikephil.charting.interfaces.datasets.IBarDataSet
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet
import com.google.android.material.chip.Chip
import kotlinx.android.synthetic.main.data_label_stub.view.*
@@ -23,10 +26,7 @@ import kotlinx.android.synthetic.main.statistics2_view.*
import me.anon.grow.R
import me.anon.lib.TdsUnit
import me.anon.lib.Unit
-import me.anon.lib.ext.T
-import me.anon.lib.ext.formatWhole
-import me.anon.lib.ext.resolveColor
-import me.anon.lib.ext.toDays
+import me.anon.lib.ext.*
import me.anon.lib.helper.StatsHelper.formatter
import me.anon.lib.helper.TimeHelper
import me.anon.model.*
@@ -40,6 +40,8 @@ import kotlin.math.min
*/
class StatisticsFragment2 : Fragment()
{
+ class StageDate(var day: Int, var total: Int, var stage: PlantStage)
+
open class template()
open class header(var label: String) : template()
open class data(label: String, val data: String) : header(label)
@@ -85,7 +87,7 @@ class StatisticsFragment2 : Fragment()
}
val additives = arrayListOf()
- val additiveDates = arrayListOf()
+ val additiveDates = arrayListOf()
val additiveValues = hashMapOf>()
var endDate = System.currentTimeMillis()
var waterDifference = 0L
@@ -136,7 +138,7 @@ class StatisticsFragment2 : Fragment()
val stageLength = (waterDate - stageChangeDate).toDays().toInt()
val totalDate = TimeHelper.toDays(action.date - plant.plantDate).toInt()
aveStageWaters.getOrPut(stage, { arrayListOf() }).add(action.date)
- additiveDates.add("${totalDate}/${stageLength}${getString(stage.printString).toLowerCase()[0]}")
+ additiveDates.add(StageDate(stageLength, totalDate, stage))
// add additives to pre calculated list
action.additives.forEach { additive ->
@@ -312,6 +314,7 @@ class StatisticsFragment2 : Fragment()
val selectedAdditives = arrayListOf()
val additiveStats = LinkedHashMap()
+ var totalMax = Double.MIN_VALUE
fun displayStats()
{
@@ -345,25 +348,45 @@ class StatisticsFragment2 : Fragment()
fun displayChart()
{
+ val barSets = arrayListOf()
val dataSets = arrayListOf()
var index = 0
- additiveValues.toSortedMap().forEach { (k, v) ->
- if (selectedAdditives.contains(k))
- {
- dataSets += LineDataSet(v, k).apply {
- color = statsColours.get(index)
- fillColor = color
- setCircleColor(color)
- styleDataset(context!!, this, color)
+ additiveValues.toSortedMap().let {
+ it.forEach { (k, v) ->
+ if (selectedAdditives.contains(k))
+ {
+ dataSets += LineDataSet(v, k).apply {
+ color = statsColours.get(index)
+ fillColor = color
+ setCircleColor(color)
+ styleDataset(context!!, this, color)
+ }
}
+
+ index++
+ if (index >= statsColours.size) index = 0
}
+ }
- index++
- if (index >= statsColours.size) index = 0
+ val stageEntries = plantStages.keys.toList().asReversed()
+ additiveDates.forEachIndexed { additiveIndex, date ->
+ barSets += BarDataSet(arrayListOf(BarEntry(additiveIndex.toFloat(), totalMax.toFloat())), null).apply {
+ color = ColorUtils.setAlphaComponent(statsColours[stageEntries.indexOf(date.stage) % statsColours.size], 127)
+ }
}
val lineData = LineData(dataSets)
- additives_chart.data = lineData
+ val barData = BarData(barSets).apply {
+ setDrawValues(false)
+ this.isHighlightEnabled = false
+ this.barWidth = 1.0f
+ this.groupBars(0f, 0f, 0f)
+ }
+
+ val data = CombinedData()
+ data.setData(barData)
+ data.setData(lineData)
+ additives_chart.data = data
additives_chart.notifyDataSetChanged()
additives_chart.invalidate()
}
@@ -375,6 +398,8 @@ class StatisticsFragment2 : Fragment()
min = min(min.isNaN() T Double.MAX_VALUE ?: min, additive.amount ?: 0.0)
max = max(max.isNaN() T Double.MIN_VALUE ?: max, additive.amount ?: 0.0)
count++
+
+ totalMax = max(totalMax, max)
}
}
}
@@ -395,6 +420,11 @@ class StatisticsFragment2 : Fragment()
additive_chips_container += chip
}
+ // draw bars behind lines
+ additives_chart.drawOrder = arrayOf(
+ DrawOrder.BAR, DrawOrder.LINE
+ )
+ additives_chart.setVisibleYRangeMaximum(totalMax.toFloat(), YAxis.AxisDependency.LEFT)
additives_chart.setDrawGridBackground(false)
additives_chart.description = null
additives_chart.isScaleYEnabled = false
@@ -423,12 +453,15 @@ class StatisticsFragment2 : Fragment()
{
override fun getAxisLabel(value: Float, axis: AxisBase?): String
{
- return additiveDates.getOrElse(value.toInt()) { "" }
+ return additiveDates.getOrNull(value.toInt())?.transform {
+ "${total}/${day}${getString(stage.printString).toLowerCase()[0]}"
+ } ?: ""
}
}
additives_chart.legend.textColor = R.attr.colorOnSurface.resolveColor(context!!)
additives_chart.legend.isWordWrapEnabled = true
+ additives_chart.legend.setCustom(arrayListOf())
displayChart()
displayStats()
}
diff --git a/app/src/main/res/layout/statistics2_view.xml b/app/src/main/res/layout/statistics2_view.xml
index 90d168d7..54add56a 100644
--- a/app/src/main/res/layout/statistics2_view.xml
+++ b/app/src/main/res/layout/statistics2_view.xml
@@ -83,7 +83,7 @@
/>
-
Date: Sun, 19 Apr 2020 20:05:35 +0100
Subject: [PATCH 081/152] Adds totals pie chart
---
.../anon/grow/fragment/StatisticsFragment2.kt | 31 ++++++++++++++++++
app/src/main/res/layout/statistics2_view.xml | 32 +++++++++++++++----
app/src/main/res/values/strings.xml | 3 ++
3 files changed, 60 insertions(+), 6 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index 6d5c2bf8..1b28c05b 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -391,6 +391,30 @@ class StatisticsFragment2 : Fragment()
additives_chart.invalidate()
}
+ fun displayTotalsChart()
+ {
+ val pieData = arrayListOf()
+ selectedAdditives.forEach { selected ->
+ additiveStats.get(selected)?.let { additive ->
+ pieData += PieEntry(additive.total.toFloat())
+ }
+ }
+
+ additives_count_chart.data = PieData(PieDataSet(pieData, "").apply {
+ this.colors = statsColours
+ this.valueTextSize = 14f
+ this.valueFormatter = object : ValueFormatter()
+ {
+ override fun getFormattedValue(value: Float): String
+ {
+ return "${value.formatWhole()}${selectedMeasurementUnit.label}"
+ }
+ }
+ })
+ additives_count_chart.notifyDataSetChanged()
+ additives_count_chart.invalidate()
+ }
+
additives.sortedBy { it.description }.forEach { additive ->
additive.description?.let { key ->
additiveStats.getOrPut(key, { additiveStat() }).apply {
@@ -462,7 +486,14 @@ class StatisticsFragment2 : Fragment()
additives_chart.legend.textColor = R.attr.colorOnSurface.resolveColor(context!!)
additives_chart.legend.isWordWrapEnabled = true
additives_chart.legend.setCustom(arrayListOf())
+
+// additives_count_chart.holeRadius = 10f
+ additives_count_chart.description = null
+ additives_count_chart.setHoleColor(0x00ffffff.toInt())
+ additives_count_chart.legend.setCustom(arrayListOf())
+
displayChart()
+ displayTotalsChart()
displayStats()
}
diff --git a/app/src/main/res/layout/statistics2_view.xml b/app/src/main/res/layout/statistics2_view.xml
index 54add56a..6a445ebd 100644
--- a/app/src/main/res/layout/statistics2_view.xml
+++ b/app/src/main/res/layout/statistics2_view.xml
@@ -83,22 +83,42 @@
/>
+
+
+
+
+
+
%s stats
Ave. each feeding:
Total amount:
+
+ Additives over time
+ Additives distribution
From edcea197d873fd4412dd72d47d0d0d05386b4cc3 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sat, 25 Apr 2020 16:20:07 +0100
Subject: [PATCH 082/152] Fixes total amount calculations
---
.../anon/grow/fragment/StatisticsFragment2.kt | 327 ++++++++++++++----
app/src/main/java/me/anon/lib/Unit.java | 5 +-
app/src/main/res/layout/statistics2_view.xml | 18 +-
app/src/main/res/values/strings.xml | 2 +
4 files changed, 275 insertions(+), 77 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index 1b28c05b..1c734f05 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -13,9 +13,7 @@ import androidx.core.graphics.ColorUtils
import androidx.core.view.plusAssign
import androidx.fragment.app.Fragment
import com.github.mikephil.charting.charts.CombinedChart.DrawOrder
-import com.github.mikephil.charting.components.AxisBase
-import com.github.mikephil.charting.components.XAxis
-import com.github.mikephil.charting.components.YAxis
+import com.github.mikephil.charting.components.*
import com.github.mikephil.charting.data.*
import com.github.mikephil.charting.formatter.ValueFormatter
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet
@@ -86,9 +84,11 @@ class StatisticsFragment2 : Fragment()
}
}
- val additives = arrayListOf()
+ val additives = hashMapOf>()
val additiveDates = arrayListOf()
val additiveValues = hashMapOf>()
+ val additiveTotalValues = hashMapOf>()
+
var endDate = System.currentTimeMillis()
var waterDifference = 0L
var lastWater = 0L
@@ -145,15 +145,25 @@ class StatisticsFragment2 : Fragment()
if (additive.description != null)
{
additive.amount?.let { amount ->
- val amount = Unit.ML.to(selectedMeasurementUnit, amount)
- val entry = Entry(additiveIndex.toFloat(), amount.toFloat())
- additiveValues.getOrPut(additive.description!!, { arrayListOf() }).add(entry)
+ with (additiveValues) {
+ val amount = Unit.ML.to(selectedMeasurementUnit, amount)
+ val entry = Entry(additiveIndex.toFloat(), amount.toFloat())
+ getOrPut(additive.description!!, { arrayListOf() }).add(entry)
+ }
+
+ with (additiveTotalValues) {
+ val totalDelivery = Unit.ML.to(selectedDeliveryUnit, action.amount ?: 1000.0)
+ val additiveAmount = Unit.ML.to(selectedMeasurementUnit, amount)
+
+ val entry = Entry(additiveIndex.toFloat(), Unit.toTwoDecimalPlaces(additiveAmount * totalDelivery).toFloat())
+ getOrPut(additive.description!!, { arrayListOf() }).add(entry)
+ }
}
}
}
additiveIndex++
- additives.addAll(action.additives)
+ additives.getOrPut(action) { arrayListOf() }.addAll(action.additives)
}
is EmptyAction -> {
@@ -310,7 +320,13 @@ class StatisticsFragment2 : Fragment()
private fun populateAdditiveStates()
{
- class additiveStat(var total: Double = 0.0, var count: Int = 0, var min: Double = Double.NaN, var max: Double = Double.NaN)
+ class additiveStat(
+ var total: Double = 0.0,
+ var totalAdjusted: Double = 0.0,
+ var count: Int = 0,
+ var min: Double = Double.NaN,
+ var max: Double = Double.NaN
+ )
val selectedAdditives = arrayListOf()
val additiveStats = LinkedHashMap()
@@ -336,9 +352,13 @@ class StatisticsFragment2 : Fragment()
label = getString(R.string.additive_average_usage_label),
data = "${Unit.ML.to(selectedMeasurementUnit, stat.total / stat.count.toDouble()).formatWhole()} ${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
)
+ stats += data(
+ label = getString(R.string.additive_usage_count_label),
+ data = "${stat.count}"
+ )
stats += data(
label = getString(R.string.additive_total_usage_label),
- data = "${Unit.ML.to(selectedMeasurementUnit, stat.total).formatWhole()} ${selectedMeasurementUnit.label}"
+ data = "${Unit.ML.to(selectedMeasurementUnit, stat.totalAdjusted).formatWhole()} ${selectedMeasurementUnit.label}"
)
renderStats(additives_stats_container, stats)
@@ -346,7 +366,7 @@ class StatisticsFragment2 : Fragment()
}
}
- fun displayChart()
+ fun displayConcentrationChart()
{
val barSets = arrayListOf()
val dataSets = arrayListOf()
@@ -356,7 +376,7 @@ class StatisticsFragment2 : Fragment()
if (selectedAdditives.contains(k))
{
dataSets += LineDataSet(v, k).apply {
- color = statsColours.get(index)
+ color = statsColours[index]
fillColor = color
setCircleColor(color)
styleDataset(context!!, this, color)
@@ -384,25 +404,41 @@ class StatisticsFragment2 : Fragment()
}
val data = CombinedData()
- data.setData(barData)
+ //data.setData(barData)
data.setData(lineData)
- additives_chart.data = data
- additives_chart.notifyDataSetChanged()
- additives_chart.invalidate()
+ additives_concentration_chart.data = data
+ additives_concentration_chart.notifyDataSetChanged()
+ additives_concentration_chart.invalidate()
}
fun displayTotalsChart()
{
val pieData = arrayListOf()
- selectedAdditives.forEach { selected ->
- additiveStats.get(selected)?.let { additive ->
- pieData += PieEntry(additive.total.toFloat())
+ val colors = arrayListOf()
+ additiveTotalValues.toSortedMap().let { values ->
+ var index = 0
+
+ values.forEach { (k, v) ->
+ if (selectedAdditives.contains(k))
+ {
+ var total = 0.0
+ v.forEach { entry ->
+ total += entry.y
+ }
+
+ pieData += PieEntry(total.toFloat()).apply {
+ colors += statsColours[index]
+ }
+ }
+
+ index++
+ if (index >= statsColours.size) index = 0
}
}
additives_count_chart.data = PieData(PieDataSet(pieData, "").apply {
- this.colors = statsColours
- this.valueTextSize = 14f
+ this.colors = colors
+ this.valueTextSize = 12f
this.valueFormatter = object : ValueFormatter()
{
override fun getFormattedValue(value: Float): String
@@ -415,15 +451,91 @@ class StatisticsFragment2 : Fragment()
additives_count_chart.invalidate()
}
- additives.sortedBy { it.description }.forEach { additive ->
- additive.description?.let { key ->
- additiveStats.getOrPut(key, { additiveStat() }).apply {
- total += additive.amount ?: 0.0
- min = min(min.isNaN() T Double.MAX_VALUE ?: min, additive.amount ?: 0.0)
- max = max(max.isNaN() T Double.MIN_VALUE ?: max, additive.amount ?: 0.0)
- count++
+ fun displayOvertimeChart()
+ {
+ val barSets = arrayListOf()
+ val dataSets = arrayListOf()
+ var index = 0
+ val newValues = sortedMapOf>()
+
+ additiveTotalValues.toSortedMap().let {
+ it.forEach { (key, entries) ->
+ if (selectedAdditives.contains(key))
+ {
+ val newEntries = arrayListOf()
+ var lastEntry: Entry? = null
+ entries.forEach { entry ->
+ val newEntry = Entry(entry.x, entry.y + (lastEntry?.y ?: 0.0f))
+ newEntries.add(newEntry)
+ lastEntry = newEntry
+ }
+
+ newValues[key] = newEntries
+
+ dataSets += LineDataSet(newValues[key], key).apply {
+ color = statsColours[index]
+ fillColor = color
+ setCircleColor(color)
+ styleDataset(context!!, this, color)
+ }
+ }
- totalMax = max(totalMax, max)
+ index++
+ if (index >= statsColours.size) index = 0
+ }
+ }
+
+ val stageEntries = plantStages.keys.toList().asReversed()
+ additiveDates.forEachIndexed { additiveIndex, date ->
+ barSets += BarDataSet(arrayListOf(BarEntry(additiveIndex.toFloat(), totalMax.toFloat())), null).apply {
+ color = ColorUtils.setAlphaComponent(statsColours[stageEntries.indexOf(date.stage) % statsColours.size], 127)
+ }
+ }
+
+ val lineData = LineData(dataSets)
+ val barData = BarData(barSets).apply {
+ setDrawValues(false)
+ this.isHighlightEnabled = false
+ this.barWidth = 1.0f
+ this.groupBars(0f, 0f, 0f)
+ }
+
+ val data = CombinedData()
+ //data.setData(barData)
+ data.setData(lineData)
+ additives_overtime_chart.data = data
+ additives_overtime_chart.notifyDataSetChanged()
+ additives_overtime_chart.invalidate()
+ }
+
+ fun refreshCharts()
+ {
+ displayConcentrationChart()
+ displayTotalsChart()
+ displayOvertimeChart()
+ displayStats()
+ }
+
+ additives.keys.forEach { water ->
+ additives[water]?.sortedBy { it.description }?.forEach { additive ->
+ additive.description?.let { key ->
+ additiveStats.getOrPut(key, { additiveStat() }).apply {
+ total += additive.amount ?: 0.0
+ min = min(min.isNaN() T Double.MAX_VALUE ?: min, additive.amount ?: 0.0)
+ max = max(max.isNaN() T Double.MIN_VALUE ?: max, additive.amount ?: 0.0)
+
+ additiveTotalValues[key]?.let { totalValues ->
+ var total = 0.0
+ totalValues.forEach { entry ->
+ total += entry.y
+ }
+
+ totalAdjusted = total
+ }
+
+ count++
+ totalMax = max(totalMax, max)
+ }
}
}
}
@@ -436,65 +548,136 @@ class StatisticsFragment2 : Fragment()
if (isChecked) selectedAdditives += k
else selectedAdditives -= k
- displayChart()
- displayStats()
+ refreshCharts()
}
selectedAdditives += k
additive_chips_container += chip
}
- // draw bars behind lines
- additives_chart.drawOrder = arrayOf(
- DrawOrder.BAR, DrawOrder.LINE
- )
- additives_chart.setVisibleYRangeMaximum(totalMax.toFloat(), YAxis.AxisDependency.LEFT)
- additives_chart.setDrawGridBackground(false)
- additives_chart.description = null
- additives_chart.isScaleYEnabled = false
- additives_chart.setDrawBorders(false)
-
- additives_chart.axisLeft.granularity = 1f
- additives_chart.axisLeft.setDrawGridLines(false)
- additives_chart.axisLeft.textColor = R.attr.colorOnSurface.resolveColor(context!!)
- additives_chart.axisLeft.valueFormatter = object : ValueFormatter()
- {
- override fun getAxisLabel(value: Float, axis: AxisBase?): String
- {
- return "${value.formatWhole()}${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ val entries = arrayListOf()
+ additiveValues.toSortedMap().let {
+ var index = 0
+ it.forEach { (k, v) ->
+ if (selectedAdditives.contains(k))
+ {
+ entries.add(LegendEntry().apply {
+ label = k
+ formColor = statsColours[index]
+ })
+ }
+
+ index++
+ if (index >= statsColours.size) index = 0
}
}
- additives_chart.axisRight.setDrawLabels(false)
- additives_chart.axisRight.setDrawGridLines(false)
- additives_chart.axisRight.setDrawAxisLine(false)
+ with (additives_concentration_chart) {
+ drawOrder = arrayOf(
+ DrawOrder.BAR, DrawOrder.LINE
+ )
+ setVisibleYRangeMaximum(totalMax.toFloat(), YAxis.AxisDependency.LEFT)
+ setDrawGridBackground(false)
+ description = null
+ isScaleYEnabled = false
+ setDrawBorders(false)
+
+ axisLeft.granularity = 1f
+ axisLeft.setDrawGridLines(false)
+ axisLeft.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ axisLeft.valueFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return "${value.formatWhole()}${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ }
+ }
- additives_chart.xAxis.setDrawGridLines(false)
- additives_chart.xAxis.granularity = 1f
- additives_chart.xAxis.position = XAxis.XAxisPosition.BOTTOM
- additives_chart.xAxis.textColor = R.attr.colorOnSurface.resolveColor(context!!)
- additives_chart.xAxis.valueFormatter = object : ValueFormatter()
- {
- override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ axisRight.setDrawLabels(false)
+ axisRight.setDrawGridLines(false)
+ axisRight.setDrawAxisLine(false)
+
+ xAxis.setDrawGridLines(false)
+ xAxis.granularity = 1f
+ xAxis.position = XAxis.XAxisPosition.BOTTOM
+ xAxis.yOffset = 10f
+ xAxis.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ xAxis.valueFormatter = object : ValueFormatter()
{
- return additiveDates.getOrNull(value.toInt())?.transform {
- "${total}/${day}${getString(stage.printString).toLowerCase()[0]}"
- } ?: ""
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return additiveDates.getOrNull(value.toInt())?.transform {
+ "${total}/${day}${getString(stage.printString).toLowerCase()[0]}"
+ } ?: ""
+ }
}
+
+ legend.setCustom(entries)
+ legend.form = Legend.LegendForm.CIRCLE
+ legend.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ legend.isWordWrapEnabled = true
+ legend.yOffset = 10f
+ legend.xOffset = 10f
}
- additives_chart.legend.textColor = R.attr.colorOnSurface.resolveColor(context!!)
- additives_chart.legend.isWordWrapEnabled = true
- additives_chart.legend.setCustom(arrayListOf())
+ with (additives_overtime_chart) {
+ drawOrder = arrayOf(
+ DrawOrder.BAR, DrawOrder.LINE
+ )
+ setVisibleYRangeMaximum(totalMax.toFloat(), YAxis.AxisDependency.LEFT)
+ setDrawGridBackground(false)
+ description = null
+ isScaleYEnabled = false
+ setDrawBorders(false)
+
+ axisLeft.granularity = 1f
+ axisLeft.setDrawGridLines(false)
+ axisLeft.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ axisLeft.valueFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return "${value.formatWhole()}${selectedMeasurementUnit.label}"
+ }
+ }
+
+ axisRight.setDrawLabels(false)
+ axisRight.setDrawGridLines(false)
+ axisRight.setDrawAxisLine(false)
-// additives_count_chart.holeRadius = 10f
- additives_count_chart.description = null
- additives_count_chart.setHoleColor(0x00ffffff.toInt())
- additives_count_chart.legend.setCustom(arrayListOf())
+ xAxis.setDrawGridLines(false)
+ xAxis.granularity = 1f
+ xAxis.position = XAxis.XAxisPosition.BOTTOM
+ xAxis.yOffset = 10f
+ xAxis.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ xAxis.valueFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return additiveDates.getOrNull(value.toInt())?.transform {
+ "${total}/${day}${getString(stage.printString).toLowerCase()[0]}"
+ } ?: ""
+ }
+ }
+
+ legend.setCustom(entries)
+ legend.form = Legend.LegendForm.CIRCLE
+ legend.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ legend.isWordWrapEnabled = true
+ legend.yOffset = 10f
+ legend.xOffset = 10f
+ }
+
+ with (additives_count_chart) {
+ description = null
+ setHoleColor(0x00ffffff)
+ legend.setCustom(entries)
+ legend.form = Legend.LegendForm.CIRCLE
+ legend.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ legend.isWordWrapEnabled = true
+ }
- displayChart()
- displayTotalsChart()
- displayStats()
+ refreshCharts()
}
private fun renderStats(container: ViewGroup, templates: ArrayList)
diff --git a/app/src/main/java/me/anon/lib/Unit.java b/app/src/main/java/me/anon/lib/Unit.java
index b87535eb..aad0c1e9 100644
--- a/app/src/main/java/me/anon/lib/Unit.java
+++ b/app/src/main/java/me/anon/lib/Unit.java
@@ -3,9 +3,6 @@
import android.content.Context;
import android.preference.PreferenceManager;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-
/**
* Unit class used for measurement input
*/
@@ -177,7 +174,7 @@ public String getLabel()
public static Double toTwoDecimalPlaces(double input)
{
- return Double.isInfinite(input) || Double.isNaN(input) ? 0.0d : new BigDecimal(input).setScale(2, RoundingMode.HALF_EVEN).doubleValue();
+ return Double.isInfinite(input) || Double.isNaN(input) ? 0.0d : input;
}
/**
diff --git a/app/src/main/res/layout/statistics2_view.xml b/app/src/main/res/layout/statistics2_view.xml
index 6a445ebd..83bad141 100644
--- a/app/src/main/res/layout/statistics2_view.xml
+++ b/app/src/main/res/layout/statistics2_view.xml
@@ -83,17 +83,31 @@
/>
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index fb4ff925..c030fc39 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -443,8 +443,10 @@
%s stats
Ave. each feeding:
+ Times used:
Total amount:
+ Additive concentration
Additives over time
Additives distribution
From 327db42264035a63e3515f16519d0aecc02e7508 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sun, 26 Apr 2020 15:51:25 +0100
Subject: [PATCH 083/152] Adds pH stats
---
.../anon/grow/fragment/StatisticsFragment2.kt | 212 ++++++++++++++++--
.../main/java/me/anon/lib/ext/NumberUtils.kt | 20 ++
app/src/main/res/layout/data_label_stub.xml | 2 +-
app/src/main/res/layout/statistics2_view.xml | 51 +++++
4 files changed, 270 insertions(+), 15 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index 1c734f05..d09a7257 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -39,6 +39,7 @@ import kotlin.math.min
class StatisticsFragment2 : Fragment()
{
class StageDate(var day: Int, var total: Int, var stage: PlantStage)
+ class StatWrapper(var min: Double? = null, var max: Double? = null, var average: Double? = null)
open class template()
open class header(var label: String) : template()
@@ -85,10 +86,16 @@ class StatisticsFragment2 : Fragment()
}
val additives = hashMapOf>()
- val additiveDates = arrayListOf()
+ val waterDates = arrayListOf()
val additiveValues = hashMapOf>()
val additiveTotalValues = hashMapOf>()
+ val phValues = arrayListOf()
+ val phStats = StatWrapper()
+
+ val runoffValues = arrayListOf()
+ val runoffStats = StatWrapper()
+
var endDate = System.currentTimeMillis()
var waterDifference = 0L
var lastWater = 0L
@@ -111,12 +118,15 @@ class StatisticsFragment2 : Fragment()
calculateStats()
populateGeneralStats()
- populateAdditiveStates()
+ populateAdditiveStats()
+ populatePhStats()
}
private fun calculateStats()
{
- var additiveIndex = 0
+ val tempPhValues = arrayListOf()
+ val tempRunoffValues = arrayListOf()
+ var waterIndex = 0
plant.actions?.forEach { action ->
when (action)
{
@@ -137,8 +147,26 @@ class StatisticsFragment2 : Fragment()
val waterDate = action.date
val stageLength = (waterDate - stageChangeDate).toDays().toInt()
val totalDate = TimeHelper.toDays(action.date - plant.plantDate).toInt()
- aveStageWaters.getOrPut(stage, { arrayListOf() }).add(action.date)
- additiveDates.add(StageDate(stageLength, totalDate, stage))
+ waterDates.add(StageDate(stageLength, totalDate, stage))
+ aveStageWaters.getOrPut(stage, { arrayListOf() }).add(action.date)
+
+ // pH stats
+ action.ph?.let {
+ tempPhValues += it
+ phStats.max = max(phStats.max ?: Double.MIN_VALUE, it)
+ phStats.min = min(phStats.min ?: Double.MAX_VALUE, it)
+
+ phValues += Entry(waterIndex.toFloat(), it.toFloat())
+ }
+
+ // runoff stats
+ action.runoff?.let {
+ tempRunoffValues += it
+ runoffStats.max = max(runoffStats.max ?: Double.MIN_VALUE, it)
+ runoffStats.min = min(runoffStats.min ?: Double.MAX_VALUE, it)
+
+ runoffValues += Entry(waterIndex.toFloat(), it.toFloat())
+ }
// add additives to pre calculated list
action.additives.forEach { additive ->
@@ -147,7 +175,7 @@ class StatisticsFragment2 : Fragment()
additive.amount?.let { amount ->
with (additiveValues) {
val amount = Unit.ML.to(selectedMeasurementUnit, amount)
- val entry = Entry(additiveIndex.toFloat(), amount.toFloat())
+ val entry = Entry(waterIndex.toFloat(), amount.toFloat())
getOrPut(additive.description!!, { arrayListOf() }).add(entry)
}
@@ -155,14 +183,14 @@ class StatisticsFragment2 : Fragment()
val totalDelivery = Unit.ML.to(selectedDeliveryUnit, action.amount ?: 1000.0)
val additiveAmount = Unit.ML.to(selectedMeasurementUnit, amount)
- val entry = Entry(additiveIndex.toFloat(), Unit.toTwoDecimalPlaces(additiveAmount * totalDelivery).toFloat())
+ val entry = Entry(waterIndex.toFloat(), Unit.toTwoDecimalPlaces(additiveAmount * totalDelivery).toFloat())
getOrPut(additive.description!!, { arrayListOf() }).add(entry)
}
}
}
}
- additiveIndex++
+ waterIndex++
additives.getOrPut(action) { arrayListOf() }.addAll(action.additives)
}
@@ -171,6 +199,9 @@ class StatisticsFragment2 : Fragment()
}
}
}
+
+ phStats.average = if (tempPhValues.isNotEmpty()) tempPhValues.average() else null
+ runoffStats.average = if (tempRunoffValues.isNotEmpty()) tempRunoffValues.average() else null
}
private fun populateGeneralStats()
@@ -318,7 +349,7 @@ class StatisticsFragment2 : Fragment()
stage_chart.legend.isWordWrapEnabled = true
}
- private fun populateAdditiveStates()
+ private fun populateAdditiveStats()
{
class additiveStat(
var total: Double = 0.0,
@@ -389,7 +420,7 @@ class StatisticsFragment2 : Fragment()
}
val stageEntries = plantStages.keys.toList().asReversed()
- additiveDates.forEachIndexed { additiveIndex, date ->
+ waterDates.forEachIndexed { additiveIndex, date ->
barSets += BarDataSet(arrayListOf(BarEntry(additiveIndex.toFloat(), totalMax.toFloat())), null).apply {
color = ColorUtils.setAlphaComponent(statsColours[stageEntries.indexOf(date.stage) % statsColours.size], 127)
}
@@ -486,7 +517,7 @@ class StatisticsFragment2 : Fragment()
}
val stageEntries = plantStages.keys.toList().asReversed()
- additiveDates.forEachIndexed { additiveIndex, date ->
+ waterDates.forEachIndexed { additiveIndex, date ->
barSets += BarDataSet(arrayListOf(BarEntry(additiveIndex.toFloat(), totalMax.toFloat())), null).apply {
color = ColorUtils.setAlphaComponent(statsColours[stageEntries.indexOf(date.stage) % statsColours.size], 127)
}
@@ -606,7 +637,7 @@ class StatisticsFragment2 : Fragment()
{
override fun getAxisLabel(value: Float, axis: AxisBase?): String
{
- return additiveDates.getOrNull(value.toInt())?.transform {
+ return waterDates.getOrNull(value.toInt())?.transform {
"${total}/${day}${getString(stage.printString).toLowerCase()[0]}"
} ?: ""
}
@@ -654,7 +685,7 @@ class StatisticsFragment2 : Fragment()
{
override fun getAxisLabel(value: Float, axis: AxisBase?): String
{
- return additiveDates.getOrNull(value.toInt())?.transform {
+ return waterDates.getOrNull(value.toInt())?.transform {
"${total}/${day}${getString(stage.printString).toLowerCase()[0]}"
} ?: ""
}
@@ -680,6 +711,159 @@ class StatisticsFragment2 : Fragment()
refreshCharts()
}
+ private fun populatePhStats()
+ {
+ val INPUT_PH = R.string.stat_input_ph
+ val RUNOFF_PH = R.string.stat_runoff_ph
+ val AVERAGE_PH = R.string.stat_average_ph
+ val selectedModes = arrayListOf()
+
+ fun refreshCharts()
+ {
+ val sets = arrayListOf()
+
+ if (INPUT_PH in selectedModes)
+ {
+ sets += LineDataSet(phValues, getString(R.string.stat_input_ph)).apply {
+ color = statsColours[0]
+ fillColor = color
+ setCircleColor(color)
+ styleDataset(context!!, this, color)
+ }
+ }
+
+ if (RUNOFF_PH in selectedModes)
+ {
+ sets += LineDataSet(runoffValues, getString(R.string.stat_runoff_ph)).apply {
+ color = statsColours[1]
+ fillColor = color
+ setCircleColor(color)
+ styleDataset(context!!, this, color)
+ }
+ }
+
+ if (AVERAGE_PH in selectedModes)
+ {
+ val averageEntries = arrayListOf()
+ phValues.foldIndexed(0.0f) { index, acc, entry ->
+ if (acc > 0) averageEntries += Entry(index.toFloat(), acc / index)
+ entry.y + acc
+ }
+ sets += LineDataSet(averageEntries, getString(R.string.stat_average_ph)).apply {
+ color = ColorUtils.blendARGB(statsColours[0], 0xffffffff.toInt(), 0.4f)
+ setDrawCircles(false)
+ setDrawValues(false)
+ setDrawCircleHole(false)
+ setDrawHighlightIndicators(true)
+ cubicIntensity = 1f
+ lineWidth = 2.0f
+ isHighlightEnabled = false
+ }
+ }
+
+ input_ph.data = LineData(sets)
+ input_ph.notifyDataSetChanged()
+ input_ph.invalidate()
+ }
+
+ fun displayStats()
+ {
+ ph_stats_container.removeAllViews()
+
+ selectedModes.forEach { mode ->
+ val stats = arrayListOf()
+ stats += header(getString(mode))
+
+ val stat = when (mode)
+ {
+ INPUT_PH -> phStats
+ RUNOFF_PH -> runoffStats
+ else -> null
+ }
+
+ stat ?: return@forEach
+ stat.min?.let {
+ stats += data(
+ label = getString(R.string.min),
+ data = it.formatWhole()
+ )
+ }
+
+ stat.max?.let {
+ stats += data(
+ label = getString(R.string.max),
+ data = it.formatWhole()
+ )
+ }
+
+ stat.average?.let {
+ stats += data(
+ label = getString(R.string.ave),
+ data = it.formatWhole()
+ )
+ }
+
+ if (stats.size > 1) renderStats(ph_stats_container, stats)
+ }
+ }
+
+ arrayListOf(INPUT_PH, RUNOFF_PH, AVERAGE_PH).forEach { mode ->
+ val chip = LayoutInflater.from(context!!).inflate(R.layout.filter_chip_stub, additive_chips_container, false) as Chip
+ chip.setText(mode)
+ chip.isChecked = true
+ chip.setOnCheckedChangeListener { buttonView, isChecked ->
+ if (isChecked) selectedModes += mode
+ else selectedModes -= mode
+
+ refreshCharts()
+ displayStats()
+ }
+
+ selectedModes += mode
+ ph_chips_container += chip
+ }
+
+ with (input_ph) {
+ setVisibleYRangeMaximum(max(phStats.max?.toFloat() ?: 0.0f, runoffStats.max?.toFloat() ?: 0.0f), YAxis.AxisDependency.LEFT)
+ setDrawGridBackground(false)
+ description = null
+ isScaleYEnabled = false
+ setDrawBorders(false)
+
+ axisLeft.labelCount = 8
+ axisLeft.setDrawTopYLabelEntry(true)
+ axisLeft.setDrawZeroLine(true)
+ axisLeft.setDrawGridLines(false)
+ axisLeft.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+
+ axisRight.setDrawLabels(false)
+ axisRight.setDrawGridLines(false)
+ axisRight.setDrawAxisLine(false)
+
+ xAxis.setDrawGridLines(false)
+ xAxis.granularity = 1f
+ xAxis.position = XAxis.XAxisPosition.BOTTOM
+ xAxis.yOffset = 10f
+ xAxis.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ xAxis.valueFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return waterDates.getOrNull(value.toInt())?.transform {
+ "${total}/${day}${getString(stage.printString).toLowerCase()[0]}"
+ } ?: ""
+ }
+ }
+
+ legend.form = Legend.LegendForm.CIRCLE
+ legend.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ legend.isWordWrapEnabled = true
+ }
+
+ refreshCharts()
+ displayStats()
+ }
+
private fun renderStats(container: ViewGroup, templates: ArrayList)
{
templates.forEach { template ->
@@ -713,7 +897,7 @@ class StatisticsFragment2 : Fragment()
data.valueTextColor = R.attr.colorAccent.resolveColor(context)
data.setCircleColor(R.attr.colorAccent.resolveColor(context))
data.cubicIntensity = 0.2f
- data.lineWidth = 2.0f
+ data.lineWidth = 3.0f
data.setDrawCircleHole(true)
data.color = colour
data.setCircleColor(colour)
diff --git a/app/src/main/java/me/anon/lib/ext/NumberUtils.kt b/app/src/main/java/me/anon/lib/ext/NumberUtils.kt
index 2dfe9e6d..e52313c9 100644
--- a/app/src/main/java/me/anon/lib/ext/NumberUtils.kt
+++ b/app/src/main/java/me/anon/lib/ext/NumberUtils.kt
@@ -36,3 +36,23 @@ public fun Number.dip(context: Context): Float = TypedValue.applyDimension(Typed
public fun Number.sp(context: Context): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, this.toFloat(), context.resources.displayMetrics)
public fun Number.mm(context: Context): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, this.toFloat(), context.resources.displayMetrics)
public fun Number.pt(context: Context): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PT, this.toFloat(), context.resources.displayMetrics)
+
+public fun Double?.max(other: Double?): Double?
+{
+ return when
+ {
+ other == null -> this
+ this == null -> other
+ else -> kotlin.math.max(this, other)
+ }
+}
+
+public fun Double?.min(other: Double?): Double?
+{
+ return when
+ {
+ other == null -> this
+ this == null -> other
+ else -> kotlin.math.min(this, other)
+ }
+}
diff --git a/app/src/main/res/layout/data_label_stub.xml b/app/src/main/res/layout/data_label_stub.xml
index 9407e5a9..73d0402b 100644
--- a/app/src/main/res/layout/data_label_stub.xml
+++ b/app/src/main/res/layout/data_label_stub.xml
@@ -5,7 +5,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
- android:minWidth="160dp"
+ android:minWidth="120dp"
>
+
+
+
+
+
+
+
+
+
+
+
+
From 26b56397c2da9ced429382b1c1477cd0766e9438 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Mon, 27 Apr 2020 17:20:47 +0100
Subject: [PATCH 084/152] Adds basic TDS stats
---
.../anon/grow/fragment/StatisticsFragment2.kt | 193 ++++++++++++++++--
app/src/main/res/layout/statistics2_view.xml | 53 +++++
app/src/main/res/values/strings.xml | 2 +
3 files changed, 236 insertions(+), 12 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index d09a7257..d1616d9d 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -10,6 +10,7 @@ import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.graphics.ColorUtils
+import androidx.core.view.forEach
import androidx.core.view.plusAssign
import androidx.fragment.app.Fragment
import com.github.mikephil.charting.charts.CombinedChart.DrawOrder
@@ -29,6 +30,7 @@ import me.anon.lib.helper.StatsHelper.formatter
import me.anon.lib.helper.TimeHelper
import me.anon.model.*
import java.lang.Math.abs
+import kotlin.math.absoluteValue
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.min
@@ -40,6 +42,7 @@ class StatisticsFragment2 : Fragment()
{
class StageDate(var day: Int, var total: Int, var stage: PlantStage)
class StatWrapper(var min: Double? = null, var max: Double? = null, var average: Double? = null)
+ class StageEntry(var dateIndex: Int, x: Float, y: Float): Entry(x, y)
open class template()
open class header(var label: String) : template()
@@ -87,15 +90,18 @@ class StatisticsFragment2 : Fragment()
val additives = hashMapOf>()
val waterDates = arrayListOf()
- val additiveValues = hashMapOf>()
- val additiveTotalValues = hashMapOf>()
+ val additiveValues = hashMapOf>()
+ val additiveTotalValues = hashMapOf>()
- val phValues = arrayListOf()
+ val phValues = arrayListOf()
val phStats = StatWrapper()
- val runoffValues = arrayListOf()
+ val runoffValues = arrayListOf()
val runoffStats = StatWrapper()
+ val tdsValues = hashMapOf>()
+ val tdsStats = hashMapOf()
+
var endDate = System.currentTimeMillis()
var waterDifference = 0L
var lastWater = 0L
@@ -120,12 +126,14 @@ class StatisticsFragment2 : Fragment()
populateGeneralStats()
populateAdditiveStats()
populatePhStats()
+ populateTdsStats()
}
private fun calculateStats()
{
val tempPhValues = arrayListOf()
val tempRunoffValues = arrayListOf()
+ val tempTdsValues = hashMapOf>()
var waterIndex = 0
plant.actions?.forEach { action ->
when (action)
@@ -156,7 +164,7 @@ class StatisticsFragment2 : Fragment()
phStats.max = max(phStats.max ?: Double.MIN_VALUE, it)
phStats.min = min(phStats.min ?: Double.MAX_VALUE, it)
- phValues += Entry(waterIndex.toFloat(), it.toFloat())
+ phValues += StageEntry(waterDates.size - 1, waterIndex.toFloat(), it.toFloat())
}
// runoff stats
@@ -165,7 +173,20 @@ class StatisticsFragment2 : Fragment()
runoffStats.max = max(runoffStats.max ?: Double.MIN_VALUE, it)
runoffStats.min = min(runoffStats.min ?: Double.MAX_VALUE, it)
- runoffValues += Entry(waterIndex.toFloat(), it.toFloat())
+ runoffValues += StageEntry(waterDates.size - 1, waterIndex.toFloat(), it.toFloat())
+ }
+
+ // tds stats
+ action.tds?.let { tds ->
+ tds.amount?.let { amount ->
+ tempTdsValues.getOrPut(tds.type) { arrayListOf() }.add(amount)
+ tdsStats.getOrPut(tds.type) { StatWrapper() }.apply {
+ this.max = max(this.max ?: Double.MIN_VALUE, amount)
+ this.min = min(this.min ?: Double.MAX_VALUE, amount)
+ }
+
+ tdsValues.getOrPut(tds.type) { arrayListOf() }.add(StageEntry(waterDates.size - 1, waterIndex.toFloat(), amount.toFloat()))
+ }
}
// add additives to pre calculated list
@@ -175,7 +196,7 @@ class StatisticsFragment2 : Fragment()
additive.amount?.let { amount ->
with (additiveValues) {
val amount = Unit.ML.to(selectedMeasurementUnit, amount)
- val entry = Entry(waterIndex.toFloat(), amount.toFloat())
+ val entry = StageEntry(waterDates.size - 1, waterIndex.toFloat(), amount.toFloat())
getOrPut(additive.description!!, { arrayListOf() }).add(entry)
}
@@ -183,7 +204,7 @@ class StatisticsFragment2 : Fragment()
val totalDelivery = Unit.ML.to(selectedDeliveryUnit, action.amount ?: 1000.0)
val additiveAmount = Unit.ML.to(selectedMeasurementUnit, amount)
- val entry = Entry(waterIndex.toFloat(), Unit.toTwoDecimalPlaces(additiveAmount * totalDelivery).toFloat())
+ val entry = StageEntry(waterDates.size - 1, waterIndex.toFloat(), Unit.toTwoDecimalPlaces(additiveAmount * totalDelivery).toFloat())
getOrPut(additive.description!!, { arrayListOf() }).add(entry)
}
}
@@ -202,6 +223,11 @@ class StatisticsFragment2 : Fragment()
phStats.average = if (tempPhValues.isNotEmpty()) tempPhValues.average() else null
runoffStats.average = if (tempRunoffValues.isNotEmpty()) tempRunoffValues.average() else null
+ tdsStats.forEach { (k, v) ->
+ tempTdsValues[k]?.let {
+ tdsStats[k]?.average = if (it.isNotEmpty()) it.average() else null
+ }
+ }
}
private fun populateGeneralStats()
@@ -406,7 +432,7 @@ class StatisticsFragment2 : Fragment()
it.forEach { (k, v) ->
if (selectedAdditives.contains(k))
{
- dataSets += LineDataSet(v, k).apply {
+ dataSets += LineDataSet(v as List, k).apply {
color = statsColours[index]
fillColor = color
setCircleColor(color)
@@ -724,7 +750,7 @@ class StatisticsFragment2 : Fragment()
if (INPUT_PH in selectedModes)
{
- sets += LineDataSet(phValues, getString(R.string.stat_input_ph)).apply {
+ sets += LineDataSet(phValues as List, getString(R.string.stat_input_ph)).apply {
color = statsColours[0]
fillColor = color
setCircleColor(color)
@@ -734,7 +760,7 @@ class StatisticsFragment2 : Fragment()
if (RUNOFF_PH in selectedModes)
{
- sets += LineDataSet(runoffValues, getString(R.string.stat_runoff_ph)).apply {
+ sets += LineDataSet(runoffValues as List, getString(R.string.stat_runoff_ph)).apply {
color = statsColours[1]
fillColor = color
setCircleColor(color)
@@ -808,7 +834,7 @@ class StatisticsFragment2 : Fragment()
}
arrayListOf(INPUT_PH, RUNOFF_PH, AVERAGE_PH).forEach { mode ->
- val chip = LayoutInflater.from(context!!).inflate(R.layout.filter_chip_stub, additive_chips_container, false) as Chip
+ val chip = LayoutInflater.from(context!!).inflate(R.layout.filter_chip_stub, ph_chips_container, false) as Chip
chip.setText(mode)
chip.isChecked = true
chip.setOnCheckedChangeListener { buttonView, isChecked ->
@@ -864,6 +890,149 @@ class StatisticsFragment2 : Fragment()
displayStats()
}
+ private fun populateTdsStats()
+ {
+ var selectedUnit: TdsUnit = selectedTdsUnit
+
+ fun refreshCharts()
+ {
+ val sets = arrayListOf()
+ var index = 0
+
+ tdsValues[selectedUnit]?.let {
+ sets += LineDataSet(it as List, getString(selectedUnit.strRes)).apply {
+ color = statsColours[tdsValues.keys.indexOfFirst { it == selectedUnit }.absoluteValue % statsColours.size]
+ fillColor = color
+ setCircleColor(color)
+ styleDataset(context!!, this, color)
+ }
+ }
+
+ val averageEntries = arrayListOf()
+ tdsValues[selectedUnit]?.let { values ->
+ values.foldIndexed(0.0f) { index, acc, entry ->
+ if (acc > 0) averageEntries += Entry(index.toFloat(), acc / index)
+ entry.y + acc
+ }
+
+ sets += LineDataSet(averageEntries, getString(R.string.stat_average_tds, selectedTdsUnit.label)).apply {
+ color = ColorUtils.blendARGB(statsColours[tdsValues.keys.indexOfFirst { it == selectedUnit }.absoluteValue % statsColours.size], 0xffffffff.toInt(), 0.4f)
+ setDrawCircles(false)
+ setDrawValues(false)
+ setDrawCircleHole(false)
+ setDrawHighlightIndicators(true)
+ cubicIntensity = 1f
+ lineWidth = 2.0f
+ isHighlightEnabled = false
+ }
+ }
+
+ tds_chart.data = LineData(sets)
+ tds_chart.notifyDataSetChanged()
+ tds_chart.invalidate()
+ }
+
+ fun displayStats()
+ {
+ tds_stats_container.removeAllViews()
+
+ tdsStats[selectedUnit]?.let { stat ->
+ val stats = arrayListOf()
+ stats += header(getString(selectedUnit.strRes))
+
+ stat.min?.let {
+ stats += data(
+ label = getString(R.string.min),
+ data = it.formatWhole()
+ )
+ }
+
+ stat.max?.let {
+ stats += data(
+ label = getString(R.string.max),
+ data = it.formatWhole()
+ )
+ }
+
+ stat.average?.let {
+ stats += data(
+ label = getString(R.string.ave),
+ data = it.formatWhole()
+ )
+ }
+
+ if (stats.size > 1) renderStats(tds_stats_container, stats)
+ }
+ }
+
+ val values = TdsUnit.values().filter { it in tdsValues.keys }
+ if (values.size > 1)
+ {
+ values.forEach { unit ->
+ val chip = LayoutInflater.from(context!!).inflate(R.layout.filter_chip_stub, tds_chips_container, false) as Chip
+ chip.setText(unit.strRes)
+ chip.isCheckable = true
+ chip.id = unit.strRes
+
+ chip.setOnCheckedChangeListener { buttonView, isChecked ->
+ if (isChecked) selectedUnit = unit
+
+ refreshCharts()
+ displayStats()
+ }
+
+ tds_chips_container += chip
+ }
+
+ tds_chips_container.check(selectedUnit.strRes)
+ }
+ else
+ {
+ tds_chips_container.isVisible = false
+ selectedUnit = values.firstOrNull() ?: selectedTdsUnit
+ }
+
+ with (tds_chart) {
+// setVisibleYRangeMaximum(max(phStats.max?.toFloat() ?: 0.0f, runoffStats.max?.toFloat() ?: 0.0f), YAxis.AxisDependency.LEFT)
+ setDrawGridBackground(false)
+ description = null
+ isScaleYEnabled = false
+ setDrawBorders(false)
+
+ axisLeft.labelCount = 8
+ axisLeft.setDrawTopYLabelEntry(true)
+ axisLeft.setDrawZeroLine(true)
+ axisLeft.setDrawGridLines(false)
+ axisLeft.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+
+ axisRight.setDrawLabels(false)
+ axisRight.setDrawGridLines(false)
+ axisRight.setDrawAxisLine(false)
+
+ xAxis.setDrawGridLines(false)
+ xAxis.granularity = 1f
+ xAxis.position = XAxis.XAxisPosition.BOTTOM
+ xAxis.yOffset = 10f
+ xAxis.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ xAxis.valueFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return waterDates.getOrNull(value.toInt())?.transform {
+ "${total}/${day}${getString(stage.printString).toLowerCase()[0]}"
+ } ?: ""
+ }
+ }
+
+ legend.form = Legend.LegendForm.CIRCLE
+ legend.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ legend.isWordWrapEnabled = true
+ }
+
+ refreshCharts()
+ displayStats()
+ }
+
private fun renderStats(container: ViewGroup, templates: ArrayList)
{
templates.forEach { template ->
diff --git a/app/src/main/res/layout/statistics2_view.xml b/app/src/main/res/layout/statistics2_view.xml
index 574f9a97..099c3168 100644
--- a/app/src/main/res/layout/statistics2_view.xml
+++ b/app/src/main/res/layout/statistics2_view.xml
@@ -191,6 +191,59 @@
app:dividerDrawableVertical="@drawable/divider_8dp"
/>
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c030fc39..186d847e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -151,6 +151,7 @@
Ave. %s water:
Filter additives
pH
+ TDS
Min:
Max:
@@ -272,6 +273,7 @@
Input pH
Runoff pH
Average pH
+ Average %s
Plant photos
From 7fc50288ee137d79518138c6cfb998f93410c14b Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Mon, 27 Apr 2020 17:36:29 +0100
Subject: [PATCH 085/152] Fixes averages
---
.../anon/grow/fragment/StatisticsFragment2.kt | 56 ++++++++++---------
1 file changed, 30 insertions(+), 26 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index d1616d9d..ae413178 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -42,7 +42,6 @@ class StatisticsFragment2 : Fragment()
{
class StageDate(var day: Int, var total: Int, var stage: PlantStage)
class StatWrapper(var min: Double? = null, var max: Double? = null, var average: Double? = null)
- class StageEntry(var dateIndex: Int, x: Float, y: Float): Entry(x, y)
open class template()
open class header(var label: String) : template()
@@ -90,16 +89,16 @@ class StatisticsFragment2 : Fragment()
val additives = hashMapOf>()
val waterDates = arrayListOf()
- val additiveValues = hashMapOf>()
- val additiveTotalValues = hashMapOf>()
+ val additiveValues = hashMapOf>()
+ val additiveTotalValues = hashMapOf>()
- val phValues = arrayListOf()
+ val phValues = arrayListOf()
val phStats = StatWrapper()
- val runoffValues = arrayListOf()
+ val runoffValues = arrayListOf()
val runoffStats = StatWrapper()
- val tdsValues = hashMapOf>()
+ val tdsValues = hashMapOf>()
val tdsStats = hashMapOf()
var endDate = System.currentTimeMillis()
@@ -164,7 +163,7 @@ class StatisticsFragment2 : Fragment()
phStats.max = max(phStats.max ?: Double.MIN_VALUE, it)
phStats.min = min(phStats.min ?: Double.MAX_VALUE, it)
- phValues += StageEntry(waterDates.size - 1, waterIndex.toFloat(), it.toFloat())
+ phValues += Entry(waterIndex.toFloat(), it.toFloat())
}
// runoff stats
@@ -173,7 +172,7 @@ class StatisticsFragment2 : Fragment()
runoffStats.max = max(runoffStats.max ?: Double.MIN_VALUE, it)
runoffStats.min = min(runoffStats.min ?: Double.MAX_VALUE, it)
- runoffValues += StageEntry(waterDates.size - 1, waterIndex.toFloat(), it.toFloat())
+ runoffValues += Entry(waterIndex.toFloat(), it.toFloat())
}
// tds stats
@@ -185,7 +184,7 @@ class StatisticsFragment2 : Fragment()
this.min = min(this.min ?: Double.MAX_VALUE, amount)
}
- tdsValues.getOrPut(tds.type) { arrayListOf() }.add(StageEntry(waterDates.size - 1, waterIndex.toFloat(), amount.toFloat()))
+ tdsValues.getOrPut(tds.type) { arrayListOf() }.add(Entry(waterIndex.toFloat(), amount.toFloat()))
}
}
@@ -196,7 +195,7 @@ class StatisticsFragment2 : Fragment()
additive.amount?.let { amount ->
with (additiveValues) {
val amount = Unit.ML.to(selectedMeasurementUnit, amount)
- val entry = StageEntry(waterDates.size - 1, waterIndex.toFloat(), amount.toFloat())
+ val entry = Entry(waterIndex.toFloat(), amount.toFloat())
getOrPut(additive.description!!, { arrayListOf() }).add(entry)
}
@@ -204,7 +203,7 @@ class StatisticsFragment2 : Fragment()
val totalDelivery = Unit.ML.to(selectedDeliveryUnit, action.amount ?: 1000.0)
val additiveAmount = Unit.ML.to(selectedMeasurementUnit, amount)
- val entry = StageEntry(waterDates.size - 1, waterIndex.toFloat(), Unit.toTwoDecimalPlaces(additiveAmount * totalDelivery).toFloat())
+ val entry = Entry(waterIndex.toFloat(), Unit.toTwoDecimalPlaces(additiveAmount * totalDelivery).toFloat())
getOrPut(additive.description!!, { arrayListOf() }).add(entry)
}
}
@@ -432,7 +431,7 @@ class StatisticsFragment2 : Fragment()
it.forEach { (k, v) ->
if (selectedAdditives.contains(k))
{
- dataSets += LineDataSet(v as List, k).apply {
+ dataSets += LineDataSet(v, k).apply {
color = statsColours[index]
fillColor = color
setCircleColor(color)
@@ -750,7 +749,7 @@ class StatisticsFragment2 : Fragment()
if (INPUT_PH in selectedModes)
{
- sets += LineDataSet(phValues as List, getString(R.string.stat_input_ph)).apply {
+ sets += LineDataSet(phValues, getString(R.string.stat_input_ph)).apply {
color = statsColours[0]
fillColor = color
setCircleColor(color)
@@ -760,7 +759,7 @@ class StatisticsFragment2 : Fragment()
if (RUNOFF_PH in selectedModes)
{
- sets += LineDataSet(runoffValues as List, getString(R.string.stat_runoff_ph)).apply {
+ sets += LineDataSet(runoffValues, getString(R.string.stat_runoff_ph)).apply {
color = statsColours[1]
fillColor = color
setCircleColor(color)
@@ -771,9 +770,12 @@ class StatisticsFragment2 : Fragment()
if (AVERAGE_PH in selectedModes)
{
val averageEntries = arrayListOf()
- phValues.foldIndexed(0.0f) { index, acc, entry ->
- if (acc > 0) averageEntries += Entry(index.toFloat(), acc / index)
- entry.y + acc
+ if (phValues.isNotEmpty())
+ {
+ phValues.foldIndexed(phValues.first().y) { index, acc, entry ->
+ averageEntries += Entry(phValues[index].x.toFloat(), acc / (index + 1))
+ entry.y + acc
+ }
}
sets += LineDataSet(averageEntries, getString(R.string.stat_average_ph)).apply {
color = ColorUtils.blendARGB(statsColours[0], 0xffffffff.toInt(), 0.4f)
@@ -899,23 +901,24 @@ class StatisticsFragment2 : Fragment()
val sets = arrayListOf()
var index = 0
- tdsValues[selectedUnit]?.let {
- sets += LineDataSet(it as List, getString(selectedUnit.strRes)).apply {
+ tdsValues[selectedUnit]?.let { values ->
+ sets += LineDataSet(values, getString(selectedUnit.strRes)).apply {
color = statsColours[tdsValues.keys.indexOfFirst { it == selectedUnit }.absoluteValue % statsColours.size]
fillColor = color
setCircleColor(color)
styleDataset(context!!, this, color)
}
- }
- val averageEntries = arrayListOf()
- tdsValues[selectedUnit]?.let { values ->
- values.foldIndexed(0.0f) { index, acc, entry ->
- if (acc > 0) averageEntries += Entry(index.toFloat(), acc / index)
- entry.y + acc
+ val averageEntries = arrayListOf()
+ if (values.isNotEmpty())
+ {
+ values.foldIndexed(values.first().y) { index, acc, entry ->
+ averageEntries += Entry(values[index].x.toFloat(), acc / (index + 1))
+ entry.y + acc
+ }
}
- sets += LineDataSet(averageEntries, getString(R.string.stat_average_tds, selectedTdsUnit.label)).apply {
+ sets += LineDataSet(averageEntries, getString(R.string.stat_average_tds, selectedUnit.label)).apply {
color = ColorUtils.blendARGB(statsColours[tdsValues.keys.indexOfFirst { it == selectedUnit }.absoluteValue % statsColours.size], 0xffffffff.toInt(), 0.4f)
setDrawCircles(false)
setDrawValues(false)
@@ -929,6 +932,7 @@ class StatisticsFragment2 : Fragment()
tds_chart.data = LineData(sets)
tds_chart.notifyDataSetChanged()
+ tds_chart.fitScreen()
tds_chart.invalidate()
}
From 8c1f659412738b0c5c90d63bb4603b4c3225ff28 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Mon, 27 Apr 2020 20:58:42 +0100
Subject: [PATCH 086/152] Code tidyups
---
.../anon/grow/fragment/StatisticsFragment2.kt | 252 ++++--------------
app/src/main/java/me/anon/lib/ext/EntryExt.kt | 51 ++++
app/src/main/res/layout/statistics2_view.xml | 56 ++--
app/src/main/res/values/strings.xml | 1 +
4 files changed, 130 insertions(+), 230 deletions(-)
create mode 100644 app/src/main/java/me/anon/lib/ext/EntryExt.kt
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index ae413178..dee26aec 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -10,11 +10,12 @@ import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.graphics.ColorUtils
-import androidx.core.view.forEach
import androidx.core.view.plusAssign
import androidx.fragment.app.Fragment
-import com.github.mikephil.charting.charts.CombinedChart.DrawOrder
-import com.github.mikephil.charting.components.*
+import com.github.mikephil.charting.components.AxisBase
+import com.github.mikephil.charting.components.Legend
+import com.github.mikephil.charting.components.LegendEntry
+import com.github.mikephil.charting.components.YAxis
import com.github.mikephil.charting.data.*
import com.github.mikephil.charting.formatter.ValueFormatter
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet
@@ -108,6 +109,16 @@ class StatisticsFragment2 : Fragment()
var totalWaterAmount = 0.0
var totalFlush = 0
+ val datesFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return waterDates.getOrNull(value.toInt())?.transform {
+ "${total}/${day}${getString(stage.printString).toLowerCase()[0]}"
+ } ?: ""
+ }
+ }
+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
= inflater.inflate(R.layout.statistics2_view, container, false)
@@ -325,7 +336,7 @@ class StatisticsFragment2 : Fragment()
val stageData = BarDataSet(stageEntries, "")
stageData.isHighlightEnabled = false
stageData.stackLabels = labels
- stageData.setColors(statsColours)
+ stageData.colors = statsColours
stageData.valueTypeface = Typeface.DEFAULT_BOLD
stageData.valueTextSize = 10f
stageData.valueFormatter = object : ValueFormatter()
@@ -376,7 +387,7 @@ class StatisticsFragment2 : Fragment()
private fun populateAdditiveStats()
{
- class additiveStat(
+ class AdditiveStat(
var total: Double = 0.0,
var totalAdjusted: Double = 0.0,
var count: Int = 0,
@@ -385,7 +396,7 @@ class StatisticsFragment2 : Fragment()
)
val selectedAdditives = arrayListOf()
- val additiveStats = LinkedHashMap()
+ val additiveStats = LinkedHashMap()
var totalMax = Double.MIN_VALUE
fun displayStats()
@@ -424,7 +435,6 @@ class StatisticsFragment2 : Fragment()
fun displayConcentrationChart()
{
- val barSets = arrayListOf()
val dataSets = arrayListOf()
var index = 0
additiveValues.toSortedMap().let {
@@ -444,25 +454,9 @@ class StatisticsFragment2 : Fragment()
}
}
- val stageEntries = plantStages.keys.toList().asReversed()
- waterDates.forEachIndexed { additiveIndex, date ->
- barSets += BarDataSet(arrayListOf(BarEntry(additiveIndex.toFloat(), totalMax.toFloat())), null).apply {
- color = ColorUtils.setAlphaComponent(statsColours[stageEntries.indexOf(date.stage) % statsColours.size], 127)
- }
- }
-
val lineData = LineData(dataSets)
- val barData = BarData(barSets).apply {
- setDrawValues(false)
- this.isHighlightEnabled = false
- this.barWidth = 1.0f
- this.groupBars(0f, 0f, 0f)
- }
- val data = CombinedData()
- //data.setData(barData)
- data.setData(lineData)
- additives_concentration_chart.data = data
+ additives_concentration_chart.data = lineData
additives_concentration_chart.notifyDataSetChanged()
additives_concentration_chart.invalidate()
}
@@ -549,17 +543,8 @@ class StatisticsFragment2 : Fragment()
}
val lineData = LineData(dataSets)
- val barData = BarData(barSets).apply {
- setDrawValues(false)
- this.isHighlightEnabled = false
- this.barWidth = 1.0f
- this.groupBars(0f, 0f, 0f)
- }
- val data = CombinedData()
- //data.setData(barData)
- data.setData(lineData)
- additives_overtime_chart.data = data
+ additives_overtime_chart.data = lineData
additives_overtime_chart.notifyDataSetChanged()
additives_overtime_chart.invalidate()
}
@@ -575,7 +560,7 @@ class StatisticsFragment2 : Fragment()
additives.keys.forEach { water ->
additives[water]?.sortedBy { it.description }?.forEach { additive ->
additive.description?.let { key ->
- additiveStats.getOrPut(key, { additiveStat() }).apply {
+ additiveStats.getOrPut(key, { AdditiveStat() }).apply {
total += additive.amount ?: 0.0
min = min(min.isNaN() T Double.MAX_VALUE ?: min, additive.amount ?: 0.0)
max = max(max.isNaN() T Double.MIN_VALUE ?: max, additive.amount ?: 0.0)
@@ -629,18 +614,10 @@ class StatisticsFragment2 : Fragment()
}
with (additives_concentration_chart) {
- drawOrder = arrayOf(
- DrawOrder.BAR, DrawOrder.LINE
- )
setVisibleYRangeMaximum(totalMax.toFloat(), YAxis.AxisDependency.LEFT)
- setDrawGridBackground(false)
- description = null
- isScaleYEnabled = false
- setDrawBorders(false)
+ style()
axisLeft.granularity = 1f
- axisLeft.setDrawGridLines(false)
- axisLeft.textColor = R.attr.colorOnSurface.resolveColor(context!!)
axisLeft.valueFormatter = object : ValueFormatter()
{
override fun getAxisLabel(value: Float, axis: AxisBase?): String
@@ -649,77 +626,29 @@ class StatisticsFragment2 : Fragment()
}
}
- axisRight.setDrawLabels(false)
- axisRight.setDrawGridLines(false)
- axisRight.setDrawAxisLine(false)
-
- xAxis.setDrawGridLines(false)
- xAxis.granularity = 1f
- xAxis.position = XAxis.XAxisPosition.BOTTOM
- xAxis.yOffset = 10f
- xAxis.textColor = R.attr.colorOnSurface.resolveColor(context!!)
- xAxis.valueFormatter = object : ValueFormatter()
- {
- override fun getAxisLabel(value: Float, axis: AxisBase?): String
- {
- return waterDates.getOrNull(value.toInt())?.transform {
- "${total}/${day}${getString(stage.printString).toLowerCase()[0]}"
- } ?: ""
- }
- }
+ xAxis.valueFormatter = datesFormatter
legend.setCustom(entries)
- legend.form = Legend.LegendForm.CIRCLE
- legend.textColor = R.attr.colorOnSurface.resolveColor(context!!)
- legend.isWordWrapEnabled = true
legend.yOffset = 10f
legend.xOffset = 10f
}
with (additives_overtime_chart) {
- drawOrder = arrayOf(
- DrawOrder.BAR, DrawOrder.LINE
- )
setVisibleYRangeMaximum(totalMax.toFloat(), YAxis.AxisDependency.LEFT)
- setDrawGridBackground(false)
- description = null
- isScaleYEnabled = false
- setDrawBorders(false)
+ style()
axisLeft.granularity = 1f
- axisLeft.setDrawGridLines(false)
- axisLeft.textColor = R.attr.colorOnSurface.resolveColor(context!!)
axisLeft.valueFormatter = object : ValueFormatter()
{
override fun getAxisLabel(value: Float, axis: AxisBase?): String
{
- return "${value.formatWhole()}${selectedMeasurementUnit.label}"
+ return "${value.formatWhole()}${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
}
}
- axisRight.setDrawLabels(false)
- axisRight.setDrawGridLines(false)
- axisRight.setDrawAxisLine(false)
-
- xAxis.setDrawGridLines(false)
- xAxis.granularity = 1f
- xAxis.position = XAxis.XAxisPosition.BOTTOM
- xAxis.yOffset = 10f
- xAxis.textColor = R.attr.colorOnSurface.resolveColor(context!!)
- xAxis.valueFormatter = object : ValueFormatter()
- {
- override fun getAxisLabel(value: Float, axis: AxisBase?): String
- {
- return waterDates.getOrNull(value.toInt())?.transform {
- "${total}/${day}${getString(stage.printString).toLowerCase()[0]}"
- } ?: ""
- }
- }
+ xAxis.valueFormatter = datesFormatter
legend.setCustom(entries)
- legend.form = Legend.LegendForm.CIRCLE
- legend.textColor = R.attr.colorOnSurface.resolveColor(context!!)
- legend.isWordWrapEnabled = true
legend.yOffset = 10f
legend.xOffset = 10f
}
@@ -755,6 +684,20 @@ class StatisticsFragment2 : Fragment()
setCircleColor(color)
styleDataset(context!!, this, color)
}
+
+ if (AVERAGE_PH in selectedModes)
+ {
+ sets += LineDataSet(phValues.rollingAverage(), getString(R.string.stat_average_runoff_ph)).apply {
+ color = ColorUtils.blendARGB(statsColours[0], 0xffffffff.toInt(), 0.4f)
+ setDrawCircles(false)
+ setDrawValues(false)
+ setDrawCircleHole(false)
+ setDrawHighlightIndicators(true)
+ cubicIntensity = 1f
+ lineWidth = 2.0f
+ isHighlightEnabled = false
+ }
+ }
}
if (RUNOFF_PH in selectedModes)
@@ -765,28 +708,20 @@ class StatisticsFragment2 : Fragment()
setCircleColor(color)
styleDataset(context!!, this, color)
}
- }
- if (AVERAGE_PH in selectedModes)
- {
- val averageEntries = arrayListOf()
- if (phValues.isNotEmpty())
+ if (AVERAGE_PH in selectedModes)
{
- phValues.foldIndexed(phValues.first().y) { index, acc, entry ->
- averageEntries += Entry(phValues[index].x.toFloat(), acc / (index + 1))
- entry.y + acc
+ sets += LineDataSet(runoffValues.rollingAverage(), getString(R.string.stat_average_runoff_ph)).apply {
+ color = ColorUtils.blendARGB(statsColours[1], 0xffffffff.toInt(), 0.4f)
+ setDrawCircles(false)
+ setDrawValues(false)
+ setDrawCircleHole(false)
+ setDrawHighlightIndicators(true)
+ cubicIntensity = 1f
+ lineWidth = 2.0f
+ isHighlightEnabled = false
}
}
- sets += LineDataSet(averageEntries, getString(R.string.stat_average_ph)).apply {
- color = ColorUtils.blendARGB(statsColours[0], 0xffffffff.toInt(), 0.4f)
- setDrawCircles(false)
- setDrawValues(false)
- setDrawCircleHole(false)
- setDrawHighlightIndicators(true)
- cubicIntensity = 1f
- lineWidth = 2.0f
- isHighlightEnabled = false
- }
}
input_ph.data = LineData(sets)
@@ -835,7 +770,11 @@ class StatisticsFragment2 : Fragment()
}
}
- arrayListOf(INPUT_PH, RUNOFF_PH, AVERAGE_PH).forEach { mode ->
+ arrayListOf().apply {
+ if (phValues.isNotEmpty()) add(INPUT_PH)
+ if (runoffValues.isNotEmpty()) add(RUNOFF_PH)
+ if (isNotEmpty()) add(AVERAGE_PH)
+ }.forEach { mode ->
val chip = LayoutInflater.from(context!!).inflate(R.layout.filter_chip_stub, ph_chips_container, false) as Chip
chip.setText(mode)
chip.isChecked = true
@@ -853,39 +792,8 @@ class StatisticsFragment2 : Fragment()
with (input_ph) {
setVisibleYRangeMaximum(max(phStats.max?.toFloat() ?: 0.0f, runoffStats.max?.toFloat() ?: 0.0f), YAxis.AxisDependency.LEFT)
- setDrawGridBackground(false)
- description = null
- isScaleYEnabled = false
- setDrawBorders(false)
-
- axisLeft.labelCount = 8
- axisLeft.setDrawTopYLabelEntry(true)
- axisLeft.setDrawZeroLine(true)
- axisLeft.setDrawGridLines(false)
- axisLeft.textColor = R.attr.colorOnSurface.resolveColor(context!!)
-
- axisRight.setDrawLabels(false)
- axisRight.setDrawGridLines(false)
- axisRight.setDrawAxisLine(false)
-
- xAxis.setDrawGridLines(false)
- xAxis.granularity = 1f
- xAxis.position = XAxis.XAxisPosition.BOTTOM
- xAxis.yOffset = 10f
- xAxis.textColor = R.attr.colorOnSurface.resolveColor(context!!)
- xAxis.valueFormatter = object : ValueFormatter()
- {
- override fun getAxisLabel(value: Float, axis: AxisBase?): String
- {
- return waterDates.getOrNull(value.toInt())?.transform {
- "${total}/${day}${getString(stage.printString).toLowerCase()[0]}"
- } ?: ""
- }
- }
-
- legend.form = Legend.LegendForm.CIRCLE
- legend.textColor = R.attr.colorOnSurface.resolveColor(context!!)
- legend.isWordWrapEnabled = true
+ style()
+ xAxis.valueFormatter = datesFormatter
}
refreshCharts()
@@ -899,7 +807,6 @@ class StatisticsFragment2 : Fragment()
fun refreshCharts()
{
val sets = arrayListOf()
- var index = 0
tdsValues[selectedUnit]?.let { values ->
sets += LineDataSet(values, getString(selectedUnit.strRes)).apply {
@@ -909,16 +816,7 @@ class StatisticsFragment2 : Fragment()
styleDataset(context!!, this, color)
}
- val averageEntries = arrayListOf()
- if (values.isNotEmpty())
- {
- values.foldIndexed(values.first().y) { index, acc, entry ->
- averageEntries += Entry(values[index].x.toFloat(), acc / (index + 1))
- entry.y + acc
- }
- }
-
- sets += LineDataSet(averageEntries, getString(R.string.stat_average_tds, selectedUnit.label)).apply {
+ sets += LineDataSet(values.rollingAverage(), getString(R.string.stat_average_tds, selectedUnit.label)).apply {
color = ColorUtils.blendARGB(statsColours[tdsValues.keys.indexOfFirst { it == selectedUnit }.absoluteValue % statsColours.size], 0xffffffff.toInt(), 0.4f)
setDrawCircles(false)
setDrawValues(false)
@@ -997,40 +895,8 @@ class StatisticsFragment2 : Fragment()
}
with (tds_chart) {
-// setVisibleYRangeMaximum(max(phStats.max?.toFloat() ?: 0.0f, runoffStats.max?.toFloat() ?: 0.0f), YAxis.AxisDependency.LEFT)
- setDrawGridBackground(false)
- description = null
- isScaleYEnabled = false
- setDrawBorders(false)
-
- axisLeft.labelCount = 8
- axisLeft.setDrawTopYLabelEntry(true)
- axisLeft.setDrawZeroLine(true)
- axisLeft.setDrawGridLines(false)
- axisLeft.textColor = R.attr.colorOnSurface.resolveColor(context!!)
-
- axisRight.setDrawLabels(false)
- axisRight.setDrawGridLines(false)
- axisRight.setDrawAxisLine(false)
-
- xAxis.setDrawGridLines(false)
- xAxis.granularity = 1f
- xAxis.position = XAxis.XAxisPosition.BOTTOM
- xAxis.yOffset = 10f
- xAxis.textColor = R.attr.colorOnSurface.resolveColor(context!!)
- xAxis.valueFormatter = object : ValueFormatter()
- {
- override fun getAxisLabel(value: Float, axis: AxisBase?): String
- {
- return waterDates.getOrNull(value.toInt())?.transform {
- "${total}/${day}${getString(stage.printString).toLowerCase()[0]}"
- } ?: ""
- }
- }
-
- legend.form = Legend.LegendForm.CIRCLE
- legend.textColor = R.attr.colorOnSurface.resolveColor(context!!)
- legend.isWordWrapEnabled = true
+ style()
+ xAxis.valueFormatter = datesFormatter
}
refreshCharts()
diff --git a/app/src/main/java/me/anon/lib/ext/EntryExt.kt b/app/src/main/java/me/anon/lib/ext/EntryExt.kt
new file mode 100644
index 00000000..91b573d8
--- /dev/null
+++ b/app/src/main/java/me/anon/lib/ext/EntryExt.kt
@@ -0,0 +1,51 @@
+package me.anon.lib.ext
+
+import com.github.mikephil.charting.charts.LineChart
+import com.github.mikephil.charting.components.Legend
+import com.github.mikephil.charting.components.XAxis
+import com.github.mikephil.charting.data.Entry
+import me.anon.grow.R
+
+/**
+ * // TODO: Add class description
+ */
+public fun List.rollingAverage(): List
+{
+ val averageEntries = mutableListOf()
+
+ foldIndexed(0f) { index, acc, entry ->
+ val ret = entry.y + acc
+ averageEntries += Entry(this[index].x, ret / (index + 1))
+ ret
+ }
+
+ return averageEntries
+}
+
+public fun LineChart.style()
+{
+ setDrawGridBackground(false)
+ description = null
+ isScaleYEnabled = false
+ setDrawBorders(false)
+
+ axisLeft.labelCount = 8
+ axisLeft.setDrawTopYLabelEntry(true)
+ axisLeft.setDrawZeroLine(true)
+ axisLeft.setDrawGridLines(false)
+ axisLeft.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+
+ axisRight.setDrawLabels(false)
+ axisRight.setDrawGridLines(false)
+ axisRight.setDrawAxisLine(false)
+
+ xAxis.setDrawGridLines(false)
+ xAxis.granularity = 1f
+ xAxis.position = XAxis.XAxisPosition.BOTTOM
+ xAxis.yOffset = 10f
+ xAxis.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+
+ legend.form = Legend.LegendForm.CIRCLE
+ legend.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ legend.isWordWrapEnabled = true
+}
diff --git a/app/src/main/res/layout/statistics2_view.xml b/app/src/main/res/layout/statistics2_view.xml
index 099c3168..ee75434c 100644
--- a/app/src/main/res/layout/statistics2_view.xml
+++ b/app/src/main/res/layout/statistics2_view.xml
@@ -68,20 +68,14 @@
style="@style/SectionTitle"
/>
-
-
-
+ app:chipSpacing="4dp"
+ app:chipSpacingVertical="0dp"
+ />
-
-
-
-
-
+ app:chipSpacing="4dp"
+ app:chipSpacingVertical="0dp"
+ />
-
-
-
+ app:chipSpacing="4dp"
+ app:chipSpacingVertical="0dp"
+ app:singleSelection="true"
+ app:selectionRequired="true"
+ />
Input pH
Runoff pH
Average pH
+ Average runoff pH
Average %s
Plant photos
From 4dbac3464d665d3207b59aa8de27d2d913124138 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Mon, 27 Apr 2020 21:15:43 +0100
Subject: [PATCH 087/152] Adds temperature chart
---
.../anon/grow/fragment/StatisticsFragment2.kt | 82 +++++++++++++++++++
app/src/main/res/layout/statistics2_view.xml | 36 ++++++++
app/src/main/res/values/strings.xml | 1 +
3 files changed, 119 insertions(+)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index dee26aec..3530794f 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -25,6 +25,7 @@ import kotlinx.android.synthetic.main.data_label_stub.view.*
import kotlinx.android.synthetic.main.statistics2_view.*
import me.anon.grow.R
import me.anon.lib.TdsUnit
+import me.anon.lib.TempUnit
import me.anon.lib.Unit
import me.anon.lib.ext.*
import me.anon.lib.helper.StatsHelper.formatter
@@ -60,6 +61,7 @@ class StatisticsFragment2 : Fragment()
private val selectedTdsUnit by lazy { TdsUnit.getSelectedTdsUnit(activity!!) }
private val selectedDeliveryUnit by lazy { Unit.getSelectedDeliveryUnit(activity!!) }
private val selectedMeasurementUnit by lazy { Unit.getSelectedMeasurementUnit(activity!!) }
+ private val selectedTempUnit by lazy { TempUnit.getSelectedTemperatureUnit(activity!!) }
private val checkedAdditives = setOf()
private val statsColours by lazy {
resources.getStringArray(R.array.stats_colours).map {
@@ -102,6 +104,9 @@ class StatisticsFragment2 : Fragment()
val tdsValues = hashMapOf>()
val tdsStats = hashMapOf()
+ val tempValues = ArrayList()
+ val tempStats = StatWrapper()
+
var endDate = System.currentTimeMillis()
var waterDifference = 0L
var lastWater = 0L
@@ -137,10 +142,12 @@ class StatisticsFragment2 : Fragment()
populateAdditiveStats()
populatePhStats()
populateTdsStats()
+ populateTempStats()
}
private fun calculateStats()
{
+ val tempTempValues = arrayListOf()
val tempPhValues = arrayListOf()
val tempRunoffValues = arrayListOf()
val tempTdsValues = hashMapOf>()
@@ -199,6 +206,15 @@ class StatisticsFragment2 : Fragment()
}
}
+ // temp stats
+ action.temp?.let {
+ tempTempValues += it
+ tempStats.max = max(tempStats.max ?: Double.MIN_VALUE, it)
+ tempStats.min = min(tempStats.min ?: Double.MAX_VALUE, it)
+
+ tempValues += Entry(waterIndex.toFloat(), it.toFloat())
+ }
+
// add additives to pre calculated list
action.additives.forEach { additive ->
if (additive.description != null)
@@ -233,6 +249,7 @@ class StatisticsFragment2 : Fragment()
phStats.average = if (tempPhValues.isNotEmpty()) tempPhValues.average() else null
runoffStats.average = if (tempRunoffValues.isNotEmpty()) tempRunoffValues.average() else null
+ tempStats.average = if (tempTempValues.isNotEmpty()) tempTempValues.average() else null
tdsStats.forEach { (k, v) ->
tempTdsValues[k]?.let {
tdsStats[k]?.average = if (it.isNotEmpty()) it.average() else null
@@ -903,6 +920,71 @@ class StatisticsFragment2 : Fragment()
displayStats()
}
+ private fun populateTempStats()
+ {
+ with (temp_chart) {
+ setVisibleYRangeMaximum(tempStats.max?.toFloat() ?: 0.0f, YAxis.AxisDependency.LEFT)
+ style()
+
+ axisLeft.valueFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return "${value.formatWhole()}°${selectedTempUnit.label}"
+ }
+ }
+
+ xAxis.valueFormatter = datesFormatter
+ }
+
+ val sets = arrayListOf()
+
+ sets += LineDataSet(tempValues, getString(R.string.stat_input_ph)).apply {
+ color = statsColours[0]
+ fillColor = color
+ setCircleColor(color)
+ styleDataset(context!!, this, color)
+ }
+
+ sets += LineDataSet(tempValues.rollingAverage(), getString(R.string.stat_average_temp)).apply {
+ color = ColorUtils.blendARGB(statsColours[0], 0xffffffff.toInt(), 0.4f)
+ setDrawCircles(false)
+ setDrawValues(false)
+ setDrawCircleHole(false)
+ setDrawHighlightIndicators(true)
+ cubicIntensity = 1f
+ lineWidth = 2.0f
+ isHighlightEnabled = false
+ }
+
+ temp_chart.data = LineData(sets)
+
+ val stats = arrayListOf()
+ tempStats.min?.let {
+ stats += data(
+ label = getString(R.string.min),
+ data = "${it.formatWhole()}°${selectedTempUnit.label}"
+ )
+ }
+
+ tempStats.max?.let {
+ stats += data(
+ label = getString(R.string.max),
+ data = "${it.formatWhole()}°${selectedTempUnit.label}"
+ )
+ }
+
+ tempStats.average?.let {
+ stats += data(
+ label = getString(R.string.ave),
+ data = "${it.formatWhole()}°${selectedTempUnit.label}"
+ )
+ }
+
+ if (stats.size > 0) renderStats(temp_stats_container, stats)
+ }
+
+
private fun renderStats(container: ViewGroup, templates: ArrayList)
{
templates.forEach { template ->
diff --git a/app/src/main/res/layout/statistics2_view.xml b/app/src/main/res/layout/statistics2_view.xml
index ee75434c..906429bc 100644
--- a/app/src/main/res/layout/statistics2_view.xml
+++ b/app/src/main/res/layout/statistics2_view.xml
@@ -226,6 +226,42 @@
app:dividerDrawableVertical="@drawable/divider_8dp"
/>
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5c1c00a4..a67badd0 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -273,6 +273,7 @@
Input pH
Runoff pH
Average pH
+ Average temp
Average runoff pH
Average %s
From 90de7faf6e991441464e907f274ffd658d4f8267 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Mon, 27 Apr 2020 21:41:57 +0100
Subject: [PATCH 088/152] Adds marker functionality
---
.../grow/fragment/StatisticsFragment.java | 9 --
.../anon/grow/fragment/StatisticsFragment2.kt | 90 +++++++++++++++++--
app/src/main/res/layout/chart_marker.xml | 11 +--
3 files changed, 91 insertions(+), 19 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment.java b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment.java
index 7575a663..1cdcc067 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment.java
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment.java
@@ -12,15 +12,7 @@
import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.charts.LineChart;
-import com.github.mikephil.charting.components.MarkerView;
-import com.github.mikephil.charting.components.YAxis;
-import com.github.mikephil.charting.data.BarData;
-import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
-import com.github.mikephil.charting.data.Entry;
-import com.github.mikephil.charting.formatter.ValueFormatter;
-import com.github.mikephil.charting.highlight.Highlight;
-import com.github.mikephil.charting.utils.ViewPortHandler;
import com.google.android.flexbox.FlexboxLayout;
import java.util.ArrayList;
@@ -37,7 +29,6 @@
import me.anon.lib.TempUnit;
import me.anon.lib.Unit;
import me.anon.lib.Views;
-import me.anon.lib.ext.IntUtilsKt;
import me.anon.lib.ext.NumberUtilsKt;
import me.anon.lib.helper.StatsHelper;
import me.anon.lib.helper.TimeHelper;
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index 3530794f..cbe128ba 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -12,14 +12,13 @@ import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.graphics.ColorUtils
import androidx.core.view.plusAssign
import androidx.fragment.app.Fragment
-import com.github.mikephil.charting.components.AxisBase
-import com.github.mikephil.charting.components.Legend
-import com.github.mikephil.charting.components.LegendEntry
-import com.github.mikephil.charting.components.YAxis
+import com.github.mikephil.charting.components.*
import com.github.mikephil.charting.data.*
import com.github.mikephil.charting.formatter.ValueFormatter
+import com.github.mikephil.charting.highlight.Highlight
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet
+import com.github.mikephil.charting.utils.MPPointF
import com.google.android.material.chip.Chip
import kotlinx.android.synthetic.main.data_label_stub.view.*
import kotlinx.android.synthetic.main.statistics2_view.*
@@ -634,6 +633,22 @@ class StatisticsFragment2 : Fragment()
setVisibleYRangeMaximum(totalMax.toFloat(), YAxis.AxisDependency.LEFT)
style()
+ marker = object : MarkerView(activity, R.layout.chart_marker)
+ {
+ override fun refreshContent(e: Entry, highlight: Highlight): kotlin.Unit
+ {
+ val color = additives_concentration_chart.data.dataSets[highlight.dataSetIndex].color
+ with (this.findViewById(R.id.content)) {
+ text = "${e.y.formatWhole()} ${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ setTextColor(color)
+ }
+
+ super.refreshContent(e, highlight)
+ }
+
+ override fun getOffset(): MPPointF = MPPointF.getInstance(-(width / 2f), -(height * 1.2f))
+ }
+
axisLeft.granularity = 1f
axisLeft.valueFormatter = object : ValueFormatter()
{
@@ -654,6 +669,22 @@ class StatisticsFragment2 : Fragment()
setVisibleYRangeMaximum(totalMax.toFloat(), YAxis.AxisDependency.LEFT)
style()
+ marker = object : MarkerView(activity, R.layout.chart_marker)
+ {
+ override fun refreshContent(e: Entry, highlight: Highlight): kotlin.Unit
+ {
+ val color = additives_overtime_chart.data.dataSets[highlight.dataSetIndex].color
+ with (this.findViewById(R.id.content)) {
+ text = "${e.y.formatWhole()} ${selectedMeasurementUnit.label}"
+ setTextColor(color)
+ }
+
+ super.refreshContent(e, highlight)
+ }
+
+ override fun getOffset(): MPPointF = MPPointF.getInstance(-(width / 2f), -(height * 1.2f))
+ }
+
axisLeft.granularity = 1f
axisLeft.valueFormatter = object : ValueFormatter()
{
@@ -810,6 +841,23 @@ class StatisticsFragment2 : Fragment()
with (input_ph) {
setVisibleYRangeMaximum(max(phStats.max?.toFloat() ?: 0.0f, runoffStats.max?.toFloat() ?: 0.0f), YAxis.AxisDependency.LEFT)
style()
+
+ marker = object : MarkerView(activity, R.layout.chart_marker)
+ {
+ override fun refreshContent(e: Entry, highlight: Highlight): kotlin.Unit
+ {
+ val color = input_ph.data.dataSets[highlight.dataSetIndex].color
+ with (this.findViewById(R.id.content)) {
+ text = e.y.formatWhole()
+ setTextColor(color)
+ }
+
+ super.refreshContent(e, highlight)
+ }
+
+ override fun getOffset(): MPPointF = MPPointF.getInstance(-(width / 2f), -(height * 1.2f))
+ }
+
xAxis.valueFormatter = datesFormatter
}
@@ -913,6 +961,23 @@ class StatisticsFragment2 : Fragment()
with (tds_chart) {
style()
+
+ marker = object : MarkerView(activity, R.layout.chart_marker)
+ {
+ override fun refreshContent(e: Entry, highlight: Highlight): kotlin.Unit
+ {
+ val color = tds_chart.data.dataSets[highlight.dataSetIndex].color
+ with (this.findViewById(R.id.content)) {
+ text = e.y.formatWhole()
+ setTextColor(color)
+ }
+
+ super.refreshContent(e, highlight)
+ }
+
+ override fun getOffset(): MPPointF = MPPointF.getInstance(-(width / 2f), -(height * 1.2f))
+ }
+
xAxis.valueFormatter = datesFormatter
}
@@ -934,6 +999,22 @@ class StatisticsFragment2 : Fragment()
}
}
+ marker = object : MarkerView(activity, R.layout.chart_marker)
+ {
+ override fun refreshContent(e: Entry, highlight: Highlight): kotlin.Unit
+ {
+ val color = temp_chart.data.dataSets[highlight.dataSetIndex].color
+ with (this.findViewById(R.id.content)) {
+ text = "${e.y.formatWhole()}°${selectedTempUnit.label}"
+ setTextColor(color)
+ }
+
+ super.refreshContent(e, highlight)
+ }
+
+ override fun getOffset(): MPPointF = MPPointF.getInstance(-(width / 2f), -(height * 1.2f))
+ }
+
xAxis.valueFormatter = datesFormatter
}
@@ -984,7 +1065,6 @@ class StatisticsFragment2 : Fragment()
if (stats.size > 0) renderStats(temp_stats_container, stats)
}
-
private fun renderStats(container: ViewGroup, templates: ArrayList)
{
templates.forEach { template ->
diff --git a/app/src/main/res/layout/chart_marker.xml b/app/src/main/res/layout/chart_marker.xml
index 2d73540f..621e08db 100644
--- a/app/src/main/res/layout/chart_marker.xml
+++ b/app/src/main/res/layout/chart_marker.xml
@@ -5,22 +5,23 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginBottom="4dp"
- app:cardBackgroundColor="#40000000"
+ app:cardBackgroundColor="#F0000000"
app:cardCornerRadius="4dp"
>
From 9adbee7ae7b18c3cf213efe00b5c7ff3ac593dcb Mon Sep 17 00:00:00 2001
From: "transifex-integration[bot]"
<43880903+transifex-integration[bot]@users.noreply.github.com>
Date: Tue, 28 Apr 2020 10:36:49 +0000
Subject: [PATCH 089/152] Apply translations in nl_NL
translation completed for the source file '/app/src/main/res/values/strings.xml'
on the 'nl_NL' language.
---
app/src/main/res/values-nl-rNL/strings.xml | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/app/src/main/res/values-nl-rNL/strings.xml b/app/src/main/res/values-nl-rNL/strings.xml
index 1d584291..fb9383db 100644
--- a/app/src/main/res/values-nl-rNL/strings.xml
+++ b/app/src/main/res/values-nl-rNL/strings.xml
@@ -145,9 +145,13 @@
Totaaltijd:
Totaal water gegeven:
Totaal bijgesteld:
+ Totaal waterverbruik:
+ Gem. waterverbruik:
Gem. tijd tussen water geven:
+ Gemiddeld %swater:
Toevoegingen filteren
pH-waarde
+ TDS
Min.:
Max.:
@@ -269,6 +273,9 @@
Toevoer-pH-waarde
Afvoer-pH-waarde
Gemiddelde pH-waarde
+ Gemiddelde temperatuur
+ Gemiddelde afvoer-pH-waarde
+ Gemiddeld %s
Plantenfoto\'s
@@ -419,4 +426,13 @@
Kan planten niet importeren uit bestand
Planten importeren uit bestand
De planten zijn geïmporteerd
+
+ %s-statistieken
+ Gem. per voeding:
+ Aantal keer gebruikt:
+ Totaal:
+
+ Toegevoegde concentratie
+ Toevoegingen in de loop der tijd
+ Toegevoegde verspreiding
From 17d7e68904121b5e5e1bd26a1f5130ff407df5a1 Mon Sep 17 00:00:00 2001
From: 7LPdWcaW <7LPdWcaW@gmail.com>
Date: Sat, 9 May 2020 20:12:01 +0100
Subject: [PATCH 090/152] Adds new stats in export
---
.../anon/grow/fragment/StatisticsFragment2.kt | 546 ++++++-------
.../java/me/anon/lib/export/ExportHelper.kt | 739 ++++++++++++++++--
.../me/anon/lib/export/ExportProcessor.kt | 2 +
.../me/anon/lib/export/MarkdownProcessor.kt | 237 ++++--
4 files changed, 1104 insertions(+), 420 deletions(-)
diff --git a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
index cbe128ba..241dbffd 100644
--- a/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
+++ b/app/src/main/java/me/anon/grow/fragment/StatisticsFragment2.kt
@@ -23,6 +23,7 @@ import com.google.android.material.chip.Chip
import kotlinx.android.synthetic.main.data_label_stub.view.*
import kotlinx.android.synthetic.main.statistics2_view.*
import me.anon.grow.R
+import me.anon.grow.fragment.StatisticsFragment2.template.*
import me.anon.lib.TdsUnit
import me.anon.lib.TempUnit
import me.anon.lib.Unit
@@ -41,83 +42,239 @@ import kotlin.math.min
*/
class StatisticsFragment2 : Fragment()
{
- class StageDate(var day: Int, var total: Int, var stage: PlantStage)
- class StatWrapper(var min: Double? = null, var max: Double? = null, var average: Double? = null)
-
- open class template()
- open class header(var label: String) : template()
- open class data(label: String, val data: String) : header(label)
-
- companion object
+ class StatisticsViewModel(
+ val selectedTdsUnit: TdsUnit,
+ val selectedDeliveryUnit: Unit,
+ val selectedMeasurementUnit: Unit,
+ val selectedTempUnit: TempUnit,
+ val plant: Plant
+ )
{
- @JvmStatic
- public fun newInstance(args: Bundle) = StatisticsFragment2().apply {
- this.arguments = args
- }
- }
-
- private lateinit var plant: Plant
- private val selectedTdsUnit by lazy { TdsUnit.getSelectedTdsUnit(activity!!) }
- private val selectedDeliveryUnit by lazy { Unit.getSelectedDeliveryUnit(activity!!) }
- private val selectedMeasurementUnit by lazy { Unit.getSelectedMeasurementUnit(activity!!) }
- private val selectedTempUnit by lazy { TempUnit.getSelectedTemperatureUnit(activity!!) }
- private val checkedAdditives = setOf()
- private val statsColours by lazy {
- resources.getStringArray(R.array.stats_colours).map {
- Color.parseColor(it)
- }
- }
+ class StageDate(var day: Int, var total: Int, var stage: PlantStage)
+ class StatWrapper(var min: Double? = null, var max: Double? = null, var average: Double? = null)
+ class AdditiveStat(
+ var total: Double = 0.0,
+ var totalAdjusted: Double = 0.0,
+ var count: Int = 0,
+ var min: Double = Double.NaN,
+ var max: Double = Double.NaN
+ )
- // stat variables
- val stageChanges by lazy {
+ // stat variables
+ public val stageChanges by lazy {
plant.getStages().also {
it.toSortedMap(Comparator { first, second ->
(it[first]?.date ?: 0).compareTo(it[second]?.date ?: 0)
})
}
- }
+ }
- val plantStages by lazy {
- plant.calculateStageTime().also {
- it.remove(PlantStage.HARVESTED)
+ public val plantStages by lazy {
+ plant.calculateStageTime().also {
+ it.remove(PlantStage.HARVESTED)
+ }
}
- }
- val aveStageWaters by lazy {
- LinkedHashMap>().also { waters ->
- waters.putAll(plantStages.keys.map { it }.associateWith { arrayListOf() })
+ public val aveStageWaters by lazy {
+ LinkedHashMap>().also { waters ->
+ waters.putAll(plantStages.keys.map { it }.associateWith { arrayListOf() })
+ }
}
- }
- val additives = hashMapOf>()
- val waterDates = arrayListOf()
- val additiveValues = hashMapOf>()
- val additiveTotalValues = hashMapOf>()
+ public val additiveStats = LinkedHashMap()
+ public val additives = hashMapOf>()
+ public val waterDates = arrayListOf()
+ public val additiveValues = hashMapOf>()
+ public val additiveTotalValues = hashMapOf>()
+
+ public val phValues = arrayListOf()
+ public val phStats = StatWrapper()
+
+ public val runoffValues = arrayListOf()
+ public val runoffStats = StatWrapper()
- val phValues = arrayListOf()
- val phStats = StatWrapper()
+ public val tdsValues = hashMapOf>()
+ public val tdsStats = hashMapOf()
- val runoffValues = arrayListOf()
- val runoffStats = StatWrapper()
+ public val tempValues = ArrayList()
+ public val tempStats = StatWrapper()
- val tdsValues = hashMapOf>()
- val tdsStats = hashMapOf()
+ public var endDate = System.currentTimeMillis()
+ public var waterDifference = 0L
+ public var lastWater = 0L
+ public var totalWater = 0
+ public var totalWaterAmount = 0.0
+ public var totalFlush = 0
- val tempValues = ArrayList()
- val tempStats = StatWrapper()
+ public val startDate = plant.plantDate
+ public val totalDays = ((endDate - startDate) / 1000.0) * 0.0000115741
- var endDate = System.currentTimeMillis()
- var waterDifference = 0L
- var lastWater = 0L
- var totalWater = 0
- var totalWaterAmount = 0.0
- var totalFlush = 0
+ init { calculateStats() }
+
+ public fun calculateStats()
+ {
+ val tempTempValues = arrayListOf()
+ val tempPhValues = arrayListOf()
+ val tempRunoffValues = arrayListOf()
+ val tempTdsValues = hashMapOf>()
+ var waterIndex = 0
+ plant.actions?.forEach { action ->
+ when (action)
+ {
+ is StageChange -> {
+ if (action.newStage == PlantStage.HARVESTED) endDate = action.date
+ }
+
+ is Water -> {
+ if (lastWater != 0L) waterDifference += abs(action.date - lastWater)
+ totalWater++
+ totalWaterAmount += action.amount ?: 0.0
+ lastWater = action.date
+
+ // find the stage change where the date is older than the watering
+ val sortedStageChange = stageChanges.filterValues { it.date <= action.date }.toSortedMap()
+ val stage = sortedStageChange.lastKey()
+ val stageChangeDate = sortedStageChange[stage]?.date ?: 0
+ val waterDate = action.date
+ val stageLength = (waterDate - stageChangeDate).toDays().toInt()
+ val totalDate = TimeHelper.toDays(action.date - plant.plantDate).toInt()
+ waterDates.add(StageDate(stageLength, totalDate, stage))
+ aveStageWaters.getOrPut(stage, { arrayListOf() }).add(action.date)
+
+ // pH stats
+ action.ph?.let {
+ tempPhValues += it
+ phStats.max = max(phStats.max ?: Double.MIN_VALUE, it)
+ phStats.min = min(phStats.min ?: Double.MAX_VALUE, it)
+
+ phValues += Entry(waterIndex.toFloat(), it.toFloat())
+ }
+
+ // runoff stats
+ action.runoff?.let {
+ tempRunoffValues += it
+ runoffStats.max = max(runoffStats.max ?: Double.MIN_VALUE, it)
+ runoffStats.min = min(runoffStats.min ?: Double.MAX_VALUE, it)
+
+ runoffValues += Entry(waterIndex.toFloat(), it.toFloat())
+ }
+
+ // tds stats
+ action.tds?.let { tds ->
+ tds.amount?.let { amount ->
+ tempTdsValues.getOrPut(tds.type) { arrayListOf() }.add(amount)
+ tdsStats.getOrPut(tds.type) { StatWrapper() }.apply {
+ this.max = max(this.max ?: Double.MIN_VALUE, amount)
+ this.min = min(this.min ?: Double.MAX_VALUE, amount)
+ }
+
+ tdsValues.getOrPut(tds.type) { arrayListOf() }.add(Entry(waterIndex.toFloat(), amount.toFloat()))
+ }
+ }
+
+ // temp stats
+ action.temp?.let {
+ tempTempValues += it
+ tempStats.max = max(tempStats.max ?: Double.MIN_VALUE, it)
+ tempStats.min = min(tempStats.min ?: Double.MAX_VALUE, it)
+
+ tempValues += Entry(waterIndex.toFloat(), it.toFloat())
+ }
+
+ // add additives to pre calculated list
+ action.additives.forEach { additive ->
+ if (additive.description != null)
+ {
+ additive.amount?.let { amount ->
+ with (additiveValues) {
+ val amount = Unit.ML.to(selectedMeasurementUnit, amount)
+ val entry = Entry(waterIndex.toFloat(), amount.toFloat())
+ getOrPut(additive.description!!, { arrayListOf() }).add(entry)
+ }
+
+ with (additiveTotalValues) {
+ val totalDelivery = Unit.ML.to(selectedDeliveryUnit, action.amount ?: 1000.0)
+ val additiveAmount = Unit.ML.to(selectedMeasurementUnit, amount)
+
+ val entry = Entry(waterIndex.toFloat(), Unit.toTwoDecimalPlaces(additiveAmount * totalDelivery).toFloat())
+ getOrPut(additive.description!!, { arrayListOf() }).add(entry)
+ }
+ }
+ }
+ }
+
+ waterIndex++
+ additives.getOrPut(action) { arrayListOf() }.addAll(action.additives)
+ }
+
+ is EmptyAction -> {
+ if (action.action == Action.ActionName.FLUSH) totalFlush++
+ }
+ }
+ }
+
+ phStats.average = if (tempPhValues.isNotEmpty()) tempPhValues.average() else null
+ runoffStats.average = if (tempRunoffValues.isNotEmpty()) tempRunoffValues.average() else null
+ tempStats.average = if (tempTempValues.isNotEmpty()) tempTempValues.average() else null
+ tdsStats.forEach { (k, v) ->
+ tempTdsValues[k]?.let {
+ tdsStats[k]?.average = if (it.isNotEmpty()) it.average() else null
+ }
+ }
+
+ additives.keys.forEach { water ->
+ additives[water]?.sortedBy { it.description }?.forEach { additive ->
+ additive.description?.let { key ->
+ additiveStats.getOrPut(key, { AdditiveStat() }).apply {
+ total += additive.amount ?: 0.0
+ min = min(min.isNaN() T Double.MAX_VALUE ?: min, additive.amount ?: 0.0)
+ max = max(max.isNaN() T Double.MIN_VALUE ?: max, additive.amount ?: 0.0)
+
+ additiveTotalValues[key]?.let { totalValues ->
+ var total = 0.0
+ totalValues.forEach { entry ->
+ total += entry.y
+ }
+
+ totalAdjusted = total
+ }
+
+ count++
+ }
+ }
+ }
+ }
+ }
+ }
+
+ sealed class template
+ {
+ open class header(var label: String) : template()
+ open class data(label: String, val data: String) : header(label)
+ }
+
+ companion object
+ {
+ @JvmStatic
+ public fun newInstance(args: Bundle) = StatisticsFragment2().apply {
+ this.arguments = args
+ }
+ }
+
+ private lateinit var plant: Plant
+ private lateinit var viewModel: StatisticsViewModel
+ private val checkedAdditives = setOf()
+ private val statsColours by lazy {
+ resources.getStringArray(R.array.stats_colours).map {
+ Color.parseColor(it)
+ }
+ }
val datesFormatter = object : ValueFormatter()
{
override fun getAxisLabel(value: Float, axis: AxisBase?): String
{
- return waterDates.getOrNull(value.toInt())?.transform {
+ return viewModel.waterDates.getOrNull(value.toInt())?.transform {
"${total}/${day}${getString(stage.printString).toLowerCase()[0]}"
} ?: ""
}
@@ -136,7 +293,18 @@ class StatisticsFragment2 : Fragment()
if (!::plant.isInitialized) return
- calculateStats()
+ val selectedTdsUnit = TdsUnit.getSelectedTdsUnit(requireContext())
+ val selectedDeliveryUnit = Unit.getSelectedDeliveryUnit(requireContext())
+ val selectedMeasurementUnit = Unit.getSelectedMeasurementUnit(requireContext())
+ val selectedTempUnit = TempUnit.getSelectedTemperatureUnit(requireContext())
+
+ viewModel = StatisticsViewModel(
+ selectedTdsUnit,
+ selectedDeliveryUnit,
+ selectedMeasurementUnit,
+ selectedTempUnit,
+ plant
+ )
populateGeneralStats()
populateAdditiveStats()
populatePhStats()
@@ -144,118 +312,6 @@ class StatisticsFragment2 : Fragment()
populateTempStats()
}
- private fun calculateStats()
- {
- val tempTempValues = arrayListOf()
- val tempPhValues = arrayListOf()
- val tempRunoffValues = arrayListOf()
- val tempTdsValues = hashMapOf>()
- var waterIndex = 0
- plant.actions?.forEach { action ->
- when (action)
- {
- is StageChange -> {
- if (action.newStage == PlantStage.HARVESTED) endDate = action.date
- }
-
- is Water -> {
- if (lastWater != 0L) waterDifference += abs(action.date - lastWater)
- totalWater++
- totalWaterAmount += action.amount ?: 0.0
- lastWater = action.date
-
- // find the stage change where the date is older than the watering
- val sortedStageChange = stageChanges.filterValues { it.date <= action.date }.toSortedMap()
- val stage = sortedStageChange.lastKey()
- val stageChangeDate = sortedStageChange[stage]?.date ?: 0
- val waterDate = action.date
- val stageLength = (waterDate - stageChangeDate).toDays().toInt()
- val totalDate = TimeHelper.toDays(action.date - plant.plantDate).toInt()
- waterDates.add(StageDate(stageLength, totalDate, stage))
- aveStageWaters.getOrPut(stage, { arrayListOf() }).add(action.date)
-
- // pH stats
- action.ph?.let {
- tempPhValues += it
- phStats.max = max(phStats.max ?: Double.MIN_VALUE, it)
- phStats.min = min(phStats.min ?: Double.MAX_VALUE, it)
-
- phValues += Entry(waterIndex.toFloat(), it.toFloat())
- }
-
- // runoff stats
- action.runoff?.let {
- tempRunoffValues += it
- runoffStats.max = max(runoffStats.max ?: Double.MIN_VALUE, it)
- runoffStats.min = min(runoffStats.min ?: Double.MAX_VALUE, it)
-
- runoffValues += Entry(waterIndex.toFloat(), it.toFloat())
- }
-
- // tds stats
- action.tds?.let { tds ->
- tds.amount?.let { amount ->
- tempTdsValues.getOrPut(tds.type) { arrayListOf() }.add(amount)
- tdsStats.getOrPut(tds.type) { StatWrapper() }.apply {
- this.max = max(this.max ?: Double.MIN_VALUE, amount)
- this.min = min(this.min ?: Double.MAX_VALUE, amount)
- }
-
- tdsValues.getOrPut(tds.type) { arrayListOf() }.add(Entry(waterIndex.toFloat(), amount.toFloat()))
- }
- }
-
- // temp stats
- action.temp?.let {
- tempTempValues += it
- tempStats.max = max(tempStats.max ?: Double.MIN_VALUE, it)
- tempStats.min = min(tempStats.min ?: Double.MAX_VALUE, it)
-
- tempValues += Entry(waterIndex.toFloat(), it.toFloat())
- }
-
- // add additives to pre calculated list
- action.additives.forEach { additive ->
- if (additive.description != null)
- {
- additive.amount?.let { amount ->
- with (additiveValues) {
- val amount = Unit.ML.to(selectedMeasurementUnit, amount)
- val entry = Entry(waterIndex.toFloat(), amount.toFloat())
- getOrPut(additive.description!!, { arrayListOf() }).add(entry)
- }
-
- with (additiveTotalValues) {
- val totalDelivery = Unit.ML.to(selectedDeliveryUnit, action.amount ?: 1000.0)
- val additiveAmount = Unit.ML.to(selectedMeasurementUnit, amount)
-
- val entry = Entry(waterIndex.toFloat(), Unit.toTwoDecimalPlaces(additiveAmount * totalDelivery).toFloat())
- getOrPut(additive.description!!, { arrayListOf() }).add(entry)
- }
- }
- }
- }
-
- waterIndex++
- additives.getOrPut(action) { arrayListOf() }.addAll(action.additives)
- }
-
- is EmptyAction -> {
- if (action.action == Action.ActionName.FLUSH) totalFlush++
- }
- }
- }
-
- phStats.average = if (tempPhValues.isNotEmpty()) tempPhValues.average() else null
- runoffStats.average = if (tempRunoffValues.isNotEmpty()) tempRunoffValues.average() else null
- tempStats.average = if (tempTempValues.isNotEmpty()) tempTempValues.average() else null
- tdsStats.forEach { (k, v) ->
- tempTdsValues[k]?.let {
- tdsStats[k]?.average = if (it.isNotEmpty()) it.average() else null
- }
- }
- }
-
private fun populateGeneralStats()
{
val statTemplates = arrayListOf()
@@ -263,9 +319,9 @@ class StatisticsFragment2 : Fragment()
stats_container.removeAllViews()
PlantStage.values().forEach { stage ->
- if (plantStages.containsKey(stage))
+ if (viewModel.plantStages.containsKey(stage))
{
- plantStages[stage]?.let { time ->
+ viewModel.plantStages[stage]?.let { time ->
statTemplates += data(
label = "${getString(stage.printString)}:",
data = "${TimeHelper.toDays(time).toInt()} ${resources.getQuantityString(R.plurals.time_day, TimeHelper.toDays(time).toInt())}"
@@ -274,13 +330,10 @@ class StatisticsFragment2 : Fragment()
}
}
- val startDate = plant.plantDate
- val days = ((endDate - startDate) / 1000.0) * 0.0000115741
-
// total time
statTemplates += data(
label = getString(R.string.total_time_label),
- data = "${days.formatWhole()} ${resources.getQuantityString(R.plurals.time_day, days.toInt())}"
+ data = "${viewModel.totalDays.formatWhole()} ${resources.getQuantityString(R.plurals.time_day, viewModel.totalDays.toInt())}"
)
statTemplates += header("Water stats")
@@ -288,37 +341,37 @@ class StatisticsFragment2 : Fragment()
// total waters
statTemplates += data(
label = getString(R.string.total_waters_label),
- data = "${totalWater.formatWhole()}"
+ data = "${viewModel.totalWater.formatWhole()}"
)
// total flushes
statTemplates += data(
label = getString(R.string.total_flushes_label),
- data = "${totalFlush.formatWhole()}"
+ data = "${viewModel.totalFlush.formatWhole()}"
)
// total water amount
statTemplates += data(
label = getString(R.string.total_water_amount_label),
- data = "${Unit.ML.to(selectedDeliveryUnit, totalWaterAmount).formatWhole()} ${selectedDeliveryUnit.label}"
+ data = "${Unit.ML.to(viewModel.selectedDeliveryUnit, viewModel.totalWaterAmount).formatWhole()} ${viewModel.selectedDeliveryUnit.label}"
)
// average water amount
statTemplates += data(
label = getString(R.string.ave_water_amount_label),
- data = "${Unit.ML.to(selectedDeliveryUnit, (totalWaterAmount / totalWater.toDouble())).formatWhole()} ${selectedDeliveryUnit.label}"
+ data = "${Unit.ML.to(viewModel.selectedDeliveryUnit, (viewModel.totalWaterAmount / viewModel.totalWater.toDouble())).formatWhole()} ${viewModel.selectedDeliveryUnit.label}"
)
// ave time between water
statTemplates += data(
label = getString(R.string.ave_time_between_water_label),
- data = (TimeHelper.toDays(waterDifference) / totalWater).let { d ->
+ data = (TimeHelper.toDays(viewModel.waterDifference) / viewModel.totalWater).let { d ->
"${d.formatWhole()} ${resources.getQuantityString(R.plurals.time_day, ceil(d).toInt())}"
}
)
// ave water time between stages
- aveStageWaters
+ viewModel.aveStageWaters
.toSortedMap(Comparator { first, second -> first.ordinal.compareTo(second.ordinal) })
.forEach { (stage, dates) ->
if (dates.isNotEmpty())
@@ -336,18 +389,18 @@ class StatisticsFragment2 : Fragment()
renderStats(stats_container, statTemplates)
// stage chart
- val labels = arrayOfNulls(plantStages.size)
- val yVals = FloatArray(plantStages.size)
+ val labels = arrayOfNulls(viewModel.plantStages.size)
+ val yVals = FloatArray(viewModel.plantStages.size)
- var index = plantStages.size - 1
- for (plantStage in plantStages.keys)
+ var index = viewModel.plantStages.size - 1
+ for (plantStage in viewModel.plantStages.keys)
{
- yVals[index] = max(TimeHelper.toDays(plantStages[plantStage] ?: 0).toFloat(), 1f)
+ yVals[index] = max(TimeHelper.toDays(viewModel.plantStages[plantStage] ?: 0).toFloat(), 1f)
labels[index--] = getString(plantStage.printString)
}
val stageEntries = arrayListOf()
- stageEntries += BarEntry(0f, yVals, plantStages.keys.toList().asReversed())
+ stageEntries += BarEntry(0f, yVals, viewModel.plantStages.keys.toList().asReversed())
val stageData = BarDataSet(stageEntries, "")
stageData.isHighlightEnabled = false
@@ -403,16 +456,7 @@ class StatisticsFragment2 : Fragment()
private fun populateAdditiveStats()
{
- class AdditiveStat(
- var total: Double = 0.0,
- var totalAdjusted: Double = 0.0,
- var count: Int = 0,
- var min: Double = Double.NaN,
- var max: Double = Double.NaN
- )
-
val selectedAdditives = arrayListOf()
- val additiveStats = LinkedHashMap()
var totalMax = Double.MIN_VALUE
fun displayStats()
@@ -420,20 +464,20 @@ class StatisticsFragment2 : Fragment()
additives_stats_container.removeAllViews()
selectedAdditives.forEach { name ->
- additiveStats[name]?.let { stat ->
+ viewModel.additiveStats[name]?.let { stat ->
val stats = arrayListOf()
stats += header(getString(R.string.additive_stat_header, name))
stats += data(
label = getString(R.string.min),
- data = "${Unit.ML.to(selectedMeasurementUnit, stat.min).formatWhole()} ${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ data = "${Unit.ML.to(viewModel.selectedMeasurementUnit, stat.min).formatWhole()} ${viewModel.selectedMeasurementUnit.label}/${viewModel.selectedDeliveryUnit.label}"
)
stats += data(
label = getString(R.string.max),
- data = "${Unit.ML.to(selectedMeasurementUnit, stat.max).formatWhole()} ${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ data = "${Unit.ML.to(viewModel.selectedMeasurementUnit, stat.max).formatWhole()} ${viewModel.selectedMeasurementUnit.label}/${viewModel.selectedDeliveryUnit.label}"
)
stats += data(
label = getString(R.string.additive_average_usage_label),
- data = "${Unit.ML.to(selectedMeasurementUnit, stat.total / stat.count.toDouble()).formatWhole()} ${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ data = "${Unit.ML.to(viewModel.selectedMeasurementUnit, stat.total / stat.count.toDouble()).formatWhole()} ${viewModel.selectedMeasurementUnit.label}/${viewModel.selectedDeliveryUnit.label}"
)
stats += data(
label = getString(R.string.additive_usage_count_label),
@@ -441,7 +485,7 @@ class StatisticsFragment2 : Fragment()
)
stats += data(
label = getString(R.string.additive_total_usage_label),
- data = "${Unit.ML.to(selectedMeasurementUnit, stat.totalAdjusted).formatWhole()} ${selectedMeasurementUnit.label}"
+ data = "${Unit.ML.to(viewModel.selectedMeasurementUnit, stat.totalAdjusted).formatWhole()} ${viewModel.selectedMeasurementUnit.label}"
)
renderStats(additives_stats_container, stats)
@@ -453,7 +497,7 @@ class StatisticsFragment2 : Fragment()
{
val dataSets = arrayListOf()
var index = 0
- additiveValues.toSortedMap().let {
+ viewModel.additiveValues.toSortedMap().let {
it.forEach { (k, v) ->
if (selectedAdditives.contains(k))
{
@@ -481,7 +525,7 @@ class StatisticsFragment2 : Fragment()
{
val pieData = arrayListOf()
val colors = arrayListOf()
- additiveTotalValues.toSortedMap().let { values ->
+ viewModel.additiveTotalValues.toSortedMap().let { values ->
var index = 0
values.forEach { (k, v) ->
@@ -509,7 +553,7 @@ class StatisticsFragment2 : Fragment()
{
override fun getFormattedValue(value: Float): String
{
- return "${value.formatWhole()}${selectedMeasurementUnit.label}"
+ return "${value.formatWhole()}${viewModel.selectedMeasurementUnit.label}"
}
}
})
@@ -524,7 +568,7 @@ class StatisticsFragment2 : Fragment()
var index = 0
val newValues = sortedMapOf>()
- additiveTotalValues.toSortedMap().let {
+ viewModel.additiveTotalValues.toSortedMap().let {
it.forEach { (key, entries) ->
if (selectedAdditives.contains(key))
{
@@ -551,8 +595,8 @@ class StatisticsFragment2 : Fragment()
}
}
- val stageEntries = plantStages.keys.toList().asReversed()
- waterDates.forEachIndexed { additiveIndex, date ->
+ val stageEntries = viewModel.plantStages.keys.toList().asReversed()
+ viewModel.waterDates.forEachIndexed { additiveIndex, date ->
barSets += BarDataSet(arrayListOf(BarEntry(additiveIndex.toFloat(), totalMax.toFloat())), null).apply {
color = ColorUtils.setAlphaComponent(statsColours[stageEntries.indexOf(date.stage) % statsColours.size], 127)
}
@@ -573,31 +617,7 @@ class StatisticsFragment2 : Fragment()
displayStats()
}
- additives.keys.forEach { water ->
- additives[water]?.sortedBy { it.description }?.forEach { additive ->
- additive.description?.let { key ->
- additiveStats.getOrPut(key, { AdditiveStat() }).apply {
- total += additive.amount ?: 0.0
- min = min(min.isNaN() T Double.MAX_VALUE ?: min, additive.amount ?: 0.0)
- max = max(max.isNaN() T Double.MIN_VALUE ?: max, additive.amount ?: 0.0)
-
- additiveTotalValues[key]?.let { totalValues ->
- var total = 0.0
- totalValues.forEach { entry ->
- total += entry.y
- }
-
- totalAdjusted = total
- }
-
- count++
- totalMax = max(totalMax, max)
- }
- }
- }
- }
-
- additiveStats.forEach { (k, v) ->
+ viewModel.additiveStats.forEach { (k, v) ->
val chip = LayoutInflater.from(context!!).inflate(R.layout.filter_chip_stub, additive_chips_container, false) as Chip
chip.text = k
chip.isChecked = true
@@ -613,7 +633,7 @@ class StatisticsFragment2 : Fragment()
}
val entries = arrayListOf()
- additiveValues.toSortedMap().let {
+ viewModel.additiveValues.toSortedMap().let {
var index = 0
it.forEach { (k, v) ->
if (selectedAdditives.contains(k))
@@ -639,7 +659,7 @@ class StatisticsFragment2 : Fragment()
{
val color = additives_concentration_chart.data.dataSets[highlight.dataSetIndex].color
with (this.findViewById(R.id.content)) {
- text = "${e.y.formatWhole()} ${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ text = "${e.y.formatWhole()} ${viewModel.selectedMeasurementUnit.label}/${viewModel.selectedDeliveryUnit.label}"
setTextColor(color)
}
@@ -654,7 +674,7 @@ class StatisticsFragment2 : Fragment()
{
override fun getAxisLabel(value: Float, axis: AxisBase?): String
{
- return "${value.formatWhole()}${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ return "${value.formatWhole()}${viewModel.selectedMeasurementUnit.label}/${viewModel.selectedDeliveryUnit.label}"
}
}
@@ -675,7 +695,7 @@ class StatisticsFragment2 : Fragment()
{
val color = additives_overtime_chart.data.dataSets[highlight.dataSetIndex].color
with (this.findViewById(R.id.content)) {
- text = "${e.y.formatWhole()} ${selectedMeasurementUnit.label}"
+ text = "${e.y.formatWhole()} ${viewModel.selectedMeasurementUnit.label}"
setTextColor(color)
}
@@ -690,7 +710,7 @@ class StatisticsFragment2 : Fragment()
{
override fun getAxisLabel(value: Float, axis: AxisBase?): String
{
- return "${value.formatWhole()}${selectedMeasurementUnit.label}/${selectedDeliveryUnit.label}"
+ return "${value.formatWhole()}${viewModel.selectedMeasurementUnit.label}/${viewModel.selectedDeliveryUnit.label}"
}
}
@@ -726,7 +746,7 @@ class StatisticsFragment2 : Fragment()
if (INPUT_PH in selectedModes)
{
- sets += LineDataSet(phValues, getString(R.string.stat_input_ph)).apply {
+ sets += LineDataSet(viewModel.phValues, getString(R.string.stat_input_ph)).apply {
color = statsColours[0]
fillColor = color
setCircleColor(color)
@@ -735,7 +755,7 @@ class StatisticsFragment2 : Fragment()
if (AVERAGE_PH in selectedModes)
{
- sets += LineDataSet(phValues.rollingAverage(), getString(R.string.stat_average_runoff_ph)).apply {
+ sets += LineDataSet(viewModel.phValues.rollingAverage(), getString(R.string.stat_average_runoff_ph)).apply {
color = ColorUtils.blendARGB(statsColours[0], 0xffffffff.toInt(), 0.4f)
setDrawCircles(false)
setDrawValues(false)
@@ -750,7 +770,7 @@ class StatisticsFragment2 : Fragment()
if (RUNOFF_PH in selectedModes)
{
- sets += LineDataSet(runoffValues, getString(R.string.stat_runoff_ph)).apply {
+ sets += LineDataSet(viewModel.runoffValues, getString(R.string.stat_runoff_ph)).apply {
color = statsColours[1]
fillColor = color
setCircleColor(color)
@@ -759,7 +779,7 @@ class StatisticsFragment2 : Fragment()
if (AVERAGE_PH in selectedModes)
{
- sets += LineDataSet(runoffValues.rollingAverage(), getString(R.string.stat_average_runoff_ph)).apply {
+ sets += LineDataSet(viewModel.runoffValues.rollingAverage(), getString(R.string.stat_average_runoff_ph)).apply {
color = ColorUtils.blendARGB(statsColours[1], 0xffffffff.toInt(), 0.4f)
setDrawCircles(false)
setDrawValues(false)
@@ -787,8 +807,8 @@ class StatisticsFragment2 : Fragment()
val stat = when (mode)
{
- INPUT_PH -> phStats
- RUNOFF_PH -> runoffStats
+ INPUT_PH -> viewModel.phStats
+ RUNOFF_PH -> viewModel.runoffStats
else -> null
}
@@ -819,8 +839,8 @@ class StatisticsFragment2 : Fragment()
}
arrayListOf().apply {
- if (phValues.isNotEmpty()) add(INPUT_PH)
- if (runoffValues.isNotEmpty()) add(RUNOFF_PH)
+ if (viewModel.phValues.isNotEmpty()) add(INPUT_PH)
+ if (viewModel.runoffValues.isNotEmpty()) add(RUNOFF_PH)
if (isNotEmpty()) add(AVERAGE_PH)
}.forEach { mode ->
val chip = LayoutInflater.from(context!!).inflate(R.layout.filter_chip_stub, ph_chips_container, false) as Chip
@@ -839,7 +859,7 @@ class StatisticsFragment2 : Fragment()
}
with (input_ph) {
- setVisibleYRangeMaximum(max(phStats.max?.toFloat() ?: 0.0f, runoffStats.max?.toFloat() ?: 0.0f), YAxis.AxisDependency.LEFT)
+ setVisibleYRangeMaximum(max(viewModel.phStats.max?.toFloat() ?: 0.0f, viewModel.runoffStats.max?.toFloat() ?: 0.0f), YAxis.AxisDependency.LEFT)
style()
marker = object : MarkerView(activity, R.layout.chart_marker)
@@ -867,22 +887,22 @@ class StatisticsFragment2 : Fragment()
private fun populateTdsStats()
{
- var selectedUnit: TdsUnit = selectedTdsUnit
+ var selectedUnit: TdsUnit = viewModel.selectedTdsUnit
fun refreshCharts()
{
val sets = arrayListOf()
- tdsValues[selectedUnit]?.let { values ->
+ viewModel.tdsValues[selectedUnit]?.let { values ->
sets += LineDataSet(values, getString(selectedUnit.strRes)).apply {
- color = statsColours[tdsValues.keys.indexOfFirst { it == selectedUnit }.absoluteValue % statsColours.size]
+ color = statsColours[viewModel.tdsValues.keys.indexOfFirst { it == selectedUnit }.absoluteValue % statsColours.size]
fillColor = color
setCircleColor(color)
styleDataset(context!!, this, color)
}
sets += LineDataSet(values.rollingAverage(), getString(R.string.stat_average_tds, selectedUnit.label)).apply {
- color = ColorUtils.blendARGB(statsColours[tdsValues.keys.indexOfFirst { it == selectedUnit }.absoluteValue % statsColours.size], 0xffffffff.toInt(), 0.4f)
+ color = ColorUtils.blendARGB(statsColours[viewModel.tdsValues.keys.indexOfFirst { it == selectedUnit }.absoluteValue % statsColours.size], 0xffffffff.toInt(), 0.4f)
setDrawCircles(false)
setDrawValues(false)
setDrawCircleHole(false)
@@ -903,7 +923,7 @@ class StatisticsFragment2 : Fragment()
{
tds_stats_container.removeAllViews()
- tdsStats[selectedUnit]?.let { stat ->
+ viewModel.tdsStats[selectedUnit]?.let { stat ->
val stats = arrayListOf()
stats += header(getString(selectedUnit.strRes))
@@ -932,7 +952,7 @@ class StatisticsFragment2 : Fragment()
}
}
- val values = TdsUnit.values().filter { it in tdsValues.keys }
+ val values = TdsUnit.values().filter { it in viewModel.tdsValues.keys }
if (values.size > 1)
{
values.forEach { unit ->
@@ -956,7 +976,7 @@ class StatisticsFragment2 : Fragment()
else
{
tds_chips_container.isVisible = false
- selectedUnit = values.firstOrNull() ?: selectedTdsUnit
+ selectedUnit = values.firstOrNull() ?: viewModel.selectedTdsUnit
}
with (tds_chart) {
@@ -988,14 +1008,14 @@ class StatisticsFragment2 : Fragment()
private fun populateTempStats()
{
with (temp_chart) {
- setVisibleYRangeMaximum(tempStats.max?.toFloat() ?: 0.0f, YAxis.AxisDependency.LEFT)
+ setVisibleYRangeMaximum(viewModel.tempStats.max?.toFloat() ?: 0.0f, YAxis.AxisDependency.LEFT)
style()
axisLeft.valueFormatter = object : ValueFormatter()
{
override fun getAxisLabel(value: Float, axis: AxisBase?): String
{
- return "${value.formatWhole()}°${selectedTempUnit.label}"
+ return "${value.formatWhole()}°${viewModel.selectedTempUnit.label}"
}
}
@@ -1005,7 +1025,7 @@ class StatisticsFragment2 : Fragment()
{
val color = temp_chart.data.dataSets[highlight.dataSetIndex].color
with (this.findViewById(R.id.content)) {
- text = "${e.y.formatWhole()}°${selectedTempUnit.label}"
+ text = "${e.y.formatWhole()}°${viewModel.selectedTempUnit.label}"
setTextColor(color)
}
@@ -1020,14 +1040,14 @@ class StatisticsFragment2 : Fragment()
val sets = arrayListOf()
- sets += LineDataSet(tempValues, getString(R.string.stat_input_ph)).apply {
+ sets += LineDataSet(viewModel.tempValues, getString(R.string.stat_input_ph)).apply {
color = statsColours[0]
fillColor = color
setCircleColor(color)
styleDataset(context!!, this, color)
}
- sets += LineDataSet(tempValues.rollingAverage(), getString(R.string.stat_average_temp)).apply {
+ sets += LineDataSet(viewModel.tempValues.rollingAverage(), getString(R.string.stat_average_temp)).apply {
color = ColorUtils.blendARGB(statsColours[0], 0xffffffff.toInt(), 0.4f)
setDrawCircles(false)
setDrawValues(false)
@@ -1041,24 +1061,24 @@ class StatisticsFragment2 : Fragment()
temp_chart.data = LineData(sets)
val stats = arrayListOf()
- tempStats.min?.let {
+ viewModel.tempStats.min?.let {
stats += data(
label = getString(R.string.min),
- data = "${it.formatWhole()}°${selectedTempUnit.label}"
+ data = "${it.formatWhole()}°${viewModel.selectedTempUnit.label}"
)
}
- tempStats.max?.let {
+ viewModel.tempStats.max?.let {
stats += data(
label = getString(R.string.max),
- data = "${it.formatWhole()}°${selectedTempUnit.label}"
+ data = "${it.formatWhole()}°${viewModel.selectedTempUnit.label}"
)
}
- tempStats.average?.let {
+ viewModel.tempStats.average?.let {
stats += data(
label = getString(R.string.ave),
- data = "${it.formatWhole()}°${selectedTempUnit.label}"
+ data = "${it.formatWhole()}°${viewModel.selectedTempUnit.label}"
)
}
diff --git a/app/src/main/java/me/anon/lib/export/ExportHelper.kt b/app/src/main/java/me/anon/lib/export/ExportHelper.kt
index 1c875dd6..59c76eb9 100644
--- a/app/src/main/java/me/anon/lib/export/ExportHelper.kt
+++ b/app/src/main/java/me/anon/lib/export/ExportHelper.kt
@@ -6,16 +6,36 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
+import android.graphics.Color
+import android.graphics.Typeface
import android.os.AsyncTask
import android.os.Environment
import android.view.View
import android.view.ViewGroup
+import android.widget.TextView
+import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.app.NotificationCompat
import androidx.core.content.FileProvider
+import androidx.core.graphics.ColorUtils
+import com.github.mikephil.charting.charts.HorizontalBarChart
import com.github.mikephil.charting.charts.LineChart
+import com.github.mikephil.charting.charts.PieChart
+import com.github.mikephil.charting.components.AxisBase
+import com.github.mikephil.charting.components.LegendEntry
+import com.github.mikephil.charting.components.MarkerView
+import com.github.mikephil.charting.components.YAxis
+import com.github.mikephil.charting.data.*
+import com.github.mikephil.charting.formatter.ValueFormatter
+import com.github.mikephil.charting.highlight.Highlight
+import com.github.mikephil.charting.interfaces.datasets.IBarDataSet
+import com.github.mikephil.charting.interfaces.datasets.ILineDataSet
+import com.github.mikephil.charting.utils.MPPointF
+import kotlinx.android.synthetic.main.statistics2_view.*
import me.anon.grow.R
+import me.anon.grow.fragment.StatisticsFragment2
import me.anon.lib.TdsUnit
import me.anon.lib.TempUnit
+import me.anon.lib.ext.*
import me.anon.lib.helper.NotificationHelper
import me.anon.lib.helper.StatsHelper
import me.anon.lib.helper.TimeHelper
@@ -31,6 +51,8 @@ import java.text.SimpleDateFormat
import java.time.format.DateTimeFormatter
import java.util.*
import kotlin.collections.ArrayList
+import kotlin.math.absoluteValue
+import kotlin.math.max
/**
* // TODO: Add class description
@@ -41,6 +63,12 @@ class ExportHelper(
val includeImages: Boolean = true
)
{
+ private val statsColours by lazy {
+ context.resources.getStringArray(R.array.stats_colours).map {
+ Color.parseColor(it)
+ }
+ }
+
public fun exportPlants(plants: ArrayList)
{
val intent = Intent(context, ExportService::class.java)
@@ -96,11 +124,12 @@ class ExportHelper(
params.compressionLevel = Zip4jConstants.DEFLATE_LEVEL_NORMAL
garden?.let {
- val processor = exportProcessor.newInstance().apply {
- this.selectedDelivery = deliveryUnit
- this.selectedMeasurement = measureUnit
- this.selectedTemp = tempUnit
- this.selectedTds = tdsUnit
+ val processor = exportProcessor.newInstance().also {
+ it.context = context.applicationContext
+ it.selectedDelivery = deliveryUnit
+ it.selectedMeasurement = measureUnit
+ it.selectedTemp = tempUnit
+ it.selectedTds = tdsUnit
}
processor.beginDocument(false)
@@ -123,11 +152,12 @@ class ExportHelper(
}
plants.forEach { plant ->
- val processor = exportProcessor.newInstance().apply {
- this.selectedDelivery = deliveryUnit
- this.selectedMeasurement = measureUnit
- this.selectedTemp = tempUnit
- this.selectedTds = tdsUnit
+ val processor = exportProcessor.newInstance().also {
+ it.context = context.applicationContext
+ it.selectedDelivery = deliveryUnit
+ it.selectedMeasurement = measureUnit
+ it.selectedTemp = tempUnit
+ it.selectedTds = tdsUnit
}
processor.beginDocument()
@@ -189,10 +219,12 @@ class ExportHelper(
val width = 1024 + (totalWater * 20)
val height = 512
- saveTempChart(width, height, plant, zipPathPrefix, outFile)
- saveTdsCharts(width, height, plant, zipPathPrefix, outFile)
- saveInputPhChart(width, height, plant, zipPathPrefix, outFile)
- saveAdditiveChart(width, height, plant, zipPathPrefix, outFile)
+ val viewModel = StatisticsFragment2.StatisticsViewModel(tdsUnit, deliveryUnit, measureUnit, tempUnit, plant)
+ saveStagesChart(1024 + (viewModel.totalDays * 20).toInt(), height, viewModel, zipPathPrefix, outFile)
+ saveTempChart(width, height, viewModel, zipPathPrefix, outFile)
+ saveTdsCharts(width, height, viewModel, zipPathPrefix, outFile)
+ saveInputPhChart(width, height, viewModel, zipPathPrefix, outFile)
+ saveAdditiveChart(width, height, viewModel, zipPathPrefix, outFile)
processor.printRaw(plant)
processor.endDocument(outFile, zipPathPrefix)
@@ -413,34 +445,99 @@ class ExportHelper(
}
}
- private fun saveTempChart(width: Int, height: Int, plant: Plant, pathPrefix: String, outZip: ZipFile)
+ private fun saveStagesChart(width: Int, height: Int, viewModel: StatisticsFragment2.StatisticsViewModel, pathPrefix: String, outZip: ZipFile)
{
try
{
val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY)
val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)
- val temp = LineChart(context)
- temp.setExtraOffsets(30f, 30f, 30f, 30f)
- temp.setPadding(100, 100, 100, 100)
- temp.layoutParams = ViewGroup.LayoutParams(width, height)
- temp.minimumWidth = width
- temp.minimumHeight = height
- temp.measure(widthMeasureSpec, heightMeasureSpec)
- temp.requestLayout()
- temp.layout(0, 0, width, height)
- StatsHelper.setTempData(plant, context, temp, null)
- temp.data.setDrawValues(true)
+ val stagesChart = HorizontalBarChart(context)
+
+ with (stagesChart) {
+ setExtraOffsets(30f, 30f, 30f, 30f)
+ setPadding(100, 100, 100, 100)
+ layoutParams = ViewGroup.LayoutParams(width, height)
+ minimumWidth = width
+ minimumHeight = height
+ measure(widthMeasureSpec, heightMeasureSpec)
+ requestLayout()
+ layout(0, 0, width, height)
+
+ // stage chart
+ val labels = arrayOfNulls(viewModel.plantStages.size)
+ val yVals = FloatArray(viewModel.plantStages.size)
+
+ var index = viewModel.plantStages.size - 1
+ for (plantStage in viewModel.plantStages.keys)
+ {
+ yVals[index] = max(TimeHelper.toDays(viewModel.plantStages[plantStage] ?: 0).toFloat(), 1f)
+ labels[index--] = context.getString(plantStage.printString)
+ }
+
+ val stageEntries = arrayListOf()
+ stageEntries += BarEntry(0f, yVals, viewModel.plantStages.keys.toList().asReversed())
+
+ val stageData = BarDataSet(stageEntries, "")
+ stageData.isHighlightEnabled = false
+ stageData.stackLabels = labels
+ stageData.colors = statsColours
+ stageData.valueTypeface = Typeface.DEFAULT_BOLD
+ stageData.valueTextSize = 10f
+ stageData.valueFormatter = object : ValueFormatter()
+ {
+ override fun getBarStackedLabel(value: Float, stackedEntry: BarEntry?): String
+ {
+ stackedEntry?.let {
+ (it.data as? List)?.let { stages ->
+ val stageIndex = it.yVals.indexOf(value)
+ return "${value.toInt()}${context.getString(stages[stageIndex].printString)[0].toLowerCase()}"
+ }
+ }
+
+ return super.getBarStackedLabel(value, stackedEntry)
+ }
+ }
+
+ val barData = BarData(stageData)
+ data = barData
+ setDrawGridBackground(false)
+ description = null
+ isScaleYEnabled = false
+ setDrawBorders(false)
+ setDrawValueAboveBar(false)
+
+ axisLeft.setDrawGridLines(false)
+ axisLeft.axisMinimum = 0f
+ axisLeft.textColor = R.attr.colorOnSurface.resolveColor(context!!)
+ axisLeft.valueFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return "${value.toInt()}${context.getString(R.string.day_abbr)}"
+ }
+ }
+
+ axisRight.setDrawLabels(false)
+ axisRight.setDrawGridLines(false)
+
+ xAxis.setDrawGridLines(false)
+ xAxis.setDrawAxisLine(false)
+ xAxis.setDrawLabels(false)
+
+ legend.textColor = R.attr.colorOnSurface.resolveColor(context!!).toInt()
+ legend.isWordWrapEnabled = true
+ }
try
{
val parameters = ZipParameters()
parameters.compressionMethod = Zip4jConstants.COMP_DEFLATE
- parameters.fileNameInZip = pathPrefix + "temp.jpg"
+ parameters.fileNameInZip = pathPrefix + "stages.jpg"
parameters.isSourceExternalStream = true
val outputStream = ByteArrayOutputStream()
- temp.chartBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
+ stagesChart.chartBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
val stream = ByteArrayInputStream(outputStream.toByteArray())
outZip.addStream(stream, parameters)
@@ -457,22 +554,116 @@ class ExportHelper(
}
}
- private fun saveTdsCharts(width: Int, height: Int, plant: Plant, pathPrefix: String, outZip: ZipFile)
+ private fun saveTempChart(width: Int, height: Int, viewModel: StatisticsFragment2.StatisticsViewModel, pathPrefix: String, outZip: ZipFile)
{
- val tdsNames = TreeSet()
- for (action in plant.actions!!)
+ try
{
- if (action is Water && action.tds != null)
+ val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY)
+ val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)
+
+ val temp_chart = LineChart(context)
+ temp_chart.setExtraOffsets(30f, 30f, 30f, 30f)
+ temp_chart.setPadding(100, 100, 100, 100)
+ temp_chart.layoutParams = ViewGroup.LayoutParams(width, height)
+ temp_chart.minimumWidth = width
+ temp_chart.minimumHeight = height
+ temp_chart.measure(widthMeasureSpec, heightMeasureSpec)
+ temp_chart.requestLayout()
+ temp_chart.layout(0, 0, width, height)
+
+ with (temp_chart) {
+ setVisibleYRangeMaximum(viewModel.tempStats.max?.toFloat() ?: 0.0f, com.github.mikephil.charting.components.YAxis.AxisDependency.LEFT)
+ style()
+
+ axisLeft.valueFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return "${value.formatWhole()}°${viewModel.selectedTempUnit.label}"
+ }
+ }
+
+ marker = object : MarkerView(context, me.anon.grow.R.layout.chart_marker)
+ {
+ override fun refreshContent(e: Entry, highlight: Highlight): kotlin.Unit
+ {
+ val color = temp_chart.data.dataSets[highlight.dataSetIndex].color
+ kotlin.with(this.findViewById(me.anon.grow.R.id.content)) {
+ text = "${e.y.formatWhole()}°${viewModel.selectedTempUnit.label}"
+ setTextColor(color)
+ }
+
+ super.refreshContent(e, highlight)
+ }
+
+ override fun getOffset(): MPPointF = com.github.mikephil.charting.utils.MPPointF.getInstance(-(width / 2f), -(height * 1.2f))
+ }
+
+ xAxis.valueFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return viewModel.waterDates.getOrNull(value.toInt())?.transform {
+ "${total}/${day}${context.getString(stage.printString).toLowerCase()[0]}"
+ } ?: ""
+ }
+ }
+ }
+
+ val sets = arrayListOf()
+
+ sets += LineDataSet(viewModel.tempValues, context.getString(R.string.stat_input_ph)).apply {
+ color = statsColours[0]
+ fillColor = color
+ setCircleColor(color)
+ styleDataset(context!!, this, color)
+ }
+
+ sets += LineDataSet(viewModel.tempValues.rollingAverage(), context.getString(R.string.stat_average_temp)).apply {
+ color = ColorUtils.blendARGB(statsColours[0], 0xffffffff.toInt(), 0.4f)
+ setDrawCircles(false)
+ setDrawValues(false)
+ setDrawCircleHole(false)
+ setDrawHighlightIndicators(true)
+ cubicIntensity = 1f
+ lineWidth = 2.0f
+ isHighlightEnabled = false
+ }
+
+ temp_chart.data = LineData(sets)
+ temp_chart.data.setDrawValues(true)
+
+ try
+ {
+ val parameters = ZipParameters()
+ parameters.compressionMethod = Zip4jConstants.COMP_DEFLATE
+ parameters.fileNameInZip = pathPrefix + "temp.jpg"
+ parameters.isSourceExternalStream = true
+
+ val outputStream = ByteArrayOutputStream()
+ temp_chart.chartBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
+ val stream = ByteArrayInputStream(outputStream.toByteArray())
+ outZip.addStream(stream, parameters)
+
+ stream.close()
+ }
+ catch (e: Exception)
{
- tdsNames.add(action.tds!!.type)
+ e.printStackTrace()
}
}
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+ private fun saveTdsCharts(width: Int, height: Int, viewModel: StatisticsFragment2.StatisticsViewModel, pathPrefix: String, outZip: ZipFile)
+ {
val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY)
val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)
- for (tdsName in tdsNames)
- {
+ viewModel.tdsValues.forEach { (name, values) ->
val tds = LineChart(context)
tds.setExtraOffsets(30f, 30f, 30f, 30f)
tds.setPadding(100, 100, 100, 100)
@@ -482,14 +673,63 @@ class ExportHelper(
tds.measure(widthMeasureSpec, heightMeasureSpec)
tds.requestLayout()
tds.layout(0, 0, width, height)
- StatsHelper.setTdsData(plant, context, tds, null, tdsName)
- tds.data.setDrawValues(true)
+
+ with (tds) {
+ style()
+
+ marker = object : MarkerView(context, R.layout.chart_marker)
+ {
+ override fun refreshContent(e: Entry, highlight: Highlight): kotlin.Unit
+ {
+ val color = tds.data.dataSets[highlight.dataSetIndex].color
+ kotlin.with(this.findViewById(R.id.content)) {
+ text = e.y.formatWhole()
+ setTextColor(color)
+ }
+
+ super.refreshContent(e, highlight)
+ }
+
+ override fun getOffset(): MPPointF = MPPointF.getInstance(-(width / 2f), -(height * 1.2f))
+ }
+
+ xAxis.valueFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return viewModel.waterDates.getOrNull(value.toInt())?.transform {
+ "${total}/${day}${context.getString(stage.printString).toLowerCase()[0]}"
+ } ?: ""
+ }
+ }
+
+ val sets = arrayListOf()
+ sets += LineDataSet(values, context.getString(name.strRes)).apply {
+ color = statsColours[viewModel.tdsValues.keys.indexOfFirst { it == name }.absoluteValue % statsColours.size]
+ fillColor = color
+ setCircleColor(color)
+ styleDataset(context!!, this, color)
+ }
+ sets += LineDataSet(values.rollingAverage(), context.getString(R.string.stat_average_tds, name.label)).apply {
+ color = ColorUtils.blendARGB(statsColours[viewModel.tdsValues.keys.indexOfFirst { it == name }.absoluteValue % statsColours.size], 0xffffffff.toInt(), 0.4f)
+ setDrawCircles(false)
+ setDrawValues(false)
+ setDrawCircleHole(false)
+ setDrawHighlightIndicators(true)
+ cubicIntensity = 1f
+ lineWidth = 2.0f
+ isHighlightEnabled = false
+ }
+
+ data = LineData(sets)
+ data.setDrawValues(true)
+ }
try
{
val parameters = ZipParameters()
parameters.compressionMethod = Zip4jConstants.COMP_DEFLATE
- parameters.fileNameInZip = pathPrefix + tdsName.enStr + ".jpg"
+ parameters.fileNameInZip = pathPrefix + name.label + ".jpg"
parameters.isSourceExternalStream = true
val outputStream = ByteArrayOutputStream()
@@ -506,7 +746,7 @@ class ExportHelper(
}
}
- private fun saveInputPhChart(width: Int, height: Int, plant: Plant, pathPrefix: String, outZip: ZipFile)
+ private fun saveInputPhChart(width: Int, height: Int, viewModel: StatisticsFragment2.StatisticsViewModel, pathPrefix: String, outZip: ZipFile)
{
try
{
@@ -522,14 +762,80 @@ class ExportHelper(
inputPh.measure(widthMeasureSpec, heightMeasureSpec)
inputPh.requestLayout()
inputPh.layout(0, 0, width, height)
- StatsHelper.setInputData(plant, context, inputPh, null)
+
+ with (inputPh) {
+ setVisibleYRangeMaximum(kotlin.math.max(viewModel.phStats.max?.toFloat() ?: 0.0f, viewModel.runoffStats.max?.toFloat() ?: 0.0f), com.github.mikephil.charting.components.YAxis.AxisDependency.LEFT)
+ style()
+
+ marker = object : MarkerView(context, me.anon.grow.R.layout.chart_marker)
+ {
+ override fun refreshContent(e: Entry, highlight: Highlight): kotlin.Unit
+ {
+ val color = inputPh.data.dataSets[highlight.dataSetIndex].color
+ kotlin.with(this.findViewById(me.anon.grow.R.id.content)) {
+ text = e.y.formatWhole()
+ setTextColor(color)
+ }
+
+ super.refreshContent(e, highlight)
+ }
+
+ override fun getOffset(): MPPointF = com.github.mikephil.charting.utils.MPPointF.getInstance(-(width / 2f), -(height * 1.2f))
+ }
+
+ xAxis.valueFormatter = object : ValueFormatter()
+ {
+ override fun getAxisLabel(value: Float, axis: AxisBase?): String
+ {
+ return viewModel.waterDates.getOrNull(value.toInt())?.transform {
+ "${total}/${day}${context.getString(stage.printString).toLowerCase()[0]}"
+ } ?: ""
+ }
+ }
+ }
+
+ val sets = arrayListOf()
+ sets += LineDataSet(viewModel.phValues, context.getString(R.string.stat_input_ph)).apply {
+ color = statsColours[0]
+ fillColor = color
+ setCircleColor(color)
+ styleDataset(context!!, this, color)
+ }
+ sets += LineDataSet(viewModel.phValues.rollingAverage(), context.getString(R.string.stat_average_runoff_ph)).apply {
+ color = ColorUtils.blendARGB(statsColours[0], 0xffffffff.toInt(), 0.4f)
+ setDrawCircles(false)
+ setDrawValues(false)
+ setDrawCircleHole(false)
+ setDrawHighlightIndicators(true)
+ cubicIntensity = 1f
+ lineWidth = 2.0f
+ isHighlightEnabled = false
+ }
+ sets += LineDataSet(viewModel.runoffValues, context.getString(R.string.stat_runoff_ph)).apply {
+ color = statsColours[1]
+ fillColor = color
+ setCircleColor(color)
+ styleDataset(context!!, this, color)
+ }
+ sets += LineDataSet(viewModel.runoffValues.rollingAverage(), context.getString(R.string.stat_average_runoff_ph)).apply {
+ color = ColorUtils.blendARGB(statsColours[1], 0xffffffff.toInt(), 0.4f)
+ setDrawCircles(false)
+ setDrawValues(false)
+ setDrawCircleHole(false)
+ setDrawHighlightIndicators(true)
+ cubicIntensity = 1f
+ lineWidth = 2.0f
+ isHighlightEnabled = false
+ }
+
+ inputPh.data = LineData(sets)
inputPh.data.setDrawValues(true)
try
{
val parameters = ZipParameters()
parameters.compressionMethod = Zip4jConstants.COMP_DEFLATE
- parameters.fileNameInZip = pathPrefix + "input-ph.jpg"
+ parameters.fileNameInZip = pathPrefix + "ph.jpg"
parameters.isSourceExternalStream = true
val outputStream = ByteArrayOutputStream()
@@ -550,56 +856,345 @@ class ExportHelper(
}
}
- private fun saveAdditiveChart(width: Int, height: Int, plant: Plant, pathPrefix: String, outZip: ZipFile)
+ private fun saveAdditiveChart(width: Int, height: Int, viewModel: StatisticsFragment2.StatisticsViewModel, pathPrefix: String, outZip: ZipFile)
{
- try
+ val entries = arrayListOf