diff --git a/app/build.gradle b/app/build.gradle index 73e2905b..ca0de058 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -168,4 +168,7 @@ dependencies { // Sweet Alert Dialog implementation 'cn.pedant.sweetalert:library:1.3' + + // MPAndroid chart lib + implementation("ir.mahozad.android:pie-chart:0.7.0") } \ No newline at end of file diff --git a/app/src/main/java/com/steve_md/smartmkulima/model/FarmConditions.kt b/app/src/main/java/com/steve_md/smartmkulima/model/FarmConditions.kt index b9e35bb6..45f4d173 100644 --- a/app/src/main/java/com/steve_md/smartmkulima/model/FarmConditions.kt +++ b/app/src/main/java/com/steve_md/smartmkulima/model/FarmConditions.kt @@ -3,5 +3,9 @@ package com.steve_md.smartmkulima.model data class FarmConditions( val temperature: Double, val humidity: Double, - val soilMoisture: Double + val soilMoisture: Double, + val windspeed: Double, + val precipitation: Double, + val lightDensity: Double, + val nbkLevel: Double ) \ No newline at end of file diff --git a/app/src/main/java/com/steve_md/smartmkulima/model/mapmodels/Place.kt b/app/src/main/java/com/steve_md/smartmkulima/model/mapmodels/Place.kt index a0a881da..b6c9e1ac 100644 --- a/app/src/main/java/com/steve_md/smartmkulima/model/mapmodels/Place.kt +++ b/app/src/main/java/com/steve_md/smartmkulima/model/mapmodels/Place.kt @@ -11,6 +11,9 @@ import com.steve_md.smartmkulima.model.mapmodels.responses.toPlace import java.io.InputStream import java.io.InputStreamReader +/** + * Place Name, Latitude, Longitude, Address, Rating :( + */ data class Place( val name: String, val latLng: LatLng, @@ -28,7 +31,6 @@ data class Place( override fun getSnippet(): String { return address } - } class PlacesReader(private val context: Context) { diff --git a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/LocateAgriTechCompaniesFragment.kt b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/LocateAgriTechCompaniesFragment.kt index 59b4ec7b..187e4b6e 100644 --- a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/LocateAgriTechCompaniesFragment.kt +++ b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/LocateAgriTechCompaniesFragment.kt @@ -343,7 +343,6 @@ class LocateAgriTechCompaniesFragment : Fragment() , OnMapReadyCallback { override fun onResume() { super.onResume() mapView.onResume() - promptUserForLocationPermissions() } override fun onPause() { diff --git a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/MonitorFarmConditionFragment.kt b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/MonitorFarmConditionFragment.kt index 208bd169..bfd7bffc 100644 --- a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/MonitorFarmConditionFragment.kt +++ b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/MonitorFarmConditionFragment.kt @@ -1,7 +1,10 @@ package com.steve_md.smartmkulima.ui.fragments.main import android.Manifest +import android.annotation.SuppressLint import android.content.pm.PackageManager +import android.content.res.Resources +import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -26,6 +29,8 @@ import com.steve_md.smartmkulima.model.FarmConditions import com.steve_md.smartmkulima.ui.fragments.others.LocationProvider import com.steve_md.smartmkulima.utils.displaySnackBar import dagger.hilt.android.AndroidEntryPoint +import ir.mahozad.android.PieChart +import ir.mahozad.android.unit.Dimension import timber.log.Timber @AndroidEntryPoint @@ -33,7 +38,7 @@ class MonitorFarmConditionFragment : Fragment(),OnMapReadyCallback { private lateinit var mapView: MapView private lateinit var googleMap: GoogleMap - private var LOCATION_PERMISSION_REQUEST_CODE = 1 + private var LOCATIONPERMISSIONREQUESTCODE = 1 private lateinit var locationProvider: LocationProvider override fun onCreateView( @@ -77,27 +82,81 @@ class MonitorFarmConditionFragment : Fragment(),OnMapReadyCallback { displaySnackBar("Could not update your location") } } + + setUpChart() + } + + private fun setUpChart() { + val pieChart = view?.findViewById(R.id.pieChart) + + pieChart?.slices = listOf( + PieChart.Slice(0.3f, Color.rgb(120, 181, 0), Color.rgb(149, 224, 0), legend = "Temperature"), + PieChart.Slice(0.2f, Color.rgb(204, 168, 0), Color.rgb(249, 228, 0), legend = "Humidity"), + PieChart.Slice(0.2f, Color.rgb(0, 162, 216), Color.rgb(31, 199, 255), legend = "Soil Moisture"), + PieChart.Slice(0.17f, Color.rgb(255, 4, 4), Color.rgb(255, 72, 86), legend = "Wind speed"), + PieChart.Slice(0.13f, Color.rgb(160, 165, 170), Color.rgb(175, 180, 185), legend = "Precipitation") , + PieChart.Slice(0.13f, Color.rgb(160, 165, 170), Color.rgb(175, 180, 185), legend = "Light Density"), + PieChart.Slice(0.13f, Color.rgb(160, 165, 170), Color.rgb(175, 180, 185), legend = "NBK level") + ) + + pieChart?.gradientType = PieChart.GradientType.RADIAL + pieChart?.legendIconsMargin = Dimension.DP(8F) + pieChart?.legendTitleMargin = Dimension.DP(14F) + pieChart?.legendLinesMargin = Dimension.DP(10F) + pieChart?.legendsMargin = Dimension.DP(20F) + pieChart?.legendsPercentageMargin = Dimension.DP(8F) + pieChart?.legendsSize = Dimension.DP(11F) + pieChart?.legendsPercentageSize = Dimension.DP(11F) + pieChart?.legendsIcon = PieChart.DefaultIcons.SQUARE } + val Float.toSp get() = this * Resources.getSystem().displayMetrics.scaledDensity + + fun dpToPx(dp: Int): Int { + return (dp * Resources.getSystem().displayMetrics.density).toInt() + } // Mock farm conditions with Fake DATA private fun monitorFarmConditions(latitude: Double, longitude: Double) { val mockFarmConditions = FarmConditions( - temperature = 22.0, - humidity = 69.7, - soilMoisture = 0.6 + temperature = 25.8, + humidity = 67.7, + soilMoisture = 32.7, + windspeed = 9.0, + precipitation = 5.8, + lightDensity = 45000.0, + nbkLevel = 30.5 ) + + /* + val temperature: Double, + val humidity: Double, + val soilMoisture: Double, + val windspeed: Double, + val precipitation: Double, + val lightDensity: Double, + val nbkLevel: Double + */ // Process the farm conditions data as needed displayFarmConditions(mockFarmConditions) } + @SuppressLint("SetTextI18n") private fun displayFarmConditions(mockFarmConditions: FarmConditions) { val temperature = view?.findViewById(R.id.textViewTemperature) val humidity = view?.findViewById(R.id.textViewHumidity) val soilMoisture = view?.findViewById(R.id.textViewSoilMoisture) - - temperature?.text = mockFarmConditions.temperature.toString() - humidity?.text = mockFarmConditions.humidity.toString() - soilMoisture?.text = mockFarmConditions.soilMoisture.toString() + val windspeed = view?.findViewById(R.id.textViewWindSpeed) + val precipitation = view?.findViewById(R.id.textViewPrecipitation) + val lightDensity = view?.findViewById(R.id.textViewLightDensity) + val nbkLevel = view?.findViewById(R.id.textViewNBKLevel) + + temperature?.text = "${mockFarmConditions.temperature}°C" + humidity?.text = "${mockFarmConditions.humidity}%" + soilMoisture?.text = "${mockFarmConditions.soilMoisture}%" + windspeed?.text = "${mockFarmConditions.windspeed} m/s" + precipitation?.text = "${mockFarmConditions.precipitation} mm" + lightDensity?.text = "${mockFarmConditions.windspeed} lux" + nbkLevel?.text = "${mockFarmConditions.nbkLevel} %" } override fun onMapReady(p0: GoogleMap) { @@ -113,7 +172,10 @@ class MonitorFarmConditionFragment : Fragment(),OnMapReadyCallback { } else { requestLocationPermission() } - val location = LatLng(0.5699258, 34.5566803) + + // Sample farm Location // Not Real Data + val location = LatLng(-1.2860732, 36.8103714) + googleMap.addMarker(MarkerOptions().position(location).title("Your Farm is Here")) ?.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)) googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(location, 12f)) @@ -123,13 +185,13 @@ class MonitorFarmConditionFragment : Fragment(),OnMapReadyCallback { ActivityCompat.requestPermissions( requireActivity(), arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), - LOCATION_PERMISSION_REQUEST_CODE + LOCATIONPERMISSIONREQUESTCODE ) } /** * Handle lifecycle for the Map - * This is implemented in order for it ot work well + * This is implemented in order for it to work pretty well */ override fun onPause() { super.onPause() diff --git a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/PredictYourCropProductionFragment.kt b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/PredictYourCropProductionFragment.kt index 21b45403..e427c803 100644 --- a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/PredictYourCropProductionFragment.kt +++ b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/PredictYourCropProductionFragment.kt @@ -33,31 +33,35 @@ class PredictYourCropProductionFragment : Fragment() { } binding.buttonPredict.setOnClickListener { - val temperature = binding.inputTemperature.text.toString().toDouble() - val rainfall = binding.inputRainfall.text.toString().toDouble() + val temperature = binding.inputTemperature.text.toString().toDouble().toString() + val rainfall = binding.inputRainfall.text.toString().toDouble().toString() val soilQualityPh = binding.inputSoilQualityPh.text.toString() val selectedCrop = binding.spinnerCropPredict.selectedItem.toString() val selectedSeason = binding.spinnerSowingSeason.selectedItem.toString() + + if (temperature.isNotEmpty() && rainfall.isNotEmpty() && soilQualityPh.isNotEmpty()) { + + } else { + + } // call prediction function here :) - if (temperature != null && rainfall != null && - soilQualityPh != null && selectedCrop!= null - && selectedSeason!=null){ + if (temperature != null && rainfall != null && selectedCrop!= null && selectedSeason!=null){ val prediction = predictFarmProduce( - temperature, - rainfall, + temperature.toDouble(), + rainfall.toDouble(), soilQualityPh, selectedSeason, selectedCrop ) binding.textViewResult.text = "Expected production: $prediction" - Timber.tag(this.tag.toString()).v("Prediction: $prediction") } else { binding.enterTemperature.error = "Empty strings" binding.enterRainfall.error = "Empty strings" binding.enterSoilQualityPh.error = "Empty strings" + Timber.tag(this.tag.toString()).v("Em") } } } diff --git a/app/src/main/res/layout/fragment_monitor_farm_condition.xml b/app/src/main/res/layout/fragment_monitor_farm_condition.xml index 1c532b5a..a392c38e 100644 --- a/app/src/main/res/layout/fragment_monitor_farm_condition.xml +++ b/app/src/main/res/layout/fragment_monitor_farm_condition.xml @@ -1,22 +1,31 @@ - + + + @@ -43,7 +53,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:fontFamily="@font/montserrat_medium" - android:text="0.00" + android:text="0.00°C" android:textSize="22sp" app:layout_constraintBottom_toBottomOf="@+id/textView57" app:layout_constraintStart_toEndOf="@+id/textView57" @@ -55,11 +65,11 @@ android:layout_height="wrap_content" android:fontFamily="@font/montserrat_medium" android:text="Humidity : " - android:textSize="22sp" - app:layout_constraintBottom_toBottomOf="parent" + android:textSize="18sp" + android:textColor="@color/black" + android:layout_marginTop="@dimen/_4dp" app:layout_constraintStart_toStartOf="@+id/textView57" - app:layout_constraintTop_toBottomOf="@+id/textView57" - app:layout_constraintVertical_bias="0.132" /> + app:layout_constraintTop_toBottomOf="@+id/textView57" /> @@ -77,10 +86,11 @@ android:id="@+id/textView61" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="8dp" + android:layout_marginTop="4dp" android:fontFamily="@font/montserrat_medium" android:text="Soil Moisture : " - android:textSize="22sp" + android:textSize="18sp" + android:textColor="@color/black" app:layout_constraintStart_toStartOf="@+id/textView59" app:layout_constraintTop_toBottomOf="@+id/textView59" /> @@ -89,7 +99,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:fontFamily="@font/montserrat_medium" - android:text="0.00" + android:text="0.00%" android:textSize="22sp" app:layout_constraintBottom_toBottomOf="@+id/textView61" app:layout_constraintStart_toEndOf="@+id/textView61" @@ -104,7 +114,7 @@ android:text="This Week" android:textColor="@color/main" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0.113" + app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> @@ -120,6 +130,115 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + + + + + + + + + + + + + + + + + + @@ -152,32 +271,31 @@ android:text="Monitor Your Farm" /> - - - \ No newline at end of file + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_new_farming_technology.xml b/app/src/main/res/layout/fragment_new_farming_technology.xml index f79612f8..d91df5bb 100644 --- a/app/src/main/res/layout/fragment_new_farming_technology.xml +++ b/app/src/main/res/layout/fragment_new_farming_technology.xml @@ -161,7 +161,7 @@ android:layout_height="wrap_content" android:layout_marginTop="4dp" android:fontFamily="@font/montserrat_medium" - android:text="Predict Farm\n Produce" + android:text="Predict Crop \n Yield" app:layout_constraintEnd_toEndOf="@+id/cardViewPredictFarmProduce" app:layout_constraintStart_toStartOf="@+id/cardViewPredictFarmProduce" app:layout_constraintTop_toBottomOf="@+id/cardViewPredictFarmProduce" /> diff --git a/app/src/main/res/layout/fragment_predict_your_crop_production.xml b/app/src/main/res/layout/fragment_predict_your_crop_production.xml index 045a3998..27c079fd 100644 --- a/app/src/main/res/layout/fragment_predict_your_crop_production.xml +++ b/app/src/main/res/layout/fragment_predict_your_crop_production.xml @@ -17,7 +17,7 @@ android:layout_marginTop="84dp" android:layout_marginEnd="24dp" android:fontFamily="@font/montserrat" - android:text="@string/we_use_linear_regression_machine_learning_algorithm_to_predict_your_farm_output" + android:text="@string/we_use_linear_regression_machine_learning_algorithm_to_predict_your_farm_crop_yields" android:textSize="18sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" @@ -59,9 +59,9 @@ style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginStart="45dp" + android:layout_marginStart="16dp" android:layout_marginTop="24dp" - android:layout_marginEnd="45dp" + android:layout_marginEnd="16dp" android:elevation="10dp" android:hint="Temperature in degrees celcius" app:boxCornerRadiusBottomEnd="10dp" @@ -91,9 +91,9 @@ style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginStart="45dp" + android:layout_marginStart="16dp" android:layout_marginTop="8dp" - android:layout_marginEnd="45dp" + android:layout_marginEnd="16dp" android:elevation="10dp" android:textColorHint="@color/textColor" android:hint="Rainfall in mm" @@ -124,7 +124,8 @@ android:layout_marginStart="32dp" android:layout_marginTop="228dp" android:layout_marginEnd="32dp" - android:text="Predict crop" + android:text="Predict yield" + android:fontFamily="@font/montserrat_semibold" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" @@ -137,7 +138,7 @@ android:layout_marginStart="32dp" android:layout_marginTop="32dp" android:layout_marginEnd="32dp" - android:fontFamily="@font/montserrat" + android:fontFamily="@font/montserrat_medium" android:text="Result?" android:textSize="22sp" android:textColor="@color/black" @@ -149,10 +150,10 @@ android:id="@+id/spinnerCropPredict" android:layout_width="match_parent" android:layout_height="50dp" - android:layout_marginStart="45dp" + android:layout_marginStart="16dp" android:layout_marginTop="8dp" android:background="@drawable/rounded_corner" - android:layout_marginEnd="45dp" + android:layout_marginEnd="16dp" android:entries="@array/crop_list" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -163,9 +164,9 @@ style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginStart="45dp" + android:layout_marginStart="16dp" android:layout_marginTop="8dp" - android:layout_marginEnd="45dp" + android:layout_marginEnd="16dp" android:elevation="10dp" android:textColorHint="@color/textColor" android:hint="Soil Quality(pH value)" @@ -194,10 +195,10 @@ android:id="@+id/spinnerSowingSeason" android:layout_width="match_parent" android:layout_height="50dp" - android:layout_marginStart="45dp" + android:layout_marginStart="16dp" android:layout_marginTop="8dp" android:background="@drawable/rounded_corner" - android:layout_marginEnd="45dp" + android:layout_marginEnd="16dp" android:entries="@array/season" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/raw/places.json b/app/src/main/res/raw/places.json index 249b3b03..e362255f 100644 --- a/app/src/main/res/raw/places.json +++ b/app/src/main/res/raw/places.json @@ -62,6 +62,153 @@ "rating": 4.7, "vicinity": "Haile Selassie Ave, Nairobi" }, + { + "geometry": { + "location": { + "lat": -1.2720571, + "lng": 36.7961583 + }, + "viewport": { + "northeast": { + "lat": -1.2720571, + "lng": 36.7961583 + }, + "southwest": { + "lat": -1.2720571, + "lng": 36.7961583 + } + } + }, + "name": "Lessos Agrovets", + "rating": 1.0, + "vicinity": "Kapsabet main Street, Next To Baraton Building, Kapsabet" + }, + { + "geometry": { + "location": { + "lat": -1.2720571, + "lng": 36.7961583 + }, + "viewport": { + "northeast": { + "lat": -1.2720571, + "lng": 36.7961583 + }, + "southwest": { + "lat": -1.2720571, + "lng": 36.7961583 + } + } + }, + "name": "Lessos Agrovets", + "rating": 1.0, + "vicinity": "Kapsabet main Street, Next To Baraton Building, Kapsabet" + }, + { + "geometry": { + "location": { + "lat": -1.2720571, + "lng": 36.7961583 + }, + "viewport": { + "northeast": { + "lat": -1.2720571, + "lng": 36.7961583 + }, + "southwest": { + "lat": -1.2720571, + "lng": 36.7961583 + } + } + }, + "name": "Lessos Agrovets", + "rating": 1.0, + "vicinity": "Kapsabet main Street, Next To Baraton Building, Kapsabet" + }, + { + "geometry": { + "location": { + "lat": -1.2720571, + "lng": 36.7961583 + }, + "viewport": { + "northeast": { + "lat": -1.2720571, + "lng": 36.7961583 + }, + "southwest": { + "lat": -1.2720571, + "lng": 36.7961583 + } + } + }, + "name": "Lessos Agrovets", + "rating": 1.0, + "vicinity": "Kapsabet main Street, Next To Baraton Building, Kapsabet" + }, + { + "geometry": { + "location": { + "lat": -1.2720571, + "lng": 36.7961583 + }, + "viewport": { + "northeast": { + "lat": -1.2720571, + "lng": 36.7961583 + }, + "southwest": { + "lat": -1.2720571, + "lng": 36.7961583 + } + } + }, + "name": "Lessos Agrovets", + "rating": 1.0, + "vicinity": "Kapsabet main Street, Next To Baraton Building, Kapsabet" + }, + { + "geometry": { + "location": { + "lat": -1.2720571, + "lng": 36.7961583 + }, + "viewport": { + "northeast": { + "lat": -1.2720571, + "lng": 36.7961583 + }, + "southwest": { + "lat": -1.2720571, + "lng": 36.7961583 + } + } + }, + "name": "Lessos Agrovets", + "rating": 1.0, + "vicinity": "Kapsabet main Street, Next To Baraton Building, Kapsabet" + }, + { + "geometry": { + "location": { + "lat": -1.2720571, + "lng": 36.7961583 + }, + "viewport": { + "northeast": { + "lat": -1.2720571, + "lng": 36.7961583 + }, + "southwest": { + "lat": -1.2720571, + "lng": 36.7961583 + } + } + }, + "name": "Lessos Agrovets", + "rating": 1.0, + "vicinity": "Kapsabet main Street, Next To Baraton Building, Kapsabet" + }, { "geometry": { "location": { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7461e06d..50237560 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -30,6 +30,7 @@ View All GAPs Proceed Timeout + We use Linear Regression Machine Learning Algorithm to predict your farm crop yields. Crop Cycle diff --git a/build.gradle b/build.gradle index ba96dd1f..16a5d4d9 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,7 @@ buildscript { google() mavenCentral() maven { url 'https://jitpack.io' } + maven { url "https://jcenter.bintray.com/" } } dependencies { classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10' @@ -13,7 +14,7 @@ buildscript { classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.7.7" classpath 'com.google.dagger:hilt-android-gradle-plugin:2.50' - classpath 'com.google.gms:google-services:4.4.1' + classpath 'com.google.gms:google-services:4.4.2' classpath "com.android.tools.build:gradle:8.0.2" } }