Skip to content

Commit

Permalink
Update generateSafetyForPaths and helper functions
Browse files Browse the repository at this point in the history
  • Loading branch information
jpan82 authored Aug 18, 2023
1 parent 8f12301 commit 86192a1
Showing 1 changed file with 178 additions and 25 deletions.
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 {

This comment has been minimized.

Copy link
@alicia-lyu

alicia-lyu Aug 24, 2023

Owner

@jpan82 You shouldn't change my types without me knowing it. You should instead change your code to conform to this type change. Such changes could break a lot of things if you work as a SDE.

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],

This comment has been minimized.

Copy link
@alicia-lyu

alicia-lyu Aug 24, 2023

Owner

@jpan82 Unfortunately, you are not adding the coordinates of the segment (min. 2 coordinates) but only a single coordinate point. That's why the coloring isn't showing up, because we are coloring something with no length.

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){

This comment has been minimized.

Copy link
@alicia-lyu

alicia-lyu Aug 24, 2023

Owner

@jpan82 Your addSafestPathToState, addSecondSafestPathToState, and addMorePathToState are almost identical. Another gold principle of software engineering is "Don't Repeat Yourself". You should come up with a way to merge this three methods into one. ChatGPT is a good resource for refactoring.

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
}


}

0 comments on commit 86192a1

Please sign in to comment.