Refactor database interaction to use centralized API; update game type retrieval and cache management logic (minor changes lol)

This commit is contained in:
bobbert committed 2026-04-03 01:19:18 +01:00
1 parent 17ed120ce8
commit d67522a71d
8 files changed
+75 -612

No files matched your search

+2 -2
View File
@@ -16,11 +16,11 @@ expo start --android
- `src/components/layout`: shared screen wrapper. - `src/components/layout`: shared screen wrapper.
- `src/components/UI`: shared UI components. - `src/components/UI`: shared UI components.
- `src/components/screens`: app screens. - `src/components/screens`: app screens.
- `src/hooks`: app state, local DB link, and feature hooks. - `src/hooks`: app state, API link, and feature hooks.
- `DB`: local JSON data files. - `DB`: local JSON data files.
## Notes ## Notes
- The app uses local JSON data from `DB` through `src/hooks/DbController.js`. - The app accesses game/auth data through the centralized API endpoint via `src/hooks/dbLink.js`.
- Navigation is handled with React Navigation native stack. - Navigation is handled with React Navigation native stack.
+20 -2
View File
@@ -1,11 +1,28 @@
import React from 'react'; import React, {useEffect, useState} from 'react';
import {Pressable, StyleSheet, Text, View} from 'react-native'; import {Pressable, StyleSheet, Text, View} from 'react-native';
import useGameHook from '../../hooks/useGameHook'; import useGameHook from '../../hooks/useGameHook';
import Screen from '../layout/Screen'; import Screen from '../layout/Screen';
const GameTypeScreen = ({ navigation }) => { const GameTypeScreen = ({ navigation }) => {
const { getGameTypes } = useGameHook(); const { getGameTypes } = useGameHook();
const gameTypes = getGameTypes(); const [gameTypes, setGameTypes] = useState([]);
useEffect(() => {
let isMounted = true;
const load = async () => {
const types = await getGameTypes();
if (isMounted) {
setGameTypes(types || []);
}
};
load();
return () => {
isMounted = false;
};
}, [getGameTypes]);
return ( return (
<Screen style={styles.container}> <Screen style={styles.container}>
@@ -48,3 +65,4 @@ const styles = StyleSheet.create({
}); });
export default GameTypeScreen; export default GameTypeScreen;
+9 -8
View File
@@ -14,12 +14,13 @@ const ManageGameScreen = () => {
const [error, setError] = useState(''); const [error, setError] = useState('');
const [cacheRecords, setCacheRecords] = useState([]); const [cacheRecords, setCacheRecords] = useState([]);
const loadCaches = useCallback(() => { const loadCaches = useCallback(async () => {
if (!session.currentGid) { if (!session.currentGid) {
setCacheRecords([]); setCacheRecords([]);
return; return;
} }
setCacheRecords(getCaches(session.currentGid, null)); const rows = await getCaches(session.currentGid, null);
setCacheRecords(rows || []);
}, [getCaches, session.currentGid]); }, [getCaches, session.currentGid]);
useEffect(() => { useEffect(() => {
@@ -63,11 +64,11 @@ const ManageGameScreen = () => {
}; };
}, []); }, []);
const handleAddCache = (coordinate) => { const handleAddCache = async (coordinate) => {
if (!session.currentGid) { if (!session.currentGid) {
return; return;
} }
upsertCache({ await upsertCache({
gid: session.currentGid, gid: session.currentGid,
latitude: coordinate.latitude, latitude: coordinate.latitude,
longitude: coordinate.longitude, longitude: coordinate.longitude,
@@ -75,10 +76,10 @@ const ManageGameScreen = () => {
clue: `Cache ${cacheRecords.length + 1}`, clue: `Cache ${cacheRecords.length + 1}`,
subgroupId: 1, subgroupId: 1,
}); });
loadCaches(); await loadCaches();
}; };
const handleMoveCache = (cacheId, coordinate) => { const handleMoveCache = async (cacheId, coordinate) => {
if (!session.currentGid) { if (!session.currentGid) {
return; return;
} }
@@ -86,7 +87,7 @@ const ManageGameScreen = () => {
if (!current) { if (!current) {
return; return;
} }
upsertCache({ await upsertCache({
gid: session.currentGid, gid: session.currentGid,
cacheId, cacheId,
latitude: coordinate.latitude, latitude: coordinate.latitude,
@@ -95,7 +96,7 @@ const ManageGameScreen = () => {
clue: current.clue, clue: current.clue,
subgroupId: current.subgroupId, subgroupId: current.subgroupId,
}); });
loadCaches(); await loadCaches();
}; };
if (!session.currentGid) { if (!session.currentGid) {
+6 -6
View File
@@ -40,13 +40,13 @@ const MapScreen = () => {
const subgroupFilter = session.currentSGid; const subgroupFilter = session.currentSGid;
const { visibleCache, isClaiming, setIsClaiming } = usePlayerGame(userLocation, heading, activeCaches); const { visibleCache, isClaiming, setIsClaiming } = usePlayerGame(userLocation, heading, activeCaches);
const loadCaches = useCallback(() => { const loadCaches = useCallback(async () => {
if (!session.currentGid) { if (!session.currentGid) {
setCacheRecords([]); setCacheRecords([]);
return; return;
} }
const rows = getCaches(session.currentGid, subgroupFilter); const rows = await getCaches(session.currentGid, subgroupFilter);
setCacheRecords(rows); setCacheRecords(rows || []);
}, [getCaches, session.currentGid, subgroupFilter]); }, [getCaches, session.currentGid, subgroupFilter]);
useEffect(() => { useEffect(() => {
@@ -99,18 +99,18 @@ const MapScreen = () => {
}; };
}, []); }, []);
const handleClaim = (cacheId) => { const handleClaim = async (cacheId) => {
if (!session.currentGid) { if (!session.currentGid) {
return; return;
} }
claimCache({ await claimCache({
gid: session.currentGid, gid: session.currentGid,
cacheId, cacheId,
uid: session.currentUid, uid: session.currentUid,
tid: session.currentTid, tid: session.currentTid,
}); });
setIsClaiming(false); setIsClaiming(false);
loadCaches(); await loadCaches();
}; };
if (!session.currentGid) { if (!session.currentGid) {
-495
View File
@@ -1,495 +0,0 @@
import buildDbLink from './dbLink';
class DbController {
constructor(db = buildDbLink()) {
this.db = db;
}
hashPassword(value) {
let hash = 0;
for (let i = 0; i < value.length; i += 1) {
hash = (hash << 5) - hash + value.charCodeAt(i);
hash |= 0;
}
return `H_${Math.abs(hash)}`;
}
toMinuteIso(date = new Date()) {
return `${date.toISOString().slice(0, 16)}Z`;
}
generateJoinCode(length = 5) {
const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
let code = '';
for (let i = 0; i < length; i += 1) {
code += charset[Math.floor(Math.random() * charset.length)];
}
return code;
}
generateUniqueJoinCode(collection, key) {
let code = this.generateJoinCode(Math.random() > 0.5 ? 5 : 6);
while (collection.some((item) => item[key] === code)) {
code = this.generateJoinCode(Math.random() > 0.5 ? 5 : 6);
}
return code;
}
nextId(counterKey) {
const keyToCollection = {
user: { collection: 'users', field: 'Uid' },
group: { collection: 'groups', field: 'Gid' },
team: { collection: 'teams', field: 'Tid' },
};
const config = keyToCollection[counterKey];
if (!config) {
throw new Error(`Unsupported counter key: ${counterKey}`);
}
const rows = this.db[config.collection] || [];
const maxId = rows.reduce((max, row) => {
const value = Number(row[config.field] || 0);
return value > max ? value : max;
}, 0);
return maxId + 1;
}
getUserByEmail(email) {
return this.db.users.find((u) => u.email.toLowerCase() === email.toLowerCase()) || null;
}
getUserById(uid) {
return this.db.users.find((u) => u.Uid === Number(uid)) || null;
}
getGroupById(gid) {
return this.db.groups.find((group) => group.Gid === Number(gid)) || null;
}
register(payload) {
const { username, email, password, confirmPassword, accountType } = payload;
if (!username || !email || !password || !confirmPassword) {
throw new Error('Missing required registration fields');
}
if (password !== confirmPassword) {
throw new Error('Passwords do not match');
}
if (this.getUserByEmail(email)) {
throw new Error('Email already in use');
}
const uid = this.nextId('user');
const user = {
Uid: uid,
username,
email,
passwordHash: this.hashPassword(password),
isBusiness: accountType === 'Business/School',
IsAcceptedAdmin: false,
Gid: null,
SGid: null,
TGid: null,
};
this.db.users.push(user);
return user;
}
login(payload) {
const { email, password } = payload;
const user = this.getUserByEmail(email);
if (!user) {
throw new Error('Email not found');
}
const incomingHash = this.hashPassword(password);
if (incomingHash !== user.passwordHash) {
throw new Error('Invalid password');
}
return user;
}
getGameTypes() {
return this.db.game_types;
}
getSubgroupByJoinCode(joinCode) {
return this.db.subgroups.find(
(subgroup) => subgroup.JoinCode && subgroup.JoinCode === joinCode.toUpperCase(),
) || null;
}
ensureMembership(uid, gid, sgid, isAcceptedAdmin) {
const existing = this.db.subgroup_memberships.find(
(membership) => membership.Uid === uid && membership.Gid === gid,
);
if (existing) {
existing.SGid = sgid;
existing.IsAcceptedAdmin = isAcceptedAdmin;
return existing;
}
const membership = {
Uid: uid,
Gid: gid,
SGid: sgid,
IsAcceptedAdmin: isAcceptedAdmin,
};
this.db.subgroup_memberships.push(membership);
return membership;
}
ensureGroupGameData(gid) {
const existing = this.db.game_data.find((entry) => entry.Gid === gid);
if (existing) {
return existing;
}
const payload = { Gid: gid, GeoCaches: [] };
this.db.game_data.push(payload);
return payload;
}
hasActiveAdmin(gid) {
return this.db.subgroup_memberships.some(
(membership) => membership.Gid === gid && membership.SGid === 0 && membership.IsAcceptedAdmin,
);
}
canJoinTeamForSubgroup(group, sgid) {
return group.TeamsEnabled && sgid > 0;
}
createPrivateGame(payload) {
const { userId, groupName, businessOrSchoolName, gameType = 'private', isBusiness = false } = payload;
const user = this.getUserById(Number(userId));
if (!user) {
throw new Error('User not found');
}
const existing = this.db.groups.find(
(group) => group.CreatedByUid === Number(userId) && group.GameType === 'private',
);
if (existing) {
return existing;
}
const gid = this.nextId('group');
const isBusinessGroup = Boolean(isBusiness);
const group = {
Gid: gid,
GroupName: groupName,
BusinessOrSchoolName: businessOrSchoolName || groupName,
GameType: gameType,
AdminJoinCode: this.generateUniqueJoinCode(this.db.groups, 'AdminJoinCode'),
CreatedByUid: user.Uid,
MaxMemberSubgroups: isBusinessGroup ? 999 : 1,
TeamsEnabled: true,
IsBusinessGroup: isBusinessGroup,
ApprovedAdmins: isBusinessGroup ? [user.Uid] : [],
CreatedAt: this.toMinuteIso(),
};
this.db.groups.push(group);
this.ensureGroupGameData(gid);
this.db.subgroups.push({
SGid: 0,
SubGroupName: 'Admins',
Gid: group.Gid,
JoinCode: null,
IsAdminGroup: true,
IsGameStarted: false,
CacheTriggerMeters: 20,
});
if (!isBusinessGroup) {
const memberSGid = this.db.subgroups.filter((sg) => sg.Gid === gid).length;
this.db.subgroups.push({
SGid: memberSGid,
SubGroupName: 'Members',
Gid: gid,
JoinCode: this.generateUniqueJoinCode(this.db.subgroups, 'JoinCode'),
IsAdminGroup: false,
IsGameStarted: false,
CacheTriggerMeters: 20,
});
}
const ownerSgid = isBusinessGroup ? 0 : 1;
this.ensureMembership(user.Uid, gid, ownerSgid, isBusinessGroup);
user.Gid = gid;
user.SGid = ownerSgid;
user.IsAcceptedAdmin = isBusinessGroup;
return group;
}
joinPrivateGame(payload) {
const { userId, joinCode } = payload;
const user = this.getUserById(Number(userId));
const subgroup = this.getSubgroupByJoinCode(joinCode);
if (!user || !subgroup || subgroup.IsAdminGroup) {
throw new Error('Invalid subgroup join code');
}
const group = this.getGroupById(subgroup.Gid);
if (!group) {
throw new Error('Group not found');
}
this.ensureMembership(user.Uid, subgroup.Gid, subgroup.SGid, false);
user.Gid = group.Gid;
user.SGid = subgroup.SGid;
user.IsAcceptedAdmin = false;
return group;
}
joinAsAdmin(payload) {
const { userId, adminJoinCode } = payload;
const user = this.getUserById(Number(userId));
const group = this.db.groups.find((g) => g.AdminJoinCode === adminJoinCode);
if (!user || !group) {
throw new Error('Invalid admin join code or user not found');
}
if (this.hasActiveAdmin(group.Gid)) {
this.db.admin_waitlist.push({
Uid: user.Uid,
Gid: group.Gid,
RequestedAt: this.toMinuteIso(),
});
return { status: 'pending', message: 'Admin approval pending' };
}
group.ApprovedAdmins.push(user.Uid);
this.ensureMembership(user.Uid, group.Gid, 0, true);
user.Gid = group.Gid;
user.SGid = 0;
user.IsAcceptedAdmin = true;
return { status: 'approved', group };
}
getCreatedPrivateGameByUser(uid) {
return this.db.groups.find(
(group) => group.CreatedByUid === Number(uid) && group.GameType === 'private',
) || null;
}
createSubgroup(payload) {
const { gid, subgroupName, cacheTriggerMeters = 20 } = payload;
const group = this.getGroupById(gid);
if (!group) {
throw new Error('Group not found');
}
const existingCount = this.db.subgroups.filter((sg) => sg.Gid === gid).length;
if (existingCount >= group.MaxMemberSubgroups + 1) {
throw new Error('Max subgroups reached');
}
const sgid = existingCount;
const newSubgroup = {
SGid: sgid,
SubGroupName: subgroupName,
Gid: gid,
JoinCode: this.generateUniqueJoinCode(this.db.subgroups, 'JoinCode'),
IsAdminGroup: false,
IsGameStarted: false,
CacheTriggerMeters: cacheTriggerMeters,
};
this.db.subgroups.push(newSubgroup);
return newSubgroup;
}
getSubgroups(gid) {
return this.db.subgroups.filter((sg) => sg.Gid === gid);
}
getVisibleSubgroups(gid) {
return this.db.subgroups.filter((sg) => sg.Gid === gid && sg.SGid > 0);
}
updateSubgroupCacheSettings(payload) {
const { gid, sgid, cacheTriggerMeters } = payload;
const subgroup = this.db.subgroups.find((sg) => sg.Gid === gid && sg.SGid === sgid);
if (!subgroup) {
throw new Error('Subgroup not found');
}
subgroup.CacheTriggerMeters = cacheTriggerMeters;
return subgroup;
}
createTeam(payload) {
const { gid, sgid, teamName, leaderId } = payload;
const tid = this.nextId('team');
const team = {
Tid: tid,
Gid: gid,
SGid: sgid,
TeamName: teamName,
LeaderId: leaderId,
JoinCode: this.generateUniqueJoinCode(this.db.teams, 'JoinCode'),
CreatedAt: this.toMinuteIso(),
};
this.db.teams.push(team);
this.db.team_members.push({ Uid: leaderId, Tid: tid });
return team;
}
joinTeamByCode(payload) {
const { userId, joinCode } = payload;
const team = this.db.teams.find((t) => t.JoinCode === joinCode.toUpperCase());
if (!team) {
throw new Error('Team join code not found');
}
const existing = this.db.team_members.find((tm) => tm.Uid === userId && tm.Tid === team.Tid);
if (existing) {
throw new Error('User already in team');
}
this.db.team_members.push({ Uid: userId, Tid: team.Tid });
return team;
}
getLobby(gid) {
const group = this.getGroupById(gid);
const subgroups = this.getSubgroups(gid);
const teams = this.db.teams.filter((t) => t.Gid === gid);
const teamMembers = this.db.team_members;
return { group, subgroups, teams, teamMembers };
}
getTeam(tid) {
return this.db.teams.find((t) => t.Tid === tid);
}
getMapPoints(gid, sgid = null) {
const gameData = this.db.game_data.find((entry) => entry.Gid === Number(gid));
if (!gameData) {
return [];
}
if (sgid === null || sgid === undefined) {
return gameData.GeoCaches;
}
return gameData.GeoCaches.filter((cache) => cache.SGid === Number(sgid));
}
normalizeCache(cache, gid) {
return {
id: cache.CacheId ?? cache.id,
coordinates: {
latitude: Number(cache.Latitude ?? cache.coordinates?.latitude ?? 0),
longitude: Number(cache.Longitude ?? cache.coordinates?.longitude ?? 0),
},
radius: Number(cache.TriggerMeters ?? cache.radius ?? 20),
clue: cache.Title ?? cache.clue ?? 'Cache',
groupId: Number(gid),
subgroupId: Number(cache.SGid ?? cache.subgroupId ?? 1),
claimedBy: cache.ClaimedBy ?? null,
claimedAt: cache.ClaimedAt ?? null,
};
}
getCaches(gid, sgid = null) {
const gameData = this.db.game_data.find((entry) => entry.Gid === Number(gid));
if (!gameData) {
return [];
}
const caches = gameData.GeoCaches || [];
const filtered = sgid === null || sgid === undefined
? caches
: caches.filter((cache) => Number(cache.SGid) === Number(sgid));
return filtered.map((cache) => this.normalizeCache(cache, gid));
}
upsertCache(payload) {
const {
gid,
cacheId,
latitude,
longitude,
radius = 20,
clue = 'Cache',
subgroupId = 1,
} = payload;
const groupId = Number(gid);
const gameData = this.ensureGroupGameData(groupId);
const id = cacheId || `C${Date.now()}`;
const existingIndex = (gameData.GeoCaches || []).findIndex(
(cache) => (cache.CacheId ?? cache.id) === id,
);
const nextCache = {
CacheId: id,
Title: clue,
Latitude: Number(latitude),
Longitude: Number(longitude),
TriggerMeters: Number(radius),
SGid: Number(subgroupId),
ClaimedBy: existingIndex >= 0 ? gameData.GeoCaches[existingIndex].ClaimedBy ?? null : null,
ClaimedAt: existingIndex >= 0 ? gameData.GeoCaches[existingIndex].ClaimedAt ?? null : null,
};
if (!gameData.GeoCaches) {
gameData.GeoCaches = [];
}
if (existingIndex >= 0) {
gameData.GeoCaches[existingIndex] = nextCache;
} else {
gameData.GeoCaches.push(nextCache);
}
return this.normalizeCache(nextCache, groupId);
}
claimCache(payload) {
const { gid, cacheId, uid = null, tid = null } = payload;
const gameData = this.db.game_data.find((entry) => entry.Gid === Number(gid));
if (!gameData || !gameData.GeoCaches) {
throw new Error('Game data not found');
}
const target = gameData.GeoCaches.find((cache) => (cache.CacheId ?? cache.id) === cacheId);
if (!target) {
throw new Error('Cache not found');
}
target.ClaimedBy = tid || uid;
target.ClaimedAt = this.toMinuteIso();
return this.normalizeCache(target, gid);
}
updateGroupSettings(payload) {
const { gid, ...settings } = payload;
const group = this.getGroupById(gid);
if (!group) {
throw new Error('Group not found');
}
Object.assign(group, settings);
return group;
}
getState() {
return this.db;
}
}
const dbController = new DbController();
export { DbController };
export default dbController;
+19 -21
View File
@@ -1,24 +1,22 @@
import usersSeed from '../../DB/users.json'; import Constants from 'expo-constants';
import groupsSeed from '../../DB/groups.json';
import subgroupsSeed from '../../DB/subgroups.json';
import subgroupMembershipsSeed from '../../DB/subgroup-memberships.json';
import adminWaitlistSeed from '../../DB/admin-waitlist.json';
import teamsSeed from '../../DB/teams.json';
import teamMembersSeed from '../../DB/team-members.json';
import gameDataSeed from '../../DB/game-data.json';
import gameTypesSeed from '../../DB/game-types.json';
const buildDbLink = () => ({ const hostFromExpo = Constants.expoConfig?.hostUri?.split(':')[0] || null;
users: usersSeed, const apiBaseUrl = 'http://localhost:3000'; // Shirish, i need to deploy the database first so... wait until that... sorry buddy...
groups: groupsSeed, // if you want you can run your own db locally i can send you the files for it just ask :(((
subgroups: subgroupsSeed,
subgroup_memberships: subgroupMembershipsSeed,
admin_waitlist: adminWaitlistSeed,
teams: teamsSeed,
team_members: teamMembersSeed,
game_data: gameDataSeed,
game_types: gameTypesSeed,
});
export default buildDbLink; const postJson = async (path, payload) => {
const response = await fetch(`${apiBaseUrl}${path}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
const result = await response.json();
if (!response.ok) {
throw new Error(result.message || 'Request failed');
}
return result;
};
export const postDb = async (action, payload = {}) => {
return postJson('/db', { action, payload });
};
+3 -40
View File
@@ -1,24 +1,7 @@
import {useState} from 'react'; import {useState} from 'react';
import Constants from 'expo-constants'; import {postDb} from './dbLink';
import dbController from './DbController';
import {clearSession, setSessionUser} from './SessionStore'; import {clearSession, setSessionUser} from './SessionStore';
const hostFromExpo = Constants.expoConfig?.hostUri?.split(':')[0] || null;
const apiBaseUrl = process.env.EXPO_PUBLIC_API_BASE_URL || (hostFromExpo ? `http://${hostFromExpo}:3000` : 'http://localhost:3000');
const postJson = async (path, payload) => {
const response = await fetch(`${apiBaseUrl}${path}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
const result = await response.json();
if (!response.ok) {
throw new Error(result.message || 'Request failed');
}
return result;
};
const useAuthHook = () => { const useAuthHook = () => {
const [email, setEmail] = useState(''); const [email, setEmail] = useState('');
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
@@ -32,29 +15,22 @@ const useAuthHook = () => {
setError(''); setError('');
setIsLoading(true); setIsLoading(true);
try { try {
const user = await postJson('/auth/login', { email: email.trim(), password }); const user = await postDb('login', { email: email.trim(), password });
setSessionUser(user); setSessionUser(user);
setIsLoading(false); setIsLoading(false);
return user; return user;
} catch (e) { } catch (e) {
try {
const fallbackUser = dbController.login({ email: email.trim(), password });
setSessionUser(fallbackUser);
setIsLoading(false);
return fallbackUser;
} catch {
setError(e.message); setError(e.message);
setIsLoading(false); setIsLoading(false);
return null; return null;
} }
}
}; };
const register = async () => { const register = async () => {
setError(''); setError('');
setIsLoading(true); setIsLoading(true);
try { try {
const user = await postJson('/auth/register', { const user = await postDb('register', {
username: username.trim(), username: username.trim(),
email: email.trim().toLowerCase(), email: email.trim().toLowerCase(),
password, password,
@@ -65,23 +41,10 @@ const useAuthHook = () => {
setIsLoading(false); setIsLoading(false);
return user; return user;
} catch (e) { } catch (e) {
try {
const fallbackUser = dbController.register({
username: username.trim(),
email: email.trim().toLowerCase(),
password,
confirmPassword,
accountType,
});
setSessionUser(fallbackUser);
setIsLoading(false);
return fallbackUser;
} catch {
setError(e.message); setError(e.message);
setIsLoading(false); setIsLoading(false);
return null; return null;
} }
}
}; };
const logout = () => { const logout = () => {
+16 -38
View File
@@ -1,55 +1,33 @@
import dbController from './DbController'; import {postDb} from './dbLink';
const useGameHook = () => { const useGameHook = () => {
const getGameTypes = () => dbController.getGameTypes(); const request = async (action, payload = {}) => postDb(action, payload);
const getCreatedPrivateGame = (userId) => { const getGameTypes = async () => request('getGameTypes');
return dbController.getCreatedPrivateGameByUser(userId);
};
const createPrivateGame = (payload) => { const getCreatedPrivateGame = async (userId) => request('getCreatedPrivateGameByUser', { userId });
return dbController.createPrivateGame(payload);
};
const joinPrivateGame = (payload) => { const createPrivateGame = async (payload) => request('createPrivateGame', payload);
return dbController.joinPrivateGame(payload);
};
const joinAsAdmin = (payload) => { const joinPrivateGame = async (payload) => request('joinPrivateGame', payload);
return dbController.joinAsAdmin(payload);
};
const getLobby = (gid) => { const joinAsAdmin = async (payload) => request('joinAsAdmin', payload);
return dbController.getLobby(gid);
};
const getTeam = (tid) => { const getLobby = async (gid) => request('getLobby', { gid });
return dbController.getTeam(tid);
};
const createTeam = (payload) => { const getTeam = async (tid) => request('getTeam', { tid });
return dbController.createTeam(payload);
};
const joinTeamByCode = (payload) => { const createTeam = async (payload) => request('createTeam', payload);
return dbController.joinTeamByCode(payload);
};
const getMapPoints = (gid, sgid = null) => { const joinTeamByCode = async (payload) => request('joinTeamByCode', payload);
return dbController.getMapPoints(gid, sgid);
};
const getCaches = (gid, sgid = null) => { const getMapPoints = async (gid, sgid = null) => request('getMapPoints', { gid, sgid });
return dbController.getCaches(gid, sgid);
};
const upsertCache = (payload) => { const getCaches = async (gid, sgid = null) => request('getCaches', { gid, sgid });
return dbController.upsertCache(payload);
};
const claimCache = (payload) => { const upsertCache = async (payload) => request('upsertCache', payload);
return dbController.claimCache(payload);
}; const claimCache = async (payload) => request('claimCache', payload);
return { return {
getGameTypes, getGameTypes,