import type { MuseumFloor, MuseumPoi } from '@/domain/museum' interface FloorLike { id?: string | number | null label?: string | null floorId?: string | number | null floorCode?: string | null floorName?: string | null name?: string | null modelGroup?: string | null } const indoorFloorCodePattern = /^L-?\d+(?:\.\d+)?$/i const indoorFloorLabelPattern = /^(?:B\d+(?:\.\d+)?|\d+(?:\.\d+)?F)$/i const rawNumericIdPattern = /^\d{6,}$/ const nonNavigableFloorPattern = /(EXTERIOR|OUTDOOR|BUILDING|FACADE|EXTERNAL|外立面|建筑外观|建筑外立面|室外模型|室外场景|室外底图|室外建筑|室外外观|室外)$/i const normalizeValue = (value: unknown) => ( value === null || typeof value === 'undefined' ? '' : String(value).trim() ) export const isNonNavigableFloorToken = (value: unknown) => { const normalized = normalizeValue(value) return Boolean(normalized && nonNavigableFloorPattern.test(normalized)) } export const isIndoorFloorToken = (value: unknown) => { const normalized = normalizeValue(value) if (!normalized || isNonNavigableFloorToken(normalized)) return false return indoorFloorCodePattern.test(normalized) || indoorFloorLabelPattern.test(normalized) || rawNumericIdPattern.test(normalized) } export const isIndoorNavigableFloor = (floor: FloorLike | null | undefined) => { if (!floor) return false const tokens = [ floor.id, floor.label, floor.floorId, floor.floorCode, floor.floorName, floor.name, floor.modelGroup ] if (tokens.some(isNonNavigableFloorToken)) return false return tokens.some(isIndoorFloorToken) } export const isPoiOnIndoorNavigableFloor = (poi: Pick) => ( isIndoorNavigableFloor({ floorId: poi.floorId, label: poi.floorLabel }) ) export const filterIndoorNavigableFloors = (floors: T[]) => ( floors.filter((floor) => isIndoorNavigableFloor(floor)) ) export const filterPoisOnIndoorNavigableFloors = >(pois: T[]) => ( pois.filter(isPoiOnIndoorNavigableFloor) )