From b70ab9d3d8d954b6ae9ec91024efff75ab271936 Mon Sep 17 00:00:00 2001 From: cstrider Date: Wed, 21 Apr 2021 16:02:07 -0400 Subject: [PATCH] 3/25/2021 changes with grapher and gradle and settings and androidmanifest.xml. --- .idea/.name | 1 + .idea/codeStyles/Project.xml | 117 +++++ .idea/codeStyles/codeStyleConfig.xml | 5 + app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 11 +- .../stormwaterutilityandroid/GraphPicker.java | 196 +++++++ .../sf/stormwaterutilityandroid/Grapher.java | 218 ++++++++ .../stormwaterutilityandroid/PDFCreator.java | 481 ++++++++++++++++++ .../ReportAdapter.java | 4 + .../sf/stormwaterutilityandroid/Settings.java | 82 ++- .../WaterWay/WaterWayReportFragment.java | 14 +- .../WaterwayReportDetail.java | 284 +++++++++++ app/src/main/res/layout/activity_graph.xml | 32 ++ app/src/main/res/layout/activity_pdf.xml | 6 + .../main/res/layout/activity_pick_graph.xml | 130 +++++ app/src/main/res/layout/activity_reports.xml | 8 + app/src/main/res/layout/activity_settings.xml | 53 +- .../activity_waterway_report_detail.xml | 8 + build.gradle | 3 + 19 files changed, 1652 insertions(+), 5 deletions(-) create mode 100644 .idea/.name create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 app/src/main/java/com/sf/stormwaterutilityandroid/GraphPicker.java create mode 100644 app/src/main/java/com/sf/stormwaterutilityandroid/Grapher.java create mode 100644 app/src/main/java/com/sf/stormwaterutilityandroid/PDFCreator.java create mode 100644 app/src/main/res/layout/activity_graph.xml create mode 100644 app/src/main/res/layout/activity_pdf.xml create mode 100644 app/src/main/res/layout/activity_pick_graph.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..c6e7f40 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +StormWaterUtilityAndroid \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..4bec4ea --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,117 @@ + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index e22b778..21fe081 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -30,7 +30,9 @@ android { } dependencies { - + //Added this: + implementation 'com.github.AnyChart:AnyChart-Android:0.0.3' + //Done adding implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.1' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7da3a10..cf8367b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,13 +2,19 @@ + + + + + android:theme="@style/Theme.StormWaterUtilityAndroid" + android:requestLegacyExternalStorage="true"> + @@ -17,6 +23,9 @@ + + + diff --git a/app/src/main/java/com/sf/stormwaterutilityandroid/GraphPicker.java b/app/src/main/java/com/sf/stormwaterutilityandroid/GraphPicker.java new file mode 100644 index 0000000..5244c9c --- /dev/null +++ b/app/src/main/java/com/sf/stormwaterutilityandroid/GraphPicker.java @@ -0,0 +1,196 @@ +package com.sf.stormwaterutilityandroid; + +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.NumberPicker; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; + +import com.anychart.anychart.AnyChart; +import com.anychart.anychart.AnyChartView; +import com.anychart.anychart.Cartesian; +import com.anychart.anychart.DataEntry; +import com.anychart.anychart.StrokeLineCap; +import com.anychart.anychart.StrokeLineJoin; +import com.anychart.anychart.ValueDataEntry; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.firestore.FirebaseFirestore; +import com.google.firebase.firestore.Query; +import com.google.firebase.firestore.QueryDocumentSnapshot; +import com.google.firebase.firestore.QuerySnapshot; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class GraphPicker extends AppCompatActivity { + private NumberPicker np1, np2, np3, np4, np5, np6, np7, np8; + private Button btnGen; + int docCount = 0; + String sitePicked = new String(); + String formPicked = new String(); + String startMonthPicked = new String(); + int startDayPicked = 0; + int startYearPicked = 2000; + String endMonthPicked = new String(); + int endDayPicked = 0; + int endYearPicked = 2000; + + //Added for firebase stuff + private FirebaseAuth mAuth; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_pick_graph); + btnGen = findViewById(R.id.generate_button); + setupPickers(); + btnGen.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String[] forms1 = np1.getDisplayedValues(); + String[] sites1 = np2.getDisplayedValues(); + String[] startM = np3.getDisplayedValues(); + String[] endM = np6.getDisplayedValues(); + formPicked = String.valueOf(forms1[np1.getValue()]); + sitePicked = String.valueOf(sites1[np2.getValue()]); + startMonthPicked = String.valueOf(startM[np3.getValue()]); + startDayPicked = np4.getValue(); + startYearPicked = np5.getValue(); + + endMonthPicked = String.valueOf(endM[np6.getValue()]); + endDayPicked = np7.getValue(); + endYearPicked = np8.getValue(); + Log.d("TEST", "Form Picked = " + formPicked); + Log.d("TEST", "Site Picked = " + sitePicked); + Log.d("TEST", "start month = " + startMonthPicked); + Log.d("TEST", "start day = " + startDayPicked); + Log.d("TEST", "start year = " + startYearPicked); + Log.d("TEST", "end month = " + endMonthPicked); + Log.d("TEST", "end day = " + endDayPicked); + Log.d("TEST", "end year = " + endYearPicked); + + Intent intent = new Intent(GraphPicker.this, Grapher.class); + Bundle extras = new Bundle(); + extras.putString("FORM_CHOICE", formPicked); + extras.putString("SITE_CHOICE", sitePicked); + extras.putString("START_MONTH", startMonthPicked); + extras.putString("END_MONTH", endMonthPicked); + extras.putInt("START_DAY", startDayPicked); + extras.putInt("END_DAY", endDayPicked); + extras.putInt("START_YEAR", startYearPicked); + extras.putInt("END_YEAR", endYearPicked); + Log.d("graph", "ORIGINAL Collection string is " + formPicked); + Log.d("graph", "ORIGINAL Site string is " + sitePicked); + intent.putExtras(extras); + startActivity(intent); + } + }); + } + + public void setupPickers() { + //TODO: QUERY FIREBASE FOR THIS INFO + np1 = findViewById(R.id.pickForm); + np2 = findViewById(R.id.pickSite); + np3 = findViewById(R.id.pickStartMonth); + np4 = findViewById(R.id.pickStartDay); + np5 = findViewById(R.id.pickStartYear); + np6 = findViewById(R.id.pickEndMonth); + np7 = findViewById(R.id.pickEndDay); + np8 = findViewById(R.id.pickEndYear); + + //TODO: Accomodate Construction form at some point + String[] forms = {"Waterway"};//, "Construction"}; + np1.setMaxValue(forms.length - 1); + np1.setDisplayedValues(forms); + np1.setWrapSelectorWheel(false); + + //TODO: limit choices to forms? + Query WaterwaySites = FirebaseFirestore.getInstance().collection("Forms").document("purdue.edu").collection("Waterway").orderBy("SortTimeStamp", Query.Direction.ASCENDING); + WaterwaySites.get().addOnCompleteListener(this, new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + Log.d("Grapher", "Got into This thing"); + if (task.isSuccessful()) { + docCount = task.getResult().size(); + String[] WaterSites = new String[docCount]; + int i = 0; + for (QueryDocumentSnapshot document : task.getResult()) { + //Check if the string already exists in the WaterSites + if (Arrays.stream(WaterSites).anyMatch(document.getString("H_site_name")::equals)) { + //Then don't add it in + //Log.d("Graph", "This arrays things was true"); + } + else { + //Log.d("Graph", "This arrays thing was false"); + WaterSites[i] = document.getString("H_site_name"); + i++; + } + } + String[] actualSites = new String[i]; + for (int j = 0; j < i; j++) { + actualSites[j] = WaterSites[j]; + Log.d("Graph", "actualSites["+String.valueOf(j)+"] ="+String.valueOf(actualSites[j])); + } + np2.setMaxValue(actualSites.length - 1);//WaterSites.length - 1); + np2.setDisplayedValues(actualSites);//WaterSites); + np2.setWrapSelectorWheel(false); + } else { + Log.d("Graph", "Error getting documents: ", task.getException()); + } + Log.d("Graph", "docCount" + docCount); + } + }); + + String[] months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; + String[] days = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", + "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"}; + String[] years = {"1990", "1991", "1992", "1993", "1994", "1995", "1996", "1997", "1998", "1999", + "2000", "2001", "2002", "2003", "2004", "2005", "2006", "2007", "2008", "2009", + "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", + "2020", "2021", "2022", "2023", "2024", "2025", "2026", "2027", "2028", "2029"}; + + np3.setMaxValue(months.length - 1); + np3.setDisplayedValues(months); + np3.setWrapSelectorWheel(false); + np6.setMaxValue(months.length - 1); + np6.setDisplayedValues(months); + np6.setWrapSelectorWheel(false); + + /*np4.setMaxValue(days.length - 1); + np4.setDisplayedValues(days); + np7.setMaxValue(days.length - 1); + np7.setDisplayedValues(days);*/ + np4.setMinValue(1); + np4.setMaxValue(31); + np7.setMinValue(1); + np7.setMaxValue(31); + + /*np5.setMaxValue(years.length - 1); + np5.setDisplayedValues(years); + np8.setMaxValue(years.length - 1); + np8.setDisplayedValues(years);*/ + np5.setMinValue(1980); + np5.setMaxValue(2030); + np5.setWrapSelectorWheel(false); + np8.setMinValue(1980); + np8.setMaxValue(2030); + np8.setWrapSelectorWheel(false); + } + + public void pickerValues() { + + } +} diff --git a/app/src/main/java/com/sf/stormwaterutilityandroid/Grapher.java b/app/src/main/java/com/sf/stormwaterutilityandroid/Grapher.java new file mode 100644 index 0000000..b1ebff9 --- /dev/null +++ b/app/src/main/java/com/sf/stormwaterutilityandroid/Grapher.java @@ -0,0 +1,218 @@ +package com.sf.stormwaterutilityandroid; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; + +import com.anychart.anychart.AnyChart; +import com.anychart.anychart.AnyChartView; +import com.anychart.anychart.Cartesian; +import com.anychart.anychart.DataEntry; +import com.anychart.anychart.LegendItemProvider; +import com.anychart.anychart.Mapping; +import com.anychart.anychart.Set; +import com.anychart.anychart.StrokeLineCap; +import com.anychart.anychart.StrokeLineJoin; +import com.anychart.anychart.ValueDataEntry; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.android.gms.tasks.TaskCompletionSource; +import com.google.android.material.bottomnavigation.BottomNavigationView; +import com.google.firebase.auth.AuthCredential; +import com.google.firebase.auth.EmailAuthProvider; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.firestore.CollectionReference; +import com.google.firebase.firestore.DocumentSnapshot; +import com.google.firebase.firestore.FirebaseFirestore; +import com.google.firebase.firestore.Query; +import com.google.firebase.firestore.QueryDocumentSnapshot; +import com.google.firebase.firestore.QuerySnapshot; +import com.sf.stormwaterutilityandroid.WaterWay.PTI; +import com.sf.stormwaterutilityandroid.WaterWay.WQI; +import com.sf.stormwaterutilityandroid.WaterWay.WaterWay; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Grapher extends AppCompatActivity { + int docCount = 0; + String collection_string = "Waterway";//new String(); + String site_string = "Purdue";//new String(); + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_graph); + Intent intentPrev = getIntent(); + Bundle extrasPrev = intentPrev.getExtras(); + site_string = extrasPrev.getString("SITE_CHOICE"); + collection_string = extrasPrev.getString("FORM_CHOICE"); + //BottomNavigationView navView = findViewById(R.id.nav_view); + Log.d("Grapher", "Got to the graphing function"); + Log.d("graph", "Collection string is " + collection_string); + Log.d("graph", "Site string is " + site_string); + grapher(); + } + + public void grapher() { + if (collection_string == "Construction") { + Toast.makeText(this, "Sorry. That isn't currently supported", Toast.LENGTH_SHORT).show(); + return; + } + Log.d("graph", "collection_string = " + String.valueOf(collection_string)); + Query purdueThings = FirebaseFirestore.getInstance().collection("Forms").document("purdue.edu").collection(String.valueOf(collection_string))//"Waterway")//collection_string) + .orderBy("SortTimeStamp", Query.Direction.ASCENDING).whereEqualTo("H_site_name", String.valueOf(site_string));//"SD"); + Log.d("Grapher", "Firebase first is fine"); + + purdueThings.get().addOnCompleteListener(this, new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + Log.d("Grapher", "Got into This thing"); + if (task.isSuccessful()) { + docCount = task.getResult().size(); + String[] dates = new String[docCount]; + Object[] PTIs = new Object[docCount]; + Object[] WQIs = new Object[docCount]; + Object[] HEIs = new Object[docCount]; + int i = 0; + for (QueryDocumentSnapshot document : task.getResult()) {//DocumentSnapshot document : task.getResult()) { + //docCount++; + //Log.d("graph", document.getData()); + dates[i] = document.getString("H_date");//"SortTimeStamp");//Or H_date + Log.d("graph", "Other thing = " + dates[i]); + Map obMap = new HashMap<>(); + HashMap dubMap = new HashMap(); + + //document.toObject(WaterWay.class); + //Log.d("graph", "WaterWayDoubleFields = " + document.WaterWayDoubleFields) + obMap = document.getData(/*"doubleFields"*/); + //Log.d("graph", "Intermediate = " + obMap.get("doubleFields")); + dubMap = (HashMap) obMap.get("doubleFields"); + HashMap longMap = new HashMap(); + longMap = (HashMap) obMap.get("doubleFields"); + //Log.d("graph", "dubMap = " + dubMap.get("PTI").getClass()); + Log.d("graph", "test PTI = " + longMap.get("PTI").getClass());//It's a hashmap + PTIs[i] = longMap.get("PTI");//(double) dubMap.get("PTI");//.doubleValue();//calc_PTI(dubMap); + WQIs[i] = longMap.get("WQI");//(double) dubMap.get("WQI");//calc_WQI(dubMap); + HEIs[i] = longMap.get("QHEI");//(double) dubMap.get("QHEI");//calc_HEI(dubMap); + //scores[i] = (Double) dubMap.get("BM_fairly_tolerant");//document.get("BM_fairly_tolerant");//Double.parseDouble(document.getString("BM_fairly_tolerant"));//TODO: Change me. This is a filler value + i++; + Log.d("Grapher", document.getId() + " => " + document.getData()); + } + AnyChartView anyChartView = (AnyChartView) findViewById(R.id.any_chart_view); + Cartesian line_chart = AnyChart.line(); + + line_chart.setXGrid(true); + line_chart.setYGrid(true); + line_chart.setYAxis("Y Axis"); + line_chart.setXAxis("X Axis");//.labels().padding(5d, 5d, 5d, 5d); + + List data = new ArrayList<>(); + List data2 = new ArrayList<>(); + List data3 = new ArrayList<>(); + //List seriesData = new ArrayList<>(); + Object[][] stuff = new Object[docCount][4]; + for (int x = 0; x < docCount; x++) { + stuff[x][0] = dates[x]; + stuff[x][1] = PTIs[x]; + stuff[x][2] = WQIs[x]; + stuff[x][3] = HEIs[x]; + Log.d("graph", "Stuff = " + stuff[x][1] + "," + stuff[x][2] + "," + stuff[x][3]); + //Log.d("Graph", "stuff=" + scores[x]); + ////data.add(new ValueDataEntry(dates[x], PTIs[x], WQIs[x], HEIs[x])); + Double a = Double.parseDouble(String.valueOf(PTIs[x])); + Double b = Double.parseDouble(String.valueOf(WQIs[x])); + Double c = Double.parseDouble(String.valueOf(HEIs[x])); + data.add(new ValueDataEntry(dates[x], Double.valueOf(a)));//Double.valueOf(scores[x]))); + data2.add(new ValueDataEntry(dates[x], Double.valueOf(b))); + data3.add(new ValueDataEntry(dates[x], Double.valueOf(c))); + //seriesData.add(new CustomDataEntry(dates[x], a, b, c)); + //data.add(Integer.valueOf(dates[x]), (DataEntry) PTIs[x]); + } + //Set set = new Set(); + //set.setData("foo", seriesData); + //line_chart.setLegend("test"); + + + line_chart.line(data).setStroke("red", 1.0, "-", StrokeLineJoin.ROUND, StrokeLineCap.ROUND).setName("PTI").setLegendItem("PTI").setId("PTI").setMarkers(true).getLegendItem().setText("PTI").setIconEnabled(true); + //line_chart.setLineMarker("Test"); + line_chart.line(data2).setStroke("green", 1.0, "-", StrokeLineJoin.ROUND, StrokeLineCap.ROUND).setName("WQI").setLegendItem("WQI").setMarkers(true); + line_chart.line(data3).setStroke("blue", 1.0, "-", StrokeLineJoin.ROUND, StrokeLineCap.ROUND).setName("QHEI").setLegendItem("QHEI").setMarkers(true); + line_chart.setTitle(true); + //String title = new String(); + //title = "Selected Report: Waterway" + System.getProperty("line.separator") + "Selected Site: Purdue"; + line_chart.setTitle("Selected Report: Waterway"); + + + line_chart.setLegend(true).setLabel("PTI").setLabel("WQI").setLabel("QHEI").setEnabled(true); + line_chart.getLegend().setPosition("right"); + line_chart.getLegend().setItemsLayout("horizontal"); + line_chart.getLegend().setAlign("top"); + line_chart.getLegend().setItemsSourceMode("series");//or categories? + line_chart.getLegend().setPositionMode("inside"); + + //LegendItemProvider[] legendItems = new LegendItemProvider[]{}; + + //line_chart.getLegend().setItems([{0, "Chrome", "circle", "#01579B", "#0091EA"}]); + + line_chart.setLegend(true).draw(true); + + + //line_chart.setTitle("Selected Site: Purdue"); + //line_chart.setLegend("TEST"); + //line_chart.getLegend(); + //String[] labels = new String[3]; + line_chart.setLabels(true); + //line_chart.setLabel + //labels = ["PTI", "WQI", "QHEI"]; + //line_chart.setLabels(labels); + /*line_chart.setData(data);//([[data], [data2], [data3]]); + //line_chart.legend(true); + line_chart.setTitle("PTI"); + line_chart.setLabels("PTI"); + line_chart.setLegend(true); + line_chart.setSelectMarqueeStroke("red", 10.0, "-", StrokeLineJoin.ROUND, StrokeLineCap.ROUND); + //line_chart.name("PTI"); + //line_chart.stroke(); + + line_chart2.setData(data2); + line_chart2.setTitle("WQI"); + line_chart2.setLabels("WQI"); + line_chart2.setLegend(true); + line_chart2.setSelectMarqueeStroke("green", 10.0, "-", StrokeLineJoin.ROUND, StrokeLineCap.ROUND); + + line_chart3.setData(data3); + //line_chart.legend(true); + line_chart3.setTitle("QHEI"); + line_chart3.setLabels("QHEI"); + line_chart3.setLegend(true); + line_chart3.setSelectMarqueeStroke("blue", 10.0, "-", StrokeLineJoin.ROUND, StrokeLineCap.ROUND); + line_chart.draw(true); + line_chart2.draw(true); + line_chart3.draw(true);*/ + anyChartView.setChart(line_chart); + } else { + Log.d("Grapher", "Error getting documents: ", task.getException()); + } + Log.d("Grapher", "docCount" + docCount); + } + }); + } + + public class CustomDataEntry extends ValueDataEntry { + CustomDataEntry(String x, Number value, Number value2, Number value3) { + super(x, (Double) value); + setValue("value2", value2); + setValue("value3", value3); + } + } +} diff --git a/app/src/main/java/com/sf/stormwaterutilityandroid/PDFCreator.java b/app/src/main/java/com/sf/stormwaterutilityandroid/PDFCreator.java new file mode 100644 index 0000000..85ba1c1 --- /dev/null +++ b/app/src/main/java/com/sf/stormwaterutilityandroid/PDFCreator.java @@ -0,0 +1,481 @@ +package com.sf.stormwaterutilityandroid; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.graphics.pdf.PdfDocument; +import android.graphics.pdf.PdfDocument.PageInfo; +import android.graphics.pdf.PdfDocument.Page; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.util.Log; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import com.anychart.anychart.AnyChart; +import com.anychart.anychart.AnyChartView; +import com.anychart.anychart.Cartesian; +import com.anychart.anychart.DataEntry; +import com.anychart.anychart.ValueDataEntry; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.android.gms.tasks.TaskCompletionSource; +import com.google.android.material.bottomnavigation.BottomNavigationView; +import com.google.firebase.auth.AuthCredential; +import com.google.firebase.auth.EmailAuthProvider; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.firestore.CollectionReference; +import com.google.firebase.firestore.DocumentSnapshot; +import com.google.firebase.firestore.FirebaseFirestore; +import com.google.firebase.firestore.Query; +import com.google.firebase.firestore.QueryDocumentSnapshot; +import com.google.firebase.firestore.QuerySnapshot; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import androidx.core.content.ContextCompat; + +import static android.Manifest.permission.READ_EXTERNAL_STORAGE; +import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; + +public class PDFCreator extends AppCompatActivity{ + //private LinearLayout llPdf; + //private Bitmap bitmap; + private static final int PERMISSION_REQUEST_CODE = 200; + //private static PDFCreator mContext; + String title; + String [] label; + String [] body; + static Map strMap = new HashMap<>(); + static Map dubMap = new HashMap<>(); + static Map boolMap = new HashMap<>(); + static { + dubMap.put("WQI", 16.786); + dubMap.put("PTI", 20.0); + dubMap.put("QHEI", 24.0); + + strMap.put("H_inspector_name", "JL"); + strMap.put("H_site_name", "Test1"); + strMap.put("H_date", "03-30-2021");//TODO: What are inspector, site and date? + strMap.put("GOD_outfall", ""); + strMap.put("GOD_longitude", ""); + strMap.put("GOD_latitude", ""); + strMap.put("GOD_invert_elevation", ""); + strMap.put("GOD_type", ""); + strMap.put("GOD_pipe_size", ""); + strMap.put("GOD_channel_bottom_width", ""); + strMap.put("GOD_receiving_water", ""); + + boolMap.put("DWS_presence_of_flow", true); + boolMap.put("DWS_unusual_odor", true); + boolMap.put("DWS_unusual_color", true); + boolMap.put("DWS_polutants", false); + boolMap.put("DWS_obstruction", false); + boolMap.put("DWS_needs_maintenance", true); + boolMap.put("DWS_screened_OK", false); + + boolMap.put("FC_routine_evaluation", false); + boolMap.put("FC_complaint_investigation", true); + boolMap.put("FC_illicit_discharge_detected", true); + boolMap.put("FC_no_illicit_discharge_detected", false); + boolMap.put("FC_further_action_needed", false); + + dubMap.put("CT_temperature_change", 2.0); + dubMap.put("CT_turbidity", 144.0); + dubMap.put("CT_pH", 8.0); + dubMap.put("CT_nitrate", 15.0); + dubMap.put("CT_total_phosphate", 0.6); + dubMap.put("CT_dissolved_oxygen", 6.0); + dubMap.put("CT_E_coli", 150.0); + + strMap.put("CT_other1", ""); + strMap.put("CT_other2", ""); + + dubMap.put("BM_intolerant", 1.0); + dubMap.put("BM_moderately_tolerant", 4.0); + dubMap.put("BM_fairly_tolerant", 1.0); + dubMap.put("BM_very_tolerant", 2.0); + + strMap.put("HQ_substrate_size", ""); + strMap.put("HQ_smothering", "5: No"); + strMap.put("HQ_silting", "5: No"); + strMap.put("HQ_rootwads", ""); + strMap.put("HQ_overhanging_veg", "0: No"); + strMap.put("HQ_oxbowsblack_waters", ""); + strMap.put("HQ_downed_treeslogs", ""); + strMap.put("HQ_shallows", ""); + strMap.put("HQ_water_plants", ""); + strMap.put("HQ_deep_pools", ""); + strMap.put("HQ_logswoody_debris", ""); + strMap.put("HQ_boulders", ""); + strMap.put("HQ_undercut_banks", ""); + strMap.put("HQ_sinuosity", ""); + strMap.put("HQ_natural", ""); + strMap.put("HQ_riparian_width", "5: narrow (Less than 20')"); + strMap.put("HQ_land_use", ""); + strMap.put("HQ_bank_erosion", ""); + strMap.put("HQ_stream_shading", "3: Mostly"); + strMap.put("HQ_deepest_pool", ""); + strMap.put("HQ_velocity", ""); + strMap.put("HQ_rifflerun_depth", "6: Ankle-Calf Deep and Fast"); + strMap.put("HQ_rifflerun_substrate", ""); + + + } + String [] labels = new String[] {"Chemical (WQI): ", "Biological (PTI): ", "Habitat (QHEI): ", "Name of Inspector: ", "Name of Site: ", "Date: ", "Outfall #: ", "Longitude: ", "Latitude: ", "Invert Elevation: ", "Type: ", "Pipe Size: ", "Channel Bottom Width: ", "Receiving Water: ", "Presence Of Flow: ", "Unusual Odor: ", "Unusual Color: ", "Polutants (nearby): ", "Obstruction: ", "Needs Mainenance: ", "Screened Ok: ", "Routine Evaluation: ", "Complaint Investigation: ", "Illicit Discharge Detected: ", "No Illicit Discharge Detected: ", "Further Action Needed: ", "Temperature (C) Change: ", "Turbidity (NTU): ", "pH: ", "Nitrate (mg/L): ", "Total Phosphate (mg/L): ", "Dissolved Oxygen (mg/L): ", "E coli (Col/100ml): ", "Other 1: ", "Other 2: ", "Intolerant: ", "Moderately Tolerant: ", "Fairly Tolerant: ", "Very Tolerant: ", "Substrate Size: ", "Smothering: ", "Silting: ", "Rootwads: ", "Overhanging Veg.: ", "Oxbows/Black Water: ", "Downed Trees/Logs: ", "Shallows (in slow water): ", "Water Plants: ", "Deep Pools: ", "Logs/Woody Debris: ", "Boulders: ", "Undercut Banks: ", "Sinuosity: ", "Natural: ", "Riparian Width: ", "Land Use: ", "Bank Erosion: ", "Stream Shading: ", "Deepest Pool: ", "Velocity: ", "Riffle/Run Depth: ", "Riffle/Run Substrate: ", "Comments: "}; + String [] keys = new String[] {"WQI","PTI","QHEI","H_inspector_name","H_site_name","H_date","GOD_outfall","GOD_longitude","GOD_latitude","GOD_invert_elevation","GOD_type","GOD_pipe_size","GOD_channel_bottom_width","GOD_receiving_water","DWS_presence_of_flow","DWS_unusual_odor","DWS_unusual_color","DWS_polutants","DWS_obstruction","DWS_needs_maintenance","DWS_screened_OK","FC_routine_evaluation","FC_complaint_investigation","FC_illicit_discharge_detected","FC_no_illicit_discharge_detected","FC_further_action_needed","CT_temperature_change","CT_turbidity","CT_pH","CT_nitrate","CT_total_phosphate","CT_dissolved_oxygen","CT_E_coli","CT_other1","CT_other2","BM_intolerant","BM_moderately_tolerant","BM_fairly_tolerant","BM_very_tolerant","HQ_substrate_size","HQ_smothering","HQ_silting","HQ_rootwads","HQ_overhanging_veg","HQ_oxbowsblack_waters","HQ_downed_treeslogs","HQ_shallows","HQ_water_plants","HQ_deep_pools","HQ_logswoody_debris","HQ_boulders","HQ_undercut_banks","HQ_sinuosity","HQ_natural","HQ_riparian_width","HQ_land_use","HQ_bank_erosion","HQ_stream_shading","HQ_deepest_pool","HQ_velocity","HQ_rifflerun_depth","HQ_rifflerun_substrate", "CS_comments"}; + //TODO: Image + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_pdf); + + // below code is used for + // checking our permissions. + if (checkPermission()) { + Toast.makeText(this, "Permission Granted", Toast.LENGTH_SHORT).show(); + } else { + requestPermission(); + } + + createPDF(); + Log.d("Finish", "IT IS FINISHED"); + } + + /*//Constructor + PDFCreator(String title, String [] label, String [] body) { + this.title = title; + this.label = label; + this.body = body; + //mContext = this; + }*/ + //Default constructor + /*PDFCreator () { + }*/ + + public void createPDF() { + //llPdf = llPdf.findViewById(R.id.rvWWR);//TODO: IS THIS FINE? + //Create new doc + PdfDocument document = new PdfDocument(); + + //Paint paint = new Paint();//for shapes + Paint title = new Paint();//for text + + //Create page description + PageInfo pageInfo = new PageInfo.Builder((int) (8.5 * 72),11 * 72,1).create(); + + //Start page + Page page = document.startPage(pageInfo); + + /*//Draw something on the page + View content = getContentView();*/ + Canvas canvas = page.getCanvas(); + //TODO: DRAW IMAGE? + + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));//Bold text + title.setTextSize(18);//John used size 18 + //title.setColor(ContextCompat.getColor(this, R.color.purple_200)); + //String header = "Water Quality Test"; + Log.d("test", Float.toString(title.measureText("Water Quality Test"))); + canvas.drawText("Water Quality Test", (float) (((8.5*72)-title.measureText("Water Quality Test"))/2), 36, title); + + + //TODO: GET RID OF THIS AFTER TESTING + //canvas.drawText("This is a test.", 20, 20, title); + title.setTextSize(12);//15);//TODO: SHOULD I CHANGE THIS? + + writeToCanvas(canvas, title); + //Write the document content + document.finishPage(page); + + + + File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Test", "Test.pdf"); + /*try { + // Save file address + // Get the parent directory: / aaa / bbb / ccc / + String path = file.getParent(); + File check = new File(path); + // Create a folder through the parent directory, not through outFile + if (!check.exists()) { + // Create a file when the file does not exist + if (check.mkdirs() && !file.exists()) { + //Create a file + if (!file.createNewFile()) Log.e("pdf", "File to create failure!"); + } + } + } catch (IOException e ) { + e.printStackTrace(); + }*/ + //File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "Test.pdf"); + if (!file.exists()) { + Log.d("pdf", "DOESN'T EXIST"); + file.getParentFile().mkdirs(); + } + if (file.exists()) { + Log.d("pdf", "EXISTS NOW"); + } + + + try { + //write pdf ot file location + document.writeTo(new FileOutputStream(file)); + Toast.makeText(PDFCreator.this, "PDF file generated succesfully.", Toast.LENGTH_SHORT).show(); + } catch (IOException e) { + e.printStackTrace(); + } + + + /*if (this.title == "Waterway Inspections") { + addWWText(); + } + else { + + }*/ + + /*//Finish page + content.draw(page.getCanvas());*/ + + //Close document + document.close(); + } + + public void addWWText () { + + } + + private boolean checkPermission() { + // checking of permissions. + /*int permission1 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE); + int permission2 = ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_EXTERNAL_STORAGE); + //int permission1 = ContextCompat.checkSelfPermission(getApplicationContext(), WRITE_EXTERNAL_STORAGE); + //int permission2 = ContextCompat.checkSelfPermission(getApplicationContext(), READ_EXTERNAL_STORAGE); + return permission1 == PackageManager.PERMISSION_GRANTED && permission2 == PackageManager.PERMISSION_GRANTED;*/ + if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + if (checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + Log.v("pdf","Permission is granted"); + //File write logic here + return true; + } + } + return false;//if it doesn't return true, it'll return false + } + + private void requestPermission() { + // requesting permissions if not provided. + ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE,android.Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE); + //android.Manifest.permission.WRITE_EXTERNAL_STORAGE,android.Manifest.permission.READ_EXTERNAL_STORAGE + //ActivityCompat.requestPermissions(this, new String[]{WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if (requestCode == PERMISSION_REQUEST_CODE) { + if (grantResults.length > 0) { + + // after requesting permissions we are showing + // users a toast message of permission granted. + boolean writeStorage = grantResults[0] == PackageManager.PERMISSION_GRANTED; + boolean readStorage = grantResults[1] == PackageManager.PERMISSION_GRANTED; + + if (writeStorage && readStorage) { + Toast.makeText(this, "Permission Granted..", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(this, "Permission Denined.", Toast.LENGTH_SHORT).show(); + finish(); + } + } + } + } + + public void writeToCanvas(Canvas canvas, Paint title) { + //canvas.drawText("TESTING TESTING.", 20, 20, title); + //The title was at 36 + //(float) (((8.5*72)-title.measureText("Water Quality Test"))/2) + /*Rect bounds = new Rect(); + title.getTextBounds("Water Quality Test", 0, "Water Quality Test".length(), bounds); + Log.d("test", String.valueOf(bounds.height()));*/ + int currHi = 36 + 20;//getHeight(title, "Water Quality Test"); + Log.d("finish", String.valueOf(getHeight(title, "Water Quality Test"))); + int currWi = 20; + int holdHi = 0; + for (int i = 0; i <= 2; i++) { + //Log.d("test", labels[i]); + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + canvas.drawText(labels[i], currWi, currHi, title); + //title.measureText + currWi += title.measureText(labels[i]); + //Log.d("test", String.valueOf(dubMap.get(keys[i]))); + title.setColor(ContextCompat.getColor(this, R.color.red)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + canvas.drawText(String.valueOf(dubMap.get(keys[i])), currWi, currHi, title); + currWi += (int) title.measureText(String.valueOf(dubMap.get(keys[i]))) + 20; + } + title.setColor(ContextCompat.getColor(this, R.color.black)); + currHi += 16;//getHeight(title, labels[0]);//TODO: IS this ok? + for (int i=3; i<=5; i++) { + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + canvas.drawText(labels[i], 20, currHi, title); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + canvas.drawText(String.valueOf(strMap.get(keys[i])), 20 + title.measureText(labels[i]), currHi, title); + currHi += 16;//getHeight(title, labels[i]); + } + canvas.drawText("--------------------------------------------------------------------------------------------------------------------------------------------", 20, currHi, title); + currHi += 14;//getHeight(title, "---");//TODO: MAYBE CHANGE + holdHi = currHi; + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setTextSize(14); + canvas.drawText("General Outfall Data", 20, currHi,title); + currHi += 16;//getHeight(title, "General Outfall Data"); + title.setTextSize(12); + for (int i=6; i<=13; i++) { + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + canvas.drawText(labels[i], 20, currHi, title); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + canvas.drawText(String.valueOf(strMap.get(keys[i])), 20 + title.measureText(labels[i]), currHi, title); + currHi += 16;//getHeight(title, labels[i]); + } + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setTextSize(14); + canvas.drawText("Dry Weather Screening", 20, currHi,title); + currHi += 16;//getHeight(title, "Dry Weather Screening"); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + title.setTextSize(12); + for (int i=14; i<=20; i++) { + if (boolMap.get(keys[i]) == true) { + canvas.drawText("\u2611", 20, currHi, title);//checkbox + canvas.drawText(labels[i], 20 + title.measureText("\u2611"), currHi, title); + } + else { + canvas.drawText("\u25A2", 20, currHi, title);//Unchecked box + canvas.drawText(labels[i], 20 + title.measureText("\u25A2"), currHi, title); + } + currHi += 16;//getHeight(title, String.valueOf(boolMap.get(keys[i]))); + } + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setTextSize(14); + canvas.drawText("Final Conclusion", 20, currHi,title); + currHi += 16;//getHeight(title, "Final Conclusion"); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + title.setTextSize(12); + for (int i=21; i<=25; i++) { + if (boolMap.get(keys[i]) == true) { + canvas.drawText("\u2611", 20, currHi, title);//checkbox + canvas.drawText(labels[i], 20 + title.measureText("\u2611"), currHi, title); + } + else { + canvas.drawText("\u25A2", 20, currHi, title);//Unchecked box + canvas.drawText(labels[i], 20 + title.measureText("\u25A2"), currHi, title); + } + currHi += 16;//getHeight(title, String.valueOf(boolMap.get(keys[i]))); + } + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setTextSize(14); + canvas.drawText("Chemical Testing (Q-Values)", 20, currHi,title); + currHi += 16;//getHeight(title, "Chemical Testing (Q-Values)"); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTextSize(12); + for (int i=26; i<=32; i++) { + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + canvas.drawText(labels[i], 20, currHi, title); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + canvas.drawText(String.valueOf(dubMap.get(keys[i])), 20 + title.measureText(labels[i]), currHi, title); + currHi += 16;//getHeight(title, labels[i]); + } + for (int i=33; i<=34; i++) { + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + canvas.drawText(labels[i], 20, currHi, title); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + canvas.drawText(String.valueOf(strMap.get(keys[i])), 20 + title.measureText(labels[i]), currHi, title); + currHi += 16;//getHeight(title, labels[i]); + } + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setTextSize(14); + currWi = (int)(8.5 * 72) / 2; + currHi = holdHi; + canvas.drawText("Biological Monitoring (# of Taxa)", currWi, currHi,title); + currHi += 16; + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTextSize(12); + for (int i=35; i<=38; i++) { + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + canvas.drawText(labels[i], currWi, currHi, title); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + canvas.drawText(String.valueOf(dubMap.get(keys[i])), currWi + title.measureText(labels[i]), currHi, title); + currHi += 16; + } + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setTextSize(14); + canvas.drawText("Habitat Quality", currWi, currHi, title); + currHi += 16; + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTextSize(12); + for (int i=39; i<=61; i++) { + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + canvas.drawText(labels[i], currWi, currHi, title); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + canvas.drawText(String.valueOf(strMap.get(keys[i])), currWi + title.measureText(labels[i]), currHi, title); + currHi += 16; + } + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setTextSize(14); + canvas.drawText("Comments", currWi, currHi, title); + } + + public int getWidth(Paint title, String text) { + return (int) title.measureText(text); + } + public int getHeight(Paint title, String text) { + Rect bounds = new Rect(); + title.getTextBounds("Water Quality Test", 0, "Water Quality Test".length(), bounds); + Log.d("test", String.valueOf(bounds.height())); + return bounds.height(); + } + +} diff --git a/app/src/main/java/com/sf/stormwaterutilityandroid/ReportAdapter.java b/app/src/main/java/com/sf/stormwaterutilityandroid/ReportAdapter.java index b0cd8db..775a581 100644 --- a/app/src/main/java/com/sf/stormwaterutilityandroid/ReportAdapter.java +++ b/app/src/main/java/com/sf/stormwaterutilityandroid/ReportAdapter.java @@ -30,6 +30,10 @@ public ReportAdapter.MyHolder onCreateViewHolder(ViewGroup parent, int viewType) return myHolder; } + //I ADDED CODE HERE. TODO: IS THAT OK? + + //END CODE + public void onBindViewHolder(ReportAdapter.MyHolder holder, final int position) { diff --git a/app/src/main/java/com/sf/stormwaterutilityandroid/Settings.java b/app/src/main/java/com/sf/stormwaterutilityandroid/Settings.java index 8eca92d..e9cac67 100644 --- a/app/src/main/java/com/sf/stormwaterutilityandroid/Settings.java +++ b/app/src/main/java/com/sf/stormwaterutilityandroid/Settings.java @@ -1,14 +1,94 @@ package com.sf.stormwaterutilityandroid; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; +import android.content.Intent; +import android.net.Uri; import android.os.Bundle; +import android.os.Environment; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.Toast; + +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.AuthCredential; +import com.google.firebase.auth.EmailAuthProvider; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.firestore.FirebaseFirestore; +import com.google.firebase.firestore.Query; +import com.google.firebase.firestore.QueryDocumentSnapshot; +import com.google.firebase.firestore.QuerySnapshot; +import com.sf.stormwaterutilityandroid.Grapher; public class Settings extends AppCompatActivity { + private Button btnSupport, btnPrivacyPolicy, btnSignOut, btnDeleteAccount, btnGraph, btnPDF, btnReport; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_settings); + + btnSupport = findViewById(R.id.support_button); + btnPrivacyPolicy = findViewById(R.id.policy_button); + btnSignOut = findViewById(R.id.signout_button); + btnDeleteAccount = findViewById(R.id.delete_account_button); + + btnSupport.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //startActivity(new Intent(Reports.this, Site_name.class)); + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://forms.gle/LgzUmpDwgPkbNoTs6")); + startActivity(browserIntent); + } + }); + + btnPrivacyPolicy.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //startActivity(new Intent(Reports.this, Date.class)); + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://forms.gle/AkGaMazbPKpoDsdZA")); + startActivity(browserIntent); + } + }); + + btnSignOut.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //startActivity(new Intent(Reports.this, Inspector_name.class)); + FirebaseAuth.getInstance().signOut(); + } + }); + + btnDeleteAccount.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //startActivity(new Intent(Reports.this, Inspector_name.class)); + final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + + // Get auth credentials from the user for re-authentication. The example below shows + // email and password credentials but there are multiple possible providers, + // such as GoogleAuthProvider or FacebookAuthProvider. + AuthCredential credential = EmailAuthProvider.getCredential("user@example.com", "password1234"); + + // Prompt the user to re-provide their sign-in credentials + user.reauthenticate(credential).addOnCompleteListener(new OnCompleteListener() { + public void onComplete(@NonNull Task task) { + user.delete().addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()) { + Log.d("UserDelete", "User account deleted."); + } + } + }); + } + }); + } + }); } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/sf/stormwaterutilityandroid/WaterWay/WaterWayReportFragment.java b/app/src/main/java/com/sf/stormwaterutilityandroid/WaterWay/WaterWayReportFragment.java index ca422c7..736023c 100644 --- a/app/src/main/java/com/sf/stormwaterutilityandroid/WaterWay/WaterWayReportFragment.java +++ b/app/src/main/java/com/sf/stormwaterutilityandroid/WaterWay/WaterWayReportFragment.java @@ -1,5 +1,6 @@ package com.sf.stormwaterutilityandroid.WaterWay; +import android.content.Intent; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; @@ -36,6 +37,7 @@ import com.google.firebase.firestore.QueryDocumentSnapshot; import com.google.firebase.firestore.QuerySnapshot; import com.sf.stormwaterutilityandroid.ConstructionReportAdapter; +import com.sf.stormwaterutilityandroid.GraphPicker; import com.sf.stormwaterutilityandroid.R; import com.sf.stormwaterutilityandroid.ReportAdapter; @@ -53,7 +55,7 @@ public WaterWayReportFragment() { private EditText searchBar;//TODO: Make a search bar later? private RecyclerView recyclerView; - private Button btnSiteName, btnDate, btnInspectorName; + private Button btnSiteName, btnDate, btnInspectorName, btnGraph;//TODO: ADDED BTNGRAPH. FINE? List reportList; ReportAdapter reportAdapter; //TODO: Need vars for formdata @@ -75,6 +77,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, btnSiteName = view.findViewById(R.id.btn_site_name); btnDate = view.findViewById(R.id.btn_date); btnInspectorName = view.findViewById(R.id.btn_inspector_name); + btnGraph = view.findViewById(R.id.btn_grapher);//TODO: ADDED. FINE? searchBar = view.findViewById(R.id.searchView); recyclerView = view.findViewById(R.id.recyclerView); @@ -137,6 +140,15 @@ public void onClick(View v) { } }); + //TODO: ADDING THIS HERE. FINE? + btnGraph.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getContext(), GraphPicker.class);//TODO: THIS IS WEIRD. IS IT OK? + startActivity(intent); + } + }); + return view; diff --git a/app/src/main/java/com/sf/stormwaterutilityandroid/WaterwayReportDetail.java b/app/src/main/java/com/sf/stormwaterutilityandroid/WaterwayReportDetail.java index 486c36f..4436094 100644 --- a/app/src/main/java/com/sf/stormwaterutilityandroid/WaterwayReportDetail.java +++ b/app/src/main/java/com/sf/stormwaterutilityandroid/WaterwayReportDetail.java @@ -1,14 +1,28 @@ package com.sf.stormwaterutilityandroid; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.graphics.pdf.PdfDocument; import android.os.Bundle; +import android.os.Environment; import android.util.Log; +import android.view.View; import android.widget.ArrayAdapter; +import android.widget.Button; import android.widget.ListView; +import android.widget.Toast; import com.google.firebase.firestore.DocumentSnapshot; import com.google.firebase.firestore.EventListener; @@ -18,6 +32,9 @@ import com.google.firebase.firestore.QuerySnapshot; import com.sf.stormwaterutilityandroid.WaterWay.WaterWayReport; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -25,10 +42,21 @@ public class WaterwayReportDetail extends AppCompatActivity { WaterWayReport wp; ArrayList s = new ArrayList<>(); ListView listView; +private Button btnExport; +private static final int PERMISSION_REQUEST_CODE = 200; +String [] keys = new String[] {"WQI","PTI","QHEI","H_inspector_name","H_site_name","H_date","GOD_outfall","GOD_longitude","GOD_latitude","GOD_invert_elevation","GOD_type","GOD_pipe_size","GOD_channel_bottom_width","GOD_receiving_water","DWS_presence_of_flow","DWS_unusual_odor","DWS_unusual_color","DWS_polutants","DWS_obstruction","DWS_needs_maintenance","DWS_screened_OK","FC_routine_evaluation","FC_complaint_investigation","FC_illicit_discharge_detected","FC_no_illicit_discharge_detected","FC_further_action_needed","CT_temperature_change","CT_turbidity","CT_pH","CT_nitrate","CT_total_phosphate","CT_dissolved_oxygen","CT_E_coli","CT_other1","CT_other2","BM_intolerant","BM_moderately_tolerant","BM_fairly_tolerant","BM_very_tolerant","HQ_substrate_size","HQ_smothering","HQ_silting","HQ_rootwads","HQ_overhanging_veg","HQ_oxbowsblack_waters","HQ_downed_treeslogs","HQ_shallows","HQ_water_plants","HQ_deep_pools","HQ_logswoody_debris","HQ_boulders","HQ_undercut_banks","HQ_sinuosity","HQ_natural","HQ_riparian_width","HQ_land_use","HQ_bank_erosion","HQ_stream_shading","HQ_deepest_pool","HQ_velocity","HQ_rifflerun_depth","HQ_rifflerun_substrate", "CS_comments"}; @Override protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); setContentView(R.layout.activity_waterway_report_detail); + Log.d("TEST", "This is the page I'm looking for"); + btnExport = findViewById(R.id.export_button); + if (checkPermission()) { + Toast.makeText(this, "Permission Granted", Toast.LENGTH_SHORT).show(); + } else { + requestPermission(); + } wp = (WaterWayReport) getIntent().getSerializableExtra("report"); listView = findViewById(R.id.listView); String[] labels = @@ -165,5 +193,261 @@ protected void onCreate(Bundle savedInstanceState) { // Assign adapter to ListView listView.setAdapter(adapter); + btnExport.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + createPDF(labels, wp); + } + }); + } + + public void createPDF(String[] labels, WaterWayReport wp) { + //Create new doc + PdfDocument document = new PdfDocument(); + + Paint title = new Paint();//for text + + //Create page description + PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder((int) (8.5 * 72),11 * 72,1).create(); + + //Start page + PdfDocument.Page page = document.startPage(pageInfo); + + Canvas canvas = page.getCanvas(); + + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));//Bold text + title.setTextSize(18);//John used size 18 + //title.setColor(ContextCompat.getColor(this, R.color.purple_200)); + //String header = "Water Quality Test"; + Log.d("test", Float.toString(title.measureText("Water Quality Test"))); + canvas.drawText("Water Quality Test", (float) (((8.5*72)-title.measureText("Water Quality Test"))/2), 36, title); + + + //TODO: GET RID OF THIS AFTER TESTING + //canvas.drawText("This is a test.", 20, 20, title); + title.setTextSize(12);//15);//TODO: SHOULD I CHANGE THIS? + + writeToCanvas(canvas, title, labels, wp); + //Write the document content + document.finishPage(page); + + //File naming convention: inspector _ site name _ date + String fileName = String.valueOf(wp.getH_inspector_name()) + "_" + String.valueOf(wp.getH_site_name()) + "_" + String.valueOf(wp.getH_date()) + ".pdf"; + + File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), fileName);// + "/Test", fileName);//"Test.pdf"); + if (!file.exists()) { + Log.d("pdf", "DOESN'T EXIST"); + file.getParentFile().mkdirs(); + } + if (file.exists()) { + Log.d("pdf", "EXISTS NOW"); + } + + + try { + //write pdf ot file location + document.writeTo(new FileOutputStream(file)); + Toast.makeText(WaterwayReportDetail.this, "PDF file generated succesfully.", Toast.LENGTH_SHORT).show(); + } catch (IOException e) { + e.printStackTrace(); + } + + document.close(); + } + + private boolean checkPermission() { + if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + if (checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + Log.v("pdf","Permission is granted"); + //File write logic here + return true; + } + } + return false;//if it doesn't return true, it'll return false + } + + private void requestPermission() { + // requesting permissions if not provided. + ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE,android.Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE); + } + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if (requestCode == PERMISSION_REQUEST_CODE) { + if (grantResults.length > 0) { + // after requesting permissions we are showing + // users a toast message of permission granted. + boolean writeStorage = grantResults[0] == PackageManager.PERMISSION_GRANTED; + boolean readStorage = grantResults[1] == PackageManager.PERMISSION_GRANTED; + + if (writeStorage && readStorage) { + Toast.makeText(this, "Permission Granted..", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(this, "Permission Denined.", Toast.LENGTH_SHORT).show(); + finish(); + } + } + } + } + + public void writeToCanvas(Canvas canvas, Paint title, String[] labels, WaterWayReport wp) { + int currHi = 36 + 20;//getHeight(title, "Water Quality Test"); + Log.d("finish", String.valueOf(getHeight(title, "Water Quality Test"))); + int currWi = 20; + int holdHi = 0; + for (int i = 0; i <= 2; i++) { + //Log.d("test", labels[i]); + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + canvas.drawText(labels[i], currWi, currHi, title); + //title.measureText + currWi += title.measureText(labels[i]); + title.setColor(ContextCompat.getColor(this, R.color.red)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + canvas.drawText(String.valueOf(wp.getDoubleFields().get(keys[i])), currWi, currHi, title); + currWi += (int) title.measureText(String.valueOf(wp.getDoubleFields().get(keys[i]))) + 20; + } + title.setColor(ContextCompat.getColor(this, R.color.black)); + currHi += 16;//getHeight(title, labels[0]);//TODO: IS this ok? + for (int i=3; i<=5; i++) { + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + canvas.drawText(labels[i], 20, currHi, title); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + canvas.drawText(String.valueOf(wp.getStringFields().get(keys[i])), 20 + title.measureText(labels[i]), currHi, title); + currHi += 16;//getHeight(title, labels[i]); + } + canvas.drawText("--------------------------------------------------------------------------------------------------------------------------------------------", 20, currHi, title); + currHi += 14;//getHeight(title, "---");//TODO: MAYBE CHANGE + holdHi = currHi; + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setTextSize(14); + canvas.drawText("General Outfall Data", 20, currHi,title); + currHi += 16;//getHeight(title, "General Outfall Data"); + title.setTextSize(12); + for (int i=6; i<=13; i++) { + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + canvas.drawText(labels[i], 20, currHi, title); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + canvas.drawText(String.valueOf(wp.getStringFields().get(keys[i])), 20 + title.measureText(labels[i]), currHi, title); + currHi += 16;//getHeight(title, labels[i]); + } + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setTextSize(14); + canvas.drawText("Dry Weather Screening", 20, currHi,title); + currHi += 16;//getHeight(title, "Dry Weather Screening"); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + title.setTextSize(12); + for (int i=14; i<=20; i++) { + if (wp.getBoolFields().get(keys[i]) == true) { + canvas.drawText("\u2611", 20, currHi, title);//checkbox + canvas.drawText(labels[i], 20 + title.measureText("\u2611"), currHi, title); + } + else { + canvas.drawText("\u25A2", 20, currHi, title);//Unchecked box + canvas.drawText(labels[i], 20 + title.measureText("\u25A2"), currHi, title); + } + currHi += 16;//getHeight(title, String.valueOf(wp.getBoolFields().get(keys[i]))); + } + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setTextSize(14); + canvas.drawText("Final Conclusion", 20, currHi,title); + currHi += 16;//getHeight(title, "Final Conclusion"); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + title.setTextSize(12); + for (int i=21; i<=25; i++) { + if (wp.getBoolFields().get(keys[i]) == true) { + canvas.drawText("\u2611", 20, currHi, title);//checkbox + canvas.drawText(labels[i], 20 + title.measureText("\u2611"), currHi, title); + } + else { + canvas.drawText("\u25A2", 20, currHi, title);//Unchecked box + canvas.drawText(labels[i], 20 + title.measureText("\u25A2"), currHi, title); + } + currHi += 16;//getHeight(title, String.valueOf(wp.getBoolFields().get(keys[i]))); + } + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setTextSize(14); + canvas.drawText("Chemical Testing (Q-Values)", 20, currHi,title); + currHi += 16;//getHeight(title, "Chemical Testing (Q-Values)"); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTextSize(12); + for (int i=26; i<=32; i++) { + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + canvas.drawText(labels[i], 20, currHi, title); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + canvas.drawText(String.valueOf(wp.getDoubleFields().get(keys[i])), 20 + title.measureText(labels[i]), currHi, title); + currHi += 16;//getHeight(title, labels[i]); + } + for (int i=33; i<=34; i++) { + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + canvas.drawText(labels[i], 20, currHi, title); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + canvas.drawText(String.valueOf(wp.getStringFields().get(keys[i])), 20 + title.measureText(labels[i]), currHi, title); + currHi += 16;//getHeight(title, labels[i]); + } + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setTextSize(14); + currWi = (int)(8.5 * 72) / 2; + currHi = holdHi; + canvas.drawText("Biological Monitoring (# of Taxa)", currWi, currHi,title); + currHi += 16; + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTextSize(12); + for (int i=35; i<=38; i++) { + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + canvas.drawText(labels[i], currWi, currHi, title); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + canvas.drawText(String.valueOf(wp.getDoubleFields().get(keys[i])), currWi + title.measureText(labels[i]), currHi, title); + currHi += 16; + } + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setTextSize(14); + canvas.drawText("Habitat Quality", currWi, currHi, title); + currHi += 16; + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTextSize(12); + for (int i=39; i<=61; i++) { + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setColor(ContextCompat.getColor(this, R.color.black)); + canvas.drawText(labels[i], currWi, currHi, title); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + title.setColor(ContextCompat.getColor(this, R.color.gray)); + canvas.drawText(String.valueOf(wp.getStringFields().get(keys[i])), currWi + title.measureText(labels[i]), currHi, title); + currHi += 16; + } + title.setColor(ContextCompat.getColor(this, R.color.black)); + title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + title.setTextSize(14); + canvas.drawText("Comments", currWi, currHi, title); + } + + public int getWidth(Paint title, String text) { + return (int) title.measureText(text); + } + public int getHeight(Paint title, String text) { + Rect bounds = new Rect(); + title.getTextBounds("Water Quality Test", 0, "Water Quality Test".length(), bounds); + Log.d("test", String.valueOf(bounds.height())); + return bounds.height(); } } diff --git a/app/src/main/res/layout/activity_graph.xml b/app/src/main/res/layout/activity_graph.xml new file mode 100644 index 0000000..c78c5cc --- /dev/null +++ b/app/src/main/res/layout/activity_graph.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_pdf.xml b/app/src/main/res/layout/activity_pdf.xml new file mode 100644 index 0000000..61a4490 --- /dev/null +++ b/app/src/main/res/layout/activity_pdf.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_pick_graph.xml b/app/src/main/res/layout/activity_pick_graph.xml new file mode 100644 index 0000000..3a8162e --- /dev/null +++ b/app/src/main/res/layout/activity_pick_graph.xml @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +