Skip to content

Commit

Permalink
Add setting for filtering out base stations and AtoN
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasGLund99 committed Nov 21, 2024
1 parent 8961911 commit d455165
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 13 deletions.
4 changes: 2 additions & 2 deletions src/__tests__/StreamManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ beforeEach(() => {
getSimpleVessles: jest
.fn()
.mockResolvedValue([
{ mmsi: 123456, location: { point: { lon: 1, lat: 2 }, timestamp: new Date(), heading: 45 } },
{ mmsi: 123456789, location: { point: { lon: 1, lat: 2 }, timestamp: new Date(), heading: 45 } },
]),
getMonitoredVessels: jest.fn().mockResolvedValue([{ mmsi: 123456, trustworthiness: 0.9, reason: 'Test' }]),
getMonitoredVessels: jest.fn().mockResolvedValue([{ mmsi: 123456789, trustworthiness: 0.9, reason: 'Test' }]),
} as unknown as jest.Mocked<IClientHandler>

setAllVessels = jest.fn()
Expand Down
42 changes: 41 additions & 1 deletion src/components/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,17 @@ import HamburgerSVG from '../svgs/hamburgerSVG'
import CloseSVG from '../svgs/closeSVG'

export default function Navbar() {
const { myClockSpeed, setMyClockSpeed, myDateTimeRef, hideVessels, setHideVessels } = useAppContext()
const {
myClockSpeed,
setMyClockSpeed,
myDateTimeRef,
hideVessels,
setHideVessels,
showBaseStations,
setShowBaseStations,
showAtoNs,
setShowAtoNs,
} = useAppContext()
const [opened, setOpened] = useState<boolean>(false)
const [localClock, setLocalClock] = useState<Date>(myDateTimeRef.current)
const [localSpeed, setLocalSpeed] = useState<string>(myClockSpeed.toString())
Expand Down Expand Up @@ -92,6 +102,36 @@ export default function Navbar() {
<div className="w-9 h-5 bg-gray-600 hover:bg-gray-500 peer-focus:outline-0 peer-focus:ring-transparent rounded-full peer transition-all ease-in-out duration-500 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-blue-700 hover:peer-checked:bg-blue-600"></div>
</label>
</div>

<hr className="my-3 border-2 border-gray-600 rounded-md" />

<h2 className="text-lg font-bold">Filtering</h2>
<div className="flex flex-row justify-between items-center gap-4">
<span className="font-medium whitespace-nowrap">Show base stations</span>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
value=""
onChange={(e) => setShowBaseStations(e.target.checked)}
className="sr-only peer"
checked={showBaseStations}
/>
<div className="w-9 h-5 bg-gray-600 hover:bg-gray-500 peer-focus:outline-0 peer-focus:ring-transparent rounded-full peer transition-all ease-in-out duration-500 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-blue-700 hover:peer-checked:bg-blue-600"></div>
</label>
</div>
<div className="flex flex-row justify-between items-center gap-4">
<span className="font-medium whitespace-nowrap">Show AtoN (navigational aids)</span>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
value=""
onChange={(e) => setShowAtoNs(e.target.checked)}
className="sr-only peer"
checked={showAtoNs}
/>
<div className="w-9 h-5 bg-gray-600 hover:bg-gray-500 peer-focus:outline-0 peer-focus:ring-transparent rounded-full peer transition-all ease-in-out duration-500 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-blue-700 hover:peer-checked:bg-blue-600"></div>
</label>
</div>
</div>
)}
<button id="menu-icon" title="Show/hide simulation settings" className="" onClick={() => setOpened(!opened)}>
Expand Down
19 changes: 18 additions & 1 deletion src/contexts/appcontext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ interface IAppContext {
setMyClockSpeed: React.Dispatch<React.SetStateAction<number>>
hideVessels: boolean
setHideVessels: React.Dispatch<React.SetStateAction<boolean>>
showBaseStations: boolean
setShowBaseStations: React.Dispatch<React.SetStateAction<boolean>>
showAtoNs: boolean
setShowAtoNs: React.Dispatch<React.SetStateAction<boolean>>
clientHandler: IClientHandler
}

Expand All @@ -25,6 +29,8 @@ export const useAppContext = () => {
export const AppContextProvider = ({ children }: { children: React.ReactNode }) => {
const [myClockSpeed, setMyClockSpeed] = useState<number>(100)
const [hideVessels, setHideVessels] = useState<boolean>(true)
const [showBaseStations, setShowBaseStations] = useState<boolean>(false)
const [showAtoNs, setShowAtoNs] = useState<boolean>(false)
const myDateTimeRef = useRef(new Date(1725874950 * 1000)) // Initialize ref with current time

const grpcWeb = new GrpcWebImpl('http://localhost:8080', {})
Expand All @@ -44,7 +50,18 @@ export const AppContextProvider = ({ children }: { children: React.ReactNode })

return (
<AppContext.Provider
value={{ myClockSpeed, setMyClockSpeed, hideVessels, setHideVessels, clientHandler, myDateTimeRef }}
value={{
myClockSpeed,
setMyClockSpeed,
hideVessels,
setHideVessels,
showBaseStations,
setShowBaseStations,
showAtoNs,
setShowAtoNs,
clientHandler,
myDateTimeRef,
}}
>
{children}
</AppContext.Provider>
Expand Down
1 change: 0 additions & 1 deletion src/implementations/StreamManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export default class StreamManager implements IStreamManager {
const simpleVessels = await this.clientHandler.getSimpleVessles({
timestamp: Math.round(this.myDateTimeRef.current!.getTime() / 1000),
})

this.setAllVessels(simpleVessels)
}

Expand Down
28 changes: 24 additions & 4 deletions src/pages/vesselMapPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ export default function VesselMapPage() {
const [monitoredVessels, setMonitoredVessels] = useState<IMonitoredVessel[]>([])
const [map, setMap] = useState<L.Map | null>(null)
const { selectedVesselmmsi, selectedVesselPath, selectionArea, setSelectionArea } = useVesselGuiContext()
const { clientHandler, myDateTimeRef } = useAppContext()
const { clientHandler, myDateTimeRef, showAtoNs, showBaseStations } = useAppContext()
const [timelineVal, setTimelineVal] = useState<number>(0)

// Use a ref to store the StreamManager instance
const streamManagerRef = useRef(new StreamManager(clientHandler, setAllVessels, setMonitoredVessels, myDateTimeRef))
const streamManagerRef = useRef(
new StreamManager(clientHandler, setAllVessels, setMonitoredVessels, myDateTimeRef) //, showAtoNs, showBaseStations)
)
const streamStarted = useRef(false)

useEffect(() => {
Expand Down Expand Up @@ -57,6 +59,21 @@ export default function VesselMapPage() {
setTimelineVal(index)
}

function filterVessels<T extends ISimpleVessel | IMonitoredVessel>(vessels: T[]): T[] {
// Reference: https://en.wikipedia.org/wiki/Maritime_Mobile_Service_Identity

// Filter out base stations
if (!showBaseStations) {
vessels = vessels.filter((v) => v.mmsi.toString().length === 9)
}

// Filter out AtoNs (aids to navigation)
if (!showAtoNs) {
vessels = vessels.filter((v) => !v.mmsi.toString().startsWith('9'))
}
return vessels
}

return (
<div className="relative h-screen">
<div className="absolute z-20 w-[350px] flex flex-col top-5 left-5 gap-3">
Expand All @@ -73,7 +90,7 @@ export default function VesselMapPage() {

<div id="monitoring-menu-container" className="absolute min-w-[25vw] max-h-[75vh] top-5 right-5 z-10">
{monitoredVessels.length !== 0 && (
<MonitoringMenu monitoredVessels={monitoredVessels} zoomToVessel={zoomToVessel} />
<MonitoringMenu monitoredVessels={filterVessels(monitoredVessels)} zoomToVessel={zoomToVessel} />
)}
</div>

Expand All @@ -84,7 +101,10 @@ export default function VesselMapPage() {
<>
<PathOverlay path={selectedVesselPath} idx={timelineVal} />
<SelectionAreaOverlay selectionArea={selectionArea} />
<VesselMarkerOverlay simpleVessels={allVessels} monitoredVessels={monitoredVessels} />
<VesselMarkerOverlay
simpleVessels={filterVessels(allVessels)}
monitoredVessels={filterVessels(monitoredVessels)}
/>
</>
}
/>
Expand Down
8 changes: 4 additions & 4 deletions src/svgs/faviconSVG.tsx

Large diffs are not rendered by default.

0 comments on commit d455165

Please sign in to comment.