Untitled
unknown
javascript
a year ago
7.0 kB
9
Indexable
document.addEventListener('alpine:init', () => {
Alpine.data('transdevApp', () => ({
scheduleTickNr: 0,
adsTickNr: 0,
lastSuccessfulAPIFetch: '',
heapSize: '',
loadsInProgress: 0,
hasErrors: false,
firstDataGet: false,
adsLayerVisible: false,
currentAd: -1,
scheduleData: [] as ScheduleEntity[],
appSettings: { ...appDefaults, ...window.appSettings },
ads: window.initialAds,
newAds: [] as Advertisement[] | false,
get availableAds(): Advertisement[] {
return this.ads.filter((ad) => this.isCurrentTimeBetween(ad.visible_time_from, ad.visible_time_to));
},
/**
* Returns true if current time is between startTime and endTime
* If startTime > endTime, it is assumed that the time range is over midnight
* @param startTime
* @param endTime
*/
isCurrentTimeBetween: (startTime: string | null | undefined, endTime: string | null | undefined): boolean => {
if (!startTime || !endTime || startTime === '' || endTime === '') return true;
const currentTime = new Date();
const currentMs = currentTime.getHours() * 60 * 60 * 1000 +
currentTime.getMinutes() * 60 * 1000 +
currentTime.getSeconds() * 1000 +
currentTime.getMilliseconds();
const [startHours, startMinutes] = startTime.split(':').map(Number);
const [endHours, endMinutes] = endTime.split(':').map(Number);
const startMs = startHours * 60 * 60 * 1000 + startMinutes * 60 * 1000;
const endMs = endHours * 60 * 60 * 1000 + endMinutes * 60 * 1000;
if (startMs < endMs) {
return currentMs >= startMs && currentMs <= endMs;
} else {
return currentMs >= startMs || currentMs <= endMs;
}
},
loadAdsList: ()=>{},
init() {
const hardcodedDepartures: Departure[] = [
{
id: 1,
station_id: 1,
type: 'platform',
state: 'OK',
platform: '1',
transport_full_name: 'bus',
transport_name: '707',
transport_number: '1',
transport_description: null,
transport_class: null,
transport_operator: null,
origin_name: null,
destination_name: 'Zuhause',
hints: null,
departure_planned: '2024-08-02T03:55:25.000000Z',
departure_estimated: null,
departure_delay: 5,
created_at: '2024-08-02T03:55:25.000000Z',
updated_at: '2024-08-02T03:55:25.000000Z'
},
// Add more hardcoded departure objects as needed
];
const parseResponse = (response: Departure[]): ScheduleEntity[] => {
return response.map((entity) => {
const departureTime = new Date(entity.departure_planned);
const estimatedTime = entity.departure_estimated === null ? new Date(0) : new Date(entity.departure_estimated);
const connection: ScheduleEntity = {
platform: entity.platform,
departureTime,
estimatedTime,
departureString: getTimeGerman(departureTime),
estimatedString: getTimeGerman(estimatedTime),
destination: entity.destination_name,
transportTitle: entity.transport_name
? `${entity.transport_name} ${entity.transport_number}`
: (entity.transport_full_name || null),
transportClass: entity.transport_class,
transportIcon: getTranportIcon(entity.transport_class),
hint: entity.hints || '',
delay: (estimatedTime > departureTime) ? (estimatedTime.getTime() - departureTime.getTime()) / (60 * 1000) : 0
};
return connection;
}).sort((a, b) => a.departureTime.getTime() - b.departureTime.getTime());
};
const getTranportIcon = (transportClass: TransportClass): string | null => {
switch (transportClass) {
case 'BUS':
case 'CITY_BUS':
case 'EXPRESS_BUS':
case 'REGIONAL_BUS':
case 'CALL_BUS':
case 'CITIZEN_BUS':
return 'busLogo.svg';
case 'TRAM':
case 'UNDERGROUND':
return 'tramLogo.svg';
case 'REGIONAL_TRAIN':
case 'NATIONAL_TRAIN':
case 'INTERNATIONAL_TRAIN':
return 'trainLogo.svg';
case 'SUBURBAN_TRAIN':
return 'sLogo.svg';
default:
return null;
}
}
const getTimeGerman = (date: Date) => {
return date.toLocaleDateString('de-DE', { hour: 'numeric', minute: 'numeric' }).split(',')[1];
};
const doAppTick = async () => {
this.scheduleTickNr++;
const departuresData = hardcodedDepartures;
if (departuresData !== null) {
try {
this.lastSuccessfulAPIFetch = (new Date()).toLocaleDateString('de-DE', { year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' });
this.firstDataGet = true;
this.scheduleData = parseResponse(departuresData);
} catch (error) {
this.hasErrors = true;
throw new Error('Error in departures API response:' + error);
}
return;
}
};
const findNextAdIndex = (ads: Partial<Advertisement>[]) => {
const nextAd = ads.findIndex(ad => ad.id === this.currentAd);
if (nextAd === -1) {
return 0;
}
return nextAd === (ads.length - 1) ? 0 : nextAd + 1;
}
/**
* Tick load ads, but they updates only if they are in not visible time range
*/
const doAdsTick = () => {
this.adsTickNr++;
let defaultSpaceBetweenAds = this.appSettings.departuresInterval * 1000;
// const availableAds = ads.filter((ad) => isCurrentTimeBetween(ad.visible_time_from, ad.visible_time_to));
if (this.availableAds.length === 0) {
// do nothing
setTimeout(() => {
checkNewAds();
doAdsTick();
}, defaultSpaceBetweenAds);
return;
}
const nextAdIndex = findNextAdIndex(this.availableAds);
const currentAdVisibilityTime = () => {
return this.availableAds[nextAdIndex].ad_interval ? this.availableAds[nextAdIndex].ad_interval! * 1000 : this.appSettings.adInterval * 1000;
}
this.currentAd = this.availableAds[nextAdIndex].id!;
this.adsLayerVisible = true;
setTimeout(() => {
this.adsLayerVisible = false;
checkNewAds();
}, currentAdVisibilityTime());
setTimeout(() => {
doAdsTick();
}, currentAdVisibilityTime() + defaultSpaceBetweenAds);
}
const checkNewAds = () => {
if (this.newAds !== false && this.newAds.length > 0) {
this.ads = this.newAds;
this.newAds = [];
}
}
this.loadAdsList = async () => {
const adsData = window.initialAds; // Editor is loading...
Leave a Comment