export const throttle = (func: (...args: any[]) => any, wait: number) => { var lastTime = 0; var timeoutId: ReturnType | undefined; var lastArgs: any[]; return function (...args: any[]) { const now = Date.now(); lastArgs = args; if (timeoutId) clearTimeout(timeoutId); timeoutId = undefined; if (now - lastTime >= wait) { lastTime = now; func.apply(this, lastArgs); } else { timeoutId = setTimeout( () => { lastTime = Date.now(); func.apply(this, lastArgs); }, wait - (now - lastTime) ); } }; }; export const load = (id: string) => fetch("/api/" + id) .then((res) => { if (!res.ok) throw new Error("Error " + res.statusText); return res.json(); }) .then((res) => { for (let e of res.main) { if (e.date_range) { e.date_range[0] = new Date(e.date_range[0]); e.date_range[1] = new Date(e.date_range[1]); } e.day_title = e.day_title || []; } return res; }); var version_add = 1 export const save = async (id: string, v: journey) => { let body = JSON.parse(JSON.stringify(v)) body.version +=version_add; return fetch("/api/" + id, { method: "post", body: JSON.stringify(body) }) .then((res) => { if (!res.ok) throw new Error("Error " + res.statusText); return res.json(); }) .then((_res) => { version_add+=1; console.log("Saved..."); }); } export const query_nominatim = ( q: string, bb: any, f: (v: NominatimResult) => Boolean = () => true ) => { if (q.length == 0) return Promise.resolve([]) let url = new URL("/api/place/" + q, window.location.origin); url.searchParams.append("id", q); url.searchParams.append("bb", JSON.stringify(bb)); return fetch(url) .then((res) => (res.status == 200 ? res.json() : [])) .then((res) => res.filter(f)); }; export const query_flight = (q: string) => fetch("/api/flight/" + q).then((res) => res.json()); type NominatimResult = { type: string; category: string; display_name: string; // DEBUG ONLY }; export const is_restauration_type = (e: NominatimResult) => ["restaurant", "cafe", "pub", "bar", "fast_food", "food_court"].indexOf( e.type ) != -1; export const is_attraction_type = (e: NominatimResult): boolean => [ "tourism", "leisure", "place", "amenity", // "highway", "historic", "natural", "waterway", ].indexOf(e.category) != -1 || [ "place_of_worship", "national_park", "nature_reserve", "protected_area", ].indexOf(e.type) != -1 || is_travel_type(e); export const is_hotel_type = (e: NominatimResult): boolean => ["hotel", "hostel", "guest_house"].indexOf(e.type) != -1 export const is_travel_type = (e: NominatimResult): boolean => ["bus_stop", "tram_stop", "station", , "aerodrome", "parking"].indexOf(e.type) != -1 export const icon_type = (item: string | NominatimResult): string => { if (typeof (item) == "string") { return item } let t = item.type; let c = item.category; let types = { utensils: [ "restaurant", "cafe", "pub", "bar", "fast_food", "food_court", ], bed: ["hotel", "hostel", "guest_house"], landmark: [ "museum", "historic", "place_of_worship", "attraction", "information", "university", "science_park", "theatre", "opera" ], mountain: ["peak", "viewpoint"], parking: ["parking"], water: ["water", "river", "lake", "torrent", "aquarium"], building: ["community_center", "locality"], archway: ["bridge"], tree: [ "woodland", "shieling", "national_park", "park", "zoo", "garden", "nature_reserve", ], "dice-five": ["water_park", "theme_park", "casino"], "": ["?", "neighbourhood", "quarter", "highway", "place"], }; for (let k in types) { if (types[k].indexOf(t) >= 0 || types[k].indexOf(c) >= 0) return k; } console.log(item.display_name, item.category, item.type); return "question"; }; export const get_filter = function (f: string) { switch (f) { case "hotel": return is_hotel_type; case "restaurant": return is_restauration_type; case "place": return is_attraction_type; case "other": default: return () => true; } }