rmaps-online/src/types/index.ts

248 lines
7.0 KiB
TypeScript

/**
* Core types for rMaps.online
* Collaborative real-time friend-finding navigation
*/
// ============================================================================
// Room Types
// ============================================================================
export interface Room {
id: string;
slug: string; // subdomain: <slug>.rmaps.online
name: string;
createdAt: Date;
createdBy: string; // participant ID
expiresAt: Date; // auto-cleanup after inactivity
settings: RoomSettings;
participants: Map<string, Participant>;
waypoints: Waypoint[];
}
export interface RoomSettings {
maxParticipants: number; // default: 10
password?: string; // optional room password
defaultPrecision: PrecisionLevel;
allowGuestJoin: boolean;
showC3NavIndoor: boolean; // enable c3nav integration
eventId?: string; // e.g., '39c3', 'eh2025'
}
// ============================================================================
// Participant Types
// ============================================================================
export interface Participant {
id: string;
name: string;
emoji: string; // avatar emoji
color: string; // unique marker color
joinedAt: Date;
lastSeen: Date;
status: ParticipantStatus;
location?: ParticipantLocation;
privacySettings: PrivacySettings;
}
export type ParticipantStatus =
| 'online' // actively sharing
| 'away' // app backgrounded
| 'ghost' // hidden location
| 'offline'; // disconnected
export interface ParticipantLocation {
latitude: number;
longitude: number;
accuracy: number; // meters
altitude?: number;
altitudeAccuracy?: number;
heading?: number; // degrees from north
speed?: number; // m/s
timestamp: Date;
source: LocationSource;
indoor?: IndoorLocation; // c3nav indoor data
}
export type LocationSource =
| 'gps' // device GPS
| 'network' // WiFi/cell triangulation
| 'manual' // user-set location
| 'c3nav'; // c3nav positioning
export interface IndoorLocation {
level: number; // floor/level number
x: number; // c3nav local X coordinate
y: number; // c3nav local Y coordinate
spaceName?: string; // e.g., "Saal 1", "Assembly XY"
}
// ============================================================================
// Privacy Types
// ============================================================================
export type PrecisionLevel =
| 'exact' // <5m - full precision
| 'building' // ~50m - same building
| 'area' // ~500m - nearby area
| 'approximate'; // ~2km - general vicinity
export interface PrivacySettings {
sharingEnabled: boolean;
defaultPrecision: PrecisionLevel;
showIndoorFloor: boolean;
ghostMode: boolean; // hide completely
}
// ============================================================================
// Navigation Types
// ============================================================================
export interface Waypoint {
id: string;
name: string;
emoji?: string;
location: {
latitude: number;
longitude: number;
indoor?: IndoorLocation;
};
createdBy: string; // participant ID
createdAt: Date;
type: WaypointType;
metadata?: Record<string, unknown>;
}
export type WaypointType =
| 'meetup' // meeting point
| 'event' // scheduled event
| 'poi' // point of interest
| 'custom'; // user-created
export interface Route {
id: string;
from: RoutePoint;
to: RoutePoint;
segments: RouteSegment[];
totalDistance: number; // meters
estimatedTime: number; // seconds
createdAt: Date;
}
export interface RoutePoint {
type: 'participant' | 'waypoint' | 'coordinates';
id?: string; // participant or waypoint ID
coordinates?: {
latitude: number;
longitude: number;
indoor?: IndoorLocation;
};
}
export interface RouteSegment {
type: 'outdoor' | 'indoor' | 'transition';
coordinates: Array<[number, number]>; // [lng, lat] for GeoJSON
distance: number;
duration: number;
instructions?: string;
level?: number; // for indoor segments
}
// ============================================================================
// c3nav Integration Types
// ============================================================================
export interface C3NavLocation {
id: number;
slug: string;
title: string;
subtitle?: string;
can_search: boolean;
can_describe: boolean;
geometry?: GeoJSON.Geometry;
level?: number;
}
export interface C3NavRouteRequest {
origin: C3NavPoint;
destination: C3NavPoint;
options?: C3NavRouteOptions;
}
export interface C3NavPoint {
coordinates?: [number, number, number]; // [x, y, level]
slug?: string; // location slug
}
export interface C3NavRouteOptions {
mode?: 'fastest' | 'shortest';
avoid_stairs?: boolean;
avoid_escalators?: boolean;
wheelchair?: boolean;
}
export interface C3NavRouteResponse {
status: 'ok' | 'no_route';
request?: C3NavRouteRequest;
origin?: C3NavLocation;
destination?: C3NavLocation;
distance?: number;
duration?: number;
path?: Array<{
coordinates: [number, number, number];
level: number;
}>;
}
// ============================================================================
// Event Types (for real-time updates)
// ============================================================================
export type RoomEvent =
| { type: 'participant_joined'; participant: Participant }
| { type: 'participant_left'; participantId: string }
| { type: 'participant_updated'; participant: Partial<Participant> & { id: string } }
| { type: 'location_updated'; participantId: string; location: ParticipantLocation }
| { type: 'waypoint_added'; waypoint: Waypoint }
| { type: 'waypoint_removed'; waypointId: string }
| { type: 'room_settings_changed'; settings: Partial<RoomSettings> };
// ============================================================================
// Map Types
// ============================================================================
export interface MapViewport {
center: [number, number]; // [lng, lat]
zoom: number;
bearing?: number;
pitch?: number;
}
export interface MapBounds {
north: number;
south: number;
east: number;
west: number;
}
// CCC venue bounds (Hamburg Congress Center)
export const CCC_VENUE_BOUNDS: MapBounds = {
north: 53.5580,
south: 53.5520,
east: 9.9950,
west: 9.9850,
};
// ============================================================================
// Utility Types
// ============================================================================
export interface ApiResponse<T> {
success: boolean;
data?: T;
error?: string;
}
export type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};