Skip to content

Commit

Permalink
Reuse the same region geometry when only changing category.
Browse files Browse the repository at this point in the history
  • Loading branch information
01100100 committed Jul 22, 2024
1 parent 8d11131 commit 0eb3a6c
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 24 deletions.
13 changes: 11 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
- [x] Update screenshots to WhereRoulette logo.
- [x] Add a favicon.
- [x] Add a button to spin the wheel.
- [] Add filter for different types of POIs.
- [x] Add filter for different types of POIs.
- [] Handle settlement types with no polygon types.
- [] Improve logo, no AI weirdness and put "Where Roulette" in the number places.
- [x] Add sound effect of roulette wheel spinning.
Expand Down Expand Up @@ -47,4 +47,13 @@
- display using opening_hours.js
- [] Add call to action to add more info to the POI when its incomplete.
- [ ] When there is an option, divide the area into different neighborhoods. Then, spin for the neighborhood and further spin for the POI. Add cool animations.
- [] filter out "undefined" results. These are nodes which have no name ect..
- [] filter out "undefined" results. These are nodes which have no name ect..
- [] Add other types of POI except for Points/Nodes.
- [] Fix overpass query (right now "public_bookshelf" gets returned from the ).
- [] Add overature places
- [] Add overature regions
- [] Add "open now" option.
- [] Add more filtering options (eg: cuisine...)
- [] Add mapillary images for the choosen POI.
- [] Add [lib.reviews](https://lib.reviews/faq)
- [] Add way to mute the sound.
2 changes: 2 additions & 0 deletions app/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@
}

.spin-button {
max-width: 200px;
display: none;
position: absolute;
bottom: 20px;
Expand All @@ -180,6 +181,7 @@
}

