Added Haversine Formula calculation to get the radius of circles for study groups required for rendering

This commit is contained in:
Keannu Christian Bernasol 2023-09-09 20:45:29 +08:00
parent 85e2a13071
commit 7b9d05f84b
4 changed files with 225 additions and 159 deletions

View file

@ -17,10 +17,11 @@ import Button from "../../components/Button/Button";
import {
RootDrawerParamList,
StudentStatusReturnType,
LocationType,
RawLocationType,
StudentStatusType,
StudentStatusListReturnType,
StudentStatusListType,
subjectUserMapType,
} from "../../interfaces/Interfaces";
import { useNavigation } from "@react-navigation/native";
import {
@ -33,12 +34,14 @@ import {
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useToast } from "react-native-toast-notifications";
import CustomMapCallout from "../../components/CustomMapCallout/CustomMapCallout";
import ParseStudentStatusList from "../../components/ParseStudyGroupList/ParseStudyGroupList";
import React from "react";
export default function Home() {
// Switch this condition to see the main map when debugging
const map_debug = true;
const navigation = useNavigation<RootDrawerParamList>();
const [location, setLocation] = useState<LocationType | null>(null);
const [location, setLocation] = useState<RawLocationType | null>(null);
const [dist, setDist] = useState<number | null>(null);
const [feedback, setFeedback] = useState(
"To continue, please allow Stud-E permission to location services"
@ -97,7 +100,7 @@ export default function Home() {
requestLocation();
}, []);
async function GetDistanceRoundedOff(location: LocationType) {
async function GetDistanceRoundedOff(location: RawLocationType) {
let dist = GetDistance(
location.coords.latitude,
location.coords.longitude,
@ -176,8 +179,8 @@ export default function Home() {
},
});
// Can probably just get the max distance from the array and use it as radius
const [student_statuses, setStudentStatuses] = useState<any>([]);
const [study_groups, setStudyGroups] = useState<subjectUserMapType[]>([]);
// Student Status List
const StudentStatusList = useQuery({
enabled: studying,
@ -191,93 +194,7 @@ export default function Home() {
},
onSuccess: (data: StudentStatusListReturnType) => {
if (data[1]) {
// Circle generation for students in a study group
// We first flatten the data to remove nested entries
let flattened_data = data[1].map((item) => ({
active: item.active,
distance: item.distance,
landmark: item.landmark,
latitude: item.location.latitude,
longitude: item.location.longitude,
study_group: "",
subject: item.subject,
user: item.user,
weight: 1,
}));
// Dummy data
flattened_data.push({
active: true,
distance: 50,
landmark: "",
latitude: 8.498837,
longitude: 124.595422,
study_group: "",
subject: "Introduction to Computing",
user: "Dummy",
weight: 1,
});
// We get each unique subject
let unique_subjects = [
...new Set(flattened_data.map((item) => item.subject)),
];
let result: any[] = [];
// Then append all entries belonging to that subject to its own array
unique_subjects.forEach((subject, index: number) => {
index++;
let filteredData = flattened_data.filter(
(item) => item.subject === subject && item.study_group === ""
);
/*console.log(
"Subject #",
index,
"-",
filteredData[0].subject,
filteredData
);*/
// We get the circle radius based on the furthest point
let circle_radius = Math.max(
...filteredData.map((item) => item.distance)
);
console.log(
"Radius of circle:",
Math.max(...filteredData.map((item) => item.distance))
);
// We get the circle's center by averaging all the points
// Calculate the average latitude and longitude
const totalLat = filteredData.reduce(
(sum, point) => sum + point.latitude,
0
);
const totalLng = filteredData.reduce(
(sum, point) => sum + point.longitude,
0
);
const avgLat = totalLat / filteredData.length;
const avgLng = totalLng / filteredData.length;
console.log("Center Latitude:", avgLat);
console.log("Center Longitude:", avgLng);
// We now build the object
const subjectUserMap: any = {};
filteredData.forEach((item) => {
if (!subjectUserMap["users"]) {
subjectUserMap["users"] = [];
}
subjectUserMap["subject"] = item.subject;
subjectUserMap["latitude"] = avgLat;
subjectUserMap["longitude"] = avgLng;
subjectUserMap["radius"] = circle_radius;
subjectUserMap["users"].push(item.user);
});
console.log(subjectUserMap);
result = result.concat([subjectUserMap]);
});
console.log("Final Result:", result);
setStudentStatuses(result);
setStudyGroups(ParseStudentStatusList(data[1]));
}
},
onError: (error: Error) => {
@ -322,73 +239,76 @@ export default function Home() {
}}
loadingBackgroundColor={colors.secondary_2}
>
{student_statuses.map((student_status: any, index: number) => {
const randomColorWithOpacity = `rgba(${Math.floor(
Math.random() * 256
)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(
Math.random() * 256
)}, 0.7)`;
{study_groups.map(
(student_status: subjectUserMapType, index: number) => {
const randomColorWithOpacity = `rgba(${Math.floor(
Math.random() * 256
)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(
Math.random() * 256
)}, 0.7)`;
return (
<>
<Marker
coordinate={student_status}
pinColor={randomColorWithOpacity}
zIndex={1000}
onPress={() => {
toast.hideAll();
toast.show(
<View
style={{
alignContent: "center",
alignSelf: "center",
justifyContent: "center",
}}
>
<Text style={styles.text_white_tiny_bold}>
Subject: {student_status.subject}
</Text>
<Text style={styles.text_white_tiny_bold}>
Students Studying: {student_status.users.length}
</Text>
<Button
onPress={() => {
toast.show("Joined successfully", {
type: "success",
placement: "top",
duration: 2000,
animationType: "slide-in",
});
return (
<React.Fragment key={index}>
<Marker
coordinate={student_status}
pinColor={randomColorWithOpacity}
zIndex={1000}
onPress={() => {
toast.hideAll();
toast.show(
<View
style={{
alignContent: "center",
alignSelf: "center",
justifyContent: "center",
}}
>
<Text style={styles.text_white_tiny_bold}>
Create Group & Invite
Subject: {student_status.subject}
</Text>
</Button>
</View>,
{
type: "normal",
placement: "top",
duration: 2000,
animationType: "slide-in",
style: {
backgroundColor: colors.secondary_2,
borderWidth: 1,
borderColor: colors.primary_1,
},
}
);
}}
/>
<Circle
key={index}
center={student_status}
radius={student_status.radius}
fillColor={randomColorWithOpacity}
/>
</>
);
})}
<Text style={styles.text_white_tiny_bold}>
Students Studying: {student_status.users.length}
</Text>
<Button
onPress={() => {
toast.show("Joined successfully", {
type: "success",
placement: "top",
duration: 2000,
animationType: "slide-in",
});
}}
>
<Text style={styles.text_white_tiny_bold}>
Create Group & Invite
</Text>
</Button>
</View>,
{
type: "normal",
placement: "top",
duration: 2000,
animationType: "slide-in",
style: {
backgroundColor: colors.secondary_2,
borderWidth: 1,
borderColor: colors.primary_1,
},
}
);
}}
/>
<Circle
center={student_status}
radius={student_status.radius}
fillColor={randomColorWithOpacity}
strokeColor="white"
zIndex={1000}
/>
</React.Fragment>
);
}
)}
<Marker
coordinate={{
latitude: location.coords.latitude,