Refactor cache claim logic to use admin-defined claim distance; update related components for consistency

This commit is contained in:
bobbert committed 2026-04-07 18:00:30 +01:00
1 parent ecb61c4858
commit 2646c7b9bc
11 files changed
+98 -74

No files matched your search

@@ -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 })
/>
<Circle
center={cache.coordinates}
radius={cache.radius}
radius={claimDistance}
fillColor="rgba(59, 130, 246, 0.15)"
strokeColor="rgba(59, 130, 246, 0.85)"
/>
+3 -2
View File
@@ -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]);
+2 -2
View File
@@ -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 ? (
<Circle
center={visibleCache.coordinates}
radius={visibleCache.radius}
radius={claimDistance}
fillColor="rgba(250, 204, 21, 0.20)"
strokeColor="rgba(250, 204, 21, 0.90)"
/>
+4 -3
View File
@@ -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"
/>
<Circle
<Circle
center={cache.coordinates}
radius={cache.radius}
radius={claimDistance}
fillColor="rgba(59,130,246,0.15)"
strokeColor="rgba(59,130,246,0.85)"
/>
@@ -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 = () => {
</>
)}
<Text style={styles.label}>Cache Claim Distance (metres)</Text>
<TextInput
style={styles.input}
value={cacheTriggerMeters}
onChangeText={setCacheTriggerMeters}
keyboardType="numeric"
placeholder="20"
placeholderTextColor="#9ca3af"
/>
<View style={styles.codeSection}>
<Text style={styles.codeLabel}>Admin Join Code</Text>
<Text style={styles.codeValue}>{adminJoinCode || '—'}</Text>
+10 -3
View File
@@ -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 = () => {
<AdminCacheEditorView
userLocation={userLocation}
caches={cacheRecords}
claimDistance={claimDistance}
onAddCache={handleAddCache}
onMoveCache={handleMoveCache}
/>
+10 -17
View File
@@ -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}) => {
<Marker coordinate={cache.coordinates} pinColor="#9ca3af" title={cache.clue}/>
<Circle
center={cache.coordinates}
radius={cache.radius}
radius={claimDistance}
fillColor="rgba(156,163,175,0.15)"
strokeColor="rgba(156,163,175,0.6)"
/>
@@ -282,7 +283,7 @@ const MapScreen = ({navigation}) => {
/>
<Circle
center={newCoord}
radius={parseInt(newRadius) || 20}
radius={claimDistance}
fillColor="rgba(37,99,235,0.15)"
strokeColor="rgba(37,99,235,0.85)"
/>
@@ -305,8 +306,7 @@ const MapScreen = ({navigation}) => {
value={newClue}
onChangeText={setNewClue}
/>
<View style={styles.coordRow}>
<View style={styles.coordField}>
<View style={styles.coordRow}> <View style={styles.coordField}>
<Text style={styles.coordLabel}>Latitude</Text>
<TextInput
style={styles.formInput}
@@ -327,14 +327,6 @@ const MapScreen = ({navigation}) => {
/>
</View>
</View>
<TextInput
style={styles.formInput}
placeholder="Claim Radius (metres)"
placeholderTextColor="#9ca3af"
value={newRadius}
onChangeText={setNewRadius}
keyboardType="numeric"
/>
<ButtonTray>
<Button
label={editingCacheId ? 'Update Cache' : 'Save Cache'}
@@ -371,7 +363,7 @@ const MapScreen = ({navigation}) => {
<Marker coordinate={cache.coordinates} title={cache.name || cache.clue}/>
<Circle
center={cache.coordinates}
radius={cache.radius}
radius={claimDistance}
fillColor="rgba(59,130,246,0.15)"
strokeColor="rgba(59,130,246,0.85)"
/>
@@ -450,6 +442,7 @@ const MapScreen = ({navigation}) => {
userLocation={userLocation}
visibleCache={visibleCache}
heading={heading}
claimDistance={claimDistance}
/>
<Pressable style={styles.expandButton} onPress={handleExpandMap}>
<Text style={styles.expandIcon}>⛶</Text>