.reveal-button {
max-width: 200px;
display: none;
position: absolute;
bottom: 20px;
Expand Down
62 changes: 46 additions & 16 deletions app/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { fetchNominatimRelationData, fetchPoisInRelation } from "./overpass";
import { confetti } from "@tsparticles/confetti"

let selectedFeatureId: string | null = null;
let selectedRegion: string | null = null;
let selectedRegionId: string | null = null;
let selectedRegionFeature: Feature | null = null;
let boundingBox: [number, number, number, number] | null = null;
// default selectedCategory is drinks
let selectedCategory: string = "drinks";
Expand All @@ -22,15 +23,15 @@ export const categories: { [key: string]: { tag: string; emoji: string } } = {


function updateUrlWithState() {
console.log('Updating URL with state selectedFeatureId:', selectedFeatureId, 'selectedRegion:', selectedRegion, "type:", selectedCategory);
console.log('Updating URL with state selectedFeatureId:', selectedFeatureId, 'selectedRegion:', selectedRegionId, "type:", selectedCategory);
const queryParams = new URLSearchParams(window.location.search);
if (selectedFeatureId) {
queryParams.set('id', selectedFeatureId);
} else {
queryParams.delete('id');
}
if (selectedRegion) {
queryParams.set('region', selectedRegion);
if (selectedRegionId) {
queryParams.set('region', selectedRegionId);
} else {
queryParams.delete('region');
}
Expand All @@ -47,7 +48,7 @@ function updateUrlWithState() {
async function restoreStateFromUrl() {
const queryParams = new URLSearchParams(window.location.search);
selectedFeatureId = queryParams.get('id');
selectedRegion = queryParams.get('region');
selectedRegionId = queryParams.get('region');
// check if the type object is a key in the categories object and if not use the default value and log an error
// check for a type parameter in the URL and if not use the default value and log an error
if (queryParams.has('type')) {
Expand All @@ -60,8 +61,8 @@ async function restoreStateFromUrl() {
}
filterControl.updateFilterControlIcon(selectedCategory);

if (selectedRegion) {
pois = await fetchPoisForCurrentArea();
if (selectedRegionId) {
pois = await fetchPoisForAreaID(Number(selectedRegionId));
if (selectedFeatureId) {
// get some user input to avoid the error: `Autoplay is only allowed when approved by the user, the site is activated by the user, or media is muted.`
// The play method is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.
Expand All @@ -82,8 +83,24 @@ async function restoreStateFromUrl() {
}


async function fetchPoisForAreaID(selectedRegionId: number): Promise<FeatureCollection> {
const area = await fetchNominatimRelationData(selectedRegionId);
boundingBox = area.bbox;
if (boundingBox) {
recenterMapOnRegion();
}
const pois = await processArea(area);
return pois;
}

async function fetchPoisForCurrentArea(): Promise<FeatureCollection> {
const area = await fetchNominatimRelationData(Number(selectedRegion));
if (!selectedRegionFeature) {
console.error('No selected region geometry found');
return {} as FeatureCollection<Geometry, GeoJsonProperties>;
}
const area = selectedRegionFeature;
// TODO: fix this and don't ignore it!
// @ts-ignore
boundingBox = area.bbox;
if (boundingBox) {
recenterMapOnRegion();
Expand Down Expand Up @@ -196,7 +213,7 @@ geocoderControl.on('result', async (event: any) => {
hideSpinButton();
clearBoundary();
clearPoints();
selectedRegion = event.result.properties.osm_id;
selectedRegionId = event.result.properties.osm_id;
resetselectedFeature();
updateUrlWithState();
processArea(event.result);
Expand All @@ -205,6 +222,7 @@ geocoderControl.on('result', async (event: any) => {

async function processArea(carmen: any): Promise<FeatureCollection<Geometry, GeoJsonProperties>> {
hideAllContainers()
console.log('Processing area:', carmen.place_name);
// result geo could be a point, polygon, or multiline polygon.
// In this first version, we will only handle polygons and log the rest... #MVP
if (carmen.geometry.type !== 'Polygon' && carmen.geometry.type !== 'MultiPolygon') {
Expand All @@ -222,13 +240,22 @@ async function processArea(carmen: any): Promise<FeatureCollection<Geometry, Geo
}
boundingBox = carmen.bbox;
displayBoundaryOnMap(carmen.geometry)
selectedRegion = carmen.properties.osm_id;
selectedRegionFeature = carmen
selectedRegionId = carmen.properties.osm_id;
console.log('Fetching pois for category:', selectedCategory, categories[selectedCategory].emoji);
pois = await fetchPoisInRelation(carmen.properties.osm_id, selectedCategory);
displayPointsOnMap(pois);
return pois;
}

async function loadingPoisInRealtion(relationID: string, category: string) {
// show loading spinner

// fetch pois
pois = await fetchPoisInRelation(relationID, category)
displayPointsOnMap(pois)
}

const shareControl = new ShareControl("https://whereroulette.com", "Spin the wheel!", "WhereRoulette helps you choose a place to meet! 🌍 Powered by OSM ❤️‍🔥")
map.addControl(geocoderControl, "top-right");
map.addControl(new CustomAttributionControl({ compact: true }), "bottom-right");
Expand All @@ -247,8 +274,8 @@ document.getElementById("spin-button")?.addEventListener("click", async () => {
const selectedPOI = await spinTheWheel(pois);
selectedFeatureId = selectedPOI.properties?.id;
updateUrlWithState();
console.log('Selected POI:', selectedPOI?.properties?.name);
reveal(selectedPOI)
console.log('Selected POI:', selectedPOI?.properties?.name);
})

document.getElementById("reveal-button")?.addEventListener("click", async () => {
Expand All @@ -262,8 +289,8 @@ document.getElementById("reveal-button")?.addEventListener("click", async () =>
}
hideRevealButton();
const selectedPOI = await spinTheRiggedWheel(selectedFeatureId, pois);
console.log('Selected POI:', selectedPOI.properties?.name);
reveal(selectedPOI)
console.log('Selected POI:', selectedPOI.properties?.name);
})

document.getElementById("info-close-button")?.addEventListener("click", async () => {
Expand Down Expand Up @@ -470,8 +497,8 @@ export async function updateSelectedCategory(category: string) {
}
selectedCategory = category;
console.log('Updating for category:', category);
if (selectedRegion) {
fullReload()
if (selectedRegionId) {
reload()
}
updateUrlWithState();
}
Expand Down Expand Up @@ -507,21 +534,23 @@ function celebrate() {
});
}

export function reload() {
export function resetSpin() {
// Resets the map state to spin the wheel again for the current region
console.log('Reloading the wheel ready to spin again... 🔄');
hideSpinButton();
hideRevealButton();
resetselectedFeature();
updateUrlWithState();
recenterMapOnRegion();
hideAllContainers();
showSpinButton();
}

export async function fullReload() {
export async function reload() {
// Resets the map state and fetches new POIs based on the selectedCategory for the current region
console.log('Full Reloading... fetching pois for new category:', categories[selectedCategory].emoji);
hideSpinButton();
hideRevealButton();
clearPoints();
resetselectedFeature();
hideAllContainers();
Expand All @@ -539,6 +568,7 @@ async function reveal(selectedFeature: Feature<Geometry, GeoJsonProperties>): Pr
hideAllContainers();
showResults(selectedFeature);
if (selectedFeature.geometry.type === 'Point') {
// TODO: handle other geometries
const coordinates = selectedFeature.geometry.coordinates
map.flyTo({
center: coordinates as [number, number],
Expand Down
8 changes: 4 additions & 4 deletions app/src/overpass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ export function pubsInRelationQuery(relationID: number): string {
return `[out:json];node(area:${relationID + 3600000000})["amenity"="pub"];out geom;`;
}

export function poisInRelationQuery(relationID: number, poiType: string): string {
export function poisInRelationQuery(relationID: number, category: string): string {
// use the categories object to get the correct tag to use in the query
// export const categories = {
// "drinks": { "tag": '"amenity"~"pub|bar|biergarten"', "emoji": "🍺" },
// "cafe": { "tag": '"amenity"~"cafe"', "emoji": "☕" },
// "food": { "tag": '"amenity"~"restaurant|fast_food|food_court|ice_cream"', "emoji": "🍴" },
// "parks": { "tag": '"leisure"~"park|garden"', "emoji": "🌳" },
// }
const query = `[out:json];node(area:${relationID + 3600000000})[${categories[poiType].tag}];out geom;`;
const query = `[out:json];node(area:${relationID + 3600000000})[${categories[category].tag}];out geom;`;
return query;
}

Expand All @@ -49,8 +49,8 @@ export async function fetchPubsInRelation(relationID: number) {
return fc;
}

export async function fetchPoisInRelation(relationID: string, poiType: string) {
const query = poisInRelationQuery(parseInt(relationID), poiType);
export async function fetchPoisInRelation(relationID: string, category: string) {
const query = poisInRelationQuery(parseInt(relationID), category);
const osmData = await fetchOverpassData(query);
const fc = parseOSMToGeoJSON(osmData)
fc.features.forEach((feature, index) => {
Expand Down
4 changes: 2 additions & 2 deletions app/src/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { library, icon } from "@fortawesome/fontawesome-svg-core";
import { faQuestion, faShareNodes, faSpinner } from "@fortawesome/free-solid-svg-icons";
import maplibregl from "maplibre-gl";
import { Feature, Geometry, GeoJsonProperties } from "geojson";
import { updateSelectedCategory, reload } from "./main";
import { updateSelectedCategory, resetSpin } from "./main";

// register the icons with the library for future use
library.add(faQuestion, faShareNodes, faSpinner);
Expand Down Expand Up @@ -298,7 +298,7 @@ export function showResults(feature: Feature<Geometry, GeoJsonProperties>) {
spinAgainButton.className = "spin-again-button";
spinAgainButton.innerHTML = "Spin Again";
spinAgainButton.onclick = () => {
reload();
resetSpin();
};
resultsContainer.appendChild(spinAgainButton);

Expand Down

0 comments on commit 0eb3a6c

Please sign in to comment.