From 2646c7b9bcdc5cd9ffcd6d96022777193fd7f2fe Mon Sep 17 00:00:00 2001 From: mudabbir-ahmad Date: Tue, 7 Apr 2026 18:00:30 +0100 Subject: [PATCH] Refactor cache claim logic to use admin-defined claim distance; update related components for consistency --- app.json | 3 +- server/server.js | 1 + .../gameplay/AdminCacheEditorView.js | 4 +- src/components/gameplay/ClaimTimerView.js | 5 +- src/components/gameplay/PlayerMapView.js | 4 +- src/components/screens/ExpandedMapScreen.js | 7 +- src/components/screens/GameSettingsScreen.js | 13 ++++ src/components/screens/ManageGameScreen.js | 13 +++- src/components/screens/MapScreen.js | 27 +++---- src/hooks/usePlayerGame.js | 24 +++---- src/utils/geoMath.js | 71 +++++++++++-------- 11 files changed, 98 insertions(+), 74 deletions(-) diff --git a/app.json b/app.json index 4f79077..243484a 100644 --- a/app.json +++ b/app.json @@ -19,8 +19,7 @@ } }, "android": { - "usesCleartextTraffic": true, - "adaptiveIcon": { + "adaptiveIcon": { "foregroundImage": "./assets/images/android-icon-monochrome.png", "backgroundColor": "#ffffff" }, diff --git a/server/server.js b/server/server.js index 1653266..3d068a9 100644 --- a/server/server.js +++ b/server/server.js @@ -209,6 +209,7 @@ addRoute('POST', '/groups', async (req, res) => { CreatedByUid: payload.CreatedByUid, MaxMemberSubgroups: payload.MaxMemberSubgroups || 1, TeamsEnabled: payload.TeamsEnabled !== undefined ? payload.TeamsEnabled : true, + CacheTriggerMeters: payload.CacheTriggerMeters || 20, ApprovedAdmins: [payload.CreatedByUid], CreatedAt: new Date().toISOString(), }; diff --git a/src/components/gameplay/AdminCacheEditorView.js b/src/components/gameplay/AdminCacheEditorView.js index 944106d..b15c6f3 100644 --- a/src/components/gameplay/AdminCacheEditorView.js +++ b/src/components/gameplay/AdminCacheEditorView.js @@ -1,7 +1,7 @@ import React from 'react'; import MapView, {Circle, Marker} from 'react-native-maps'; -const AdminCacheEditorView = ({ userLocation, caches, onAddCache, onMoveCache }) => { +const AdminCacheEditorView = ({ userLocation, caches, claimDistance, onAddCache, onMoveCache }) => { // Initialisation ------------- // State ---------------------- // Handlers ------------------- @@ -34,7 +34,7 @@ const AdminCacheEditorView = ({ userLocation, caches, onAddCache, onMoveCache }) /> diff --git a/src/components/gameplay/ClaimTimerView.js b/src/components/gameplay/ClaimTimerView.js index 68076a8..c38315a 100644 --- a/src/components/gameplay/ClaimTimerView.js +++ b/src/components/gameplay/ClaimTimerView.js @@ -1,11 +1,12 @@ import React, {useEffect, useState} from 'react'; import {StyleSheet, Text, View} from 'react-native'; +import {CACHE_CLAIM_TIMER} from '../../utils/geoMath'; const ClaimTimerView = ({ cache, onClaimSuccess, isClaiming }) => { // Initialisation ------------- // State ---------------------- - const [timeLeft, setTimeLeft] = useState(5); + const [timeLeft, setTimeLeft] = useState(CACHE_CLAIM_TIMER); // Handlers ------------------- @@ -16,7 +17,7 @@ const ClaimTimerView = ({ cache, onClaimSuccess, isClaiming }) => { } else if (isClaiming && timeLeft === 0 && cache) { onClaimSuccess(cache.id); } else { - setTimeLeft(5); + setTimeLeft(CACHE_CLAIM_TIMER); } return () => clearTimeout(timer); }, [isClaiming, timeLeft, cache, onClaimSuccess]); diff --git a/src/components/gameplay/PlayerMapView.js b/src/components/gameplay/PlayerMapView.js index 7ac9e0c..ffdf860 100644 --- a/src/components/gameplay/PlayerMapView.js +++ b/src/components/gameplay/PlayerMapView.js @@ -2,7 +2,7 @@ import React from 'react'; import MapView, {Circle, Polygon} from 'react-native-maps'; import {getFovCone} from '../../utils/geoMath'; -const PlayerMapView = ({ userLocation, visibleCache, heading }) => { +const PlayerMapView = ({ userLocation, visibleCache, heading, claimDistance }) => { // Initialisation ------------- // State ---------------------- // Handlers ------------------- @@ -31,7 +31,7 @@ const PlayerMapView = ({ userLocation, visibleCache, heading }) => { {visibleCache ? ( diff --git a/src/components/screens/ExpandedMapScreen.js b/src/components/screens/ExpandedMapScreen.js index 4f3d41e..01b576d 100644 --- a/src/components/screens/ExpandedMapScreen.js +++ b/src/components/screens/ExpandedMapScreen.js @@ -11,8 +11,9 @@ const DEFAULT_REGION = {latitude: 51.5074, longitude: -0.1278, latitudeDelta: 0. const ExpandedMapScreen = ({route}) => { // Initialisation ------------ - const {isAdmin, cacheRecords: cacheStr} = route.params || {}; + const {isAdmin, cacheRecords: cacheStr, claimDistance: routeClaimDistance} = route.params || {}; const caches = cacheStr ? JSON.parse(cacheStr) : []; + const claimDistance = routeClaimDistance || 20; // State ---------------------- @@ -74,9 +75,9 @@ const ExpandedMapScreen = ({route}) => { title={cache.name || cache.clue} pinColor="#2563eb" /> - diff --git a/src/components/screens/GameSettingsScreen.js b/src/components/screens/GameSettingsScreen.js index d5f2902..41ec274 100644 --- a/src/components/screens/GameSettingsScreen.js +++ b/src/components/screens/GameSettingsScreen.js @@ -19,6 +19,7 @@ const GameSettingsScreen = () => { const [groupName, setGroupName] = useState(''); const [teamsEnabled, setTeamsEnabled] = useState(false); const [maxSubgroups, setMaxSubgroups] = useState('1'); + const [cacheTriggerMeters, setCacheTriggerMeters] = useState('20'); const [adminJoinCode, setAdminJoinCode] = useState(''); const [memberJoinCode, setMemberJoinCode] = useState(''); @@ -35,6 +36,7 @@ const GameSettingsScreen = () => { setGroupName(group.GroupName || ''); setTeamsEnabled(Boolean(group.TeamsEnabled)); setMaxSubgroups(String(group.MaxMemberSubgroups || 1)); + setCacheTriggerMeters(String(group.CacheTriggerMeters || 20)); setAdminJoinCode(group.AdminJoinCode || ''); } const sgs = await getSubgroups(session.currentGid); @@ -52,6 +54,7 @@ const GameSettingsScreen = () => { GroupName: groupName.trim(), TeamsEnabled: teamsEnabled, MaxMemberSubgroups: parseInt(maxSubgroups) || 1, + CacheTriggerMeters: parseInt(cacheTriggerMeters) || 20, }); setSaving(false); }; @@ -112,6 +115,16 @@ const GameSettingsScreen = () => { )} + Cache Claim Distance (metres) + + Admin Join Code {adminJoinCode || '—'} diff --git a/src/components/screens/ManageGameScreen.js b/src/components/screens/ManageGameScreen.js index 1a5530a..af9f962 100644 --- a/src/components/screens/ManageGameScreen.js +++ b/src/components/screens/ManageGameScreen.js @@ -10,7 +10,7 @@ const ManageGameScreen = () => { // Initialisation ------------ const session = getSession(); - const {getCaches, upsertCache} = useGameHook(); + const {getCaches, upsertCache, getLobby} = useGameHook(); // State ---------------------- @@ -18,6 +18,7 @@ const ManageGameScreen = () => { const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [cacheRecords, setCacheRecords] = useState([]); + const [claimDistance, setClaimDistance] = useState(20); // Handlers ------------------- @@ -32,6 +33,13 @@ const ManageGameScreen = () => { useEffect(() => { loadCaches(); }, [loadCaches]); + useEffect(() => { + if (!session.currentGid) return; + getLobby(session.currentGid).then((group) => { + if (group) setClaimDistance(group.CacheTriggerMeters || 20); + }); + }, [session.currentGid]); + useEffect(() => { let locationSub; const start = async () => { @@ -62,7 +70,6 @@ const ManageGameScreen = () => { gid: session.currentGid, latitude: coordinate.latitude, longitude: coordinate.longitude, - radius: 20, clue: `Cache ${cacheRecords.length + 1}`, subgroupId: 1, }); @@ -78,7 +85,6 @@ const ManageGameScreen = () => { cacheId, latitude: coordinate.latitude, longitude: coordinate.longitude, - radius: current.radius, clue: current.clue, subgroupId: current.subgroupId, }); @@ -125,6 +131,7 @@ const ManageGameScreen = () => { diff --git a/src/components/screens/MapScreen.js b/src/components/screens/MapScreen.js index 5fe5878..0fca762 100644 --- a/src/components/screens/MapScreen.js +++ b/src/components/screens/MapScreen.js @@ -40,13 +40,16 @@ const MapScreen = ({navigation}) => { const [newCoord, setNewCoord] = useState(null); const [newName, setNewName] = useState(''); const [newClue, setNewClue] = useState(''); - const [newRadius, setNewRadius] = useState('20'); + + // Global claim distance comes from the group's CacheTriggerMeters setting + const claimDistance = groupInfo?.CacheTriggerMeters || 20; const isPlayer = inGame && !isAdmin; const {visibleCache, isClaiming, setIsClaiming} = usePlayerGame( isPlayer ? userLocation : null, isPlayer ? heading : null, isPlayer ? cacheRecords : [], + claimDistance, ); const mapRegion = userLocation @@ -151,7 +154,6 @@ const MapScreen = ({navigation}) => { setNewCoord(fallback); setNewName(''); setNewClue(''); - setNewRadius('20'); setIsCreating(true); }; @@ -161,7 +163,6 @@ const MapScreen = ({navigation}) => { setNewCoord(cache.coordinates); setNewName(cache.name || ''); setNewClue(cache.clue || ''); - setNewRadius(String(cache.radius || 20)); setIsCreating(true); }; @@ -180,7 +181,6 @@ const MapScreen = ({navigation}) => { name: newName.trim(), latitude: newCoord.latitude, longitude: newCoord.longitude, - radius: parseInt(newRadius) || 20, clue: newClue.trim(), subgroupId: 1, }; @@ -202,6 +202,7 @@ const MapScreen = ({navigation}) => { isAdmin, cacheRecords: JSON.stringify(cacheRecords), heading: heading || 0, + claimDistance, }); }; @@ -264,7 +265,7 @@ const MapScreen = ({navigation}) => { @@ -282,7 +283,7 @@ const MapScreen = ({navigation}) => { /> @@ -305,8 +306,7 @@ const MapScreen = ({navigation}) => { value={newClue} onChangeText={setNewClue} /> - - + Latitude { /> -