diff --git a/src/stores/SafetyStore.ts b/src/stores/SafetyStore.ts index 633595e..4767e8c 100644 --- a/src/stores/SafetyStore.ts +++ b/src/stores/SafetyStore.ts @@ -2,6 +2,7 @@ import { RouteStoreCleared, RouteStoreLoaded } from "@/actions/Actions"; import RouteStore from "./RouteStore"; import Store from "./Store"; import { calcGaussianRandom } from './utils' +import { v4 as uuidv4 } from 'uuid' import { Path } from "@/api/graphhopper"; // index of safety or congestion @@ -14,11 +15,15 @@ export interface SegmentWithSafety { index: number } -export interface PathWithSafety extends Path { +export interface PathWithSafety { segments: SegmentWithSafety[], - overAllIndex: number + overAllIndex: number, + pathId: string } +type PathToIdMap = Map +export const pathToIdMap: PathToIdMap = new Map() + export default class SafetyStore extends Store { readonly routeStore: RouteStore @@ -59,8 +64,8 @@ export default class SafetyStore extends Store { * @returns the new state of SafetyStore */ private static generateSafetyForPaths(state: SafetyStoreState, action: RouteStoreLoaded): SafetyStoreState { - const newPaths = action.newPaths; - const middlePointAdded = action.middlePointsAdded; + const newPaths = action.newPaths + const middlePointAdded = action.middlePointsAdded // Use ⬆ and safestPathFound and secondSafestPathFound to find the #1, #2 safest paths: // #1 safest path: the first member in this.routeStore.state.routingResult.paths which has middlePoints added. // #2 safest path: the first member in this.routeStore.state.routingResult.paths which has no middlePoints added. @@ -68,36 +73,184 @@ export default class SafetyStore extends Store { // #1: mean 4.5, std 1 // #2: mean 3.5, std 1 // #3 and beyond: mean 2.5, std 1 - // Also, have a look at the IndexStoreState interface in src/stores/index.d.ts - - newPaths.forEach(path => { - let coordinatesArray = path.points.coordinates - coordinatesArray.forEach(coordinates => { - if (!this.checkSegmentInStore(coordinates, this.indexStoreState)) { - // replace this.indexStoreState with state - let safetyIndex = calcGaussianRandom(0.1, 0.01) + // Also, have a look at the SafetyStoreState interface + + if(middlePointAdded){ + if(newPaths.length>0){ + this.addSafestPathToState(newPaths, state) + } + } + else{ + if(newPaths.length>0){ + this.addSecondSafestPathToState(newPaths, state) + } + } + if(newPaths.length>1){ + this.addMorePathToState(newPaths, state) + } + + return state + } + + private static checkSegmentInStore(coordinatesInput: number[], state: SafetyStoreState): boolean { + // change indexStoreState to safetyStoreState + if(state.paths.length > 0) { + for(let pathWithSafety of state.paths) { + if (this.checkSegmentsInPath(coordinatesInput, pathWithSafety)) { + return true; + } + } + } + return false + } + + private static checkSegmentsInPath(coordinatesInput: number[], path: PathWithSafety): boolean { + if(path.segments.length > 0){ + for(const segmentEach of path.segments) { + let coordinates = segmentEach.coordinates + if (coordinates[0][0] == coordinatesInput[0] && coordinates[0][1] == coordinatesInput[1]) { + return true + } + } + } + return false + } + + private static checkPathInStore(path: Path, state: SafetyStoreState): boolean { + if(state.paths.length > 0 && pathToIdMap != null){ + for(let pathWithSafety of state.paths){ + if(pathToIdMap.has(path)){ + if(pathToIdMap.get(path) === pathWithSafety.pathId){ + return true + } + } + } + } + return false + } + + private static createIdForPath(path:Path): string{ + let id = uuidv4() + pathToIdMap.set(path,id) + return id + } + + private static addCoordinateForPath(pathId: string | undefined, state: SafetyStoreState, segment: SegmentWithSafety){ + if(state.paths.length > 0){ + state.paths.forEach(pathWithSafety=>{ + if(pathWithSafety.pathId === pathId){ + pathWithSafety.segments.push(segment) + } + }) + } + } + + private static addOverAllIndexForPath(pathId: string | undefined, overAllIndex: number, state: SafetyStoreState, ){ + if(state.paths.length > 0){ + state.paths.forEach(pathWithSafety=>{ + if(pathWithSafety.pathId === pathId){ + pathWithSafety.overAllIndex = overAllIndex + } + }) + } + } + + private static addSafestPathToState(newPaths: Path[], state: SafetyStoreState){ + // the first member is the #1 safest path + let safestPath = newPaths[0] + this.safestPathFound = true + // if the path is not in the store + if(!this.checkPathInStore(safestPath, state)){ + // create the PathWithSafety for the path + let pathWithSafety: PathWithSafety = { + segments: [], // will be update in the later code + overAllIndex: 0, // will be update in the later code + pathId: this.createIdForPath(safestPath) + } + state.paths.push(pathWithSafety) + let indexSum = 0 + let coordinatePairs = safestPath.points.coordinates + coordinatePairs.forEach(coordinate=>{ + // if the segment is not in the store + let safetyIndex = calcGaussianRandom(4.5, 1); + if(!this.checkSegmentInStore(coordinate, state)){ let newSegment: SegmentWithSafety = { - coordinates: [coordinates], + coordinates: [coordinate], index: safetyIndex } - this.indexStoreState.Segments.push(newSegment) + this.addCoordinateForPath(pathToIdMap.get(safestPath),state,newSegment) } + indexSum = indexSum+safetyIndex // should add out of the loop since there is shared segments between paths }) - }) - return this.indexStoreState + let overAllIndex = indexSum/safestPath.points.coordinates.length + this.addOverAllIndexForPath(pathToIdMap.get(safestPath),overAllIndex,state) + } } - private static checkSegmentInStore(coordinatesInput: number[], indexStoreState: IndexStoreState): boolean { - // change indexStoreState to safetyStoreState - // TODO (Jingwen): edit this method to use the updated data structure of IndexStoreState - if (indexStoreState.Segments != null) { - for (let SegmentWithSafety of indexStoreState.Segments) { - let coordinates = SegmentWithSafety.coordinates - if (coordinates[0][0] == coordinatesInput[0] && coordinates[0][1] == coordinatesInput[1]) { - return true + private static addSecondSafestPathToState(newPaths: Path[], state: SafetyStoreState){ + // the first member is the #2 safest path + if(newPaths.length>0){ + let secondSafestPath = newPaths[0] + this.secondSafestPathFound = true + // if the path is not in the store + if(!this.checkPathInStore(secondSafestPath, state)){ + // create the PathWithSafety for the path + let pathWithSafety: PathWithSafety = { + segments: [], // will be update in the later code + overAllIndex: 0, // will be update in the later code + pathId: this.createIdForPath(secondSafestPath) } + state.paths.push(pathWithSafety) + let coordinatePairs = secondSafestPath.points.coordinates + let indexSum = 0 + let safetyIndex = calcGaussianRandom(3.5, 1); + coordinatePairs.forEach(coordinate=>{ + if(!this.checkSegmentInStore(coordinate, state)){ + let newSegment: SegmentWithSafety = { + coordinates: [coordinate], + index: safetyIndex + } + this.addCoordinateForPath(pathToIdMap.get(secondSafestPath),state,newSegment) + } + indexSum = indexSum+safetyIndex + }) + let overAllIndex = indexSum/secondSafestPath.points.coordinates.length + this.addOverAllIndexForPath(pathToIdMap.get(secondSafestPath),overAllIndex,state) + } + } + } + + private static addMorePathToState(newPaths: Path[], state: SafetyStoreState){ + for (let i = 1; i < newPaths.length; i++) { + // the path not #1 and #2 safe + let path = newPaths[i] + // if the path is not in the store + if(!this.checkPathInStore(path, state)){ + // create the PathWithSafety for the path + let pathWithSafety: PathWithSafety = { + segments: [], // will be updated in the later code + overAllIndex: 0, // will be updated in the later code + pathId: this.createIdForPath(path) + } + state.paths.push(pathWithSafety) + let coordinatePairs = path.points.coordinates + let indexSum = 0 + let safetyIndex = calcGaussianRandom(2.5, 1); + coordinatePairs.forEach(coordinate=>{ + if(!this.checkSegmentInStore(coordinate, state)){ + let newSegment: SegmentWithSafety = { + coordinates: [coordinate], + index: safetyIndex + } + this.addCoordinateForPath(pathToIdMap.get(path),state,newSegment) + } + indexSum = indexSum+safetyIndex + }) + let overAllIndex = indexSum/path.points.coordinates.length + this.addOverAllIndexForPath(pathToIdMap.get(path),overAllIndex,state) } } - return false } + + }