v1
This commit is contained in:
+164
@@ -0,0 +1,164 @@
|
||||
const DAY_IN_MS = 8.64e+7;
|
||||
|
||||
class StopId {
|
||||
constructor(stopIdString){
|
||||
let [lineId, direction, stopId] = stopIdString.split(/\//)
|
||||
this.lineId = lineId
|
||||
this.stopId = stopId
|
||||
this.direction = direction
|
||||
}
|
||||
}
|
||||
|
||||
async function getNextTripJSON(stop_id){
|
||||
let res = await fetch(`/api/interface/tcl/next-trips/stops/${encodeURIComponent(stop_id.stopId)}/${encodeURIComponent(stop_id.lineId)}/${stop_id.direction}`);
|
||||
if(!res.ok){
|
||||
throw new Error(`Server responded with ${res.status} ${res.statusText}`)
|
||||
}
|
||||
|
||||
let result = await res.json();
|
||||
|
||||
if(!result.data){
|
||||
throw new Error(`Stop ${stop_id.stopId} not found`)
|
||||
}
|
||||
|
||||
return result.data[0]
|
||||
}
|
||||
|
||||
async function getStopsJSON(stop_id){
|
||||
let res = await fetch(`/api/interface/tcl/lines/${encodeURIComponent(stop_id.lineId)}/stops`);
|
||||
if(!res.ok){
|
||||
throw new Error(`Server responded with ${res.status} ${res.statusText}`)
|
||||
}
|
||||
|
||||
let result = await res.json();
|
||||
|
||||
if(!result.data){
|
||||
throw new Error(`Line ${stop_id.lineId} not found`)
|
||||
}
|
||||
|
||||
return result.data
|
||||
}
|
||||
|
||||
async function getTimetableJSON(stop_id, date){
|
||||
let res = await fetch(`/api/interface/tcl/timetables/${encodeURIComponent(stop_id.stopId)}/${encodeURIComponent(stop_id.lineId)}/${stop_id.direction}?date=${date.getFullYear()}-${(date.getMonth()+1).toString().padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`);
|
||||
if(!res.ok){
|
||||
throw new Error(`Server responded with ${res.status} ${res.statusText}`)
|
||||
}
|
||||
|
||||
let result = await res.json();
|
||||
|
||||
if(!result.data){
|
||||
throw new Error(`Timetable for ${stop_id.lineId} not found`)
|
||||
}
|
||||
|
||||
return result.data
|
||||
}
|
||||
|
||||
async function getLineDetailsJSON(stop_id){
|
||||
let res = await fetch(`/api/interface/tcl/lines/${encodeURIComponent(stop_id.lineId)}`);
|
||||
if(!res.ok){
|
||||
throw new Error(`Server responded with ${res.status} ${res.statusText}`)
|
||||
}
|
||||
|
||||
let result = await res.json();
|
||||
|
||||
if(!result.data){
|
||||
throw new Error(`Line ${stop_id.lineId} not found`)
|
||||
}
|
||||
|
||||
return result.data
|
||||
}
|
||||
|
||||
function getIconURL(stop_id){
|
||||
return new URL(`/api/valkyrie/assets/lines/${stop_id.lineId}.svg?type=image%2Fsvg%2Bxml`, window.location).toString()
|
||||
}
|
||||
|
||||
async function getLineDetails(stop_id){
|
||||
let line_json = await getLineDetailsJSON(stop_id)
|
||||
|
||||
let route = line_json.routes.find(it => it.direction == stop_id.direction)
|
||||
|
||||
let line = {
|
||||
id: stop_id.lineId,
|
||||
displayName: route?.name,
|
||||
picto: getIconURL(stop_id),
|
||||
name: line_json.code,
|
||||
direction: route?.name,
|
||||
timetable: null
|
||||
}
|
||||
|
||||
return line
|
||||
}
|
||||
|
||||
async function getTimetable(stop_id, date){
|
||||
let timetable_json = await getTimetableJSON(stop_id, date)
|
||||
|
||||
let timetable = []
|
||||
for(let scheduled_time of timetable_json.scheduleTimes){
|
||||
let time = new Date(scheduled_time.dateTime)
|
||||
timetable.push({
|
||||
displayHours: time.getHours().toString().padStart(2, "0"),
|
||||
displayMinutes: time.getMinutes().toString().padStart(2, "0"),
|
||||
displayTime: `${time.getHours().toString().padStart(2, "0")}h${time.getMinutes().toString().padStart(2, "0")}`,
|
||||
time
|
||||
})
|
||||
}
|
||||
|
||||
return timetable
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next Bus/Metro/Tram passage of given stop description
|
||||
* @param {String} stop_description Stop description string
|
||||
*
|
||||
* To get stop description go to https://carte-interactive.tcl.fr/public-transport/lines/
|
||||
* then find your line and your stop in this line.
|
||||
* Your URL must look like something like this
|
||||
* https://carte-interactive.tcl.fr/public-transport/lines/line:SYTNEX:C/forward/stop_point:SYTNEX:10787
|
||||
* Stop description is everything after "lines/" ("line:SYTNEX:C/forward/stop_point:SYTNEX:10787" in example above)
|
||||
*/
|
||||
export async function getNextPassage(stop_description, options = {
|
||||
timetable: +2 // Today and tomorrow
|
||||
}){
|
||||
let stopId = new StopId(stop_description);
|
||||
|
||||
let proms = [
|
||||
getLineDetails(stopId),
|
||||
getNextTripJSON(stopId),
|
||||
getStopsJSON(stopId),
|
||||
Promise.resolve([])
|
||||
]
|
||||
|
||||
let timeTableAmount = options?.timetable || +2;
|
||||
if(timeTableAmount){
|
||||
for(let dayOffset = 0; dayOffset<timeTableAmount; dayOffset++){
|
||||
let now = new Date(Date.now()+(dayOffset*DAY_IN_MS))
|
||||
proms.push(await getTimetable(stopId, now))
|
||||
}
|
||||
}
|
||||
|
||||
let [line, next_trip, line_stops, ...all_timetables] = await Promise.all(proms);
|
||||
|
||||
console.log(stopId)
|
||||
console.log("line", line)
|
||||
console.log("next trip", next_trip)
|
||||
console.log("stop", line_stops)
|
||||
console.log("timetable", all_timetables)
|
||||
|
||||
let line_timetables = []
|
||||
for(let timetable of all_timetables){
|
||||
line_timetables.push(...timetable)
|
||||
}
|
||||
line.timetable = line_timetables
|
||||
|
||||
let stop = line_stops.find(it => it.id == stopId.stopId)
|
||||
|
||||
let nextPassage = {
|
||||
line,
|
||||
displayName: stop?.name,
|
||||
displayTime: "<unsupported>",
|
||||
time: next_trip.schedules?.[0] ? new Date(next_trip.schedules?.[0].dateTime) : null
|
||||
}
|
||||
|
||||
return nextPassage
|
||||
}
|
||||
Reference in New Issue
Block a user