Commit 2148534c authored by Samarakoon S.M.A.D IT20233808's avatar Samarakoon S.M.A.D IT20233808

Merge branch 'feature/IT20233808/soilBasedCropRecommendation' into 'master'

Feature/it20233808/soil based crop recommendation

See merge request !13
parents a2f7ab56 22bbda52
No preview for this file type
import { StyleSheet, Text, View } from 'react-native';
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import TestWithButton from './components/recomendationComponentsBySoil/TestWithButton';
import SoilDataOptions from './components/recomendationComponentsBySoil/SoilDataOptions';
import ManualSoilData from './components/recomendationComponentsBySoil/ManualSoilData';
import MostSutaibleCrops from './components/recomendationComponentsBySoil/MostSutaibleCrops';
import CreateCropRotaionPlan from './components/cropRotationPlanner/cropRotationCreation';
import HomePage from './components/common/Home';
import WeatherApp from './components/weatherCrop/Weatherpredict';
import WeatherData from './components/weatherCrop/WeatherData';
import WeatherDataOptions from './components/weatherCrop/WeatherDataOptions';
import CropRotationResponse from './components/cropRotationPlanner/CropRotationResponse';
import Crops from './components/weatherCrop/Crops';
import CreateCropRotaionPlan from './components/cropRotationPlanner/CropRotationCreation';
import AgriExpertSolution from './components/agriExpertComponent/AgriExpertSolution';
import NutrientSlider from './components/agriExpertComponent/NutrientSelect';
import CustomCrop from './components/recomendationComponentsBySoil/CustomCrop';
import CustomCropSelect from './components/recomendationComponentsBySoil/CustomCropSelect';
export default function App() {
......@@ -24,13 +26,17 @@ export default function App() {
<Stack.Screen name="Soil Data Options" component={SoilDataOptions}/>
<Stack.Screen name="Most Suitable Crops" component={MostSutaibleCrops}/>
<Stack.Screen name="Add Soil Data Manually " component={ManualSoilData}/>
<Stack.Screen name="TestWithButton" component={TestWithButton}/>
<Stack.Screen name="Create Crop Rotation Plan" component={CreateCropRotaionPlan}/>
<Stack.Screen name="Crop Rotation Plan" component={CropRotationResponse}/>
<Stack.Screen name="Weather Data Options" component={WeatherDataOptions} />
<Stack.Screen name="Weather Data" component={WeatherData} />
<Stack.Screen name="Crops" component={Crops} />
<Stack.Screen name='Weather Predict' component={WeatherApp} />
<Stack.Screen name='Nutrient Slider' component={NutrientSlider} />
<Stack.Screen name='Agri Expert' component={AgriExpertSolution} />
<Stack.Screen name='Test Custom Crop' component={CustomCrop} />
<Stack.Screen name='Custom Crop Select' component={CustomCropSelect} />
</Stack.Navigator>
</NavigationContainer>
);
......
import React, { useState } from 'react';
import { View, Text, TextInput, Button, StyleSheet, ImageBackground } from 'react-native';
import { useRoute } from '@react-navigation/native';
import axios from 'axios';
const backgroundImage = require('../../assets/backgroudManualData.jpg');
export default function AddSolutionScreen() {
const [name, setName] = useState('');
const [description, setDescription] = useState('');
const [recommended_application, setRecommendedApplication] = useState('');
const route = useRoute();
const { target_nutrient } = route.params;
const handleSubmit = () => {
if (!name || !description || !recommended_application) {
alert('Please fill out all fields and select a nutrient.');
} else {
const newData = {
name,
description,
target_nutrient,
recommended_application,
};
axios
.post('http://127.0.0.1:5000/add_solution', newData, {
headers: {
'Content-Type': 'application/json',
},
})
.then((response) => {
console.log('Response from server:', response.data);
setName('');
setDescription('');
setRecommendedApplication('');
alert('Solution added successfully!');
})
.catch((error) => {
console.error('Error:', error);
alert('An error occurred while adding the solution. Please try again later.');
});
}
};
return (
<ImageBackground source={backgroundImage} style={styles.background}>
<View style={styles.container}>
<Text style={styles.label}>Name:</Text>
<TextInput
style={styles.input}
onChangeText={setName}
value={name}
placeholder="Enter the solution name"
/>
<Text style={styles.label}>Description:</Text>
<TextInput
style={[styles.input, styles.multilineInput]}
onChangeText={setDescription}
value={description}
multiline
placeholder="Enter a description of the solution"
/>
<Text style={styles.label}>Recommended Application:</Text>
<TextInput
style={styles.input}
onChangeText={setRecommendedApplication}
value={recommended_application}
placeholder="Enter recommended application details"
/>
<Button title="Submit" onPress={handleSubmit} />
</View>
</ImageBackground>
);
}
const styles = StyleSheet.create({
background: {
flex: 1,
resizeMode: 'cover',
},
container: {
flex: 1,
padding: 16,
backgroundColor: 'rgba(255, 255, 255, 0.8)',
},
label: {
fontSize: 16,
fontWeight: 'bold',
marginBottom: 5,
color: 'black', // Change text color to black
},
input: {
height: 40,
borderColor: 'black', // Change border color to black
borderWidth: 1,
borderRadius: 5,
paddingHorizontal: 10,
marginBottom: 20,
color: 'black', // Change text color to black
},
multilineInput: {
height: 100,
paddingTop: 10,
},
picker: {
height: 40,
borderColor: 'black', // Change border color to black
borderWidth: 1,
borderRadius: 5,
},
fieldContainer: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 20,
},
});
import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Animated } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import Carousel from 'react-native-snap-carousel';
const BlinkingText = () => {
const [isBlinking, setIsBlinking] = useState(true);
const fadeAnim = new Animated.Value(1);
const startBlinking = () => {
Animated.loop(
Animated.sequence([
Animated.timing(fadeAnim, {
toValue: 0,
duration: 1000,
useNativeDriver: true,
}),
Animated.timing(fadeAnim, {
toValue: 1,
duration: 1000,
useNativeDriver: true,
}),
])
).start();
};
useEffect(() => {
startBlinking();
}, []);
return (
<Animated.View style={{ opacity: fadeAnim }}>
<Text style={styles.blinkingText}>Slide to select the Nutrient</Text>
</Animated.View>
);
};
const NutrientSlider = ({ target_nutrient }) => {
const nutrientOptions = [
{ name: 'Nitrogen', color: '#FF6F61' },
{ name: 'Phosphorus', color: '#6B4226' },
{ name: 'Potassium', color: '#5E8C31' },
];
const navigation = useNavigation();
const handleNutrientSelection = (nutrient) => {
// Navigate to AgriExpert page and pass the selected nutrient
navigation.navigate('Agri Expert', { target_nutrient: nutrient });
};
return (
<View style={styles.container}>
<Text style={styles.heading}>Nutrient Select</Text>
<Carousel
data={nutrientOptions}
renderItem={({ item }) => (
<TouchableOpacity
style={[
styles.nutrientCard,
{ backgroundColor: item.color },
target_nutrient === item.name && styles.selectedCard,
]}
onPress={() => handleNutrientSelection(item.name)}
>
<View style={styles.centeredContent}>
<Text style={styles.nutrientText}>{item.name}</Text>
</View>
</TouchableOpacity>
)}
sliderWidth={300}
itemWidth={200}
loop
/>
<BlinkingText />
</View>
);
};
const styles = StyleSheet.create({
container: {
alignItems: 'center',
paddingVertical: 300,
},
heading:{
fontSize:20,
},
nutrientCard: {
borderRadius: 10,
padding: 20,
alignItems: 'center',
justifyContent: 'center',
height: 150,
},
selectedCard: {
borderColor: 'blue',
borderWidth: 2,
},
nutrientText: {
fontSize: 16,
fontWeight: 'bold',
color: '#FFF',
},
centeredContent: {
alignItems: 'center',
justifyContent: 'center',
},
blinkingText: {
fontSize: 24,
fontWeight: 'bold',
color: 'black',
marginTop: 100,
},
});
export default NutrientSlider;
const cropDescription = {
banana:"Banana can be grown in coconut lands in the wet, intermediate and dry zones. In the wet zone, it is grown as a rain fed crop.",
pomegranate: " In Sri Lanka, pomegranate can be seen grown in dry zones and it takes six-eight years to get the maximum harvest from a pomegranate tree.",
orange: " It can be grown in the village gardens in Sri Lanka. It grows best in the dry zone where low atmospheric humidity and a definite dry period aids growth and maturity of fruits. "
}
export default cropDescription
\ No newline at end of file
......@@ -13,6 +13,11 @@ const HomePage = ({ navigation }) => {
navigation.navigate('Weather Data Options');
} else if (option === 'cropRotationPlan') {
navigation.navigate('Create Crop Rotation Plan');
}else if(option === 'nutrientSlider'){
navigation.navigate('Nutrient Slider')
}
else if(option === 'customCropSelect'){
navigation.navigate('Custom Crop Select')
}
};
......@@ -31,6 +36,12 @@ const HomePage = ({ navigation }) => {
<TouchableOpacity style={styles.optionButton} onPress={() => handleOptionSelect('cropRotationPlan')}>
<Text style={styles.optionText}>Crop Rotation Plan</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.optionButton} onPress={() => handleOptionSelect('nutrientSlider')}>
<Text style={styles.optionText}>Agri Expert Solution</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.optionButton} onPress={() => handleOptionSelect('customCropSelect')}>
<Text style={styles.optionText}>Select a Crop</Text>
</TouchableOpacity>
</View>
</ImageBackground>
);
......
import React, { useState, useEffect } from 'react';
import { View, Text, FlatList, StyleSheet, ActivityIndicator, TouchableOpacity, ImageBackground } from 'react-native';
import axios from 'axios';
import { useRoute } from '@react-navigation/native';
const CustomCrop = () => {
const [data, setData] = useState({});
const [loading, setLoading] = useState(true);
const [selectedNutrient, setSelectedNutrient] = useState(null);
const route = useRoute();
const { userNpkData, crop } = route.params;
console.log("npk data :",userNpkData.Nitrogen);
useEffect(() => {
axios.post('http://127.0.0.1:5000/balancesoil', {
N: userNpkData.Nitrogen,
P: userNpkData.Phosphorus,
K: userNpkData.Potassium,
crop: crop.toLowerCase(),
})
.then(response => {
setData(response.data);
setLoading(false);
})
.catch(error => {
console.error('Error fetching data:', error);
setLoading(false);
});
}, []);
const renderNutrientItem = (nutrient) => {
return (
<View>
<Text style={styles.label}>Your Crop:{crop}</Text>
<TouchableOpacity onPress={() => setSelectedNutrient(nutrient)}>
<View style={styles.nutrientItem}>
<Text style={styles.label}>Nutrient:</Text>
<Text style={styles.value}>{nutrient}</Text>
<Text style={styles.label}>Amount:</Text>
<Text style={styles.value}>{data[nutrient]}</Text>
</View>
</TouchableOpacity>
</View>
);
};
const renderInstructions = (instructions) => {
return (
<View style={styles.instructionContainer}>
<FlatList
data={instructions}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => (
<View style={styles.instructionItem}>
<Text style={styles.label}>Description:</Text>
<Text style={styles.value}>{item.description}</Text>
<Text style={styles.label}>Recommended Application:</Text>
<Text style={styles.value}>{item.recommendedApplication || 'Not specified'}</Text>
</View>
)}
/>
<TouchableOpacity onPress={() => setSelectedNutrient(null)}>
<Text style={styles.closeButton}>Close</Text>
</TouchableOpacity>
</View>
);
};
return (
<View style={styles.container}>
<ImageBackground source={require('../../assets/backgroudManualData.jpg')} style={styles.backgroundImage}>
{loading ? (
<ActivityIndicator size="large" color="#007BFF" />
) : (
<View>
{selectedNutrient ? (
renderInstructions(data[`${selectedNutrient}_instructions`])
) : (
<FlatList
data={Object.keys(data).filter(nutrient => nutrient.endsWith('_instructions'))}
keyExtractor={(item) => item}
renderItem={({ item }) => renderNutrientItem(item.replace('_instructions', ''))}
/>
)}
</View>
)}
</ImageBackground>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
position: 'relative',
width: '100%',
height: '100%',
},
backgroundImage: {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
resizeMode: 'cover',
},
nutrientItem: {
marginVertical: 5,
backgroundColor: 'white',
padding: 10,
borderRadius: 8,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
margin:20
},
instructionContainer: {
marginVertical: 5,
backgroundColor: 'white',
padding: 10,
borderRadius: 8,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
margin:20
},
instructionItem: {
marginVertical: 5,
backgroundColor: 'white',
padding: 10,
borderRadius: 8,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
label: {
fontWeight: 'bold',
},
value: {
fontSize: 16,
},
closeButton: {
color: 'blue',
textAlign: 'center',
marginTop: 10,
},
});
export default CustomCrop;
import axios from 'axios';
import React, { useState } from 'react';
import { View, Text, TouchableOpacity, StyleSheet, ImageBackground } from 'react-native';
const CropList = ['Wheat', 'Corn', 'Rice', 'Potato', 'Soybeans'];
const CustomCropSelect = ({ navigation }) => {
const [selectedCrop, setSelectedCrop] = useState(null);
const handleCropSelect = (crop) => {
setSelectedCrop(crop);
};
const handleNextPage = async() => {
if (selectedCrop) {
const npkData = await handleArduinoRequest()
console.log("handle next page:",npkData);
navigation.navigate('Test Custom Crop', {
crop: selectedCrop,
userNpkData: npkData,
});
}
};
const handleArduinoRequest = async () => {
console.log("arduino hit in custom crop select");
try {
const response = await axios.get('http://192.168.254.241');
const userNpkData = response.data;
return userNpkData;
} catch (error) {
console.log(error);
throw error;
}
};
return (
<ImageBackground
source={require('../../assets/backgroudManualData.jpg')}
style={styles.backgroundImage}
imageStyle={{ opacity: 0.2 }}
>
<View style={styles.container}>
<Text style={styles.label}>Select a Crop:</Text>
{CropList.map((crop, index) => (
<TouchableOpacity
key={index}
onPress={() => handleCropSelect(crop)}
style={[
styles.cropItem,
{ backgroundColor: selectedCrop === crop ? '#007BFF' : 'gray' },
]}
>
<Text style={styles.cropText}>{crop}</Text>
</TouchableOpacity>
))}
<TouchableOpacity
style={[
styles.button,
{ backgroundColor: selectedCrop ? 'green' : 'gray' },
]}
disabled={!selectedCrop}
onPress={handleNextPage}
>
<Text style={styles.buttonText}>Find the deficiencies in your soil</Text>
</TouchableOpacity>
</View>
</ImageBackground>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
alignItems: 'center',
justifyContent: 'center',
},
label: {
fontSize: 28,
fontWeight: 'bold',
color: 'white',
marginBottom: 10,
marginBottom: 40,
},
cropItem: {
padding: 15,
marginVertical: 10,
borderRadius: 10,
width: '80%',
},
cropText: {
color: 'white',
fontSize: 16,
textAlign: 'center',
},
backgroundImage: {
flex: 1,
resizeMode: 'cover',
justifyContent: 'center',
backgroundColor: 'rgba(0,0,0,0.8)',
},
button: {
padding: 10,
borderRadius: 10,
width: '100%',
marginTop: 40
},
buttonText: {
color: 'white',
fontSize: 18,
textAlign: 'center',
},
});
export default CustomCropSelect;
......@@ -7,19 +7,25 @@ const ManualSoilData = ({navigation}) => {
const [potassiumLevel, setPotassiumLevel] = useState("");
const handleAddLevels = () => {
const parsedNitrogenLevel = parseFloat(nitrogenLevel);
const parsedPhosphorusLevel = parseFloat(phosphorusLevel);
const parsedPotassiumLevel = parseFloat(potassiumLevel);
const userNpkData={
Nitrogen:parsedNitrogenLevel,
Phosphorus:parsedPhosphorusLevel,
Potassium:parsedPotassiumLevel
const totalNpk = parsedNitrogenLevel + parsedPhosphorusLevel + parsedPotassiumLevel;
if (totalNpk > 10) {
alert('Total nitrogen, phosphorus, and potassium levels cannot exceed 10');
} else {
const userNpkData = {
Nitrogen: parsedNitrogenLevel,
Phosphorus: parsedPhosphorusLevel,
Potassium: parsedPotassiumLevel,
};
console.log(userNpkData);
navigation.navigate("Most Suitable Crops", { userNpkData });
}
console.log(userNpkData);
navigation.navigate("Most Suitable Crops",{userNpkData})
};
return (
<View style={styles.container}>
......
......@@ -4,33 +4,23 @@ import axios from 'axios';
import { useRoute } from '@react-navigation/native';
import BackgroundImage from '../../assets/backgroudManualData.jpg';
import cropImages from '../common/Images';
import cropDescription from '../common/Description';
const MostSuitableCrops = () => {
const [cropData, setCropData] = useState(null);
const [isLoading, setIsLoading] = useState(true); // Set initial loading state to true
const [mapObject, setMapObject] = useState({});
const [isLoading, setIsLoading] = useState(true);
const [selectedCrop, setSelectedCrop] = useState(null);
const route = useRoute();
const { userNpkData } = route.params;
// const handleArduinoClick = async () => {
// await axios.get('http://192.168.89.241')
// .then(res => {
// setCropData(res.data);
// })
// .catch(err => {
// console.log(err);
// });
// };
useEffect(() => {
const timer = setTimeout(() => {
setIsLoading(false);
setIsLoading(false);
}, 3000);
return () => clearTimeout(timer);
}, []);
useEffect(() => {
const fetchCropData = async () => {
try {
......@@ -40,7 +30,7 @@ const MostSuitableCrops = () => {
K: userNpkData['Potassium']
});
const responseData = response.data;
console.log("res data",responseData);
console.log("res data", responseData);
setCropData(responseData);
} catch (error) {
console.error('Error fetching crop data:', error);
......@@ -52,8 +42,6 @@ const MostSuitableCrops = () => {
fetchCropData();
}, []);
return (
<ImageBackground source={BackgroundImage} style={styles.backgroundImage}>
<View style={styles.container}>
......@@ -67,20 +55,36 @@ const MostSuitableCrops = () => {
<Text style={styles.title}>Most Suitable Crops:</Text>
<View style={styles.cropContainer}>
{cropData.top_three_crops.map((cropInfo) => (
<View key={cropInfo.crop} style={styles.cropItem}>
<TouchableOpacity
key={cropInfo.crop}
style={styles.cropItem}
onPress={() => setSelectedCrop(cropInfo)}
>
<Image source={cropImages[cropInfo.crop]} style={styles.cropImage} />
<Text style={styles.cropText}>{cropInfo.crop}</Text>
</View>
</TouchableOpacity>
))}
</View>
<View style={styles.nutrientContainer}>
<Text style={styles.nutrientTitle}>Nutrient Values Present in Your Soil:</Text>
<Text style={styles.nutrientText}>Nitrogen (N): {userNpkData.Nitrogen}</Text>
<Text style={styles.nutrientText}>Phosphorus (P): {userNpkData.Phosphorus}</Text>
<Text style={styles.nutrientText}>Potassium (K): {userNpkData.Potassium}</Text>
<Text style={styles.nutrientText}>Nitrogen (N): {userNpkData.Nitrogen} mg/kg</Text>
<Text style={styles.nutrientText}>Phosphorus (P): {userNpkData.Phosphorus} mg/kg</Text>
<Text style={styles.nutrientText}>Potassium (K): {userNpkData.Potassium} mg/kg</Text>
</View>
</View>
) : null}
{selectedCrop && (
<View style={styles.cropDescriptionContainer}>
<Text style={styles.cropDescriptionTitle}>How to Grow {selectedCrop.crop}:</Text>
<Text style={styles.cropDescriptionText}>{cropDescription[selectedCrop.crop]}</Text>
<TouchableOpacity
style={styles.closeButton}
onPress={() => setSelectedCrop(null)}
>
<Text style={styles.closeButtonText}>Close</Text>
</TouchableOpacity>
</View>
)}
</View>
</ImageBackground>
);
......@@ -97,7 +101,7 @@ const styles = StyleSheet.create({
justifyContent: 'center',
alignItems: 'center',
padding: 20,
backgroundColor: 'rgba(0, 0, 0, 0.5)', // Add opacity to the background color
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
card: {
backgroundColor: '#fff',
......@@ -178,6 +182,36 @@ const styles = StyleSheet.create({
textTransform: 'capitalize',
fontWeight: 'bold',
},
cropDescriptionContainer: {
marginTop: 20,
backgroundColor: '#fff',
borderRadius: 10,
padding: 20,
},
cropDescriptionTitle: {
fontSize: 16,
fontWeight: 'bold',
marginBottom: 10,
color: '#333',
},
cropDescriptionText: {
fontSize: 14,
marginBottom: 10,
color: '#333',
textAlign: 'left',
},
closeButton: {
backgroundColor: '#007AFF',
padding: 10,
borderRadius: 5,
marginTop: 10,
},
closeButtonText: {
color: '#fff',
fontSize: 16,
fontWeight: 'bold',
textAlign: 'center',
},
});
export default MostSuitableCrops;
......@@ -7,15 +7,14 @@ const SoilDataOptions = ({ navigation }) => {
const [isLoading, setIsLoading] = useState(false);
const handleArduinoRequest = async () => {
console.log("arduino hit");
setIsLoading(true);
try {
const response = await axios.get('http://192.168.73.241');
const response = await axios.get('http://192.168.254.241');
const userNpkData = response.data;
setCropData(userNpkData);
console.log(userNpkData);
navigation.navigate("Most Suitable Crops", { userNpkData });
} catch (error) {
console.log(error);
......@@ -23,6 +22,7 @@ const SoilDataOptions = ({ navigation }) => {
setIsLoading(false);
}
}
return (
<View style={styles.container}>
......
import React from 'react';
import { View } from 'react-native';
import { Button, NativeBaseProvider } from "native-base";
import { NativeBaseConfigProvider } from 'native-base/src/core/NativeBaseContext';
const TestWithButton = ({navigation}) => {
return (
<NativeBaseConfigProvider>
<NativeBaseProvider>
<Button onPress={()=>navigation.navigate("Test")}>click</Button>
</NativeBaseProvider>
</NativeBaseConfigProvider>
);
};
export default TestWithButton;
\ No newline at end of file
......@@ -3606,6 +3606,11 @@
"joi": "^17.2.1"
}
},
"@react-native-picker/picker": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@react-native-picker/picker/-/picker-2.5.1.tgz",
"integrity": "sha512-/sADUfQsosMRYtrqqL3ZYZSECRygj0fXtpRLqxJfwuMEoqfvfn40756R6B1alzusVvDRZFI0ari0iQid56hA/Q=="
},
"@react-native/assets": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@react-native/assets/-/assets-1.0.0.tgz",
......@@ -3641,6 +3646,8 @@
},
"@react-navigation/native": {
"version": "6.1.6",
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.6.tgz",
"integrity": "sha512-14PmSy4JR8HHEk04QkxQ0ZLuqtiQfb4BV9kkMXD2/jI4TZ+yc43OnO6fQ2o9wm+Bq8pY3DxyerC2AjNUz+oH7Q==",
"requires": {
"@react-navigation/core": "^6.4.8",
"escape-string-regexp": "^4.0.0",
......@@ -3650,6 +3657,8 @@
},
"@react-navigation/native-stack": {
"version": "6.9.12",
"resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.9.12.tgz",
"integrity": "sha512-kS2zXCWP0Rgt7uWaCUKrRl7U2U1Gp19rM1kyRY2YzBPXhWGVPjQ2ygBp88CTQzjgy8M07H/79jvGiZ0mlEJI+g==",
"requires": {
"@react-navigation/elements": "^1.3.17",
"warn-once": "^0.1.0"
......@@ -4439,14 +4448,6 @@
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
},
"axios": {
"version": "1.4.0",
"requires": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"babel-core": {
"version": "7.0.0-bridge.0",
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz",
......@@ -5549,6 +5550,8 @@
},
"expo": {
"version": "48.0.17",
"resolved": "https://registry.npmjs.org/expo/-/expo-48.0.17.tgz",
"integrity": "sha512-5T1CsMUlfI+xFB89GOU+/xtSSbSBBFVTqwgheAU0cQolfbs+YyJCMTKU5vN45N5OK+ym7p/LKPa6DQAxYPF8YQ==",
"requires": {
"@babel/runtime": "^7.20.0",
"@expo/cli": "0.7.1",
......@@ -5675,7 +5678,9 @@
}
},
"expo-status-bar": {
"version": "1.4.4"
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.4.4.tgz",
"integrity": "sha512-5DV0hIEWgatSC3UgQuAZBoQeaS9CqeWRZ3vzBR9R/+IUD87Adbi4FGhU10nymRqFXOizGsureButGZIXPs7zEA=="
},
"extend-shallow": {
"version": "3.0.2",
......@@ -5945,6 +5950,8 @@
},
"firebase": {
"version": "9.22.0",
"resolved": "https://registry.npmjs.org/firebase/-/firebase-9.22.0.tgz",
"integrity": "sha512-Ay1u8IOfhPh58RFAHF7A9cKHACCgV6uI2bhkzKdkjnV0n2AAxn4tDtdXvJ3BEbfhF4WWBC2dFcEXH8cd14ptaw==",
"requires": {
"@firebase/analytics": "0.10.0",
"@firebase/analytics-compat": "0.2.6",
......@@ -5979,11 +5986,6 @@
"resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.185.2.tgz",
"integrity": "sha512-2hJ5ACYeJCzNtiVULov6pljKOLygy0zddoqSI1fFetM+XRPpRshFdGEijtqlamA1XwyZ+7rhryI6FQFzvtLWUQ=="
},
"follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
},
"fontfaceobserver": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz",
......@@ -5994,16 +5996,6 @@
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
"integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ=="
},
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
},
"fragment-cache": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
......@@ -7919,6 +7911,8 @@
},
"native-base": {
"version": "3.4.28",
"resolved": "https://registry.npmjs.org/native-base/-/native-base-3.4.28.tgz",
"integrity": "sha512-EDg9UFDNmfYXPInpRbxce+4oWFEIGaM7aG6ey4hVllcvMC3PkgCvkiXEB+7EemgC7Qr8CuFjgMTx7P0vvnwZeQ==",
"requires": {
"@react-aria/visually-hidden": "^3.2.1",
"@react-native-aria/button": "^0.2.4",
......@@ -8538,11 +8532,6 @@
}
}
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
......@@ -8615,6 +8604,8 @@
},
"react": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"requires": {
"loose-envify": "^1.1.0"
}
......@@ -8637,6 +8628,8 @@
},
"react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
"requires": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.0"
......@@ -8654,6 +8647,8 @@
},
"react-native": {
"version": "0.71.8",
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.71.8.tgz",
"integrity": "sha512-ftMAuhpgTkbHU9brrqsEyxcNrpYvXKeATY+if22Nfhhg1zW+6wn95w9otwTnA3xHkljPCbng8mUhmmERjGEl7g==",
"requires": {
"@jest/create-cache-key-function": "^29.2.1",
"@react-native-community/cli": "10.2.2",
......@@ -8769,10 +8764,14 @@
"integrity": "sha512-7F6bD7B8Xsn3JllxcwHhFcsl9aHIig47+3eN4IHFNqfLhZr++3ElDrcqfMzugM+niWbaMi7bJ0kAkAL8eCpdWg=="
},
"react-native-safe-area-context": {
"version": "4.5.0"
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.5.0.tgz",
"integrity": "sha512-0WORnk9SkREGUg2V7jHZbuN5x4vcxj/1B0QOcXJjdYWrzZHgLcUzYWWIUecUPJh747Mwjt/42RZDOaFn3L8kPQ=="
},
"react-native-screens": {
"version": "3.20.0",
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.20.0.tgz",
"integrity": "sha512-joWUKWAVHxymP3mL9gYApFHAsbd9L6ZcmpoZa6Sl3W/82bvvNVMqcfP7MeNqVCg73qZ8yL4fW+J/syusHleUgg==",
"requires": {
"react-freeze": "^1.0.0",
"warn-once": "^0.1.0"
......
......@@ -10,9 +10,10 @@
},
"dependencies": {
"@expo/webpack-config": "^18.0.1",
"@react-native-picker/picker": "^2.5.1",
"@react-navigation/native": "^6.1.6",
"@react-navigation/native-stack": "^6.9.12",
"axios": "^1.4.0",
"axios": "^1.5.0",
"expo": "~48.0.9",
"expo-status-bar": "~1.4.4",
"firebase": "^9.18.0",
......@@ -22,6 +23,7 @@
"react-native": "0.71.8",
"react-native-safe-area-context": "4.5.0",
"react-native-screens": "~3.20.0",
"react-native-snap-carousel": "^3.9.1",
"react-native-svg": "^13.9.0",
"react-native-web": "~0.18.11"
},
......
......@@ -2888,6 +2888,11 @@
prompts "^2.4.0"
semver "^6.3.0"
"@react-native-picker/picker@^2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@react-native-picker/picker/-/picker-2.5.1.tgz#dfa13d5b97bfbedf1f7e7c608181a82f1d58b351"
integrity sha512-/sADUfQsosMRYtrqqL3ZYZSECRygj0fXtpRLqxJfwuMEoqfvfn40756R6B1alzusVvDRZFI0ari0iQid56hA/Q==
"@react-native/assets@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@react-native/assets/-/assets-1.0.0.tgz#c6f9bf63d274bafc8e970628de24986b30a55c8e"
......@@ -4068,10 +4073,10 @@ atob@^2.1.2:
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
axios@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f"
integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==
axios@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.0.tgz#f02e4af823e2e46a9768cfc74691fdd0517ea267"
integrity sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==
dependencies:
follow-redirects "^1.15.0"
form-data "^4.0.0"
......@@ -4888,6 +4893,11 @@ core-js-compat@^3.25.1:
dependencies:
browserslist "^4.21.5"
core-js@^1.0.0:
version "1.2.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
integrity sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA==
core-util-is@~1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
......@@ -5385,6 +5395,13 @@ encodeurl@~1.0.2:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
encoding@^0.1.11:
version "0.1.13"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==
dependencies:
iconv-lite "^0.6.2"
end-of-stream@^1.1.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
......@@ -5828,6 +5845,19 @@ fbjs-css-vars@^1.0.0:
resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8"
integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==
fbjs@^0.8.4:
version "0.8.18"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.18.tgz#9835e0addb9aca2eff53295cd79ca1cfc7c9662a"
integrity sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
loose-envify "^1.0.0"
object-assign "^4.1.0"
promise "^7.1.1"
setimmediate "^1.0.5"
ua-parser-js "^0.7.30"
fbjs@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.4.tgz#e1871c6bd3083bac71ff2da868ad5067d37716c6"
......@@ -6498,7 +6528,7 @@ iconv-lite@0.4.24:
dependencies:
safer-buffer ">= 2.1.2 < 3"
iconv-lite@^0.6.3:
iconv-lite@^0.6.2, iconv-lite@^0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
......@@ -6825,7 +6855,7 @@ is-root@^2.1.0:
resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c"
integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==
is-stream@^1.1.0:
is-stream@^1.0.1, is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==
......@@ -6886,6 +6916,14 @@ isobject@^3.0.0, isobject@^3.0.1:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
isomorphic-fetch@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
integrity sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==
dependencies:
node-fetch "^1.0.1"
whatwg-fetch ">=0.10.0"
jest-environment-node@^29.2.1:
version "29.5.0"
resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.5.0.tgz#f17219d0f0cc0e68e0727c58b792c040e332c967"
......@@ -8061,6 +8099,14 @@ node-fetch@2.6.7:
dependencies:
whatwg-url "^5.0.0"
node-fetch@^1.0.1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==
dependencies:
encoding "^0.1.11"
is-stream "^1.0.1"
node-fetch@^2.2.0, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.11, node-fetch@^2.6.7:
version "2.6.11"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25"
......@@ -8852,7 +8898,7 @@ prompts@^2.3.2, prompts@^2.4.0:
kleur "^3.0.3"
sisteransi "^1.0.5"
prop-types@*:
prop-types@*, prop-types@^15.6.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
......@@ -8998,6 +9044,14 @@ rc@^1.0.1, rc@^1.1.6, rc@~1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
react-addons-shallow-compare@15.6.2:
version "15.6.2"
resolved "https://registry.yarnpkg.com/react-addons-shallow-compare/-/react-addons-shallow-compare-15.6.2.tgz#198a00b91fc37623db64a28fd17b596ba362702f"
integrity sha512-yAV9tOObmKPiohqne1jiMcx6kDjfz7GeL8K9KHgI+HvDsbrRv148uyUzrPc6GwepZnQcJ59Q3lp1ghrkyPwtjg==
dependencies:
fbjs "^0.8.4"
object-assign "^4.1.0"
react-devtools-core@^4.26.1:
version "4.27.7"
resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.27.7.tgz#458a6541483078d60a036c75bf88f54c478086ec"
......@@ -9062,6 +9116,14 @@ react-native-screens@~3.20.0:
react-freeze "^1.0.0"
warn-once "^0.1.0"
react-native-snap-carousel@^3.9.1:
version "3.9.1"
resolved "https://registry.yarnpkg.com/react-native-snap-carousel/-/react-native-snap-carousel-3.9.1.tgz#6fd9bd8839546c2c6043a41d2035afbc6fe0443e"
integrity sha512-xWEGusacIgK1YaDXLi7Gao2+ISLoGPVEBR8fcMf4tOOJQufutlNwkoLu0l6B8Qgsrre0nTxoVZikRgGRDWlLaQ==
dependencies:
prop-types "^15.6.1"
react-addons-shallow-compare "15.6.2"
react-native-svg@^13.9.0:
version "13.13.0"
resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-13.13.0.tgz#23dedb4594dcc44128d63fa5b13c49534187fef5"
......@@ -10718,6 +10780,11 @@ websocket-extensions@>=0.1.1:
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
whatwg-fetch@>=0.10.0:
version "3.6.19"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz#caefd92ae630b91c07345537e67f8354db470973"
integrity sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==
whatwg-fetch@^3.0.0:
version "3.6.2"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c"
......
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (soil-component-BE)" project-jdk-type="Python SDK" />
<component name="PyCharmProfessionalAdvertiser">
<option name="shown" value="true" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/soil-component-BE.iml" filepath="$PROJECT_DIR$/.idea/soil-component-BE.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/env" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>
\ No newline at end of file
......@@ -10,6 +10,7 @@ class Crop:
# Function to calculate the suitability score for a crop
def calculate_suitability_score(crop, user_soil_nutrients, optimization_criteria):
global suitability
score = 0
for nutrient in user_soil_nutrients:
nutrient_value = user_soil_nutrients[nutrient]
......@@ -21,9 +22,7 @@ def calculate_suitability_score(crop, user_soil_nutrients, optimization_criteria
if difference == 0:
suitability = 100.0
else:
suitability = 0.0
else:
suitability = (1 - difference / required_value) * 100.0
suitability = (1 - difference / required_value) * 100.0
weighted_suitability = suitability * weight
score += weighted_suitability
......@@ -72,13 +71,12 @@ def receive_npk_data():
Crop("Maize", {'N': 0.6, 'P': 0.4, 'K': 0.5}),
Crop("Potato", {'N': 0.3, 'P': 0.4, 'K': 0.5}),
Crop("Tomato", {'N': 0.6, 'P': 0.6, 'K': 0.6}),
Crop("Cotton", {'N': 0.6, 'P': 0.4, 'K': 0.6})
]
optimization_criteria = {
'N': 1,
'P': 1,
'K': 1
'P': 0.5,
'K': 0.25
}
crop_scores = []
......
......@@ -62,3 +62,9 @@ Tomato,0.3,0.5,0.2
Wheat,4.47,0.29,5.24
Cotton,4.47,0.29,5.24
Tomato,4.47,0.29,5.24
Tomato,30,50,20
Wheat,30,50,20
Cotton,30,50,20
Tomato,40,30,30
Wheat,40,30,30
Cotton,40,30,30
from flask import Flask, request, jsonify
import joblib
import pandas as pd
from sklearn.metrics import accuracy_score
model = joblib.load('./soil_crop_model.joblib')
import pymongo as pymongo
# Load your trained model
model = joblib.load('./random_forest_model_v2.joblib')
eval_data = pd.read_csv('soil_crop.csv')
eval_X = eval_data[['nitrogen', 'phosphorus', 'potassium']]
eval_y = eval_data['crop']
predicted_labels = model.predict(eval_X)
accuracy = accuracy_score(eval_y, predicted_labels)
# Predict probabilities for all classes
predicted_probabilities = model.predict_proba(eval_X)
app = Flask(__name__)
mongo_client = pymongo.MongoClient("mongodb+srv://anjana:8682123abc@cluster0.bhsdkyx.mongodb.net/?retryWrites=true&w=majority")
db = mongo_client["AgriExpertSolutions"]
collection = db["organic_solutions"]
# Function to calculate the mean N, P, K values for a given crop
def get_mean_values_for_crop(crop_name):
crop_data = eval_data[eval_data['crop'] == crop_name]
if not crop_data.empty:
mean_values = crop_data[['nitrogen', 'phosphorus', 'potassium']].mean()
return mean_values.to_dict()
else:
return None
@app.route('/predict', methods=['POST'])
def predict():
input_data = request.get_json()
......@@ -22,13 +36,111 @@ def predict():
phosphorus = input_data['P']
potassium = input_data['K']
predicted_crop = model.predict([[nitrogen, phosphorus, potassium]])
# Predict probabilities for the input data
predicted_probabilities = model.predict_proba([[nitrogen, phosphorus, potassium]])
# Get the classes (crops) and their corresponding probabilities
classes = model.classes_
probabilities = predicted_probabilities[0]
# Create a list to store crop information as objects
crop_info = []
for crop, probability in zip(classes, probabilities):
crop_info.append({
'crop': crop,
'probability': probability
})
# Sort the crops by probability in descending order
sorted_crops = sorted(crop_info, key=lambda x: x['probability'], reverse=True)
# Get the top three crops
top_three_crops = sorted_crops[:3]
response = {
'crop': predicted_crop[0],
'accuracy': accuracy
'top_three_crops': top_three_crops,
'accuracy': accuracy_score(eval_y, model.predict(eval_X)) # Calculate accuracy on evaluation data
}
return jsonify(response)
@app.route('/mean_values/<crop_name>', methods=['GET'])
def get_mean_values(crop_name):
mean_values = get_mean_values_for_crop(crop_name)
if mean_values is not None:
return jsonify(mean_values)
else:
return jsonify({'error': 'Crop not found'}), 404
@app.route('/balancesoil', methods=['POST'])
def balance_soil():
input_data = request.get_json()
nitrogen_soil = input_data['N']
phosphorus_soil = input_data['P']
potassium_soil = input_data['K']
crop = input_data['crop']
# Get the mean nutrient values for the specified crop
mean_values = get_mean_values_for_crop(crop)
if mean_values is not None:
# Calculate the differences between soil values and mean values
nitrogen_diff = mean_values['nitrogen'] - nitrogen_soil
phosphorus_diff = mean_values['phosphorus'] - phosphorus_soil
potassium_diff = mean_values['potassium'] - potassium_soil
# Create a dictionary to store the lacking nutrient values
lacking_nutrients = {}
# Fetch the instructions for each nutrient deficiency from the database
if nitrogen_diff > 0:
nitrogen_instructions = list(collection.find({"target_nutrient": "Nitrogen"}))
lacking_nutrients['nitrogen'] = nitrogen_diff
lacking_nutrients['nitrogen_instructions'] = [{'description': ins['description'], 'recommendedApplication': ins['recommendedApplication']} for ins in nitrogen_instructions]
if phosphorus_diff > 0:
phosphorus_instructions = list(collection.find({"target_nutrient": "Phosphorus"}))
lacking_nutrients['phosphorus'] = phosphorus_diff
lacking_nutrients['phosphorus_instructions'] = [{'description': ins['description'], 'recommendedApplication': ins['recommendedApplication']} for ins in phosphorus_instructions]
if potassium_diff > 0:
potassium_instructions = list(collection.find({"target_nutrient": "Potassium"}))
lacking_nutrients['potassium'] = potassium_diff
lacking_nutrients['potassium_instructions'] = [{'description': ins['description'], 'recommendedApplication': ins['recommendedApplication']} for ins in potassium_instructions]
return jsonify(lacking_nutrients)
else:
return jsonify({'error': 'Crop not found'}), 404
@app.route('/add_solution', methods=['POST'])
def add_solution():
input_data = request.get_json()
print(input_data)
# Extract data from the request
name = input_data.get('name')
description = input_data.get('description')
target_nutrient = input_data.get('target_nutrient')
recommended_application = input_data.get('recommended_application')
# Insert the data into the MongoDB collection
new_solution = {
'name': name,
'description': description,
'target_nutrient': target_nutrient,
'recommendedApplication': recommended_application
}
# Insert the document into the collection
result = collection.insert_one(new_solution)
if result.inserted_id:
return jsonify({'message': 'Solution added successfully'})
else:
return jsonify({'message': 'Failed to add solution'}), 500
if __name__ == '__main__':
app.run()
import pandas as pd
# Read the CSV file into a Pandas DataFrame
df = pd.read_csv('soil_crop.csv')
# Divide the values in the "nitrogen," "phosphorus," and "potassium" columns by 10
df['nitrogen'] = df['nitrogen'] / 10
df['phosphorus'] = df['phosphorus'] / 10
df['potassium'] = df['potassium'] / 10
# Save the new dataset to a new CSV file
df.to_csv('new_soil_data.csv', index=False)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment