Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update generateSafetyForPaths and helper functions #3

Merged
merged 1 commit into from
Aug 19, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 178 additions & 25 deletions src/stores/SafetyStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<Path, string>
export const pathToIdMap: PathToIdMap = new Map()

export default class SafetyStore extends Store<SafetyStoreState> {
readonly routeStore: RouteStore

Expand Down Expand Up @@ -59,45 +64,193 @@ export default class SafetyStore extends Store<SafetyStoreState> {
* @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.
// Use different normal distribution to generate safety index for #1, #2, #3 safest paths
// #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
}


}