forked from MapComplete/MapComplete
		
	Added cyclofix capacity cargo; covered; non-bike shop; pump dyn title
This commit is contained in:
		
							parent
							
								
									a7bb4a1fcc
								
							
						
					
					
						commit
						948ff74a8b
					
				
					 23 changed files with 624 additions and 91 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -2,3 +2,4 @@ dist/* | |||
| node_modules | ||||
| .cache/* | ||||
| .idea/* | ||||
| scratch | ||||
|  |  | |||
							
								
								
									
										0
									
								
								Customizations/Layers/BikeCafes.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								Customizations/Layers/BikeCafes.ts
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										114
									
								
								Customizations/Layers/BikeOtherShops.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								Customizations/Layers/BikeOtherShops.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,114 @@ | |||
| import { LayerDefinition } from "../LayerDefinition"; | ||||
| import Translations from "../../UI/i18n/Translations"; | ||||
| import {And, Tag, Or} from "../../Logic/TagsFilter"; | ||||
| import { ImageCarouselWithUploadConstructor } from "../../UI/Image/ImageCarouselWithUpload"; | ||||
| import ShopRetail from "../Questions/bike/ShopRetail"; | ||||
| import ShopPump from "../Questions/bike/ShopPump"; | ||||
| import ShopRental from "../Questions/bike/ShopRental"; | ||||
| import ShopRepair from "../Questions/bike/ShopRepair"; | ||||
| import ShopDiy from "../Questions/bike/ShopDiy"; | ||||
| import ShopName from "../Questions/bike/ShopName"; | ||||
| import ShopSecondHand from "../Questions/bike/ShopSecondHand"; | ||||
| import { TagRenderingOptions } from "../TagRendering"; | ||||
| import { PhoneNumberQuestion } from "../Questions/PhoneNumberQuestion"; | ||||
| import Website from "../Questions/Website"; | ||||
| 
 | ||||
| 
 | ||||
| function anyValueExcept(key: string, exceptValue: string) { | ||||
|     return new And([ | ||||
|         new Tag(key, "*"), | ||||
|         new Tag(key, exceptValue, true) | ||||
|     ]) | ||||
| } | ||||
| 
 | ||||
| export default class BikeOtherShops extends LayerDefinition { | ||||
|     private readonly sellsBikes = new Tag("service:bicycle:retail", "yes") | ||||
|     private readonly repairsBikes = anyValueExcept("service:bicycle:repair", "no") | ||||
|     private readonly rentsBikes = new Tag("service:bicycle:rental", "yes") | ||||
|     private readonly hasPump = new Tag("service:bicycle:pump", "yes") | ||||
|     private readonly hasDiy = new Tag("service:bicycle:diy", "yes") | ||||
|     private readonly sellsSecondHand = anyValueExcept("service:bicycle:repair", "no") | ||||
|     private readonly hasBikeServices = new Or([ | ||||
|         this.sellsBikes, | ||||
|         this.repairsBikes, | ||||
|         // this.rentsBikes,
 | ||||
|         // this.hasPump,
 | ||||
|         // this.hasDiy,
 | ||||
|         // this.sellsSecondHand
 | ||||
|     ]) | ||||
| 
 | ||||
|     private readonly to = Translations.t.cyclofix.nonBikeShop | ||||
| 
 | ||||
|     constructor() { | ||||
|         super(); | ||||
|         this.name = this.to.name | ||||
|         this.icon = "./assets/bike/non_bike_repair_shop.svg" | ||||
|         this.overpassFilter = new And([ | ||||
|             anyValueExcept("shop", "bicycle"), | ||||
|             this.hasBikeServices | ||||
|         ]) | ||||
|         this.newElementTags = undefined | ||||
|         this.maxAllowedOverlapPercentage = 10 | ||||
|         this.wayHandling = LayerDefinition.WAYHANDLING_CENTER_AND_WAY | ||||
| 
 | ||||
|         this.minzoom = 13; | ||||
|         this.style = this.generateStyleFunction(); | ||||
|         this.title = new TagRenderingOptions({ | ||||
|             mappings: [ | ||||
|                 { | ||||
|                     k: new And([new Tag("name", "*"), this.sellsBikes]), | ||||
|                     txt: this.to.titleShopNamed | ||||
|                 }, | ||||
|                 { | ||||
|                     k: new And([new Tag("name", "*"), new Tag("service:bicycle:retail", "")]), | ||||
|                     txt: this.to.titleShop | ||||
|                 }, | ||||
|                 { | ||||
|                     k: new And([new Tag("name", "*"), new Tag("service:bicycle:retail", "no")]), | ||||
|                     txt: this.to.titleRepairNamed | ||||
|                 }, | ||||
|                 {k: this.sellsBikes, txt: this.to.titleShop}, | ||||
|                 {k: new Tag("service:bicycle:retail", " "), txt: this.to.title}, | ||||
|                 {k: new Tag("service:bicycle:retail", "no"), txt: this.to.titleRepair}, | ||||
|                 { | ||||
|                     k: new And([new Tag("name", "*")]), | ||||
|                     txt: this.to.titleNamed | ||||
|                 }, | ||||
|                 {k: null, txt: this.to.title}, | ||||
|             ] | ||||
|         }) | ||||
|          | ||||
|         this.elementsToShow = [ | ||||
|             new ImageCarouselWithUploadConstructor(), | ||||
|             new ShopName(), | ||||
|             new PhoneNumberQuestion("{name}"), | ||||
|             new Website("{name}"), | ||||
|             new ShopRetail(), | ||||
|             new ShopRental(), | ||||
|             new ShopRepair(), | ||||
|             new ShopPump(), | ||||
|             new ShopDiy(), | ||||
|             new ShopSecondHand() | ||||
|         ] | ||||
|     } | ||||
| 
 | ||||
|     private generateStyleFunction() { | ||||
|         const self = this; | ||||
|         return function (tags: any) { | ||||
|             let icon = "assets/bike/non_bike_repair_shop.svg"; | ||||
| 
 | ||||
|             if (self.sellsBikes.matchesProperties(tags)) { | ||||
|                 icon = "assets/bike/non_bike_shop.svg"; | ||||
|             } | ||||
| 
 | ||||
|             return { | ||||
|                 color: "#00bb00", | ||||
|                 icon: { | ||||
|                     iconUrl: icon, | ||||
|                     iconSize: [50, 50], | ||||
|                     iconAnchor: [25, 50] | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -1,16 +1,19 @@ | |||
| import {LayerDefinition} from "../LayerDefinition"; | ||||
| import {And, Or, Tag} from "../../Logic/TagsFilter"; | ||||
| import {And, Or, Tag, TagsFilter} from "../../Logic/TagsFilter"; | ||||
| import {OperatorTag} from "../Questions/OperatorTag"; | ||||
| import FixedText from "../Questions/FixedText"; | ||||
| import ParkingType from "../Questions/bike/ParkingType"; | ||||
| import ParkingCapacity from "../Questions/bike/ParkingCapacity"; | ||||
| import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload"; | ||||
| import BikeStationOperator from "../Questions/bike/StationOperator"; | ||||
| import Translations from "../../UI/i18n/Translations"; | ||||
| import ParkingOperator from "../Questions/bike/ParkingOperator"; | ||||
| import {TagRenderingOptions} from "../TagRendering"; | ||||
| import ParkingAccessCargo from "../Questions/bike/ParkingAccessCargo"; | ||||
| import ParkingCapacityCargo from "../Questions/bike/ParkingCapacityCargo"; | ||||
| 
 | ||||
| 
 | ||||
| export default class BikeParkings extends LayerDefinition { | ||||
|         private readonly accessCargoDesignated = new Tag("cargo_bike", "designated"); | ||||
| 
 | ||||
|     constructor() { | ||||
|         super(); | ||||
|         this.name = Translations.t.cyclofix.parking.name; | ||||
|  | @ -28,14 +31,9 @@ export default class BikeParkings extends LayerDefinition { | |||
|             new ImageCarouselWithUploadConstructor(), | ||||
|             //new ParkingOperator(),
 | ||||
|             new ParkingType(), | ||||
|             new TagRenderingOptions({ | ||||
|                 question: "How many bicycles fit in this bicycle parking?", | ||||
|                 freeform: { | ||||
|                     key: "capacity", | ||||
|                     renderTemplate: "Place for {capacity} bikes", | ||||
|                     template: "$nat$ bikes fit in here" | ||||
|                 } | ||||
|             }) | ||||
|             new ParkingCapacity(), | ||||
|             new ParkingAccessCargo(), | ||||
|             new ParkingCapacityCargo().OnlyShowIf(this.accessCargoDesignated) | ||||
|         ]; | ||||
|         this.wayHandling = LayerDefinition.WAYHANDLING_CENTER_AND_WAY; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { LayerDefinition } from "../LayerDefinition"; | ||||
| import Translations from "../../UI/i18n/Translations"; | ||||
| import {And, Tag} from "../../Logic/TagsFilter"; | ||||
| import {And, Tag, Or} from "../../Logic/TagsFilter"; | ||||
| import FixedText from "../Questions/FixedText"; | ||||
| import { ImageCarouselWithUploadConstructor } from "../../UI/Image/ImageCarouselWithUpload"; | ||||
| import ShopRetail from "../Questions/bike/ShopRetail"; | ||||
|  | @ -12,6 +12,7 @@ import ShopName from "../Questions/bike/ShopName"; | |||
| import ShopSecondHand from "../Questions/bike/ShopSecondHand"; | ||||
| import { TagRenderingOptions } from "../TagRendering"; | ||||
| import {PhoneNumberQuestion} from "../Questions/PhoneNumberQuestion"; | ||||
| import Website from "../Questions/Website"; | ||||
| 
 | ||||
| 
 | ||||
| export default class BikeShops extends LayerDefinition { | ||||
|  | @ -52,6 +53,7 @@ export default class BikeShops extends LayerDefinition { | |||
|             new ImageCarouselWithUploadConstructor(), | ||||
|             new ShopName(), | ||||
|             new PhoneNumberQuestion("{name}"), | ||||
|             new Website("{name}"), | ||||
|             new ShopRetail(), | ||||
|             new ShopRental(), | ||||
|             new ShopRepair(), | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWi | |||
| import PumpOperational from "../Questions/bike/PumpOperational"; | ||||
| import PumpValves from "../Questions/bike/PumpValves"; | ||||
| import Translations from "../../UI/i18n/Translations"; | ||||
| import { TagRenderingOptions } from "../TagRendering"; | ||||
| 
 | ||||
| 
 | ||||
| export default class BikeStations extends LayerDefinition { | ||||
|  | @ -19,6 +20,7 @@ export default class BikeStations extends LayerDefinition { | |||
|     private readonly pumpOperationalAny = new Tag("service:bicycle:pump:operational_status", "yes"); | ||||
|     private readonly pumpOperationalOk = new Or([new Tag("service:bicycle:pump:operational_status", "yes"), new Tag("service:bicycle:pump:operational_status", "operational"), new Tag("service:bicycle:pump:operational_status", "ok"), new Tag("service:bicycle:pump:operational_status", "")]); | ||||
|     private readonly tools = new Tag("service:bicycle:tools", "yes"); | ||||
|     private readonly to = Translations.t.cyclofix.station | ||||
| 
 | ||||
|     constructor() { | ||||
|         super(); | ||||
|  | @ -36,7 +38,19 @@ export default class BikeStations extends LayerDefinition { | |||
| 
 | ||||
|         this.minzoom = 13; | ||||
|         this.style = this.generateStyleFunction(); | ||||
|         this.title = new FixedText(Translations.t.cyclofix.station.title) | ||||
|         this.title = new TagRenderingOptions({ | ||||
|             mappings: [ | ||||
|                 { | ||||
|                     k: new And([this.pump, this.tools]), | ||||
|                     txt: this.to.titlePumpAndRepair | ||||
|                 }, | ||||
|                 { | ||||
|                     k: new And([this.pump]), | ||||
|                     txt: this.to.titlePump | ||||
|                 }, | ||||
|                 {k: null, txt: this.to.titleRepair}, | ||||
|             ] | ||||
|         }) | ||||
|         this.wayHandling = LayerDefinition.WAYHANDLING_CENTER_AND_WAY | ||||
| 
 | ||||
|         this.elementsToShow = [ | ||||
|  | @ -65,9 +79,9 @@ export default class BikeStations extends LayerDefinition { | |||
|             let iconName = "repair_station.svg"; | ||||
|             if (hasTools && hasPump && isOperational) { | ||||
|                 iconName = "repair_station_pump.svg" | ||||
|             }else if(hasTools){ | ||||
|             } else if(hasTools) { | ||||
|                     iconName = "repair_station.svg" | ||||
|             }else if(hasPump){ | ||||
|             } else if(hasPump) { | ||||
|                 if (isOperational) { | ||||
|                     iconName = "pump.svg" | ||||
|                 } else { | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import BikeShops from "../Layers/BikeShops"; | |||
| import Translations from "../../UI/i18n/Translations"; | ||||
| import {DrinkingWater} from "../Layers/DrinkingWater"; | ||||
| import Combine from "../../UI/Base/Combine"; | ||||
| import BikeOtherShops from "../Layers/BikeOtherShops"; | ||||
| 
 | ||||
| 
 | ||||
| export default class Cyclofix extends Layout { | ||||
|  | @ -13,7 +14,7 @@ export default class Cyclofix extends Layout { | |||
|             "cyclofix", | ||||
|             ["en", "nl", "fr"], | ||||
|             Translations.t.cyclofix.title, | ||||
|             [new BikeServices(), new BikeShops(), new DrinkingWater(), new BikeParkings()], | ||||
|             [new BikeServices(), new BikeShops(), new DrinkingWater(), new BikeParkings(), new BikeOtherShops()], | ||||
|             16, | ||||
|             50.8465573, | ||||
|             4.3516970, | ||||
|  |  | |||
							
								
								
									
										17
									
								
								Customizations/Questions/Website.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								Customizations/Questions/Website.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | |||
| import {TagRenderingOptions} from "../TagRendering"; | ||||
| import {UIElement} from "../../UI/UIElement"; | ||||
| import Translations from "../../UI/i18n/Translations"; | ||||
| 
 | ||||
| 
 | ||||
| export default class Website extends TagRenderingOptions { | ||||
|     constructor(category: string | UIElement) { | ||||
|         super({ | ||||
|             question: Translations.t.general.questions.websiteOf.Subs({category: category}), | ||||
|             freeform: { | ||||
|                 renderTemplate: Translations.t.general.questions.websiteIs.Subs({category: category}), | ||||
|                 template: "$phone$", | ||||
|                 key: "phone" | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										20
									
								
								Customizations/Questions/bike/ParkingAccessCargo.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								Customizations/Questions/bike/ParkingAccessCargo.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | |||
| import { TagRenderingOptions } from "../../TagRendering"; | ||||
| import { Tag } from "../../../Logic/TagsFilter"; | ||||
| import Translations from "../../../UI/i18n/Translations"; | ||||
| 
 | ||||
| 
 | ||||
| export default class ParkingAccessCargo extends TagRenderingOptions { | ||||
|     constructor() { | ||||
|         const key = "cargo_bike" | ||||
|         const to = Translations.t.cyclofix.parking.access_cargo | ||||
|         super({ | ||||
|             priority: 15, | ||||
|             question: to.question.Render(), | ||||
|             mappings: [ | ||||
|                 {k: new Tag(key, "yes"), txt: to.yes}, | ||||
|                 {k: new Tag(key, "designated"), txt: to.designated}, | ||||
|                 {k: new Tag(key, "no"), txt: to.no} | ||||
|             ] | ||||
|         }); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										18
									
								
								Customizations/Questions/bike/ParkingCapacity.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								Customizations/Questions/bike/ParkingCapacity.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | |||
| import Translations from "../../../UI/i18n/Translations"; | ||||
| import { TagRenderingOptions } from "../../TagRendering"; | ||||
| 
 | ||||
| 
 | ||||
| export default class ParkingCapacity extends TagRenderingOptions { | ||||
|     constructor() { | ||||
|         const to = Translations.t.cyclofix.parking.capacity | ||||
|         super({ | ||||
|             priority: 15, | ||||
|             question: to.question, | ||||
|             freeform: { | ||||
|                 key: "capacity", | ||||
|                 renderTemplate: to.render, | ||||
|                 template: to.template | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										19
									
								
								Customizations/Questions/bike/ParkingCapacityCargo.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Customizations/Questions/bike/ParkingCapacityCargo.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| import Translations from "../../../UI/i18n/Translations"; | ||||
| import { TagRenderingOptions } from "../../TagRendering"; | ||||
| import Combine from "../../../UI/Base/Combine"; | ||||
| 
 | ||||
| 
 | ||||
| export default class ParkingCapacityCargo extends TagRenderingOptions { | ||||
|     constructor() { | ||||
|         const to = Translations.t.cyclofix.parking.capacity_cargo | ||||
|         super({ | ||||
|             priority: 10, | ||||
|             question: to.question, | ||||
|             freeform: { | ||||
|                 key: "capacity:cargo_bike", | ||||
|                 renderTemplate: to.render, | ||||
|                 template: to.template | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,19 @@ | |||
| import { TagRenderingOptions } from "../../TagRendering"; | ||||
| import { Tag } from "../../../Logic/TagsFilter"; | ||||
| import Translations from "../../../UI/i18n/Translations"; | ||||
| 
 | ||||
| 
 | ||||
| export default class ParkingCovered extends TagRenderingOptions { | ||||
|     constructor() { | ||||
|         const key = 'covered' | ||||
|         const to = Translations.t.cyclofix.parking.covered | ||||
|         super({ | ||||
|             priority: 15, | ||||
|             question: to.question.Render(), | ||||
|             mappings: [ | ||||
|                 {k: new Tag(key, "yes"), txt: to.yes}, | ||||
|                 {k: new Tag(key, "no"), txt: to.no} | ||||
|             ] | ||||
|         }); | ||||
|     } | ||||
| } | ||||
|  | @ -1,37 +1,34 @@ | |||
| import {TagsFilter} from "./TagsFilter"; | ||||
| import * as OsmToGeoJson from "osmtogeojson"; | ||||
| import * as $ from "jquery"; | ||||
| import {Basemap} from "./Basemap"; | ||||
| import {UIEventSource} from "../UI/UIEventSource"; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * Interfaces overpass to get all the latest data | ||||
|  */ | ||||
| export class Overpass { | ||||
| 
 | ||||
| 
 | ||||
|     private _filter: TagsFilter; | ||||
|     public static testUrl: string = null; | ||||
|     private _filter: TagsFilter | ||||
|     public static testUrl: string = null | ||||
| 
 | ||||
|     constructor(filter: TagsFilter) { | ||||
|         this._filter = filter; | ||||
|         this._filter = filter | ||||
|     } | ||||
| 
 | ||||
|     private buildQuery(bbox: string): string { | ||||
|         const filters = this._filter.asOverpass(); | ||||
|         let filter = ""; | ||||
|     public buildQuery(bbox: string): string { | ||||
|         const filters = this._filter.asOverpass() | ||||
|         console.log(filters) | ||||
|         let filter = "" | ||||
|         for (const filterOr of filters) { | ||||
|             filter += 'nwr' + filterOr + ';'; | ||||
|             filter += 'nwr' + filterOr + ';' | ||||
|         } | ||||
|         const query = | ||||
|             '[out:json][timeout:25]' + bbox + ';(' + filter + ');out body;>;out skel qt;'; | ||||
|         console.log(query); | ||||
|         return "https://overpass-api.de/api/interpreter?data=" + encodeURIComponent(query); | ||||
|             '[out:json][timeout:25]' + bbox + ';(' + filter + ');out body;>;out skel qt;' | ||||
|         console.log(query) | ||||
|         return "https://overpass-api.de/api/interpreter?data=" + encodeURIComponent(query) | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     queryGeoJson(bbox: string, continuation: ((any) => void), onFail: ((reason) => void)): void { | ||||
|         let query = this.buildQuery(bbox); | ||||
|         let query = this.buildQuery(bbox) | ||||
| 
 | ||||
|         if(Overpass.testUrl !== null){ | ||||
|             console.log("Using testing URL") | ||||
|  | @ -53,9 +50,5 @@ export class Overpass { | |||
|                 const geojson = OsmToGeoJson.default(json); | ||||
|                 continuation(geojson); | ||||
|             }).fail(onFail) | ||||
| 
 | ||||
|         ; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | @ -51,17 +51,23 @@ export class Regex extends TagsFilter { | |||
|     substituteValues(tags: any) : TagsFilter{ | ||||
|         throw "Substituting values is not supported on regex tags" | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| export class Tag extends TagsFilter { | ||||
|     public key: string; | ||||
|     public value: string; | ||||
| 
 | ||||
|     constructor(key: string, value: string) { | ||||
| export class Tag extends TagsFilter { | ||||
|     public key: string | ||||
|     public value: string | ||||
|     public invertValue: boolean | ||||
| 
 | ||||
|     constructor(key: string, value: string, invertValue = false) { | ||||
|         super() | ||||
|         this.key = key; | ||||
|         this.value = value; | ||||
|         this.key = key | ||||
|         this.value = value | ||||
|         this.invertValue = invertValue | ||||
| 
 | ||||
|         if (value === "*" && invertValue) { | ||||
|             throw new Error("Invalid combination: invertValue && value == *") | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     matches(tags: { k: string; v: string }[]): boolean { | ||||
|  | @ -69,21 +75,22 @@ export class Tag extends TagsFilter { | |||
|             if (tag.k === this.key) { | ||||
|                 if (tag.v === "") { | ||||
|                     // This tag has been removed
 | ||||
|                     return this.value === ""; | ||||
|                     return this.value === "" | ||||
|                 } | ||||
|                 if (this.value === "*") { | ||||
|                     // Any is allowed
 | ||||
|                     return true; | ||||
|                 } | ||||
| 
 | ||||
|                 return this.value === tag.v; | ||||
|                 return this.value === tag.v !== this.invertValue | ||||
|             } | ||||
|         } | ||||
|         if(this.value === ""){ | ||||
|             return true; | ||||
| 
 | ||||
|         if (this.value === "") { | ||||
|             return true | ||||
|         } | ||||
|          | ||||
|         return false; | ||||
|         return this.invertValue | ||||
|     } | ||||
| 
 | ||||
|     asOverpass(): string[] { | ||||
|  | @ -94,17 +101,17 @@ export class Tag extends TagsFilter { | |||
|             // NOT having this key
 | ||||
|             return ['[!"' + this.key + '"]']; | ||||
|         } | ||||
|         return ['["' + this.key + '"="' + this.value + '"]']; | ||||
|         const compareOperator = this.invertValue ? '!=' : '=' | ||||
|         return ['["' + this.key + '"' + compareOperator + '"' + this.value + '"]']; | ||||
|     } | ||||
| 
 | ||||
|     substituteValues(tags: any) { | ||||
|         return new Tag(this.key, TagUtils.ApplyTemplate(this.value, tags)); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| export class Or extends TagsFilter { | ||||
| 
 | ||||
| export class Or extends TagsFilter { | ||||
|     public or: TagsFilter[] | ||||
| 
 | ||||
|     constructor(or: TagsFilter[]) { | ||||
|  | @ -112,9 +119,7 @@ export class Or extends TagsFilter { | |||
|         this.or = or; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     matches(tags: { k: string; v: string }[]): boolean { | ||||
| 
 | ||||
|         for (const tagsFilter of this.or) { | ||||
|             if (tagsFilter.matches(tags)) { | ||||
|                 return true; | ||||
|  | @ -125,7 +130,6 @@ export class Or extends TagsFilter { | |||
|     } | ||||
| 
 | ||||
|     asOverpass(): string[] { | ||||
| 
 | ||||
|         const choices = []; | ||||
|         for (const tagsFilter of this.or) { | ||||
|             const subChoices = tagsFilter.asOverpass(); | ||||
|  | @ -143,11 +147,10 @@ export class Or extends TagsFilter { | |||
|         } | ||||
|         return new Or(newChoices); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| export class And extends TagsFilter { | ||||
| 
 | ||||
| export class And extends TagsFilter { | ||||
|     public and: TagsFilter[] | ||||
| 
 | ||||
|     constructor(and: TagsFilter[]) { | ||||
|  | @ -156,7 +159,6 @@ export class And extends TagsFilter { | |||
|     } | ||||
| 
 | ||||
|     matches(tags: { k: string; v: string }[]): boolean { | ||||
| 
 | ||||
|         for (const tagsFilter of this.and) { | ||||
|             if (!tagsFilter.matches(tags)) { | ||||
|                 return false; | ||||
|  | @ -175,8 +177,7 @@ export class And extends TagsFilter { | |||
|     } | ||||
| 
 | ||||
|     asOverpass(): string[] { | ||||
| 
 | ||||
|         var allChoices = null; | ||||
|         var allChoices: string[] = null; | ||||
| 
 | ||||
|         for (const andElement of this.and) { | ||||
|             var andElementFilter = andElement.asOverpass(); | ||||
|  | @ -185,10 +186,10 @@ export class And extends TagsFilter { | |||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             var newChoices = [] | ||||
|             var newChoices: string[] = [] | ||||
|             for (var choice of allChoices) { | ||||
|                 newChoices.push( | ||||
|                     this.combine(choice, andElementFilter) | ||||
|                     ...this.combine(choice, andElementFilter) | ||||
|                 ) | ||||
|             } | ||||
|             allChoices = newChoices; | ||||
|  | @ -205,6 +206,7 @@ export class And extends TagsFilter { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| export class Not extends TagsFilter{ | ||||
|     private not: TagsFilter; | ||||
|      | ||||
|  | @ -224,12 +226,10 @@ export class Not extends TagsFilter{ | |||
|     substituteValues(tags: any): TagsFilter { | ||||
|         return new Not(this.not.substituteValues(tags)); | ||||
|     } | ||||
|      | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| export class TagUtils { | ||||
| 
 | ||||
|     static proprtiesToKV(properties: any): { k: string, v: string }[] { | ||||
|         const result = []; | ||||
|         for (const k in properties) { | ||||
|  | @ -246,5 +246,4 @@ export class TagUtils { | |||
|         } | ||||
|         return template; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -2,6 +2,7 @@ import {InputElement} from "./InputElement"; | |||
| import {UIEventSource} from "../UIEventSource"; | ||||
| import {UIElement} from "../UIElement"; | ||||
| import {FixedUiElement} from "../Base/FixedUiElement"; | ||||
| import Translations from "../i18n/Translations"; | ||||
| 
 | ||||
| 
 | ||||
| export class InputElementWrapper<T> extends InputElement<T>{ | ||||
|  | @ -16,9 +17,11 @@ export class InputElementWrapper<T> extends InputElement<T>{ | |||
|          | ||||
|     ) { | ||||
|         super(undefined); | ||||
|         this.pre = typeof(pre) === 'string' ?  new FixedUiElement(pre) : pre | ||||
|         // this.pre = typeof(pre) === 'string' ?  new FixedUiElement(pre) : pre
 | ||||
|         this.pre = Translations.W(pre) | ||||
|         this.input = input; | ||||
|         this.post =typeof(post) === 'string' ?  new FixedUiElement(post) : post | ||||
|         // this.post =typeof(post) === 'string' ?  new FixedUiElement(post) : post
 | ||||
|         this.post = Translations.W(post) | ||||
|     } | ||||
|      | ||||
|      | ||||
|  |  | |||
|  | @ -33,13 +33,13 @@ export default class Translations { | |||
|                 type: { | ||||
|                     render: new T({ | ||||
|                         en: 'This is a bicycle parking of the type: {bicycle_parking}', | ||||
|                         nl: 'Dit is een fietsenparking van het type: {bicycle_parking}', | ||||
|                         nl: 'Dit is een fietsparking van het type: {bicycle_parking}', | ||||
|                         fr: 'TODO: fr' | ||||
|                     }), | ||||
|                     template: new T({en: 'Some other type: $$$', nl: 'Een ander type: $$$', fr: 'TODO: fr'}), | ||||
|                     question: new T({ | ||||
|                         en: 'What is the type of this bicycle parking?', | ||||
|                         nl: 'Van welk type is deze fietsenparking?', | ||||
|                         nl: 'Van welk type is deze fietsparking?', | ||||
|                         fr: 'TODO: fr' | ||||
|                     }), | ||||
|                     eg: new T({en: ", for example", nl: ", bijvoorbeeld"}), | ||||
|  | @ -50,17 +50,16 @@ export default class Translations { | |||
|                     rack: new T({en: 'Rack', nl: 'Rek', fr: 'TODO: fr'}), | ||||
|                     "two-tier": new T({en: 'Two-tiered', nl: 'Dubbel (twee verdiepingen)', fr: 'TODO: fr'}), | ||||
|                 }, | ||||
| 
 | ||||
|                 operator: { | ||||
|                     render: new T({ | ||||
|                         en: 'This bike parking is operated by {operator}', | ||||
|                         nl: 'Deze fietsenparking wordt beheerd door {operator}', | ||||
|                         nl: 'Deze fietsparking wordt beheerd door {operator}', | ||||
|                         fr: 'TODO: fr' | ||||
|                     }), | ||||
|                     template: new T({en: 'A different operator: $$$', nl: 'Een andere beheerder: $$$', fr: 'TODO: fr'}), | ||||
|                     question: new T({ | ||||
|                         en: 'Who operates this bike station (name of university, shop, city...)?', | ||||
|                         nl: 'Wie beheert deze fietsenparking (naam universiteit, winkel, stad...)?', | ||||
|                         en: 'Who operates this bike parking (name of university, shop, city...)?', | ||||
|                         nl: 'Wie beheert deze fietsparking (naam universiteit, winkel, stad...)?', | ||||
|                         fr: 'TODO: fr' | ||||
|                     }), | ||||
|                     private: new T({ | ||||
|  | @ -68,15 +67,90 @@ export default class Translations { | |||
|                         nl: 'Wordt beheerd door een privépersoon', | ||||
|                         fr: 'TODO: fr' | ||||
|                     }), | ||||
|                 }, | ||||
|                 covered: { | ||||
|                     question: new T({ | ||||
|                         en: 'Is this parking covered? Also select "covered" for indoor parkings.', | ||||
|                         nl: 'Is deze parking overdekt? Selecteer ook "overdekt" voor fietsparkings binnen een gebouw.', | ||||
|                         fr: 'TODO: fr' | ||||
|                     }), | ||||
|                     yes: new T({ | ||||
|                         en: 'This parking is covered (it has a roof)', | ||||
|                         nl: 'Deze parking is overdekt (er is een afdak)', | ||||
|                         fr: 'TODO: fr' | ||||
|                     }), | ||||
|                     no: new T({ | ||||
|                         en: 'This parking is not covered', | ||||
|                         nl: 'Deze parking is niet overdekt', | ||||
|                         fr: 'TODO: fr' | ||||
|                     }) | ||||
|                 }, | ||||
|                 capacity: { | ||||
|                     question: new T({ | ||||
|                         en: "How many bicycles fit in this bicycle parking (including possible cargo bicycles)?", | ||||
|                         nl: "Voor hoeveel fietsen is er bij deze fietsparking plaats (inclusief potentiëel bakfietsen)?", | ||||
|                         fr: "TODO: fr" | ||||
|                     }), | ||||
|                     template: new T({ | ||||
|                         en: "This parking fits $nat$ bikes", | ||||
|                         nl: "Deze parking heeft plaats voor $nat$ fietsen", | ||||
|                         fr: "TODO: fr" | ||||
|                     }), | ||||
|                     render: new T({ | ||||
|                         en: "Place for {capacity} bikes (in total)", | ||||
|                         nl: "Plaats voor {capacity} fietsen (in totaal)", | ||||
|                         fr: "TODO: fr" | ||||
|                     }), | ||||
|                 }, | ||||
|                 capacity_cargo: { | ||||
|                     question: new T({ | ||||
|                         en: "How many cargo bicycles fit in this bicycle parking?", | ||||
|                         nl: "Voor hoeveel bakfietsen heeft deze fietsparking plaats?", | ||||
|                         fr: "TODO: fr" | ||||
|                     }), | ||||
|                     template: new T({ | ||||
|                         en: "This parking fits $nat$ cargo bikes", | ||||
|                         nl: "Deze parking heeft plaats voor $nat$ fietsen", | ||||
|                         fr: "TODO: fr" | ||||
|                     }), | ||||
|                     render: new T({ | ||||
|                         en: "Place for {capacity:cargo_bike} cargo bikes", | ||||
|                         nl: "Plaats voor {capacity:cargo_bike} bakfietsen", | ||||
|                         fr: "TODO: fr" | ||||
|                     }), | ||||
|                 }, | ||||
|                 access_cargo: { | ||||
|                     question: new T({ | ||||
|                         en: "Does this bicycle parking have spots for cargo bikes?", | ||||
|                         nl: "Heeft deze fietsparking plaats voor bakfietsen?", | ||||
|                         fr: "TODO: fr" | ||||
|                     }), | ||||
|                     yes: new T({ | ||||
|                         en: "This parking has room for cargo bikes", | ||||
|                         nl: "Deze parking is overdekt (er is een afdak)", | ||||
|                         fr: "TODO: fr" | ||||
|                     }), | ||||
|                     designated: new T({ | ||||
|                         en: "This parking has designated (official) spots for cargo bikes.", | ||||
|                         nl: "Deze parking is overdekt (er is een afdak)", | ||||
|                         fr: "TODO: fr" | ||||
|                     }), | ||||
|                     no: new T({ | ||||
|                         en: "You're not allowed to park cargo bikes", | ||||
|                         nl: "Je mag hier geen bakfietsen parkeren", | ||||
|                         fr: "TODO: fr" | ||||
|                     }) | ||||
|                 } | ||||
|             }, | ||||
|             station: { | ||||
|                 name: new T({ | ||||
|                     en: 'bike station (repair, pump or both)', | ||||
|                     nl: 'fietsstation (herstel, pomp of allebei)', | ||||
|                     nl: 'fietspunt (herstel, pomp of allebei)', | ||||
|                     fr: 'TODO: fr' | ||||
|                 }), | ||||
|                 title: new T({en: 'Bike station', nl: 'Fietsstation', fr: 'TODO: fr'}), | ||||
|                 titlePump: new T({en: 'Bike pump', nl: 'Fietspomp', fr: 'TODO: fr'}), | ||||
|                 titleRepair: new T({en: 'Bike repair station', nl: 'Herstelpunt', fr: 'TODO: fr'}), | ||||
|                 titlePumpAndRepair: new T({en: 'Bike station (pump & repair)', nl: 'Herstelpunt met pomp', fr: 'TODO: fr'}), | ||||
|                 manometer: { | ||||
|                     question: new T({ | ||||
|                         en: 'Does the pump have a pressure indicator or manometer?', | ||||
|  | @ -144,8 +218,8 @@ export default class Translations { | |||
|                 }, | ||||
|                 chain: { | ||||
|                     question: new T({ | ||||
|                         en: 'Does this bike station have a special tool to repair your bike chain?', | ||||
|                         nl: 'Heeft dit fietsstation een speciale reparatieset voor je ketting?', | ||||
|                         en: 'Does this bike repair station have a special tool to repair your bike chain?', | ||||
|                         nl: 'Heeft dit herstelpunt een speciale reparatieset voor je ketting?', | ||||
|                         fr: 'TODO: fr' | ||||
|                     }), | ||||
|                     yes: new T({ | ||||
|  | @ -162,7 +236,7 @@ export default class Translations { | |||
|                 operator: { | ||||
|                     render: new T({ | ||||
|                         en: 'This bike station is operated by {operator}', | ||||
|                         nl: 'Dit fietsstation wordt beheerd door {operator}', | ||||
|                         nl: 'Dit fietspunt wordt beheerd door {operator}', | ||||
|                         fr: 'TODO: fr' | ||||
|                     }), | ||||
|                     template: new T({en: 'A different operator: $$$', nl: 'Een andere beheerder: $$$', fr: 'TODO: fr'}), | ||||
|  | @ -180,7 +254,7 @@ export default class Translations { | |||
|                 services: { | ||||
|                     question: new T({ | ||||
|                         en: 'Which services are available at this bike station?', | ||||
|                         nl: 'Welke functies biedt dit fietsstation?', | ||||
|                         nl: 'Welke functies biedt dit fietspunt?', | ||||
|                         fr: 'TODO: fr' | ||||
|                     }), | ||||
|                     pump: new T({ | ||||
|  | @ -203,7 +277,7 @@ export default class Translations { | |||
|                 stand: { | ||||
|                     question: new T({ | ||||
|                         en: 'Does this bike station have a hook to suspend your bike with or a stand to elevate it?', | ||||
|                         nl: 'Heeft dit fietsstation een haak of standaard om je fiets op te hangen/zetten?', | ||||
|                         nl: 'Heeft dit herstelpunt een haak of standaard om je fiets op te hangen/zetten?', | ||||
|                         fr: 'TODO: fr' | ||||
|                     }), | ||||
|                     yes: new T({en: 'There is a hook or stand', nl: 'Er is een haak of standaard', fr: 'TODO: fr'}), | ||||
|  | @ -211,17 +285,15 @@ export default class Translations { | |||
|                 } | ||||
|             }, | ||||
|             shop: { | ||||
|                 name: new T({en: 'bike shop', nl: 'fietswinkel', fr: 'TODO: fr'}), | ||||
|                 name: new T({en: 'bike repair/shop', nl: 'fietszaak', fr: 'TODO: fr'}), | ||||
|                  | ||||
|                 title: new T({en: 'Bike shop', nl: 'Fietszaak', fr: 'TODO: fr'}), | ||||
|                 title: new T({en: 'Bike repair/shop', nl: 'Fietszaak', fr: 'TODO: fr'}), | ||||
|                 titleRepair: new T({en: 'Bike repair', nl: 'Fietsenmaker', fr: 'TODO: fr'}), | ||||
|                 titleShop: new T({en: 'Bike repair/shop', nl: 'Fietswinkel', fr: 'TODO: fr'}), | ||||
|                  | ||||
|                 titleNamed: new T({en: 'Bike repair/shop', nl: 'Fietszaak {name}', fr: 'TODO: fr'}), | ||||
|                 titleRepairNamed: new T({en: 'Bike shop', nl: 'Fietsenmaker {name}', fr: 'TODO: fr'}), | ||||
|                 titleShopNamed: new T({en: 'Bike repair/shop', nl: 'Fietswinkel {name}', fr: 'TODO: fr'}), | ||||
| 
 | ||||
|                 titleShop: new T({en: 'Bike shop', nl: 'Fietswinkel', fr: 'TODO: fr'}), | ||||
|                  | ||||
|                 titleNamed: new T({en: 'Bike repair/shop {name}', nl: 'Fietszaak {name}', fr: 'TODO: fr'}), | ||||
|                 titleRepairNamed: new T({en: 'Bike repair {name}', nl: 'Fietsenmaker {name}', fr: 'TODO: fr'}), | ||||
|                 titleShopNamed: new T({en: 'Bike shop {name}', nl: 'Fietswinkel {name}', fr: 'TODO: fr'}), | ||||
| 
 | ||||
|                 retail: { | ||||
|                     question: new T({ | ||||
|  | @ -310,6 +382,17 @@ export default class Translations { | |||
|                     }), | ||||
|                 } | ||||
|             }, | ||||
|             nonBikeShop: {              | ||||
|                 name: new T({en: 'shop that sells/repairs bikes', nl: 'winkel die fietsen verkoopt/herstelt', fr: 'TODO: fr'}), | ||||
| 
 | ||||
|                 title: new T({en: 'Shop that sells/repairs bikes', nl: 'Winkel die fietsen verkoopt/herstelt', fr: 'TODO: fr'}), | ||||
|                 titleRepair: new T({en: 'Shop that repairs bikes', nl: 'Winkel die fietsen herstelt', fr: 'TODO: fr'}), | ||||
|                 titleShop: new T({en: 'Shop that sells bikes', nl: 'Winkel die fietsen verkoopt', fr: 'TODO: fr'}), | ||||
|                  | ||||
|                 titleNamed: new T({en: '{name} (sells/repairs bikes)', nl: '{name} (verkoopt/herstelt fietsen)', fr: 'TODO: fr'}), | ||||
|                 titleRepairNamed: new T({en: '{name} (repairs bikes)', nl: '{name} (herstelt fietsen)', fr: 'TODO: fr'}), | ||||
|                 titleShopNamed: new T({en: '{name} (sells bikes)', nl: '{name} (verkoopt fietsen)', fr: 'TODO: fr'}), | ||||
|             }, | ||||
|             drinking_water: { | ||||
|                 title: new T({ | ||||
|                     en: 'Drinking water', | ||||
|  | @ -502,8 +585,15 @@ export default class Translations { | |||
|                 phoneNumberIs: new T({ | ||||
|                     en: "The phone number of this {category} is <a href='tel:{phone}' target='_blank'>{phone}</a>", | ||||
|                     nl: "Het telefoonnummer van {category} is <a href='tel:{phone}' target='_blank'>{phone}</a>" | ||||
|                 }), | ||||
|                 websiteOf: new T({ | ||||
|                     en: "What is the website of {category}?", | ||||
|                     nl: "Wat is de website van {category}?" | ||||
|                 }), | ||||
|                 websiteIs: new T({ | ||||
|                     en: "Website: <a href='{website}' target='_blank'>{website}</a>", | ||||
|                     nl: "Website: <a href='{website}' target='_blank'>{website}</a>" | ||||
|                 }) | ||||
| 
 | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
							
								
								
									
										21
									
								
								assets/bike/non_bike_repair_shop.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								assets/bike/non_bike_repair_shop.svg
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| After Width: | Height: | Size: 10 KiB | 
							
								
								
									
										164
									
								
								assets/bike/non_bike_shop.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								assets/bike/non_bike_shop.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,164 @@ | |||
| <svg width="98" height="121" viewBox="0 0 98 121" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||||
| <path d="M53.0445 111.094C51.2614 114.981 45.7386 114.981 43.9555 111.094L13.2124 44.085C11.6928 40.7729 14.1129 37 17.7569 37L79.2431 37C82.8871 37 85.3072 40.7729 83.7876 44.085L53.0445 111.094Z" fill="#805793"/> | ||||
| <circle cx="49" cy="49" r="49" fill="#805793"/> | ||||
| <g filter="url(#filter0_d)"> | ||||
| <ellipse cx="20" cy="32.5" rx="7" ry="5.5" fill="white"/> | ||||
| </g> | ||||
| <g filter="url(#filter1_d)"> | ||||
| <ellipse cx="63.5" cy="32.5" rx="7.5" ry="5.5" fill="white"/> | ||||
| </g> | ||||
| <g filter="url(#filter2_d)"> | ||||
| <ellipse cx="78" cy="32.5" rx="7" ry="5.5" fill="white"/> | ||||
| </g> | ||||
| <g filter="url(#filter3_d)"> | ||||
| <ellipse cx="49" cy="32.5" rx="7" ry="5.5" fill="white"/> | ||||
| </g> | ||||
| <g filter="url(#filter4_d)"> | ||||
| <ellipse cx="34.5" cy="32.5" rx="7.5" ry="5.5" fill="white"/> | ||||
| </g> | ||||
| <path d="M19.5 24.5L30.3253 31.5H8.67468L19.5 24.5Z" fill="white"/> | ||||
| <path d="M79 24.5L89.3253 31.5H67.6747L79 24.5Z" fill="white"/> | ||||
| <rect x="19" y="20" width="60" height="14" fill="white"/> | ||||
| <rect x="6" y="31" width="85" height="1" fill="#805793"/> | ||||
| <g filter="url(#filter5_d)"> | ||||
| <rect x="21" y="38" width="4" height="34" fill="white"/> | ||||
| </g> | ||||
| <g filter="url(#filter6_d)"> | ||||
| <rect x="74" y="39" width="4" height="34" fill="white"/> | ||||
| </g> | ||||
| <g filter="url(#filter7_d)"> | ||||
| <rect x="16" y="72" width="67" height="5" fill="white"/> | ||||
| </g> | ||||
| <g filter="url(#filter8_d)"> | ||||
| <path d="M43.1579 63.8659H33.5872L38.8076 52.2202H44.028H47.7983H51.8586M51.8586 52.2202L50.4085 48.9355H52.4386H54.4688M51.8586 52.2202L52.4386 53.7132L53.5987 56.1021L56.789 63.8659M51.8586 52.2202L49.1034 56.6993L47.4502 59.3867M46.3481 61.1784L47.4502 59.3867M40.8377 55.5049L43.7379 62.0742L37.9375 48.9355L39.6776 52.5188M45.4781 62.6714L47.4502 59.3867" stroke="white" stroke-width="2"/> | ||||
| <path d="M46.0937 63.3578C46.0937 64.25 45.395 64.9481 44.5635 64.9481C43.7321 64.9481 43.0334 64.25 43.0334 63.3578C43.0334 62.4657 43.7321 61.7676 44.5635 61.7676C45.395 61.7676 46.0937 62.4657 46.0937 63.3578Z" stroke="white"/> | ||||
| <path d="M39.7932 62.7607C39.7932 66.359 36.9675 69.2258 33.5427 69.2258C30.1179 69.2258 27.2921 66.359 27.2921 62.7607C27.2921 59.1623 30.1179 56.2955 33.5427 56.2955C36.9675 56.2955 39.7932 59.1623 39.7932 62.7607Z" stroke="white" stroke-width="2"/> | ||||
| <ellipse cx="60.279" cy="57.3748" rx="0.210172" ry="0.216394" fill="black" fill-opacity="0.49"/> | ||||
| </g> | ||||
| <g filter="url(#filter9_d)"> | ||||
| <path d="M43.1579 63.8659H33.5872L38.8076 52.2202H44.028H47.7983H51.8586M51.8586 52.2202L50.4085 48.9355H52.4386H54.4688M51.8586 52.2202L52.4386 53.7132L53.5987 56.1021L56.789 63.8659M51.8586 52.2202L49.1034 56.6993L47.4502 59.3867M46.3481 61.1784L47.4502 59.3867M40.8377 55.5049L43.7379 62.0742L37.9375 48.9355L39.6776 52.5188M45.4781 62.6714L47.4502 59.3867" stroke="white" stroke-width="2"/> | ||||
| <path d="M46.0937 63.3578C46.0937 64.25 45.395 64.9481 44.5635 64.9481C43.7321 64.9481 43.0334 64.25 43.0334 63.3578C43.0334 62.4657 43.7321 61.7676 44.5635 61.7676C45.395 61.7676 46.0937 62.4657 46.0937 63.3578Z" stroke="white"/> | ||||
| <path d="M39.7932 62.7607C39.7932 66.359 36.9675 69.2258 33.5427 69.2258C30.1179 69.2258 27.2921 66.359 27.2921 62.7607C27.2921 59.1623 30.1179 56.2955 33.5427 56.2955C36.9675 56.2955 39.7932 59.1623 39.7932 62.7607Z" stroke="white" stroke-width="2"/> | ||||
| <ellipse cx="60.279" cy="57.3748" rx="0.210172" ry="0.216394" fill="black" fill-opacity="0.49"/> | ||||
| </g> | ||||
| <g filter="url(#filter10_d)"> | ||||
| <circle cx="56.5" cy="63.5" r="6.5" stroke="white" stroke-width="2"/> | ||||
| </g> | ||||
| <path d="M63.2749 56.3586C62.6089 56.7271 61.7919 56.2445 61.7916 55.4825L61.7903 51.7748C61.79 51.0004 62.6308 50.5198 63.2971 50.9134L66.5391 52.8283C67.2055 53.2219 67.1923 54.1913 66.5155 54.5658L63.2749 56.3586Z" fill="white"/> | ||||
| <g filter="url(#filter11_d)"> | ||||
| <rect width="7.82366" height="6.20457" rx="1" transform="matrix(0.490888 -0.871223 0.870592 0.492006 61.4893 51.5931)" fill="white"/> | ||||
| </g> | ||||
| <path d="M66.0398 53.2049C62.045 51.8388 64.4607 45.5484 68.7455 48.7409" stroke="#805793" stroke-width="0.75"/> | ||||
| <path d="M63.0112 49.4193L66.8764 51.3548M63.4944 48.4516L67.5528 50.4839" stroke="#805793" stroke-width="0.75"/> | ||||
| <circle cx="63.5" cy="54.5" r="0.5" fill="#805793"/> | ||||
| <defs> | ||||
| <filter id="filter0_d" x="9" y="27" width="22" height="19" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||||
| <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> | ||||
| <feOffset dy="4"/> | ||||
| <feGaussianBlur stdDeviation="2"/> | ||||
| <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/> | ||||
| <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/> | ||||
| <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/> | ||||
| </filter> | ||||
| <filter id="filter1_d" x="52" y="27" width="23" height="19" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||||
| <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> | ||||
| <feOffset dy="4"/> | ||||
| <feGaussianBlur stdDeviation="2"/> | ||||
| <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/> | ||||
| <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/> | ||||
| <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/> | ||||
| </filter> | ||||
| <filter id="filter2_d" x="67" y="27" width="22" height="19" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||||
| <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> | ||||
| <feOffset dy="4"/> | ||||
| <feGaussianBlur stdDeviation="2"/> | ||||
| <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/> | ||||
| <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/> | ||||
| <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/> | ||||
| </filter> | ||||
| <filter id="filter3_d" x="38" y="27" width="22" height="19" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||||
| <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> | ||||
| <feOffset dy="4"/> | ||||
| <feGaussianBlur stdDeviation="2"/> | ||||
| <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/> | ||||
| <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/> | ||||
| <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/> | ||||
| </filter> | ||||
| <filter id="filter4_d" x="23" y="27" width="23" height="19" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||||
| <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> | ||||
| <feOffset dy="4"/> | ||||
| <feGaussianBlur stdDeviation="2"/> | ||||
| <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/> | ||||
| <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/> | ||||
| <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/> | ||||
| </filter> | ||||
| <filter id="filter5_d" x="17" y="38" width="12" height="42" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||||
| <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> | ||||
| <feOffset dy="4"/> | ||||
| <feGaussianBlur stdDeviation="2"/> | ||||
| <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/> | ||||
| <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/> | ||||
| <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/> | ||||
| </filter> | ||||
| <filter id="filter6_d" x="70" y="39" width="12" height="42" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||||
| <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> | ||||
| <feOffset dy="4"/> | ||||
| <feGaussianBlur stdDeviation="2"/> | ||||
| <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/> | ||||
| <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/> | ||||
| <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/> | ||||
| </filter> | ||||
| <filter id="filter7_d" x="12" y="72" width="75" height="13" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||||
| <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> | ||||
| <feOffset dy="4"/> | ||||
| <feGaussianBlur stdDeviation="2"/> | ||||
| <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/> | ||||
| <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/> | ||||
| <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/> | ||||
| </filter> | ||||
| <filter id="filter8_d" x="22.2921" y="47.9355" width="42.197" height="30.2904" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||||
| <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> | ||||
| <feOffset dy="4"/> | ||||
| <feGaussianBlur stdDeviation="2"/> | ||||
| <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/> | ||||
| <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/> | ||||
| <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/> | ||||
| </filter> | ||||
| <filter id="filter9_d" x="22.2921" y="47.9355" width="42.197" height="30.2904" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||||
| <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> | ||||
| <feOffset dy="4"/> | ||||
| <feGaussianBlur stdDeviation="2"/> | ||||
| <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/> | ||||
| <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/> | ||||
| <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/> | ||||
| </filter> | ||||
| <filter id="filter10_d" x="45" y="56" width="23" height="23" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||||
| <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> | ||||
| <feOffset dy="4"/> | ||||
| <feGaussianBlur stdDeviation="2"/> | ||||
| <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/> | ||||
| <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/> | ||||
| <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/> | ||||
| </filter> | ||||
| <filter id="filter11_d" x="57.8512" y="45.1395" width="16.5185" height="17.1438" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||||
| <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> | ||||
| <feOffset dy="4"/> | ||||
| <feGaussianBlur stdDeviation="2"/> | ||||
| <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/> | ||||
| <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/> | ||||
| <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/> | ||||
| </filter> | ||||
| </defs> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 11 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/bike/staples-annotated.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/bike/staples-annotated.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 2.7 MiB | 
|  | @ -980,6 +980,10 @@ form { | |||
|     font-weight: bold; | ||||
| } | ||||
| 
 | ||||
| .question-text img { | ||||
|     max-width: 100%; | ||||
| } | ||||
| 
 | ||||
| .question-subtext{ | ||||
|     font-size: medium; | ||||
|     font-weight: normal; | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ | |||
|     ] | ||||
|   }, | ||||
|   "scripts": { | ||||
|     "start": "parcel *.html UI/** Logic/** assets/**/* vendor/* vendor/*/*", | ||||
|     "start": "parcel *.html UI/** Logic/** assets/**/* assets/* vendor/* vendor/*/*", | ||||
|     "generate": "ts-node createLayouts.ts", | ||||
|     "build": "rm -rf dist/ && parcel build --public-url ./ *.html assets/* assets/**/* vendor/* vendor/*/*", | ||||
|     "clean": "./clean.sh", | ||||
|  |  | |||
							
								
								
									
										
											BIN
										
									
								
								static/staples-annotated.xcf
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/staples-annotated.xcf
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										36
									
								
								test.ts
									
										
									
									
									
								
							
							
						
						
									
										36
									
								
								test.ts
									
										
									
									
									
								
							|  | @ -0,0 +1,36 @@ | |||
| import { And, Tag, Or } from "./Logic/TagsFilter"; | ||||
| import { Overpass } from "./Logic/Overpass"; | ||||
| 
 | ||||
| 
 | ||||
| function anyValueExcept(key: string, exceptValue: string) { | ||||
|     return new And([ | ||||
|         new Tag(key, "*"), | ||||
|         new Tag(key, exceptValue, true) | ||||
|     ]) | ||||
| } | ||||
| 
 | ||||
| const sellsBikes = new Tag("service:bicycle:retail", "yes") | ||||
| const repairsBikes = anyValueExcept("service:bicycle:repair", "no") | ||||
| const rentsBikes = new Tag("service:bicycle:rental", "yes") | ||||
| const hasPump = new Tag("service:bicycle:pump", "yes") | ||||
| const hasDiy = new Tag("service:bicycle:diy", "yes") | ||||
| const sellsSecondHand = anyValueExcept("service:bicycle:repair", "no") | ||||
| const hasBikeServices = new Or([ | ||||
|     sellsBikes, | ||||
|     repairsBikes, | ||||
|     rentsBikes, | ||||
|     hasPump, | ||||
|     hasDiy, | ||||
|     sellsSecondHand | ||||
| ]) | ||||
| 
 | ||||
| const overpassFilter = new And([ | ||||
|     new Tag("shop", "bicycle", true), | ||||
|     hasBikeServices | ||||
| ]) | ||||
| 
 | ||||
| const overpass = new Overpass(overpassFilter) | ||||
| 
 | ||||
| // console.log(overpass.buildQuery('bbox:51.12246976163816,3.1045767593383795,51.289518504257174,3.2848313522338866'))
 | ||||
| 
 | ||||
| console.log(overpassFilter.asOverpass()) | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue