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

Feat: query api for plan details #23

Merged
merged 8 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
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
12 changes: 12 additions & 0 deletions visual-debugger/src/data-processing/Query-Batch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@
"from":"Aachen HBF",
"to": "Aachen West",
"class": "Regional"
},
{
"index":2,
"from":"Aachen West",
"to": "Aachen HBF",
"class": "Regional"
},
{
"index":3,
"from":"Aachen Bushof",
"to": "Aachen Schanz",
"class": "Regional"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* Plan type used for parsing plan responses
*/
export interface Plan{
requestParameters:string;
debugOutput: number[];
from:Place;
to: Place;
direct: Itinerary[];
itineraries: Itinerary[];
previousPageCursor: string;
nextPageCursor: string;
}

/**
* Place type used for parsing plan responses
*/
export interface Place{
name:string;
stopId:string;
lat:number;
lon:number;
level: number;
arrival: string;
departure:string;
scheduledArrival: string;
scheduledDeparture: string;
scheduledTrack:string;
track:string;
vertexType:string;
}

/**
* Itinerary type used for parsing plan responses
*/
export interface Itinerary {
duration:number;
startTime:string;
endTime:string;
transfers:number;
legs:Leg[];
}

/**
* Leg type used for parsing plan responses
*/
export interface Leg {
mode:string;
from:Place;
to:Place;
duration:number;
startTime:string;
endTime:string;
scheduledStartTime:string;
scheduledEndTime:string;
realTime:boolean;
legGeometry:EncodedPolyline;
}

/**
* EncodedPolyline type used for parsing plan responses
*/
export interface EncodedPolyline {
points:string;
length:number;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* location type used for storing stop information
*/
export interface Location {
type: string;
tokens: number[][];
name: string;
id: string;
lat: number;
lon: number;
level: number;
zip: string;
areas: Area[];
score: number;
}

/**
* area type used for storing information about the area of a stop
*/
export interface Area {
name: string;
adminLevel: number;
matched: boolean;
default: boolean;
}

/**
* Query type used for storing information about a single query
*/
export interface Query {
index: number;
from:string;
fromStopID:string;
to: string;
toStopID: string;
class:string;
}

/**
* Type used for storing all queries in a Batch
*/
export interface Batch {
queries: Query[];
}
56 changes: 56 additions & 0 deletions visual-debugger/src/data-processing/planParsing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {interpolatedQueryStore, computedPlanStore, currentPlanStore} from "../sveltestore.ts";
import type {Query} from "./parsing-types/queryInterpolationTypes.ts";
import type {Plan} from "./parsing-types/planParsingTypes.ts"
import axios from "axios";

/**
* Base URL of the MOTIS API
*/
const motisApiUrlBase = 'http://localhost:8080/api/v1/'

/**
* data of the interpolated queries
*/
let queries: Query[]

/**
* Interaction function that is accessed by the frontend to get the plan for all queries
*/
export async function computePlan(){
//get read file content from storage
interpolatedQueryStore.subscribe(file_data => {
queries = file_data;
})

// if store is empty abort data processing
if(queries == undefined){return}

let plans: Plan[] = [];
let index =0;

// compute the plan for each query
for(const query of queries){
plans[index] = await computePlanForQuery(query)
index++;
}

// put computed plans into storage and set first plan as active
computedPlanStore.set(plans)
currentPlanStore.set(plans[0])
}

/**
* Calls the MOTIS API for a specific query and returns the plan for it
* @param query the query to get the plan for
*/
export async function computePlanForQuery(query:Query){
const response = await axios
.get(
//configuration for api call parameters
`${motisApiUrlBase}plan/?fromPlace=${query.fromStopID}&toPlace=${query.toStopID}`
)
let plan: Plan = response.data
return plan
}


Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import axios from "axios";
import {queryJsonStringStore, interpolatedQueryStore} from "../sveltestore";
import type { Location, Batch } from "./parsing-types/queryInterpolationTypes.ts"

/**
* Base URL of the MOTIS API
Expand All @@ -11,66 +12,20 @@ const motisApiUrlBase = 'http://localhost:8080/api/v1/'
*/
let queryFileContent: string

/**
* location type used for storing stop information
*/
export interface Location {
type: string;
tokens: number[][];
name: string;
id: string;
lat: number;
lon: number;
level: number;
zip: string;
areas: Area[];
score: number;
}

/**
* area type used for storing information about the area of a stop
*/
export interface Area {
name: string;
adminLevel: number;
matched: boolean;
default: boolean;
}

/**
* Query type used for storing information about a single query
*/
export interface Query {
index: number;
from:string;
fromStopID:string;
to: string;
toStopID: string;
class:string;
}

/**
* Type used for storing all queries in a Batch
*/
interface Batch {
queries: Query[];
}

/**
* Reads the query batch and generates the nearest stops for the read query trips
* @param query_batch path to the query batch JSON file
* @return the query batch dataset with stop id's
*/
export async function buildQueryDataset(query_batch:string) {

// parse query batch file into readable queries
let batch: Batch = JSON.parse(query_batch)
let queries = batch.queries

// call MOTIS API to search for the nearest stations to the start and end point of the query
for (const queryTrip of queries) {
queryTrip.fromStopID = await getLocationId(queryTrip.from)
queryTrip.toStopID = await getLocationId(queryTrip.to)
queryTrip.fromStopID = await computeLocationId(queryTrip.from)
queryTrip.toStopID = await computeLocationId(queryTrip.to)
}

// update store with the new queries
Expand All @@ -82,7 +37,7 @@ export async function buildQueryDataset(query_batch:string) {
* @param locationName location the most similar stop id is needed of
* @return the id of the most similar location to the input string
*/
async function getLocationId (locationName:string){
async function computeLocationId (locationName:string){
const response = await axios
.get(
//configuration for api call parameters
Expand All @@ -95,7 +50,7 @@ async function getLocationId (locationName:string){
/**
* Interaction method for printing queries to page
*/
export function getQueryAttributes(){
export function computeQueryAttributes(){

//get read file content from storage
queryJsonStringStore.subscribe(file_data => {
Expand Down
7 changes: 0 additions & 7 deletions visual-debugger/src/demo.spec.ts

This file was deleted.

47 changes: 27 additions & 20 deletions visual-debugger/src/lib/components/ui/FileUpload.svelte
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
<script lang="ts">
import {queryJsonStringStore} from "../../../sveltestore";
let file: File | null = null; // Use TypeScript's File type

const handleFileChange = (event: Event): void => {
const input = event.target as HTMLInputElement;
file = input.files ? input.files[0] : null;
console.log(file?.name); // Logs the file name
import {computeQueryAttributes} from "../../../data-processing/queryBuild.ts";
let file: File | null = null;

// put content of read file as string into storage
file?.text().then((file_content_string) => {
queryJsonStringStore.set(file_content_string);
}
)
// When file was first uploaded, parse and interpolate the queries
$: if(!($queryJsonStringStore=="DEFAULT")){computeQueryAttributes()}

};
</script>

<div>
<input type="file" on:change={handleFileChange} />
{#if file}
<p>Selected file: {file.name}</p>
{/if}
</div>
/**
* Gets the uploaded file and puts its content into the svelte store
* @param event event that the file was uploaded
*/
const putFileIntoStorage = (event: Event): void => {
const input = event.target as HTMLInputElement;
file = input.files ? input.files[0] : null;

// put content of read file as string into storage
file?.text().then((file_content_string) => {
queryJsonStringStore.set(file_content_string);
}
)

};
</script>

<div>
<input type="file" on:change={putFileIntoStorage} />
{#if file}
<p>Selected file: {file.name}</p>
{/if}
</div>
34 changes: 34 additions & 0 deletions visual-debugger/src/lib/components/ui/PlanOverview.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script lang="ts">
import {currentPlanStore} from "../../../sveltestore.ts";
import type {Itinerary, Plan} from "../../../data-processing/parsing-types/planParsingTypes.ts";
import PlanEntry from "$lib/components/ui/subcomponents/PlanEntry.svelte";

let itineraries: Itinerary[]

// let queries be up-to-date with the store
currentPlanStore.subscribe((data) => {
if (data == undefined) {
itineraries = []
}else{
itineraries = data.itineraries;
}
}
)
</script>

<h2>Plan of Query(Routing results)</h2>
<div class="rounded-border">
{#each itineraries as itinerary}
<PlanEntry startTime="{itinerary.startTime}" endTime="{itinerary.endTime}"
duration="{itinerary.duration.toString()}" transfers="{itinerary.transfers.toString()}"/>
{/each}
</div>


<style>
.rounded-border {
border: 1px solid black;
border-radius: 8px;
padding: 10px;
}
</style>
10 changes: 0 additions & 10 deletions visual-debugger/src/lib/components/ui/QueryBatchEntry.svelte

This file was deleted.

Loading
Loading