From 87193fe11d3df874e6c9097faf395324230bd49f Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 15:25:18 -0300 Subject: [PATCH 01/23] orginize stritmix segments and variants by categories --- src/segments-variants.json | 45 +++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/src/segments-variants.json b/src/segments-variants.json index 055f994f6..ba84d6e8f 100644 --- a/src/segments-variants.json +++ b/src/segments-variants.json @@ -1,27 +1,36 @@ { + // sidewalk segments "sidewalk": ["empty", "sparse", "normal", "dense"], - "bus-lane": ["inbound|colored|typical", "outbound|colored|typical", "inbound|regular|typical", "outbound|regular|typical"], - "drive-lane": ["inbound|car","outbound|car", "inbound|truck","outbound|truck", "outbound|av", "inbound|av", "outbound|pedestrian", "inbound|pedestrian", "inbound|sharrow", "outbound|sharrow"], - "light-rail": ["inbound|regular", "inbound|colored", "inbound|grass", "outbound|regular", "outbound|colored", "outbound|grass"], - "streetcar": ["inbound|regular", "inbound|colored", "inbound|grass", "outbound|regular", "outbound|colored", "outbound|grass"], - "turn-lane": ["inbound|left", "inbound|right", "inbound|left-right-straight", "inbound|shared", "inbound|both", "inbound|left-straight", "inbound|right-straight", "inbound|straight", "outbound|left", "outbound|right", "outbound|left-right-straight", "outbound|shared", "outbound|both", "outbound|left-straight", "outbound|right-straight", "outbound|straight"], - "divider": ["buffer", "flowers", "planting-strip", "planter-box", "palm-tree", "big-tree", "bush", "dome", "bollard", "striped-buffer"], - "temporary": ["barricade", "traffic-cone", "jersey-barrier-plastic", "jersey-barrier-concrete"], - "food-truck": ["left", "right"], - "flex-zone": ["taxi|inbound|right", "taxi|inbound|left", "taxi|outbound|right", "taxi|outbound|left", "rideshare|outbound|right", "rideshare|outbound|right", "rideshare|inbound|right", "rideshare|inbound|left"], "sidewalk-wayfinding": ["large"], "sidewalk-bench": ["left", "right", "center"], "sidewalk-bike-rack":["left|sidewalk-parallel", "right|sidewalk-parallel", "left|sidewalk", "right|sidewalk"], - "magic-carpet": ["aladdin"], - "outdoor-dining": ["empty|sidewalk", "empty|road"], - "parklet": ["left", "right"], - "bikeshare": ["left|road", "right|road", "left|sidewalk", "right|sidewalk"], - "utilities": ["left", "right"], "sidewalk-tree": ["big", "palm-tree"], + // lights and utilities + "utilities": ["left", "right"], "sidewalk-lamp": ["right|modern","both|modern", "left|modern", "right|traditional", "both|traditional", "left|traditional", "right|pride", "both|pride", "left|pride"], - "transit-shelter": ["left|street-level", "right|street-level", "right|light-rail", "left|light-rail"], - "brt-station": ["center"], - "parking-lane": ["sideways|right", "sideways|left", "inbound|right", "inbound|left", "outbound|left", "outbound|right", "angled-front-left|left", "angled-front-right|left", "angled-rear-left|left", "angled-rear-right|left", "angled-front-left|right", "angled-front-right|right", "angled-rear-left|right", "angled-rear-right|right"], + // furniture segments + "parklet": ["left", "right"], + "outdoor-dining": ["empty|sidewalk", "empty|road"], + "bikeshare": ["left|road", "right|road", "left|sidewalk", "right|sidewalk"], + // bike and scooter segments "bike-lane": ["inbound|green|sidewalk", "inbound|green|road", "outbound|green|sidewalk", "outbound|green|road", "inbound|regular|sidewalk", "inbound|regular|road", "outbound|regular|sidewalk", "outbound|regular|road", "inbound|red|sidewalk", "inbound|red|road", "outbound|red|sidewalk", "outbound|red|road"], - "scooter": ["inbound|regular", "inbound|green", "inbound|red", "outbound|regular", "outbound|green", "outbound|red"] + "scooter": ["inbound|regular", "inbound|green", "inbound|red", "outbound|regular", "outbound|green", "outbound|red"], + // road segments + "bus-lane": ["inbound|colored|typical", "outbound|colored|typical", "inbound|regular|typical", "outbound|regular|typical"], + "drive-lane": ["inbound|car","outbound|car", "inbound|truck","outbound|truck", "outbound|av", "inbound|av", "outbound|pedestrian", "inbound|pedestrian", "inbound|sharrow", "outbound|sharrow"], + "turn-lane": ["inbound|left", "inbound|right", "inbound|left-right-straight", "inbound|shared", "inbound|both", "inbound|left-straight", "inbound|right-straight", "inbound|straight", "outbound|left", "outbound|right", "outbound|left-right-straight", "outbound|shared", "outbound|both", "outbound|left-straight", "outbound|right-straight", "outbound|straight"], + "parking-lane": ["sideways|right", "sideways|left", "inbound|right", "inbound|left", "outbound|left", "outbound|right", "angled-front-left|left", "angled-front-right|left", "angled-rear-left|left", "angled-rear-right|left", "angled-front-left|right", "angled-front-right|right", "angled-rear-left|right", "angled-rear-right|right"], + "food-truck": ["left", "right"], + "flex-zone": ["taxi|inbound|right", "taxi|inbound|left", "taxi|outbound|right", "taxi|outbound|left", "rideshare|outbound|right", "rideshare|outbound|right", "rideshare|inbound|right", "rideshare|inbound|left"], + // rail vehicles + "streetcar": ["inbound|regular", "inbound|colored", "inbound|grass", "outbound|regular", "outbound|colored", "outbound|grass"], + "light-rail": ["inbound|regular", "inbound|colored", "inbound|grass", "outbound|regular", "outbound|colored", "outbound|grass"], + // stations + "brt-station": ["center"], + "transit-shelter": ["left|street-level", "right|street-level", "right|light-rail", "left|light-rail"], + // divider and temporary + "divider": ["buffer", "flowers", "planting-strip", "planter-box", "palm-tree", "big-tree", "bush", "dome", "bollard", "striped-buffer"], + "temporary": ["barricade", "traffic-cone", "jersey-barrier-plastic", "jersey-barrier-concrete"], + // magic segment + "magic-carpet": ["aladdin"] } \ No newline at end of file From a48ce3f6d47f8017a7ad218f2fc6fcb451820adc Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 15:26:18 -0300 Subject: [PATCH 02/23] add conversion-mapping data and functions --- src/streetplan/conversion-map.js | 198 +++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 src/streetplan/conversion-map.js diff --git a/src/streetplan/conversion-map.js b/src/streetplan/conversion-map.js new file mode 100644 index 000000000..774e3d95d --- /dev/null +++ b/src/streetplan/conversion-map.js @@ -0,0 +1,198 @@ +// conversion map StreetPan -> Streetmix +// sidewalk segment types mapping +/* +StreetPlanType1: + { + StreetPlanSubtype: StreetmixType, + --- or --- + StreetPlanSubtype: { + "tag": StreetPlanTag, + "type": StreetmixType, + "variantString": StreetmixVariantString, + "variantStringAdd": get parameter values from this list and generate variantString, + "nameToVariantMap": mapping rule StreetPlan O1-Name -> VariantString + "names": names (StreetPlan O1-Name) for this Streetmix Segment type + }, + --- or --- + // for one (O1-Tags) there can be different streetmix segment types, + // which are determined by the name (O1-Name) + StreetPlanSubtype: [ + different options of tags (O1-Tags) and streetMix data for each + ] + } +*/ +const mapping = { + "Walkways": { + "Trees": "sidewalk-tree", + "pedestrian": "sidewalk", + "Benchs": "sidewalk-bench", + "Tables": "outdoor-dining" + }, + "Furniture": { + "Trees": "sidewalk-tree", + "season_tree": "sidewalk-tree", + "Shelters": "transit-shelter", + "planter": {"type": "divider", "variantString": "planting-strip"}, + "Pedestrian": "sidewalk", + "Benchs": "sidewalk-bench", + "Tables": "outdoor-dining", + "BikeRacks": "sidewalk-bike-rack" + }, + "Curbside": { + "Lights": "sidewalk-lamp", + "Shelters": "transit-shelter", + "Poles": "utilities", + "Benchs": "sidewalk-bench", + "BikeRacks": "sidewalk-bike-rack" + }, + "BikesPaths": { + "Bikes": "bike-lane" + }, + "Gutter": { + "Gutter": "temporary" + }, + "Transit": { + "Transit": [ + { "tag": "Rail Vehicles", "type": "streetcar", "names": + ["StreetCar Yellow", "StreetCar Blue", "StreetCar Red 1", "StreetCar Red 2"], + "variantStringAdd": "direction" }, + { "tag": "Rail Vehicles", "type": "light-rail", "names": ["UTA LightRail"], "variantStringAdd": "direction" }, + // there are only reversed light rail vehicles in Streetplan + { "tag": "Rail Vehicles Reversed", "type": "light-rail", "variantStringAdd": "direction" }, + { "tag": "Bus Vehicles", "type": "bus-lane", "variantStringAdd": "direction" } + ] + }, + "Cars": { + "Autos": {"type": "drive-lane", "variantString": "car"}, + "Truck": {"type": "drive-lane", "variantString": "truck"} + }, + "Parking": { + "Parallel": + {"tag": "Parking - Parallel", "type": "parking-lane", "variantStringAdd": "direction|side"} + , + "AngleNormal": + {"tag": "Parking - Angle", "type": "parking-lane", "nameToVariantMap": { + "Away, L. Park, Head In": "angled-rear-left", + "Toward, R. Park, Head In": "angled-front-right", + "Toward, L. Park, Head In": "angled-front-left", + "Away, R. Park, Head In": "angled-rear-right" + }, + "variantStringAdd": "side" + } + }, + "Buffers": { + "Trees": {"type": "divider", "variantString": "big-tree"}, + "tree": {"type": "divider", "variantString": "palm-tree"}, + "season_tree": {"type": "divider", "variantString": "big-tree"}, + "median": {"type": "divider", "variantString": "planting-strip"}, + "Autos": {"type": "drive-lane", "variantString": "car"}, + "AngleNormal": {}, + "Purpendicular": {"type": "parking-lane", "variantString": "sideways", "variantStringAdd": "side"}, + "planter": {"type": "divider", "variantString": "planting-strip"} + } +} +// copy repeating rules +mapping["Buffers"]["AngleNormal"] = mapping["Parking"]["AngleNormal"]; +mapping["Median/Buffer"] = mapping["Buffers"]; + +const directionMap = { + "Coming": "inbound", + "Going": "outbound", + // make default outbound direction for both variant + "Both": "both", + "NA": "" +} + + +// StreetMix variantString often has additional parameters via |, for example: taxi|outbound|right +// generate a streetMix variantString from the listed parameters in variantStringAdd +function generateVariantString(variantStringKeys, streetmixData) { + + return streetmixData['variantString'] += variantStringKeys.split('|').reduce( + (wholeString, currKey) => wholeString += streetmixData[currKey] + , ''); +} + +function getDataFromSubtypeMap(convertRule, streetmixData, streetplanData) { + if (typeof convertRule === 'string') { + // convertRule is a Streetmix type. + // Later will add another options for this case + streetmixData['type'] = convertRule; + } else if (Array.isArray(convertRule)) { + // in this case, different segment subtype options + // are associated with the different Streetmix types + // find Streetmix segment data by Streetplan tag and names(?) + const variantData = convertRule.find((element) => { + const tagValMatches = element['tag'] === streetplanData['O1-Tags']; + if (tagValMatches && element['names']) { + return element['names'].includes(streetplanData['O1-Name']); + } + return tagValMatches; + }); + streetmixData['type'] = variantData['type']; + const variantStringKeys = variantData['variantStringAdd']; + if (variantStringKeys) { + streetmixData['variantString'] += generateVariantString(variantStringKeys, streetmixData); + } + } else if (typeof convertRule === 'object') { + // in this case, different variants of the segment subtype + // are associated with different variantString of the Streetmix segment + + streetmixData['type'] = convertRule['type']; + streetmixData['variantString'] = ''; + + const variantString = convertRule['variantString']; + if (variantString && typeof variantString === 'string') { + streetmixData['variantString'] = variantString; + } + + // get variantString from "O1-Name" (StreetPlan Object Name) -> variantString mapping data + const nameToVariantMap = convertRule['nameToVariantMap']; + if (nameToVariantMap && nameToVariantMap[streetplanData['O1-Name']]) { + streetmixData['variantString'] = nameToVariantMap[streetplanData['O1-Name']]; + } + + if (convertRule['variantStringAdd']) { + streetmixData['variantString'] += generateVariantString(convertRule['variantStringAdd'], streetmixData); + } + } + + return streetmixData; +} + +// convert streetPlan segment data to Streetmix segment data +function convertSegment(data) { + let streetmixData = {}; + // streetmix variantString + let variantString = ''; + const streetplanType = data['Type']; + const streetplanSubtype = data['Subtype']; + // mapping rule for current Streetplan subtypes + const subtypeMap = mapping[streetplanType]; + + // convert elevation value to Streetmix format: 0, 1, 2 + streetmixData['elevation'] = data["MaterialH"] / 0.5; + streetmixData['width'] = data['width']; + streetmixData['direction'] = directionMap[data['Direction']]; + if (data['side']) { + streetmixData['side'] = data['side']; + } + + if (subtypeMap) { + const convertRule = subtypeMap[streetplanSubtype]; + if (convertRule) { + streetmixData = getDataFromSubtypeMap(convertRule, streetmixData, data); + } else { + streetmixData['type'] = streetplanType; + //STREET.notify.warningMessage(`The '${streetplanSubtype}' subtype of StreetPlan segment '${segmentType}' is not yet supported in 3DStreet`); + console.log(`The '${streetplanSubtype}' subtype of StreetPlan segment '${streetplanType}' is not yet supported in 3DStreet`); + } + } else { + streetmixData['type'] = streetplanType; + //STREET.notify.warningMessage(`The '${streetplanType}' StreetPlan segment type is not yet supported in 3DStreet`); + console.log(`The '${streetplanType}' StreetPlan segment type is not yet supported in 3DStreet`); + } + return streetmixData; +} + +module.exports.convertSegment = convertSegment; From b06b5b3c071a19fa1cd9635b306ee125d0af2f51 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 15:26:53 -0300 Subject: [PATCH 03/23] add example streetplan response JSON for testing --- src/streetplan/exampleJSON.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/streetplan/exampleJSON.json diff --git a/src/streetplan/exampleJSON.json b/src/streetplan/exampleJSON.json new file mode 100644 index 000000000..5c4e43fb4 --- /dev/null +++ b/src/streetplan/exampleJSON.json @@ -0,0 +1 @@ +{"status":true,"project":{"My Street":{"Boulevard Alt 1":{"segments":{"1":{"Type":"Buildings","Subtype":"Commercial","SegPos":1,"width":30,"title":"Building Blue 4floors","side":"left","Direction":"NA","Material":"Building Blue 4floors","MaterialH":"0","Markings":"Standard Concrete","O1-Name":"Building Blue 4floors","O1-Tags":"4-Story,4-Story","O2-Name":"","O2-Tags":"","O3-Name":"","O3-Tags":""},"2":{"id":2478438,"Type":"setback","Subtype":"Paths","SegPos":2,"width":3,"title":"Empty place holder","side":"left","Direction":"NA","Material":"Asphalt Blue","MaterialH":"0.5","Markings":"Setback Small","O1-Name":"Empty place holder","O1-Tags":"Business Signs","O2-Name":"Empty place holder","O2-Tags":"Business Signs","O3-Name":"","O3-Tags":""},"3":{"id":2478439,"Type":"Walkways","Subtype":"pedestrian","SegPos":3,"width":6,"title":"3 people","side":"left","Direction":"Both","Material":"Pavers Tan","MaterialH":"0.5","Markings":"Blank","O1-Name":"3 people","O1-Tags":"Many People","O2-Name":"Empty place holder","O2-Tags":"Many People","O3-Name":"","O3-Tags":""},"4":{"id":2478440,"Type":"Furniture","Subtype":"season_tree","SegPos":4,"width":7,"title":"Japanese lilac","side":"left","Direction":"NA","Material":"Pavers Tan","MaterialH":"0.5","Markings":"Blank","O1-Name":"Japanese lilac","O1-Tags":"Trees, Summer","O2-Name":"Sideview","O2-Tags":"Bike Racks","O3-Name":"trashcan","O3-Tags":"Miscellaneous"},"5":{"id":2478441,"Type":"BikesPaths","Subtype":"Bikes","SegPos":5,"width":4.5,"title":"Casual Woman","side":"left","Direction":"Coming","Material":"Asphalt Blue","MaterialH":"0.5","Markings":"Painted BufferNone NoEdge","O1-Name":"Casual Woman","O1-Tags":"Miscellaneous","O2-Name":"Empty place holder","O2-Tags":"Parking - Reverse Angle","O3-Name":"","O3-Tags":""},"6":{"id":2478442,"Type":"Curbside","Subtype":"Lights","SegPos":6,"width":2,"title":"Streetlight solar banners 1","side":"left","Direction":"NA","Material":"Pavers Tan","MaterialH":"0.5","Markings":"Blank","O1-Name":"Streetlight solar banners 1","O1-Tags":"Historic Lights","O2-Name":"Sign directory","O2-Tags":"0 mph","O3-Name":"","O3-Tags":""},"7":{"id":2478443,"Type":"Gutter","Subtype":"Gutter","SegPos":7,"width":2.5,"title":"Gutter Std. 2.5 ft, Left","side":"left","Direction":"NA","Material":"Standard Concrete","MaterialH":"0.5","Markings":"Blank","O1-Name":"Gutter Std. 2.5 ft, Left","O1-Tags":"Gutters","O2-Name":"Empty place holder","O2-Tags":"Markings - Transit Options","O3-Name":"Empty place holder","O3-Tags":"Markings - Transit Options"},"8":{"id":2478444,"Type":"Transit","Subtype":"Transit","SegPos":8,"width":11,"title":"UTA bus","side":"left","Direction":"Coming","Material":"Asphalt Black","MaterialH":"0","Markings":"Thru Only","O1-Name":"UTA bus","O1-Tags":"Bus Vehicles","O2-Name":"Yellow Sedan","O2-Tags":"Miscellaneous","O3-Name":"","O3-Tags":""},"9":{"id":2478445,"Type":"Cars","Subtype":"Autos","SegPos":9,"width":10,"title":"Red Jeep","side":"left","Direction":"Coming","Material":"Asphalt Black","MaterialH":"0","Markings":"Thru Only","O1-Name":"Red Jeep","O1-Tags":"Miscellaneous","O2-Name":"","O2-Tags":"Miscellaneous","O3-Name":"","O3-Tags":""},"10":{"id":2478446,"Type":"Median\/Buffer","Subtype":"season_tree","SegPos":10,"width":14,"title":"Japanese Zelkova","side":"median","Direction":"median","Material":"Asphalt Black","MaterialH":"0","Markings":"Center Median","O1-Name":"Japanese Zelkova","O1-Tags":"Trees, Summer","O2-Name":"TallPlantBox (12ft)","O2-Tags":"Low-Water Xeriscape","O3-Name":"","O3-Tags":""},"11":{"id":2478447,"Type":"Cars","Subtype":"Truck","SegPos":11,"width":10,"title":"Blue Truck","side":"right","Direction":"Going","Material":"Asphalt Black","MaterialH":"0","Markings":"Thru Only","O1-Name":"Blue Truck","O1-Tags":"Miscellaneous","O2-Name":"","O2-Tags":"Low-Water Xeriscape","O3-Name":"","O3-Tags":""},"12":{"id":2478448,"Type":"Transit","Subtype":"Transit","SegPos":12,"width":11,"title":"UTA bus","side":"right","Direction":"Going","Material":"Asphalt Black","MaterialH":"0","Markings":"Thru Only","O1-Name":"UTA bus","O1-Tags":"Bus Vehicles","O2-Name":"White Sedan","O2-Tags":"Miscellaneous","O3-Name":"","O3-Tags":""},"13":{"id":2478449,"Type":"Gutter","Subtype":"Gutter","SegPos":13,"width":2.5,"title":"Gutter Std. 2.5 ft, Right","side":"right","Direction":"NA","Material":"Standard Concrete","MaterialH":"0.5","Markings":"Blank","O1-Name":"Gutter Std. 2.5 ft, Right","O1-Tags":"Gutters","O2-Name":"Empty place holder","O2-Tags":"Markings - Transit Options","O3-Name":"Empty place holder","O3-Tags":"Markings - Transit Options"},"14":{"id":2478450,"Type":"Curbside","Subtype":"Lights","SegPos":14,"width":2,"title":"Streetlight solar banners 1","side":"right","Direction":"NA","Material":"Pavers Tan","MaterialH":"0.5","Markings":"Blank","O1-Name":"Streetlight solar banners 1","O1-Tags":"Historic Lights","O2-Name":"Empty place holder","O2-Tags":"30 mph","O3-Name":"","O3-Tags":""},"15":{"id":2478451,"Type":"BikesPaths","Subtype":"Bikes","SegPos":15,"width":4.5,"title":"Man Go","side":"right","Direction":"Going","Material":"Asphalt Blue","MaterialH":"0.5","Markings":"Painted BufferNone NoEdge","O1-Name":"Man Go","O1-Tags":"Miscellaneous","O2-Name":"","O2-Tags":"Markings - Transit Options","O3-Name":"","O3-Tags":""},"16":{"id":2478452,"Type":"Furniture","Subtype":"season_tree","SegPos":16,"width":7,"title":"Japanese lilac","side":"right","Direction":"NA","Material":"Pavers Tan","MaterialH":"0.5","Markings":"Blank","O1-Name":"Japanese lilac","O1-Tags":"Trees, Summer","O2-Name":"Table","O2-Tags":"Miscellaneous","O3-Name":"Empty place holder","O3-Tags":"Trees, Fall"},"17":{"id":2478453,"Type":"Walkways","Subtype":"pedestrian","SegPos":17,"width":6,"title":"2 people","side":"right","Direction":"Both","Material":"Pavers Tan","MaterialH":"0.5","Markings":"Blank","O1-Name":"2 people","O1-Tags":"Pedestrians","O2-Name":"Empty place holder","O2-Tags":"Many People","O3-Name":"","O3-Tags":""},"18":{"id":2478454,"Type":"setback","Subtype":"Paths","SegPos":18,"width":3,"title":"Empty place holder","side":"right","Direction":"NA","Material":"Asphalt Blue","MaterialH":"0.5","Markings":"Setback Small","O1-Name":"Empty place holder","O1-Tags":"Business Signs","O2-Name":"Empty place holder","O2-Tags":"Business Signs","O3-Name":"","O3-Tags":""},"19":{"Type":"Buildings","Subtype":"Commercial","SegPos":19,"width":30,"title":"Building Yellow 4floors","side":"right","Direction":"NA","Material":"Building Yellow 4floors","MaterialH":"0","Markings":"Standard Concrete","O1-Name":"Building Yellow 4floors","O1-Tags":"4-Story,4-Story","O2-Name":"","O2-Tags":"","O3-Name":"","O3-Tags":""}}}}}} \ No newline at end of file From 7d59ef5d8b115f5dc6cef2ebebd12911dd190a0b Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 15:48:31 -0300 Subject: [PATCH 04/23] change segments-variants format to add comments --- src/aframe-streetmix-parsers.js | 4 ++-- src/segments-variants.js | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/segments-variants.js diff --git a/src/aframe-streetmix-parsers.js b/src/aframe-streetmix-parsers.js index 894ac4752..94f2cab1a 100644 --- a/src/aframe-streetmix-parsers.js +++ b/src/aframe-streetmix-parsers.js @@ -3,7 +3,7 @@ // Orientation - default model orientation is "outbound" (away from camera) var streetmixParsersTested = require('./tested/aframe-streetmix-parsers-tested'); var streetmixUtils = require('./tested/streetmix-utils'); -var segmentsVariants = require('./segments-variants.json'); +var { segmentVariants } = require('./segments-variants.js'); function cloneMixinAsChildren ({ objectMixinId = '', parentEl = null, step = 15, radius = 60, rotation = '0 0 0', positionXYString = '0 0', length = undefined, randomY = false }) { for (let j = (radius * -1); j <= radius; j = j + step) { @@ -757,7 +757,7 @@ function createSeparatorElement (positionY, rotationY, mixinId, length, repeatCo function supportCheck (segmentType, segmentVariantString) { if (segmentType == 'separator') return; // variants supported in 3DStreet - const supportedVariants = segmentsVariants[segmentType]; + const supportedVariants = segmentVariants[segmentType]; if (!supportedVariants) { STREET.notify.warningMessage(`The '${segmentType}' segment type is not yet supported in 3DStreet`); console.log(`The '${segmentType}' segment type is not yet supported in 3DStreet`); diff --git a/src/segments-variants.js b/src/segments-variants.js new file mode 100644 index 000000000..46b743456 --- /dev/null +++ b/src/segments-variants.js @@ -0,0 +1,38 @@ +const segmentVariants = { + /* sidewalk segments */ + "sidewalk": ["empty", "sparse", "normal", "dense"], + "sidewalk-wayfinding": ["large"], + "sidewalk-bench": ["left", "right", "center"], + "sidewalk-bike-rack":["left|sidewalk-parallel", "right|sidewalk-parallel", "left|sidewalk", "right|sidewalk"], + "sidewalk-tree": ["big", "palm-tree"], + /* lights and utilities */ + "utilities": ["left", "right"], + "sidewalk-lamp": ["right|modern","both|modern", "left|modern", "right|traditional", "both|traditional", "left|traditional", "right|pride", "both|pride", "left|pride"], + // furniture segments + "parklet": ["left", "right"], + "outdoor-dining": ["empty|sidewalk", "empty|road"], + "bikeshare": ["left|road", "right|road", "left|sidewalk", "right|sidewalk"], + // bike and scooter segments + "bike-lane": ["inbound|green|sidewalk", "inbound|green|road", "outbound|green|sidewalk", "outbound|green|road", "inbound|regular|sidewalk", "inbound|regular|road", "outbound|regular|sidewalk", "outbound|regular|road", "inbound|red|sidewalk", "inbound|red|road", "outbound|red|sidewalk", "outbound|red|road"], + "scooter": ["inbound|regular", "inbound|green", "inbound|red", "outbound|regular", "outbound|green", "outbound|red"], + // road segments + "bus-lane": ["inbound|colored|typical", "outbound|colored|typical", "inbound|regular|typical", "outbound|regular|typical"], + "drive-lane": ["inbound|car","outbound|car", "inbound|truck","outbound|truck", "outbound|av", "inbound|av", "outbound|pedestrian", "inbound|pedestrian", "inbound|sharrow", "outbound|sharrow"], + "turn-lane": ["inbound|left", "inbound|right", "inbound|left-right-straight", "inbound|shared", "inbound|both", "inbound|left-straight", "inbound|right-straight", "inbound|straight", "outbound|left", "outbound|right", "outbound|left-right-straight", "outbound|shared", "outbound|both", "outbound|left-straight", "outbound|right-straight", "outbound|straight"], + "parking-lane": ["sideways|right", "sideways|left", "inbound|right", "inbound|left", "outbound|left", "outbound|right", "angled-front-left|left", "angled-front-right|left", "angled-rear-left|left", "angled-rear-right|left", "angled-front-left|right", "angled-front-right|right", "angled-rear-left|right", "angled-rear-right|right"], + "food-truck": ["left", "right"], + "flex-zone": ["taxi|inbound|right", "taxi|inbound|left", "taxi|outbound|right", "taxi|outbound|left", "rideshare|outbound|right", "rideshare|outbound|right", "rideshare|inbound|right", "rideshare|inbound|left"], + // rail vehicles + "streetcar": ["inbound|regular", "inbound|colored", "inbound|grass", "outbound|regular", "outbound|colored", "outbound|grass"], + "light-rail": ["inbound|regular", "inbound|colored", "inbound|grass", "outbound|regular", "outbound|colored", "outbound|grass"], + // stations + "brt-station": ["center"], + "transit-shelter": ["left|street-level", "right|street-level", "right|light-rail", "left|light-rail"], + // divider and temporary + "divider": ["buffer", "flowers", "planting-strip", "planter-box", "palm-tree", "big-tree", "bush", "dome", "bollard", "striped-buffer"], + "temporary": ["barricade", "traffic-cone", "jersey-barrier-plastic", "jersey-barrier-concrete"], + // magic segment + "magic-carpet": ["aladdin"] +} + +module.exports.segmentVariants = segmentVariants; \ No newline at end of file From c52649b1862766d47f9a9d1cc307968806893e09 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 15:52:32 -0300 Subject: [PATCH 05/23] add streetplan-loader component utils add streetplan utils --- src/components/streetplan-loader.js | 95 +++++++++++++++++++++++++++++ src/index.js | 1 + src/streetplan/streetplan-utils.js | 34 +++++++++++ 3 files changed, 130 insertions(+) create mode 100644 src/components/streetplan-loader.js create mode 100644 src/streetplan/streetplan-utils.js diff --git a/src/components/streetplan-loader.js b/src/components/streetplan-loader.js new file mode 100644 index 000000000..7ff7af51d --- /dev/null +++ b/src/components/streetplan-loader.js @@ -0,0 +1,95 @@ +/* global AFRAME, THREE, XMLHttpRequest */ +var streetplanUtils = require('../streetplan/streetplan-utils.js'); +var exampleJSON = require('../streetplan/exampleJSON.json'); + +AFRAME.registerComponent('streetplan-loader', { + dependencies: ['street'], + schema: { + streetplanStreetURL: { type: 'string' }, + streetplanAPIURL: { type: 'string' }, + streetplanEncJSON: { type: 'string' }, + showBuildings: { default: true }, + name: { default: '' } + }, + streetplanResponseParse: function (streetplanResponseObject) { + const el = this.el; + const data = this.data; + const streetplanProject = streetplanResponseObject.project; + + // convert Streetplan structure to Streetmix-like structure + const streetData = streetplanUtils.convertStreetStruct(streetplanProject); + + const streetplanSegments = streetData.segments; + + const streetplanName = streetData.name; + // streetplan alternative name + const streetplanAltName = streetData.altName; + + console.log('streetplanName', streetplanName); + //el.setAttribute('streetplan-loader', 'name', streetplanName); + + let currentSceneTitle; + const sceneEl = this.el.sceneEl; + if (sceneEl && sceneEl.getAttribute('metadata')) { + currentSceneTitle = sceneEl.getAttribute('metadata').sceneTitle; + } + if (!currentSceneTitle) { // only set title from streetplan if none exists + sceneEl.setAttribute('metadata', 'sceneTitle', streetplanName); + console.log('therefore setting metadata sceneTitle as streetplanName', streetplanName); + } + + el.setAttribute('data-layer-name', 'Streetplan • ' + streetplanName); + + if (data.showBuildings) { + el.setAttribute('street', 'right', streetData.rightBuildingVariant); + el.setAttribute('street', 'left', streetData.leftBuildingVariant); + } + el.setAttribute('street', 'type', 'streetmixSegmentsMetric'); + // set JSON attribute last or it messes things up + el.setAttribute('street', 'JSON', JSON.stringify({ streetmixSegmentsMetric: streetplanSegments })); + el.emit('streetplan-loader-street-loaded'); + }, + update: function (oldData) { // fired at start and at each subsequent change of any schema value + // This method may fire a few times when viewing a streetmix street in 3dstreet: + // First to find the proper path, once to actually load the street, and then subsequent updates such as street name + const data = this.data; + const el = this.el; + + /* ***** debugging ***** */ + this.streetplanResponseParse(exampleJSON); + return; + + // load from URL encoded Streetplan JSON + if (data.streetplanEncJSON) { + const streetplanJSON = decodeURIComponent(encodedString); + this.streetplanResponseParse(JSON.parse(streetplanJSON)); + return; + } + + // if the loader has run once already, and upon update neither URL has changed, do not take action + if ((oldData.streetplanStreetURL === data.streetplanStreetURL) && (oldData.streetplanAPIURL === data.streetplanAPIURL)) { + // console.log('[streetmix-loader]', 'Neither streetplanStreetURL nor streetplanAPIURL have changed in this component data update, not reloading street.') + return; + } + + var request = new XMLHttpRequest(); + console.log('[streetplan-loader]', 'GET ' + data.streetplanAPIURL); + + request.open('GET', data.streetplanAPIURL, true); + request.onload = function () { + if (this.status >= 200 && this.status < 400) { + // Connection success + const streetplanResponseObject = JSON.parse(this.response); + this.streetplanResponseParse(streetplanResponseObject); + } else { + // We reached our target server, but it returned an error + console.log('[streetplan-loader]', 'Loading Error: We reached the target server, but it returned an error'); + } + }; + request.onerror = function () { + // There was a connection error of some sort + console.log('[streetplan-loader]', 'Loading Error: There was a connection error of some sort'); + }; + request.send(); + } +}); diff --git a/src/index.js b/src/index.js index e89b54ee6..d9982088e 100644 --- a/src/index.js +++ b/src/index.js @@ -11,6 +11,7 @@ require('./lib/aframe-cursor-teleport-component.min.js'); require('./lib/animation-mixer.js'); require('./assets.js'); require('./components/notify.js'); +require('./components/streetplan-loader'); require('./components/create-from-json'); require('./components/screentock.js'); require('aframe-atlas-uvs-component'); diff --git a/src/streetplan/streetplan-utils.js b/src/streetplan/streetplan-utils.js new file mode 100644 index 000000000..5b48a1342 --- /dev/null +++ b/src/streetplan/streetplan-utils.js @@ -0,0 +1,34 @@ +// utils for StreetPlan parsing +mappingUtils = require('./conversion-map.js'); + +// convert width from feet to meters +function convertStreetValues (streetData) { + streetData.segments.forEach((segmentData) => { + segmentData.width *= 0.3048; + }); +} + +// convert street structure to look like Streetmix JSON Schema +function convertStreetStruct (streetProject) { + const newStruct = {}; + const streetplanName = Object.keys(streetProject)[0]; + // streetplan alternative name + const streetplanAltName = Object.keys(streetProject[streetplanName])[0]; + newStruct.name = streetplanName; + newStruct.altName = streetplanAltName; + + // remove segment indexes + newStruct.segments = Object.values(streetProject[streetplanName][streetplanAltName].segments); + + convertStreetValues(newStruct); + convertSegmentData(newStruct.segments); + console.log("TEST. Converted JSON structure: ", newStruct) + + return newStruct; +} + +module.exports.convertStreetStruct = convertStreetStruct; + +function convertSegmentData (segments) { + segments.forEach(mappingUtils.convertSegment); +} From 754fd3c2694ca92e85bac635f362fbabb3405a10 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 15:53:01 -0300 Subject: [PATCH 06/23] remove old segments-variants.json --- src/segments-variants.json | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 src/segments-variants.json diff --git a/src/segments-variants.json b/src/segments-variants.json deleted file mode 100644 index ba84d6e8f..000000000 --- a/src/segments-variants.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - // sidewalk segments - "sidewalk": ["empty", "sparse", "normal", "dense"], - "sidewalk-wayfinding": ["large"], - "sidewalk-bench": ["left", "right", "center"], - "sidewalk-bike-rack":["left|sidewalk-parallel", "right|sidewalk-parallel", "left|sidewalk", "right|sidewalk"], - "sidewalk-tree": ["big", "palm-tree"], - // lights and utilities - "utilities": ["left", "right"], - "sidewalk-lamp": ["right|modern","both|modern", "left|modern", "right|traditional", "both|traditional", "left|traditional", "right|pride", "both|pride", "left|pride"], - // furniture segments - "parklet": ["left", "right"], - "outdoor-dining": ["empty|sidewalk", "empty|road"], - "bikeshare": ["left|road", "right|road", "left|sidewalk", "right|sidewalk"], - // bike and scooter segments - "bike-lane": ["inbound|green|sidewalk", "inbound|green|road", "outbound|green|sidewalk", "outbound|green|road", "inbound|regular|sidewalk", "inbound|regular|road", "outbound|regular|sidewalk", "outbound|regular|road", "inbound|red|sidewalk", "inbound|red|road", "outbound|red|sidewalk", "outbound|red|road"], - "scooter": ["inbound|regular", "inbound|green", "inbound|red", "outbound|regular", "outbound|green", "outbound|red"], - // road segments - "bus-lane": ["inbound|colored|typical", "outbound|colored|typical", "inbound|regular|typical", "outbound|regular|typical"], - "drive-lane": ["inbound|car","outbound|car", "inbound|truck","outbound|truck", "outbound|av", "inbound|av", "outbound|pedestrian", "inbound|pedestrian", "inbound|sharrow", "outbound|sharrow"], - "turn-lane": ["inbound|left", "inbound|right", "inbound|left-right-straight", "inbound|shared", "inbound|both", "inbound|left-straight", "inbound|right-straight", "inbound|straight", "outbound|left", "outbound|right", "outbound|left-right-straight", "outbound|shared", "outbound|both", "outbound|left-straight", "outbound|right-straight", "outbound|straight"], - "parking-lane": ["sideways|right", "sideways|left", "inbound|right", "inbound|left", "outbound|left", "outbound|right", "angled-front-left|left", "angled-front-right|left", "angled-rear-left|left", "angled-rear-right|left", "angled-front-left|right", "angled-front-right|right", "angled-rear-left|right", "angled-rear-right|right"], - "food-truck": ["left", "right"], - "flex-zone": ["taxi|inbound|right", "taxi|inbound|left", "taxi|outbound|right", "taxi|outbound|left", "rideshare|outbound|right", "rideshare|outbound|right", "rideshare|inbound|right", "rideshare|inbound|left"], - // rail vehicles - "streetcar": ["inbound|regular", "inbound|colored", "inbound|grass", "outbound|regular", "outbound|colored", "outbound|grass"], - "light-rail": ["inbound|regular", "inbound|colored", "inbound|grass", "outbound|regular", "outbound|colored", "outbound|grass"], - // stations - "brt-station": ["center"], - "transit-shelter": ["left|street-level", "right|street-level", "right|light-rail", "left|light-rail"], - // divider and temporary - "divider": ["buffer", "flowers", "planting-strip", "planter-box", "palm-tree", "big-tree", "bush", "dome", "bollard", "striped-buffer"], - "temporary": ["barricade", "traffic-cone", "jersey-barrier-plastic", "jersey-barrier-concrete"], - // magic segment - "magic-carpet": ["aladdin"] -} \ No newline at end of file From e69665d71fa3f71d70a100ba8b604284184c6e1b Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 15:53:19 -0300 Subject: [PATCH 07/23] add streetplan example scene --- streetplan.html | 147 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 streetplan.html diff --git a/streetplan.html b/streetplan.html new file mode 100644 index 000000000..635e5d151 --- /dev/null +++ b/streetplan.html @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + 3DStreet + + + + + + + +
+
+
+ entities +
+
+
+ car + bus + bike +
+
+
Loading 3DStreet
+
+
+ + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 420fa32e0c8d2efd05324b59b32a41e171d74519 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 15:53:54 -0300 Subject: [PATCH 08/23] add loading from url encoded streetplan json --- src/json-utils_1.1.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/json-utils_1.1.js b/src/json-utils_1.1.js index f4af4e3dd..45fcafb2a 100644 --- a/src/json-utils_1.1.js +++ b/src/json-utils_1.1.js @@ -536,6 +536,18 @@ AFRAME.registerComponent('set-loader-from-hash', { 'streetmixStreetURL', streetURL ); + } else if (streetURL.startsWith('streetplanJSON:')) { + // load from Streetplan encoded JSON in URL + console.log( + '[set-loader-from-hash]', + 'Set streetplan-loader streetplanEncJSON to', + streetURL + ); + this.el.setAttribute( + 'streetplan-loader', + 'streetplanEncJSON', + streetURL + ); } else { // try to load JSON file from remote resource console.log( From 794b58af1ce0852aea44128cd1f2c6c1d02af0a4 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 18:19:38 -0300 Subject: [PATCH 09/23] add new blue segment-color --- src/aframe-streetmix-parsers.js | 6 ++++++ src/assets.js | 1 + 2 files changed, 7 insertions(+) diff --git a/src/aframe-streetmix-parsers.js b/src/aframe-streetmix-parsers.js index 94f2cab1a..b0a1ce7b9 100644 --- a/src/aframe-streetmix-parsers.js +++ b/src/aframe-streetmix-parsers.js @@ -236,6 +236,9 @@ function getBikeLaneMixin (variant) { if (variant === 'red') { return 'surface-red bike-lane'; } + if (variant === 'blue') { + return 'surface-blue bike-lane'; + } if (variant === 'green') { return 'surface-green bike-lane'; } @@ -246,6 +249,9 @@ function getBusLaneMixin (variant) { if (variant === 'colored' | variant === 'red') { return 'surface-red bus-lane'; } + if (variant === 'blue') { + return 'surface-blue bus-lane'; + } if (variant === 'grass') { return 'surface-green bus-lane'; } diff --git a/src/assets.js b/src/assets.js index 4d5a6d534..90e998325 100644 --- a/src/assets.js +++ b/src/assets.js @@ -142,6 +142,7 @@ function buildAssetHTML (assetUrl, categories) { + `, 'lane-separator': ` From 6cb35574ad598a846351f13ca6961a64647dce61 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 19:03:40 -0300 Subject: [PATCH 10/23] add timeout to load libraries first - notify for example --- src/components/streetplan-loader.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/streetplan-loader.js b/src/components/streetplan-loader.js index 7ff7af51d..13dad3d37 100644 --- a/src/components/streetplan-loader.js +++ b/src/components/streetplan-loader.js @@ -56,7 +56,10 @@ AFRAME.registerComponent('streetplan-loader', { const el = this.el; /* ***** debugging ***** */ - this.streetplanResponseParse(exampleJSON); + setTimeout(()=> { + this.streetplanResponseParse(exampleJSON); + }, 1000); + return; // load from URL encoded Streetplan JSON From 9e47dc29fda122f9690ee2b1a9548b2177019a1c Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 19:04:23 -0300 Subject: [PATCH 11/23] load streetplan-loader component last --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index d9982088e..a0b3fc41a 100644 --- a/src/index.js +++ b/src/index.js @@ -11,10 +11,10 @@ require('./lib/aframe-cursor-teleport-component.min.js'); require('./lib/animation-mixer.js'); require('./assets.js'); require('./components/notify.js'); -require('./components/streetplan-loader'); require('./components/create-from-json'); require('./components/screentock.js'); require('aframe-atlas-uvs-component'); +require('./components/streetplan-loader'); AFRAME.registerComponent('street', { schema: { From 2b89a77078d714a09488e5cc6244fea9fb0c42de Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 19:12:02 -0300 Subject: [PATCH 12/23] update convertion-map add variantString to all types and subtypes add tagToVariantString JSON mapping option support fix generating VariantString from keys ad basic materials mapping --- src/streetplan/conversion-map.js | 103 +++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 33 deletions(-) diff --git a/src/streetplan/conversion-map.js b/src/streetplan/conversion-map.js index 774e3d95d..72f39af1c 100644 --- a/src/streetplan/conversion-map.js +++ b/src/streetplan/conversion-map.js @@ -10,7 +10,8 @@ StreetPlanType1: "type": StreetmixType, "variantString": StreetmixVariantString, "variantStringAdd": get parameter values from this list and generate variantString, - "nameToVariantMap": mapping rule StreetPlan O1-Name -> VariantString + "nameToVariantMap": mapping rule StreetPlan O1-Name -> VariantString, + "tagToVariantMap": mapping rule StreetPlan O1-Tags -> VariantString, "names": names (StreetPlan O1-Name) for this Streetmix Segment type }, --- or --- @@ -23,33 +24,37 @@ StreetPlanType1: */ const mapping = { "Walkways": { - "Trees": "sidewalk-tree", - "pedestrian": "sidewalk", - "Benchs": "sidewalk-bench", - "Tables": "outdoor-dining" + "Trees": {"type": "sidewalk-tree", "variantString": "big"}, + "pedestrian": {"type": "sidewalk", "variantString": "dense"}, + "Benchs": {"type": "sidewalk-bench", "variantStringAdd": "side" }, + "Tables": {"type": "outdoor-dining", "variantString": "occupied|sidewalk"} }, "Furniture": { - "Trees": "sidewalk-tree", - "season_tree": "sidewalk-tree", - "Shelters": "transit-shelter", + "Trees": {"type": "sidewalk-tree", "variantString": "big"}, + "season_tree": {"type": "sidewalk-tree", "variantString": "big"}, + "Shelters": { "type": "transit-shelter", "variantString": "street-level", "variantStringAdd": "side|variantString" }, "planter": {"type": "divider", "variantString": "planting-strip"}, - "Pedestrian": "sidewalk", - "Benchs": "sidewalk-bench", - "Tables": "outdoor-dining", - "BikeRacks": "sidewalk-bike-rack" + "Pedestrian": {"type": "sidewalk", "variantString": "dense"}, + "Benchs": {"type": "sidewalk-bench", "variantStringAdd": "side" }, + "Tables": {"type": "outdoor-dining", "variantString": "occupied|sidewalk"}, + "BikeRacks": {"type": "sidewalk-bike-rack", "variantString": "sidewalk-parallel", "variantStringAdd": "side|variantString" }, }, "Curbside": { - "Lights": "sidewalk-lamp", - "Shelters": "transit-shelter", - "Poles": "utilities", - "Benchs": "sidewalk-bench", - "BikeRacks": "sidewalk-bike-rack" + "Lights": {"type": "sidewalk-lamp", "tagToVariantMap": { + "Historic Lights": "traditional", + "Regular Lights": "modern" + }, "variantStringAdd": "side|variantString" + }, + "Shelters": { "type": "transit-shelter", "variantString": "street-level", "variantStringAdd": "side|variantString" }, + "Poles": { "type": "utilities", "variantStringAdd": "side" }, + "Benchs": {"type": "sidewalk-bench", "variantStringAdd": "side" }, + "BikeRacks": {"type": "sidewalk-bike-rack", "variantString": "sidewalk-parallel", "variantStringAdd": "side|variantString" }, }, "BikesPaths": { - "Bikes": "bike-lane" + "Bikes": {"type": "bike-lane", "variantString": "sidewalk", "variantStringAdd": "direction|material|variantString"} }, "Gutter": { - "Gutter": "temporary" + "Gutter": {"type":"divider","variantString":"median"} }, "Transit": { "Transit": [ @@ -59,12 +64,12 @@ const mapping = { { "tag": "Rail Vehicles", "type": "light-rail", "names": ["UTA LightRail"], "variantStringAdd": "direction" }, // there are only reversed light rail vehicles in Streetplan { "tag": "Rail Vehicles Reversed", "type": "light-rail", "variantStringAdd": "direction" }, - { "tag": "Bus Vehicles", "type": "bus-lane", "variantStringAdd": "direction" } + { "tag": "Bus Vehicles", "type": "bus-lane", "variantString": "typical", "variantStringAdd": "direction|material|variantString" } ] }, "Cars": { - "Autos": {"type": "drive-lane", "variantString": "car"}, - "Truck": {"type": "drive-lane", "variantString": "truck"} + "Autos": {"type": "drive-lane", "variantString": "car", "variantStringAdd": "direction|variantString"}, + "Truck": {"type": "drive-lane", "variantString": "truck", "variantStringAdd": "direction|variantString"} }, "Parking": { "Parallel": @@ -85,7 +90,7 @@ const mapping = { "tree": {"type": "divider", "variantString": "palm-tree"}, "season_tree": {"type": "divider", "variantString": "big-tree"}, "median": {"type": "divider", "variantString": "planting-strip"}, - "Autos": {"type": "drive-lane", "variantString": "car"}, + "Autos": {}, "AngleNormal": {}, "Purpendicular": {"type": "parking-lane", "variantString": "sideways", "variantStringAdd": "side"}, "planter": {"type": "divider", "variantString": "planting-strip"} @@ -93,6 +98,7 @@ const mapping = { } // copy repeating rules mapping["Buffers"]["AngleNormal"] = mapping["Parking"]["AngleNormal"]; +mapping["Buffers"]["Autos"] = mapping["Cars"]["Autos"]; mapping["Median/Buffer"] = mapping["Buffers"]; const directionMap = { @@ -103,14 +109,24 @@ const directionMap = { "NA": "" } +const materialMap = { + "Asphalt Black": "regular", + "Asphalt Blue": "blue", + "Asphalt Red 1": "red", + "Asphalt Red 2": "red", + "Asphalt Green": "green", + "Asphalt Old": "regular", + "Grass": "grass", + "Grass Dead": "grass" +} // StreetMix variantString often has additional parameters via |, for example: taxi|outbound|right -// generate a streetMix variantString from the listed parameters in variantStringAdd +// generate a streetMix like variantString from the listed parameters in variantStringAdd function generateVariantString(variantStringKeys, streetmixData) { - - return streetmixData['variantString'] += variantStringKeys.split('|').reduce( - (wholeString, currKey) => wholeString += streetmixData[currKey] - , ''); + const variantString = variantStringKeys.split('|') + .map((currKey) => streetmixData[currKey]) + .join('|'); + return variantString; } function getDataFromSubtypeMap(convertRule, streetmixData, streetplanData) { @@ -121,7 +137,8 @@ function getDataFromSubtypeMap(convertRule, streetmixData, streetplanData) { } else if (Array.isArray(convertRule)) { // in this case, different segment subtype options // are associated with the different Streetmix types - // find Streetmix segment data by Streetplan tag and names(?) + + // find the desired Streetmix segment data from the array by Streetplan tag and names(?) const variantData = convertRule.find((element) => { const tagValMatches = element['tag'] === streetplanData['O1-Tags']; if (tagValMatches && element['names']) { @@ -129,10 +146,19 @@ function getDataFromSubtypeMap(convertRule, streetmixData, streetplanData) { } return tagValMatches; }); + + streetmixData['variantString'] = ''; + + const variantString = variantData['variantString']; + if (variantString && typeof variantString === 'string') { + streetmixData['variantString'] = variantString; + } + + // generate a streetMix like variantString from the listed parameter values streetmixData['type'] = variantData['type']; const variantStringKeys = variantData['variantStringAdd']; if (variantStringKeys) { - streetmixData['variantString'] += generateVariantString(variantStringKeys, streetmixData); + streetmixData['variantString'] = generateVariantString(variantStringKeys, streetmixData); } } else if (typeof convertRule === 'object') { // in this case, different variants of the segment subtype @@ -146,14 +172,22 @@ function getDataFromSubtypeMap(convertRule, streetmixData, streetplanData) { streetmixData['variantString'] = variantString; } - // get variantString from "O1-Name" (StreetPlan Object Name) -> variantString mapping data + // get variantString from {"O1-Name" (StreetPlan Object Name) : variantString} mapping data const nameToVariantMap = convertRule['nameToVariantMap']; if (nameToVariantMap && nameToVariantMap[streetplanData['O1-Name']]) { streetmixData['variantString'] = nameToVariantMap[streetplanData['O1-Name']]; } - if (convertRule['variantStringAdd']) { - streetmixData['variantString'] += generateVariantString(convertRule['variantStringAdd'], streetmixData); + // get variantString from {"O1-Tags" (StreetPlan Tag) : variantString} mapping data + const tagToVariantMap = convertRule['tagToVariantMap']; + if (tagToVariantMap && tagToVariantMap[streetplanData['O1-Tags']]) { + streetmixData['variantString'] = tagToVariantMap[streetplanData['O1-Tags']]; + } + + // generate a streetMix like variantString from the listed parameter values + const variantStringKeys = convertRule['variantStringAdd']; + if (variantStringKeys) { + streetmixData['variantString'] = generateVariantString(variantStringKeys, streetmixData); } } @@ -177,6 +211,9 @@ function convertSegment(data) { if (data['side']) { streetmixData['side'] = data['side']; } + if (data['Material']) { + streetmixData['material'] = materialMap[data['Material']]; + } if (subtypeMap) { const convertRule = subtypeMap[streetplanSubtype]; From f603f97866c94b11b757cb1a77dccba9e40d0957 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 19:14:00 -0300 Subject: [PATCH 13/23] add segments filter. Remove Buildings and setback types fix errors --- src/streetplan/streetplan-utils.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/streetplan/streetplan-utils.js b/src/streetplan/streetplan-utils.js index 5b48a1342..c384aa565 100644 --- a/src/streetplan/streetplan-utils.js +++ b/src/streetplan/streetplan-utils.js @@ -21,7 +21,13 @@ function convertStreetStruct (streetProject) { newStruct.segments = Object.values(streetProject[streetplanName][streetplanAltName].segments); convertStreetValues(newStruct); - convertSegmentData(newStruct.segments); + + // remove buildings and setback for now. To add them in another place + newStruct.segments = convertSegmentData(newStruct.segments) + .filter((segmentData) => { + return !["Buildings", "setback"].includes(segmentData['type']) + }); + console.log("TEST. Converted JSON structure: ", newStruct) return newStruct; @@ -30,5 +36,5 @@ function convertStreetStruct (streetProject) { module.exports.convertStreetStruct = convertStreetStruct; function convertSegmentData (segments) { - segments.forEach(mappingUtils.convertSegment); + return segments.map(mappingUtils.convertSegment); } From 7868d77d44fa2e55596d95108b6ed6474fd8ea11 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 19:53:19 -0300 Subject: [PATCH 14/23] add empty suptypes to all types --- src/streetplan/conversion-map.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/streetplan/conversion-map.js b/src/streetplan/conversion-map.js index 72f39af1c..bc455a2ea 100644 --- a/src/streetplan/conversion-map.js +++ b/src/streetplan/conversion-map.js @@ -24,12 +24,14 @@ StreetPlanType1: */ const mapping = { "Walkways": { + "": {"type": "sidewalk", "variantString": "empty"}, "Trees": {"type": "sidewalk-tree", "variantString": "big"}, "pedestrian": {"type": "sidewalk", "variantString": "dense"}, "Benchs": {"type": "sidewalk-bench", "variantStringAdd": "side" }, "Tables": {"type": "outdoor-dining", "variantString": "occupied|sidewalk"} }, "Furniture": { + "": {"type": "sidewalk", "variantString": "empty"}, "Trees": {"type": "sidewalk-tree", "variantString": "big"}, "season_tree": {"type": "sidewalk-tree", "variantString": "big"}, "Shelters": { "type": "transit-shelter", "variantString": "street-level", "variantStringAdd": "side|variantString" }, @@ -40,6 +42,7 @@ const mapping = { "BikeRacks": {"type": "sidewalk-bike-rack", "variantString": "sidewalk-parallel", "variantStringAdd": "side|variantString" }, }, "Curbside": { + "": {"type": "sidewalk", "variantString": "empty"}, "Lights": {"type": "sidewalk-lamp", "tagToVariantMap": { "Historic Lights": "traditional", "Regular Lights": "modern" @@ -51,27 +54,32 @@ const mapping = { "BikeRacks": {"type": "sidewalk-bike-rack", "variantString": "sidewalk-parallel", "variantStringAdd": "side|variantString" }, }, "BikesPaths": { + "": {"type": "bike-lane", "variantString": "sidewalk"}, "Bikes": {"type": "bike-lane", "variantString": "sidewalk", "variantStringAdd": "direction|material|variantString"} }, "Gutter": { + "": {"type":"divider","variantString":"median"}, "Gutter": {"type":"divider","variantString":"median"} }, "Transit": { + "": { "tag": "Bus Vehicles", "type": "bus-lane", "variantString": "typical", "variantStringAdd": "direction|material|variantString" }, "Transit": [ { "tag": "Rail Vehicles", "type": "streetcar", "names": ["StreetCar Yellow", "StreetCar Blue", "StreetCar Red 1", "StreetCar Red 2"], - "variantStringAdd": "direction" }, - { "tag": "Rail Vehicles", "type": "light-rail", "names": ["UTA LightRail"], "variantStringAdd": "direction" }, + "variantStringAdd": "direction|material" }, + { "tag": "Rail Vehicles", "type": "light-rail", "names": ["UTA LightRail"], "variantStringAdd": "direction|material" }, // there are only reversed light rail vehicles in Streetplan - { "tag": "Rail Vehicles Reversed", "type": "light-rail", "variantStringAdd": "direction" }, + { "tag": "Rail Vehicles Reversed", "type": "light-rail", "variantStringAdd": "direction|material" }, { "tag": "Bus Vehicles", "type": "bus-lane", "variantString": "typical", "variantStringAdd": "direction|material|variantString" } ] }, "Cars": { + "": {"type": "drive-lane", "variantString": "car", "variantStringAdd": "direction|variantString"}, "Autos": {"type": "drive-lane", "variantString": "car", "variantStringAdd": "direction|variantString"}, "Truck": {"type": "drive-lane", "variantString": "truck", "variantStringAdd": "direction|variantString"} }, "Parking": { + "": {"tag": "Parking - Parallel", "type": "parking-lane", "variantStringAdd": "direction|side"}, "Parallel": {"tag": "Parking - Parallel", "type": "parking-lane", "variantStringAdd": "direction|side"} , @@ -86,6 +94,7 @@ const mapping = { } }, "Buffers": { + "": {"type":"divider","variantString":"median"}, "Trees": {"type": "divider", "variantString": "big-tree"}, "tree": {"type": "divider", "variantString": "palm-tree"}, "season_tree": {"type": "divider", "variantString": "big-tree"}, From 01a89d11a27c6898cb1e6e8c1c1c5ead89131c71 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Fri, 22 Mar 2024 19:54:02 -0300 Subject: [PATCH 15/23] dont show error if variantString is not provided --- src/aframe-streetmix-parsers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aframe-streetmix-parsers.js b/src/aframe-streetmix-parsers.js index b0a1ce7b9..3cc0c3e56 100644 --- a/src/aframe-streetmix-parsers.js +++ b/src/aframe-streetmix-parsers.js @@ -804,7 +804,7 @@ function processSegments (segments, showStriping, length, globalAnimated, showVe var positionY = 0; // get variantString - var variantList = segments[i].variantString.split('|'); + var variantList = segments[i].variantString ? segments[i].variantString.split('|'): ""; // show warning message if segment or variantString are not supported supportCheck(segments[i].type, segments[i].variantString); From 3aba39054d852dcf705f191341b6045a87e2994d Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Mon, 25 Mar 2024 19:32:02 -0300 Subject: [PATCH 16/23] add red bus lane for streetmix support variant list --- src/segments-variants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/segments-variants.js b/src/segments-variants.js index 46b743456..2a5f68c3a 100644 --- a/src/segments-variants.js +++ b/src/segments-variants.js @@ -16,7 +16,7 @@ const segmentVariants = { "bike-lane": ["inbound|green|sidewalk", "inbound|green|road", "outbound|green|sidewalk", "outbound|green|road", "inbound|regular|sidewalk", "inbound|regular|road", "outbound|regular|sidewalk", "outbound|regular|road", "inbound|red|sidewalk", "inbound|red|road", "outbound|red|sidewalk", "outbound|red|road"], "scooter": ["inbound|regular", "inbound|green", "inbound|red", "outbound|regular", "outbound|green", "outbound|red"], // road segments - "bus-lane": ["inbound|colored|typical", "outbound|colored|typical", "inbound|regular|typical", "outbound|regular|typical"], + "bus-lane": ["inbound|colored|typical", "outbound|colored|typical", "inbound|regular|typical", "outbound|regular|typical", "inbound|red|typical", "outbound|red|typical"], "drive-lane": ["inbound|car","outbound|car", "inbound|truck","outbound|truck", "outbound|av", "inbound|av", "outbound|pedestrian", "inbound|pedestrian", "inbound|sharrow", "outbound|sharrow"], "turn-lane": ["inbound|left", "inbound|right", "inbound|left-right-straight", "inbound|shared", "inbound|both", "inbound|left-straight", "inbound|right-straight", "inbound|straight", "outbound|left", "outbound|right", "outbound|left-right-straight", "outbound|shared", "outbound|both", "outbound|left-straight", "outbound|right-straight", "outbound|straight"], "parking-lane": ["sideways|right", "sideways|left", "inbound|right", "inbound|left", "outbound|left", "outbound|right", "angled-front-left|left", "angled-front-right|left", "angled-rear-left|left", "angled-rear-right|left", "angled-front-left|right", "angled-front-right|right", "angled-rear-left|right", "angled-rear-right|right"], From 45bbecbb770648bddb3756ab8d57ecefeb998104 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Mon, 25 Mar 2024 19:33:45 -0300 Subject: [PATCH 17/23] update conversion-map add description add more variants support fix some existing variants support --- src/streetplan/conversion-map.js | 63 +++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 18 deletions(-) diff --git a/src/streetplan/conversion-map.js b/src/streetplan/conversion-map.js index bc455a2ea..e03a992cc 100644 --- a/src/streetplan/conversion-map.js +++ b/src/streetplan/conversion-map.js @@ -1,15 +1,19 @@ -// conversion map StreetPan -> Streetmix -// sidewalk segment types mapping +// conversion map StreetPan -> Streetmix sidewalk segment types mapping /* StreetPlanType1: { - StreetPlanSubtype: StreetmixType, + StreetPlanSubtype: StreetmixType, --- or --- - StreetPlanSubtype: { + StreetPlanSubtype: { "tag": StreetPlanTag, "type": StreetmixType, - "variantString": StreetmixVariantString, - "variantStringAdd": get parameter values from this list and generate variantString, + "variantString": Streetmix VariantString, can be formed based on other Streetplan parameters + (Name or Tag) or be constant, like: 'sidewalk', + + "variantStringAdd": get parameter values from this list and generate variantString. + Often variantString looks like this: 'outbound|regular|road' - example for bike-path. + variantStringAdd will be: 'direction|material|variantString', + "nameToVariantMap": mapping rule StreetPlan O1-Name -> VariantString, "tagToVariantMap": mapping rule StreetPlan O1-Tags -> VariantString, "names": names (StreetPlan O1-Name) for this Streetmix Segment type @@ -17,12 +21,18 @@ StreetPlanType1: --- or --- // for one (O1-Tags) there can be different streetmix segment types, // which are determined by the name (O1-Name) - StreetPlanSubtype: [ + StreetPlanSubtype: [ different options of tags (O1-Tags) and streetMix data for each ] } */ const mapping = { + "Setback": { + "": {"type": "sidewalk", "variantString": "empty"}, + "Trees": {"type": "sidewalk-tree", "variantString": "big"}, + "tree": {"type": "divider", "variantString": "palm-tree"}, + "Benchs": {"type": "sidewalk-bench", "variantStringAdd": "side" }, + }, "Walkways": { "": {"type": "sidewalk", "variantString": "empty"}, "Trees": {"type": "sidewalk-tree", "variantString": "big"}, @@ -35,11 +45,7 @@ const mapping = { "Trees": {"type": "sidewalk-tree", "variantString": "big"}, "season_tree": {"type": "sidewalk-tree", "variantString": "big"}, "Shelters": { "type": "transit-shelter", "variantString": "street-level", "variantStringAdd": "side|variantString" }, - "planter": {"type": "divider", "variantString": "planting-strip"}, "Pedestrian": {"type": "sidewalk", "variantString": "dense"}, - "Benchs": {"type": "sidewalk-bench", "variantStringAdd": "side" }, - "Tables": {"type": "outdoor-dining", "variantString": "occupied|sidewalk"}, - "BikeRacks": {"type": "sidewalk-bike-rack", "variantString": "sidewalk-parallel", "variantStringAdd": "side|variantString" }, }, "Curbside": { "": {"type": "sidewalk", "variantString": "empty"}, @@ -48,10 +54,12 @@ const mapping = { "Regular Lights": "modern" }, "variantStringAdd": "side|variantString" }, - "Shelters": { "type": "transit-shelter", "variantString": "street-level", "variantStringAdd": "side|variantString" }, "Poles": { "type": "utilities", "variantStringAdd": "side" }, - "Benchs": {"type": "sidewalk-bench", "variantStringAdd": "side" }, - "BikeRacks": {"type": "sidewalk-bike-rack", "variantString": "sidewalk-parallel", "variantStringAdd": "side|variantString" }, + "BikeRacks": {"type": "sidewalk-bike-rack", "nameToVariantMap": { + "Sideview Modern": "sidewalk-parallel", + "Sideview": "sidewalk-parallel", + "NYC Bike Rack": "sidewalk", + }, "variantStringAdd": "side|variantString" }, }, "BikesPaths": { "": {"type": "bike-lane", "variantString": "sidewalk"}, @@ -91,7 +99,8 @@ const mapping = { "Away, R. Park, Head In": "angled-rear-right" }, "variantStringAdd": "side" - } + }, + "Perpendicular": {"type": "parking-lane", "variantString": "sideways", "variantStringAdd": "variantString|side"}, }, "Buffers": { "": {"type":"divider","variantString":"median"}, @@ -99,16 +108,34 @@ const mapping = { "tree": {"type": "divider", "variantString": "palm-tree"}, "season_tree": {"type": "divider", "variantString": "big-tree"}, "median": {"type": "divider", "variantString": "planting-strip"}, - "Autos": {}, - "AngleNormal": {}, - "Purpendicular": {"type": "parking-lane", "variantString": "sideways", "variantStringAdd": "side"}, "planter": {"type": "divider", "variantString": "planting-strip"} } } // copy repeating rules mapping["Buffers"]["AngleNormal"] = mapping["Parking"]["AngleNormal"]; mapping["Buffers"]["Autos"] = mapping["Cars"]["Autos"]; +mapping["Buffers"]["Purpendicular"] = mapping["Parking"]["Perpendicular"]; mapping["Median/Buffer"] = mapping["Buffers"]; +mapping["Setback"]["tree"] = mapping["Buffers"]["tree"]; +mapping["Setback"]["Trees"] = mapping["Buffers"]["Trees"]; +mapping["Setback"]["season_tree"] = mapping["Buffers"]["season_tree"]; +// fix for typo Purpendicular +mapping["Parking"]["Purpendicular"] = mapping["Parking"]["Perpendicular"]; +mapping["Setback"]["Purpendicular"] = mapping["Parking"]["Perpendicular"]; +mapping["Setback"]["AngleNormal"] = mapping["Parking"]["AngleNormal"]; +mapping["Setback"]["planter"] = mapping["Buffers"]["planter"]; +mapping["Setback"]["BikeRacks"] = mapping["Curbside"]["BikeRacks"]; +mapping["Setback"]["Tables"] = mapping["Walkways"]["Tables"]; +mapping["Setback"]["Poles"] = mapping["Curbside"]["Poles"]; + +mapping["Curbside"]["Shelters"] = mapping["Furniture"]["Shelters"]; +mapping["Curbside"]["Benchs"] = mapping["Walkways"]["Benchs"]; + +mapping["Furniture"]["planter"] = mapping["Buffers"]["planter"]; +mapping["Furniture"]["Benchs"] = mapping["Walkways"]["Benchs"]; +mapping["Furniture"]["BikeRacks"] = mapping["Curbside"]["BikeRacks"]; +mapping["Furniture"]["Tables"] = mapping["Walkways"]["Tables"]; + const directionMap = { "Coming": "inbound", From a043771f60f632862e2e1bd8d1683d7bef3a390f Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Mon, 25 Mar 2024 19:34:16 -0300 Subject: [PATCH 18/23] change example streetplan json --- src/streetplan/exampleJSON.json | 414 +++++++++++++++++++++++++++++++- 1 file changed, 413 insertions(+), 1 deletion(-) diff --git a/src/streetplan/exampleJSON.json b/src/streetplan/exampleJSON.json index 5c4e43fb4..4c46d65e1 100644 --- a/src/streetplan/exampleJSON.json +++ b/src/streetplan/exampleJSON.json @@ -1 +1,413 @@ -{"status":true,"project":{"My Street":{"Boulevard Alt 1":{"segments":{"1":{"Type":"Buildings","Subtype":"Commercial","SegPos":1,"width":30,"title":"Building Blue 4floors","side":"left","Direction":"NA","Material":"Building Blue 4floors","MaterialH":"0","Markings":"Standard Concrete","O1-Name":"Building Blue 4floors","O1-Tags":"4-Story,4-Story","O2-Name":"","O2-Tags":"","O3-Name":"","O3-Tags":""},"2":{"id":2478438,"Type":"setback","Subtype":"Paths","SegPos":2,"width":3,"title":"Empty place holder","side":"left","Direction":"NA","Material":"Asphalt Blue","MaterialH":"0.5","Markings":"Setback Small","O1-Name":"Empty place holder","O1-Tags":"Business Signs","O2-Name":"Empty place holder","O2-Tags":"Business Signs","O3-Name":"","O3-Tags":""},"3":{"id":2478439,"Type":"Walkways","Subtype":"pedestrian","SegPos":3,"width":6,"title":"3 people","side":"left","Direction":"Both","Material":"Pavers Tan","MaterialH":"0.5","Markings":"Blank","O1-Name":"3 people","O1-Tags":"Many People","O2-Name":"Empty place holder","O2-Tags":"Many People","O3-Name":"","O3-Tags":""},"4":{"id":2478440,"Type":"Furniture","Subtype":"season_tree","SegPos":4,"width":7,"title":"Japanese lilac","side":"left","Direction":"NA","Material":"Pavers Tan","MaterialH":"0.5","Markings":"Blank","O1-Name":"Japanese lilac","O1-Tags":"Trees, Summer","O2-Name":"Sideview","O2-Tags":"Bike Racks","O3-Name":"trashcan","O3-Tags":"Miscellaneous"},"5":{"id":2478441,"Type":"BikesPaths","Subtype":"Bikes","SegPos":5,"width":4.5,"title":"Casual Woman","side":"left","Direction":"Coming","Material":"Asphalt Blue","MaterialH":"0.5","Markings":"Painted BufferNone NoEdge","O1-Name":"Casual Woman","O1-Tags":"Miscellaneous","O2-Name":"Empty place holder","O2-Tags":"Parking - Reverse Angle","O3-Name":"","O3-Tags":""},"6":{"id":2478442,"Type":"Curbside","Subtype":"Lights","SegPos":6,"width":2,"title":"Streetlight solar banners 1","side":"left","Direction":"NA","Material":"Pavers Tan","MaterialH":"0.5","Markings":"Blank","O1-Name":"Streetlight solar banners 1","O1-Tags":"Historic Lights","O2-Name":"Sign directory","O2-Tags":"0 mph","O3-Name":"","O3-Tags":""},"7":{"id":2478443,"Type":"Gutter","Subtype":"Gutter","SegPos":7,"width":2.5,"title":"Gutter Std. 2.5 ft, Left","side":"left","Direction":"NA","Material":"Standard Concrete","MaterialH":"0.5","Markings":"Blank","O1-Name":"Gutter Std. 2.5 ft, Left","O1-Tags":"Gutters","O2-Name":"Empty place holder","O2-Tags":"Markings - Transit Options","O3-Name":"Empty place holder","O3-Tags":"Markings - Transit Options"},"8":{"id":2478444,"Type":"Transit","Subtype":"Transit","SegPos":8,"width":11,"title":"UTA bus","side":"left","Direction":"Coming","Material":"Asphalt Black","MaterialH":"0","Markings":"Thru Only","O1-Name":"UTA bus","O1-Tags":"Bus Vehicles","O2-Name":"Yellow Sedan","O2-Tags":"Miscellaneous","O3-Name":"","O3-Tags":""},"9":{"id":2478445,"Type":"Cars","Subtype":"Autos","SegPos":9,"width":10,"title":"Red Jeep","side":"left","Direction":"Coming","Material":"Asphalt Black","MaterialH":"0","Markings":"Thru Only","O1-Name":"Red Jeep","O1-Tags":"Miscellaneous","O2-Name":"","O2-Tags":"Miscellaneous","O3-Name":"","O3-Tags":""},"10":{"id":2478446,"Type":"Median\/Buffer","Subtype":"season_tree","SegPos":10,"width":14,"title":"Japanese Zelkova","side":"median","Direction":"median","Material":"Asphalt Black","MaterialH":"0","Markings":"Center Median","O1-Name":"Japanese Zelkova","O1-Tags":"Trees, Summer","O2-Name":"TallPlantBox (12ft)","O2-Tags":"Low-Water Xeriscape","O3-Name":"","O3-Tags":""},"11":{"id":2478447,"Type":"Cars","Subtype":"Truck","SegPos":11,"width":10,"title":"Blue Truck","side":"right","Direction":"Going","Material":"Asphalt Black","MaterialH":"0","Markings":"Thru Only","O1-Name":"Blue Truck","O1-Tags":"Miscellaneous","O2-Name":"","O2-Tags":"Low-Water Xeriscape","O3-Name":"","O3-Tags":""},"12":{"id":2478448,"Type":"Transit","Subtype":"Transit","SegPos":12,"width":11,"title":"UTA bus","side":"right","Direction":"Going","Material":"Asphalt Black","MaterialH":"0","Markings":"Thru Only","O1-Name":"UTA bus","O1-Tags":"Bus Vehicles","O2-Name":"White Sedan","O2-Tags":"Miscellaneous","O3-Name":"","O3-Tags":""},"13":{"id":2478449,"Type":"Gutter","Subtype":"Gutter","SegPos":13,"width":2.5,"title":"Gutter Std. 2.5 ft, Right","side":"right","Direction":"NA","Material":"Standard Concrete","MaterialH":"0.5","Markings":"Blank","O1-Name":"Gutter Std. 2.5 ft, Right","O1-Tags":"Gutters","O2-Name":"Empty place holder","O2-Tags":"Markings - Transit Options","O3-Name":"Empty place holder","O3-Tags":"Markings - Transit Options"},"14":{"id":2478450,"Type":"Curbside","Subtype":"Lights","SegPos":14,"width":2,"title":"Streetlight solar banners 1","side":"right","Direction":"NA","Material":"Pavers Tan","MaterialH":"0.5","Markings":"Blank","O1-Name":"Streetlight solar banners 1","O1-Tags":"Historic Lights","O2-Name":"Empty place holder","O2-Tags":"30 mph","O3-Name":"","O3-Tags":""},"15":{"id":2478451,"Type":"BikesPaths","Subtype":"Bikes","SegPos":15,"width":4.5,"title":"Man Go","side":"right","Direction":"Going","Material":"Asphalt Blue","MaterialH":"0.5","Markings":"Painted BufferNone NoEdge","O1-Name":"Man Go","O1-Tags":"Miscellaneous","O2-Name":"","O2-Tags":"Markings - Transit Options","O3-Name":"","O3-Tags":""},"16":{"id":2478452,"Type":"Furniture","Subtype":"season_tree","SegPos":16,"width":7,"title":"Japanese lilac","side":"right","Direction":"NA","Material":"Pavers Tan","MaterialH":"0.5","Markings":"Blank","O1-Name":"Japanese lilac","O1-Tags":"Trees, Summer","O2-Name":"Table","O2-Tags":"Miscellaneous","O3-Name":"Empty place holder","O3-Tags":"Trees, Fall"},"17":{"id":2478453,"Type":"Walkways","Subtype":"pedestrian","SegPos":17,"width":6,"title":"2 people","side":"right","Direction":"Both","Material":"Pavers Tan","MaterialH":"0.5","Markings":"Blank","O1-Name":"2 people","O1-Tags":"Pedestrians","O2-Name":"Empty place holder","O2-Tags":"Many People","O3-Name":"","O3-Tags":""},"18":{"id":2478454,"Type":"setback","Subtype":"Paths","SegPos":18,"width":3,"title":"Empty place holder","side":"right","Direction":"NA","Material":"Asphalt Blue","MaterialH":"0.5","Markings":"Setback Small","O1-Name":"Empty place holder","O1-Tags":"Business Signs","O2-Name":"Empty place holder","O2-Tags":"Business Signs","O3-Name":"","O3-Tags":""},"19":{"Type":"Buildings","Subtype":"Commercial","SegPos":19,"width":30,"title":"Building Yellow 4floors","side":"right","Direction":"NA","Material":"Building Yellow 4floors","MaterialH":"0","Markings":"Standard Concrete","O1-Name":"Building Yellow 4floors","O1-Tags":"4-Story,4-Story","O2-Name":"","O2-Tags":"","O3-Name":"","O3-Tags":""}}}}}} \ No newline at end of file +{ + "status": true, + "project": + { + "My Street": + { + "Boulevard Alt 1": + { + "segments": + { + "1": + { + "Type": "Buildings", + "Subtype": "Commercial", + "SegPos": 1, + "width": 30, + "title": "Building Blue 4floors", + "side": "left", + "Direction": "NA", + "Material": "Building Blue 4floors", + "MaterialH": "0", + "Markings": "Standard Concrete", + "O1-Name": "Building Blue 4floors", + "O1-Tags": "4-Story,4-Story", + "O2-Name": "", + "O2-Tags": "", + "O3-Name": "", + "O3-Tags": "" + }, + "2": + { + "id": 2478438, + "Type": "setback", + "Subtype": "AngleNormal", + "SegPos": 2, + "width": 3, + "title": "Toward, R. Park, Head In", + "side": "left", + "Direction": "NA", + "Material": "Asphalt Blue", + "MaterialH": "0.5", + "Markings": "Setback Small", + "O1-Name": "Toward, R. Park, Head In", + "O1-Tags": "Parking - Angle", + "O2-Name": "Empty place holder", + "O2-Tags": "Business Signs", + "O3-Name": "", + "O3-Tags": "" + }, + "3": + { + "id": 2478439, + "Type": "Walkways", + "Subtype": "pedestrian", + "SegPos": 3, + "width": 6, + "title": "3 people", + "side": "left", + "Direction": "Both", + "Material": "Pavers Tan", + "MaterialH": "0.5", + "Markings": "Blank", + "O1-Name": "3 people", + "O1-Tags": "Many People", + "O2-Name": "Empty place holder", + "O2-Tags": "Many People", + "O3-Name": "", + "O3-Tags": "" + }, + "4": + { + "id": 2478440, + "Type": "Furniture", + "Subtype": "BikeRacks", + "SegPos": 4, + "width": 7, + "title": "NYC Bike Rack", + "side": "left", + "Direction": "NA", + "Material": "Pavers Tan", + "MaterialH": "0.5", + "Markings": "Blank", + "O1-Name": "NYC Bike Rack", + "O1-Tags": "Bike Racks", + "O2-Name": "Empty place holder", + "O2-Tags": "Trees, Fall", + "O3-Name": "Empty place holder", + "O3-Tags": "Trees, Fall" + }, + "5": + { + "id": 2478441, + "Type": "BikesPaths", + "Subtype": "Bikes", + "SegPos": 5, + "width": 4.5, + "title": "Casual woman 2", + "side": "left", + "Direction": "Coming", + "Material": "Asphalt Blue", + "MaterialH": "0.5", + "Markings": "Painted BufferNone NoEdge", + "O1-Name": "Casual woman 2", + "O1-Tags": "Miscellaneous", + "O2-Name": "Empty place holder", + "O2-Tags": "Parking - Reverse Angle", + "O3-Name": "", + "O3-Tags": "" + }, + "6": + { + "id": 2478442, + "Type": "Curbside", + "Subtype": "", + "SegPos": 6, + "width": 6, + "title": "Empty place holder", + "side": "left", + "Direction": "NA", + "Material": "Pavers Tan", + "MaterialH": "0.5", + "Markings": "Blank", + "O1-Name": "Empty place holder", + "O1-Tags": "Markings - Transit Options", + "O2-Name": "Shelter", + "O2-Tags": "0 mph", + "O3-Name": "", + "O3-Tags": "" + }, + "7": + { + "id": 2478443, + "Type": "Gutter", + "Subtype": "Gutter", + "SegPos": 7, + "width": 2.5, + "title": "Gutter Std. 2.5 ft, Left", + "side": "left", + "Direction": "NA", + "Material": "Standard Concrete", + "MaterialH": "0.5", + "Markings": "Blank", + "O1-Name": "Gutter Std. 2.5 ft, Left", + "O1-Tags": "Gutters", + "O2-Name": "Empty place holder", + "O2-Tags": "Markings - Transit Options", + "O3-Name": "Empty place holder", + "O3-Tags": "Markings - Transit Options" + }, + "8": + { + "id": 2478540, + "Type": "Parking", + "Subtype": "Purpendicular", + "SegPos": 8, + "width": 19, + "title": "Purpendicular Right side, Blue", + "side": "left", + "Direction": "Coming", + "Material": "Asphalt Black", + "MaterialH": "0", + "Markings": "Parking Left", + "O1-Name": "Purpendicular Right side, Blue", + "O1-Tags": "Private Parking", + "O2-Name": "", + "O2-Tags": "Markings - Transit Options", + "O3-Name": "", + "O3-Tags": "" + }, + "9": + { + "id": 2478444, + "Type": "Transit", + "Subtype": "Transit", + "SegPos": 9, + "width": 11, + "title": "UTA bus", + "side": "left", + "Direction": "Coming", + "Material": "Asphalt Red 2", + "MaterialH": "0", + "Markings": "Thru Only", + "O1-Name": "UTA bus", + "O1-Tags": "Bus Vehicles", + "O2-Name": "Yellow Sedan", + "O2-Tags": "Miscellaneous", + "O3-Name": "", + "O3-Tags": "" + }, + "10": + { + "id": 2478445, + "Type": "Cars", + "Subtype": "", + "SegPos": 10, + "width": 10, + "title": "Empty place holder", + "side": "left", + "Direction": "Coming", + "Material": "Asphalt Black", + "MaterialH": "0", + "Markings": "Thru Only", + "O1-Name": "Empty place holder", + "O1-Tags": "SUVs\/Pickups Reversed", + "O2-Name": "", + "O2-Tags": "Miscellaneous", + "O3-Name": "", + "O3-Tags": "" + }, + "11": + { + "id": 2478446, + "Type": "Median\/Buffer", + "Subtype": "season_tree", + "SegPos": 11, + "width": 14, + "title": "Japanese Zelkova", + "side": "median", + "Direction": "median", + "Material": "Asphalt Black", + "MaterialH": "0", + "Markings": "Center Median", + "O1-Name": "Japanese Zelkova", + "O1-Tags": "Trees, Summer", + "O2-Name": "TallPlantBox (12ft)", + "O2-Tags": "Low-Water Xeriscape", + "O3-Name": "", + "O3-Tags": "" + }, + "12": + { + "id": 2478447, + "Type": "Cars", + "Subtype": "Truck", + "SegPos": 12, + "width": 10, + "title": "Blue Truck", + "side": "right", + "Direction": "Going", + "Material": "Asphalt Black", + "MaterialH": "0", + "Markings": "Thru Only", + "O1-Name": "Blue Truck", + "O1-Tags": "Miscellaneous", + "O2-Name": "", + "O2-Tags": "Low-Water Xeriscape", + "O3-Name": "", + "O3-Tags": "" + }, + "13": + { + "id": 2478448, + "Type": "Transit", + "Subtype": "Transit", + "SegPos": 13, + "width": 11, + "title": "StreetCar Yellow", + "side": "right", + "Direction": "Going", + "Material": "Grass", + "MaterialH": "0", + "Markings": "Thru Only", + "O1-Name": "StreetCar Yellow", + "O1-Tags": "Rail Vehicles", + "O2-Name": "White Sedan", + "O2-Tags": "Miscellaneous", + "O3-Name": "", + "O3-Tags": "" + }, + "14": + { + "id": 2478449, + "Type": "Gutter", + "Subtype": "Gutter", + "SegPos": 14, + "width": 2.5, + "title": "Gutter Std. 2.5 ft, Right", + "side": "right", + "Direction": "NA", + "Material": "Standard Concrete", + "MaterialH": "0.5", + "Markings": "Blank", + "O1-Name": "Gutter Std. 2.5 ft, Right", + "O1-Tags": "Gutters", + "O2-Name": "Empty place holder", + "O2-Tags": "Markings - Transit Options", + "O3-Name": "Empty place holder", + "O3-Tags": "Markings - Transit Options" + }, + "15": + { + "id": 2478450, + "Type": "Curbside", + "Subtype": "Lights", + "SegPos": 15, + "width": 2, + "title": "Streetlight solar banners 1", + "side": "right", + "Direction": "NA", + "Material": "Pavers Tan", + "MaterialH": "0.5", + "Markings": "Blank", + "O1-Name": "Streetlight solar banners 1", + "O1-Tags": "Historic Lights", + "O2-Name": "BikeRack Bollard", + "O2-Tags": "30 mph", + "O3-Name": "", + "O3-Tags": "" + }, + "16": + { + "id": 2478451, + "Type": "BikesPaths", + "Subtype": "Bikes", + "SegPos": 16, + "width": 4.5, + "title": "Man Go", + "side": "right", + "Direction": "Going", + "Material": "Asphalt Blue", + "MaterialH": "0.5", + "Markings": "Painted BufferNone NoEdge", + "O1-Name": "Man Go", + "O1-Tags": "Miscellaneous", + "O2-Name": "", + "O2-Tags": "Bike Racks", + "O3-Name": "", + "O3-Tags": "" + }, + "17": + { + "id": 2478452, + "Type": "Furniture", + "Subtype": "Tables", + "SegPos": 17, + "width": 7, + "title": "Table", + "side": "right", + "Direction": "NA", + "Material": "Pavers Tan", + "MaterialH": "0.5", + "Markings": "Blank", + "O1-Name": "Table", + "O1-Tags": "Miscellaneous", + "O2-Name": "Table", + "O2-Tags": "Miscellaneous", + "O3-Name": "Empty place holder", + "O3-Tags": "Trees, Fall" + }, + "18": + { + "id": 2478453, + "Type": "Walkways", + "Subtype": "pedestrian", + "SegPos": 18, + "width": 6, + "title": "3 people", + "side": "right", + "Direction": "Both", + "Material": "Pavers Tan", + "MaterialH": "0.5", + "Markings": "Blank", + "O1-Name": "3 people", + "O1-Tags": "Many People", + "O2-Name": "Empty place holder", + "O2-Tags": "Many People", + "O3-Name": "", + "O3-Tags": "" + }, + "19": + { + "id": 2478454, + "Type": "setback", + "Subtype": "Paths", + "SegPos": 19, + "width": 3, + "title": "Empty place holder", + "side": "right", + "Direction": "NA", + "Material": "Asphalt Blue", + "MaterialH": "0.5", + "Markings": "Setback Small", + "O1-Name": "Empty place holder", + "O1-Tags": "Business Signs", + "O2-Name": "Empty place holder", + "O2-Tags": "Business Signs", + "O3-Name": "", + "O3-Tags": "" + }, + "20": + { + "Type": "Buildings", + "Subtype": "Commercial", + "SegPos": 20, + "width": 30, + "title": "Building Yellow 4floors", + "side": "right", + "Direction": "NA", + "Material": "Building Yellow 4floors", + "MaterialH": "0", + "Markings": "Standard Concrete", + "O1-Name": "Building Yellow 4floors", + "O1-Tags": "4-Story,4-Story", + "O2-Name": "", + "O2-Tags": "", + "O3-Name": "", + "O3-Tags": "" + } + } + } + } + } +} \ No newline at end of file From d44f098c755acf8d1ce8ada07c21741210fe5b3e Mon Sep 17 00:00:00 2001 From: Kieran Farr Date: Wed, 10 Apr 2024 17:00:51 -0700 Subject: [PATCH 19/23] make work with url passed in hash use this url to test: http://localhost:7001/streetplan.html#https://api.allorigins.win/raw?url=https://upd.streetplan.net/streets-3d-data/79303 --- src/components/streetplan-loader.js | 16 ++++++++-------- src/json-utils_1.1.js | 6 +++--- streetplan.html | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/components/streetplan-loader.js b/src/components/streetplan-loader.js index 13dad3d37..4d6533667 100644 --- a/src/components/streetplan-loader.js +++ b/src/components/streetplan-loader.js @@ -38,7 +38,7 @@ AFRAME.registerComponent('streetplan-loader', { console.log('therefore setting metadata sceneTitle as streetplanName', streetplanName); } - el.setAttribute('data-layer-name', 'Streetplan • ' + streetplanName); + el.setAttribute('data-layer-name', 'StreetPlan • ' + streetplanName); if (data.showBuildings) { el.setAttribute('street', 'right', streetData.rightBuildingVariant); @@ -52,15 +52,15 @@ AFRAME.registerComponent('streetplan-loader', { update: function (oldData) { // fired at start and at each subsequent change of any schema value // This method may fire a few times when viewing a streetmix street in 3dstreet: // First to find the proper path, once to actually load the street, and then subsequent updates such as street name + const that = this; const data = this.data; const el = this.el; - /* ***** debugging ***** */ - setTimeout(()=> { - this.streetplanResponseParse(exampleJSON); - }, 1000); - - return; + // /* ***** debugging ***** */ + // setTimeout(()=> { + // this.streetplanResponseParse(exampleJSON); + // }, 1000); + // return; // load from URL encoded Streetplan JSON if (data.streetplanEncJSON) { @@ -83,7 +83,7 @@ AFRAME.registerComponent('streetplan-loader', { if (this.status >= 200 && this.status < 400) { // Connection success const streetplanResponseObject = JSON.parse(this.response); - this.streetplanResponseParse(streetplanResponseObject); + that.streetplanResponseParse(streetplanResponseObject); } else { // We reached our target server, but it returned an error console.log('[streetplan-loader]', 'Loading Error: We reached the target server, but it returned an error'); diff --git a/src/json-utils_1.1.js b/src/json-utils_1.1.js index 45fcafb2a..897d06077 100644 --- a/src/json-utils_1.1.js +++ b/src/json-utils_1.1.js @@ -536,16 +536,16 @@ AFRAME.registerComponent('set-loader-from-hash', { 'streetmixStreetURL', streetURL ); - } else if (streetURL.startsWith('streetplanJSON:')) { + } else if (streetURL.includes('streetplan.net')) { // load from Streetplan encoded JSON in URL console.log( '[set-loader-from-hash]', - 'Set streetplan-loader streetplanEncJSON to', + 'Set streetplan-loader streetplanAPIURL to', streetURL ); this.el.setAttribute( 'streetplan-loader', - 'streetplanEncJSON', + 'streetplanAPIURL', streetURL ); } else { diff --git a/streetplan.html b/streetplan.html index 635e5d151..6d0c630ec 100644 --- a/streetplan.html +++ b/streetplan.html @@ -89,7 +89,7 @@ - + From 4fae032ee0b0968168c1c7c5b879e9b950b0c4ae Mon Sep 17 00:00:00 2001 From: Kieran Farr Date: Thu, 11 Apr 2024 11:24:07 -0700 Subject: [PATCH 20/23] hash URL loader logic improvement - remove streetmix-loader dependency since streetplan-loader may be used instead - add a bit more to our hacky matching string of streetplan to reduce unintended collisions, such as a streetmix street title --- src/json-utils_1.1.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/json-utils_1.1.js b/src/json-utils_1.1.js index 897d06077..49970e9cf 100644 --- a/src/json-utils_1.1.js +++ b/src/json-utils_1.1.js @@ -509,7 +509,6 @@ AFRAME.registerComponent('scene-title', { }); AFRAME.registerComponent('set-loader-from-hash', { - dependencies: ['streetmix-loader'], schema: { defaultURL: { type: 'string' } }, @@ -536,7 +535,7 @@ AFRAME.registerComponent('set-loader-from-hash', { 'streetmixStreetURL', streetURL ); - } else if (streetURL.includes('streetplan.net')) { + } else if (streetURL.includes('streetplan.net/')) { // load from Streetplan encoded JSON in URL console.log( '[set-loader-from-hash]', From 87dc3aa57287689b2c210ad58e8c0dbf828f979c Mon Sep 17 00:00:00 2001 From: Kieran Farr Date: Thu, 11 Apr 2024 11:27:30 -0700 Subject: [PATCH 21/23] lint fix and npm run dist --- dist/aframe-street-component.js | 4 +- src/aframe-streetmix-parsers.js | 4 +- src/components/streetplan-loader.js | 2 +- src/segments-variants.js | 54 ++-- src/streetplan/conversion-map.js | 434 ++++++++++++++-------------- src/streetplan/streetplan-utils.js | 46 +-- 6 files changed, 275 insertions(+), 269 deletions(-) diff --git a/dist/aframe-street-component.js b/dist/aframe-street-component.js index 3d62b710b..194e586dd 100644 --- a/dist/aframe-street-component.js +++ b/dist/aframe-street-component.js @@ -1,4 +1,4 @@ -!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r=e();for(var n in r)("object"==typeof exports?exports:t)[n]=r[n]}}(self,(()=>(()=>{var t={631:t=>{var e=[new THREE.Vector2,new THREE.Vector2,new THREE.Vector2,new THREE.Vector2];function r(t,r,n,i){const a=1/i,o=1/n;return e[0].set(a*r,o*t+o),e[1].set(a*r,o*t),e[2].set(a*r+a,o*t),e[3].set(a*r+a,o*t+o),e}AFRAME.registerComponent("atlas-uvs",{dependencies:["geometry"],schema:{totalColumns:{type:"int",default:1},totalRows:{type:"int",default:1},column:{type:"int",default:1},row:{type:"int",default:1}},update:function(){const t=this.data,e=r(t.row-1,t.column-1,t.totalRows,t.totalColumns),n=this.el.getObject3D("mesh").geometry;var i=new Float32Array([e[0].x,e[0].y,e[3].x,e[3].y,e[1].x,e[1].y,e[2].x,e[2].y]);n.setAttribute("uv",new THREE.BufferAttribute(i,2)),n.uvsNeedUpdate=!0}}),AFRAME.registerComponent("dynamic-texture-atlas",{schema:{canvasId:{default:"dynamicAtlas"},canvasHeight:{default:1024},canvasWidth:{default:1024},debug:{default:!1},numColumns:{default:8},numRows:{default:8}},multiple:!0,init:function(){const t=this.canvas=document.createElement("canvas");t.id=this.data.canvasId,t.height=this.data.canvasHeight,t.width=this.data.canvasWidth,this.ctx=t.getContext("2d"),document.body.appendChild(t),this.data.debug&&(t.style.left=0,t.style.top=0,t.style.position="fixed",t.style.zIndex=9999999999)},drawTexture:function(t,e,n,i,a){const o=this.canvas,s=this.data;t.complete||(t.onload=()=>{this.drawTexture(t,e,n)});const c=a||o.height/s.numRows,u=i||o.width/s.numColumns;return this.ctx.drawImage(t,u*e,u*n,u,c),r(e,n,s.numRows,s.numColumns)}}),t.exports.getGridUvs=r},5236:(t,e,r)=>{"use strict";if(r(412),r(7588),r(8327),r.g._babelPolyfill)throw new Error("only one instance of babel-polyfill is allowed");r.g._babelPolyfill=!0;function n(t,e,r){t[e]||Object.defineProperty(t,e,{writable:!0,configurable:!0,value:r})}n(String.prototype,"padLeft","".padStart),n(String.prototype,"padRight","".padEnd),"pop,reverse,shift,keys,values,entries,indexOf,every,some,forEach,map,filter,find,findIndex,includes,join,slice,concat,push,splice,unshift,sort,lastIndexOf,reduce,reduceRight,copyWithin,fill".split(",").forEach((function(t){[][t]&&n(Array,t,Function.call.bind([][t]))}))},8327:(t,e,r)=>{r(9217),t.exports=r(7984).RegExp.escape},8304:t=>{t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},5811:(t,e,r)=>{var n=r(9519);t.exports=function(t,e){if("number"!=typeof t&&"Number"!=n(t))throw TypeError(e);return+t}},6224:(t,e,r)=>{var n=r(8076)("unscopables"),i=Array.prototype;null==i[n]&&r(9247)(i,n,{}),t.exports=function(t){i[n][t]=!0}},2774:(t,e,r)=>{"use strict";var n=r(5813)(!0);t.exports=function(t,e,r){return e+(r?n(t,e).length:1)}},264:t=>{t.exports=function(t,e,r,n){if(!(t instanceof e)||void 0!==n&&n in t)throw TypeError(r+": incorrect invocation!");return t}},9204:(t,e,r)=>{var n=r(9603);t.exports=function(t){if(!n(t))throw TypeError(t+" is not an object!");return t}},8734:(t,e,r)=>{"use strict";var n=r(6415),i=r(7149),a=r(1773);t.exports=[].copyWithin||function(t,e){var r=n(this),o=a(r.length),s=i(t,o),c=i(e,o),u=arguments.length>2?arguments[2]:void 0,l=Math.min((void 0===u?o:i(u,o))-c,o-s),f=1;for(c0;)c in r?r[s]=r[c]:delete r[s],s+=f,c+=f;return r}},6436:(t,e,r)=>{"use strict";var n=r(6415),i=r(7149),a=r(1773);t.exports=function(t){for(var e=n(this),r=a(e.length),o=arguments.length,s=i(o>1?arguments[1]:void 0,r),c=o>2?arguments[2]:void 0,u=void 0===c?r:i(c,r);u>s;)e[s++]=t;return e}},9349:(t,e,r)=>{var n=r(1725);t.exports=function(t,e){var r=[];return n(t,!1,r.push,r,e),r}},3997:(t,e,r)=>{var n=r(3057),i=r(1773),a=r(7149);t.exports=function(t){return function(e,r,o){var s,c=n(e),u=i(c.length),l=a(o,u);if(t&&r!=r){for(;u>l;)if((s=c[l++])!=s)return!0}else for(;u>l;l++)if((t||l in c)&&c[l]===r)return t||l||0;return!t&&-1}}},2026:(t,e,r)=>{var n=r(9124),i=r(3424),a=r(6415),o=r(1773),s=r(4164);t.exports=function(t,e){var r=1==t,c=2==t,u=3==t,l=4==t,f=6==t,d=5==t||f,h=e||s;return function(e,s,p){for(var m,g,v=a(e),y=i(v),b=n(s,p,3),x=o(y.length),w=0,A=r?h(e,x):c?h(e,0):void 0;x>w;w++)if((d||w in y)&&(g=b(m=y[w],w,v),t))if(r)A[w]=g;else if(g)switch(t){case 3:return!0;case 5:return m;case 6:return w;case 2:A.push(m)}else if(l)return!1;return f?-1:u||l?l:A}}},1457:(t,e,r)=>{var n=r(8304),i=r(6415),a=r(3424),o=r(1773);t.exports=function(t,e,r,s,c){n(e);var u=i(t),l=a(u),f=o(u.length),d=c?f-1:0,h=c?-1:1;if(r<2)for(;;){if(d in l){s=l[d],d+=h;break}if(d+=h,c?d<0:f<=d)throw TypeError("Reduce of empty array with no initial value")}for(;c?d>=0:f>d;d+=h)d in l&&(s=e(s,l[d],d,u));return s}},5720:(t,e,r)=>{var n=r(9603),i=r(7375),a=r(8076)("species");t.exports=function(t){var e;return i(t)&&("function"!=typeof(e=t.constructor)||e!==Array&&!i(e.prototype)||(e=void 0),n(e)&&null===(e=e[a])&&(e=void 0)),void 0===e?Array:e}},4164:(t,e,r)=>{var n=r(5720);t.exports=function(t,e){return new(n(t))(e)}},6371:(t,e,r)=>{"use strict";var n=r(8304),i=r(9603),a=r(3436),o=[].slice,s={};t.exports=Function.bind||function(t){var e=n(this),r=o.call(arguments,1),c=function(){var n=r.concat(o.call(arguments));return this instanceof c?function(t,e,r){if(!(e in s)){for(var n=[],i=0;i{var n=r(9519),i=r(8076)("toStringTag"),a="Arguments"==n(function(){return arguments}());t.exports=function(t){var e,r,o;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(r=function(t,e){try{return t[e]}catch(t){}}(e=Object(t),i))?r:a?n(e):"Object"==(o=n(e))&&"function"==typeof e.callee?"Arguments":o}},9519:t=>{var e={}.toString;t.exports=function(t){return e.call(t).slice(8,-1)}},947:(t,e,r)=>{"use strict";var n=r(5234).f,i=r(4958),a=r(4584),o=r(9124),s=r(264),c=r(1725),u=r(7091),l=r(4165),f=r(6538),d=r(1329),h=r(4787).fastKey,p=r(2023),m=d?"_s":"size",g=function(t,e){var r,n=h(e);if("F"!==n)return t._i[n];for(r=t._f;r;r=r.n)if(r.k==e)return r};t.exports={getConstructor:function(t,e,r,u){var l=t((function(t,n){s(t,l,e,"_i"),t._t=e,t._i=i(null),t._f=void 0,t._l=void 0,t[m]=0,null!=n&&c(n,r,t[u],t)}));return a(l.prototype,{clear:function(){for(var t=p(this,e),r=t._i,n=t._f;n;n=n.n)n.r=!0,n.p&&(n.p=n.p.n=void 0),delete r[n.i];t._f=t._l=void 0,t[m]=0},delete:function(t){var r=p(this,e),n=g(r,t);if(n){var i=n.n,a=n.p;delete r._i[n.i],n.r=!0,a&&(a.n=i),i&&(i.p=a),r._f==n&&(r._f=i),r._l==n&&(r._l=a),r[m]--}return!!n},forEach:function(t){p(this,e);for(var r,n=o(t,arguments.length>1?arguments[1]:void 0,3);r=r?r.n:this._f;)for(n(r.v,r.k,this);r&&r.r;)r=r.p},has:function(t){return!!g(p(this,e),t)}}),d&&n(l.prototype,"size",{get:function(){return p(this,e)[m]}}),l},def:function(t,e,r){var n,i,a=g(t,e);return a?a.v=r:(t._l=a={i:i=h(e,!0),k:e,v:r,p:n=t._l,n:void 0,r:!1},t._f||(t._f=a),n&&(n.n=a),t[m]++,"F"!==i&&(t._i[i]=a)),t},getEntry:g,setStrong:function(t,e,r){u(t,e,(function(t,r){this._t=p(t,e),this._k=r,this._l=void 0}),(function(){for(var t=this,e=t._k,r=t._l;r&&r.r;)r=r.p;return t._t&&(t._l=r=r?r.n:t._t._f)?l(0,"keys"==e?r.k:"values"==e?r.v:[r.k,r.v]):(t._t=void 0,l(1))}),r?"entries":"values",!r,!0),f(e)}}},5741:(t,e,r)=>{var n=r(9382),i=r(9349);t.exports=function(t){return function(){if(n(this)!=t)throw TypeError(t+"#toJSON isn't generic");return i(this)}}},5268:(t,e,r)=>{"use strict";var n=r(4584),i=r(4787).getWeak,a=r(9204),o=r(9603),s=r(264),c=r(1725),u=r(2026),l=r(1262),f=r(2023),d=u(5),h=u(6),p=0,m=function(t){return t._l||(t._l=new g)},g=function(){this.a=[]},v=function(t,e){return d(t.a,(function(t){return t[0]===e}))};g.prototype={get:function(t){var e=v(this,t);if(e)return e[1]},has:function(t){return!!v(this,t)},set:function(t,e){var r=v(this,t);r?r[1]=e:this.a.push([t,e])},delete:function(t){var e=h(this.a,(function(e){return e[0]===t}));return~e&&this.a.splice(e,1),!!~e}},t.exports={getConstructor:function(t,e,r,a){var u=t((function(t,n){s(t,u,e,"_i"),t._t=e,t._i=p++,t._l=void 0,null!=n&&c(n,r,t[a],t)}));return n(u.prototype,{delete:function(t){if(!o(t))return!1;var r=i(t);return!0===r?m(f(this,e)).delete(t):r&&l(r,this._i)&&delete r[this._i]},has:function(t){if(!o(t))return!1;var r=i(t);return!0===r?m(f(this,e)).has(t):r&&l(r,this._i)}}),u},def:function(t,e,r){var n=i(a(e),!0);return!0===n?m(t).set(e,r):n[t._i]=r,t},ufstore:m}},1405:(t,e,r)=>{"use strict";var n=r(2276),i=r(3350),a=r(1951),o=r(4584),s=r(4787),c=r(1725),u=r(264),l=r(9603),f=r(4308),d=r(3490),h=r(6668),p=r(1906);t.exports=function(t,e,r,m,g,v){var y=n[t],b=y,x=g?"set":"add",w=b&&b.prototype,A={},E=function(t){var e=w[t];a(w,t,"delete"==t||"has"==t?function(t){return!(v&&!l(t))&&e.call(this,0===t?0:t)}:"get"==t?function(t){return v&&!l(t)?void 0:e.call(this,0===t?0:t)}:"add"==t?function(t){return e.call(this,0===t?0:t),this}:function(t,r){return e.call(this,0===t?0:t,r),this})};if("function"==typeof b&&(v||w.forEach&&!f((function(){(new b).entries().next()})))){var S=new b,_=S[x](v?{}:-0,1)!=S,M=f((function(){S.has(1)})),k=d((function(t){new b(t)})),T=!v&&f((function(){for(var t=new b,e=5;e--;)t[x](e,e);return!t.has(-0)}));k||((b=e((function(e,r){u(e,b,t);var n=p(new y,e,b);return null!=r&&c(r,g,n[x],n),n}))).prototype=w,w.constructor=b),(M||T)&&(E("delete"),E("has"),g&&E("get")),(T||_)&&E(x),v&&w.clear&&delete w.clear}else b=m.getConstructor(e,t,g,x),o(b.prototype,r),s.NEED=!0;return h(b,t),A[t]=b,i(i.G+i.W+i.F*(b!=y),A),v||m.setStrong(b,t,g),b}},7984:t=>{var e=t.exports={version:"2.6.12"};"number"==typeof __e&&(__e=e)},2122:(t,e,r)=>{"use strict";var n=r(5234),i=r(9933);t.exports=function(t,e,r){e in t?n.f(t,e,i(0,r)):t[e]=r}},9124:(t,e,r)=>{var n=r(8304);t.exports=function(t,e,r){if(n(t),void 0===e)return t;switch(r){case 1:return function(r){return t.call(e,r)};case 2:return function(r,n){return t.call(e,r,n)};case 3:return function(r,n,i){return t.call(e,r,n,i)}}return function(){return t.apply(e,arguments)}}},4041:(t,e,r)=>{"use strict";var n=r(4308),i=Date.prototype.getTime,a=Date.prototype.toISOString,o=function(t){return t>9?t:"0"+t};t.exports=n((function(){return"0385-07-25T07:06:39.999Z"!=a.call(new Date(-50000000000001))}))||!n((function(){a.call(new Date(NaN))}))?function(){if(!isFinite(i.call(this)))throw RangeError("Invalid time value");var t=this,e=t.getUTCFullYear(),r=t.getUTCMilliseconds(),n=e<0?"-":e>9999?"+":"";return n+("00000"+Math.abs(e)).slice(n?-6:-4)+"-"+o(t.getUTCMonth()+1)+"-"+o(t.getUTCDate())+"T"+o(t.getUTCHours())+":"+o(t.getUTCMinutes())+":"+o(t.getUTCSeconds())+"."+(r>99?r:"0"+o(r))+"Z"}:a},768:(t,e,r)=>{"use strict";var n=r(9204),i=r(4276),a="number";t.exports=function(t){if("string"!==t&&t!==a&&"default"!==t)throw TypeError("Incorrect hint");return i(n(this),t!=a)}},2099:t=>{t.exports=function(t){if(null==t)throw TypeError("Can't call method on "+t);return t}},1329:(t,e,r)=>{t.exports=!r(4308)((function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a}))},7233:(t,e,r)=>{var n=r(9603),i=r(2276).document,a=n(i)&&n(i.createElement);t.exports=function(t){return a?i.createElement(t):{}}},120:t=>{t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},5084:(t,e,r)=>{var n=r(1720),i=r(1259),a=r(6418);t.exports=function(t){var e=n(t),r=i.f;if(r)for(var o,s=r(t),c=a.f,u=0;s.length>u;)c.call(t,o=s[u++])&&e.push(o);return e}},3350:(t,e,r)=>{var n=r(2276),i=r(7984),a=r(9247),o=r(1951),s=r(9124),c="prototype",u=function(t,e,r){var l,f,d,h,p=t&u.F,m=t&u.G,g=t&u.S,v=t&u.P,y=t&u.B,b=m?n:g?n[e]||(n[e]={}):(n[e]||{})[c],x=m?i:i[e]||(i[e]={}),w=x[c]||(x[c]={});for(l in m&&(r=e),r)d=((f=!p&&b&&void 0!==b[l])?b:r)[l],h=y&&f?s(d,n):v&&"function"==typeof d?s(Function.call,d):d,b&&o(b,l,d,t&u.U),x[l]!=d&&a(x,l,h),v&&w[l]!=d&&(w[l]=d)};n.core=i,u.F=1,u.G=2,u.S=4,u.P=8,u.B=16,u.W=32,u.U=64,u.R=128,t.exports=u},2381:(t,e,r)=>{var n=r(8076)("match");t.exports=function(t){var e=/./;try{"/./"[t](e)}catch(r){try{return e[n]=!1,!"/./"[t](e)}catch(t){}}return!0}},4308:t=>{t.exports=function(t){try{return!!t()}catch(t){return!0}}},1658:(t,e,r)=>{"use strict";r(5761);var n=r(1951),i=r(9247),a=r(4308),o=r(2099),s=r(8076),c=r(3323),u=s("species"),l=!a((function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$")})),f=function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var r="ab".split(t);return 2===r.length&&"a"===r[0]&&"b"===r[1]}();t.exports=function(t,e,r){var d=s(t),h=!a((function(){var e={};return e[d]=function(){return 7},7!=""[t](e)})),p=h?!a((function(){var e=!1,r=/a/;return r.exec=function(){return e=!0,null},"split"===t&&(r.constructor={},r.constructor[u]=function(){return r}),r[d](""),!e})):void 0;if(!h||!p||"replace"===t&&!l||"split"===t&&!f){var m=/./[d],g=r(o,d,""[t],(function(t,e,r,n,i){return e.exec===c?h&&!i?{done:!0,value:m.call(e,r,n)}:{done:!0,value:t.call(r,e,n)}:{done:!1}})),v=g[0],y=g[1];n(String.prototype,t,v),i(RegExp.prototype,d,2==e?function(t,e){return y.call(t,this,e)}:function(t){return y.call(t,this)})}}},9388:(t,e,r)=>{"use strict";var n=r(9204);t.exports=function(){var t=n(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},7849:(t,e,r)=>{"use strict";var n=r(7375),i=r(9603),a=r(1773),o=r(9124),s=r(8076)("isConcatSpreadable");t.exports=function t(e,r,c,u,l,f,d,h){for(var p,m,g=l,v=0,y=!!d&&o(d,h,3);v0)g=t(e,r,p,a(p.length),g,f-1)-1;else{if(g>=9007199254740991)throw TypeError();e[g]=p}g++}v++}return g}},1725:(t,e,r)=>{var n=r(9124),i=r(228),a=r(99),o=r(9204),s=r(1773),c=r(8837),u={},l={},f=t.exports=function(t,e,r,f,d){var h,p,m,g,v=d?function(){return t}:c(t),y=n(r,f,e?2:1),b=0;if("function"!=typeof v)throw TypeError(t+" is not iterable!");if(a(v)){for(h=s(t.length);h>b;b++)if((g=e?y(o(p=t[b])[0],p[1]):y(t[b]))===u||g===l)return g}else for(m=v.call(t);!(p=m.next()).done;)if((g=i(m,y,p.value,e))===u||g===l)return g};f.BREAK=u,f.RETURN=l},7650:(t,e,r)=>{t.exports=r(3259)("native-function-to-string",Function.toString)},2276:t=>{var e=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=e)},1262:t=>{var e={}.hasOwnProperty;t.exports=function(t,r){return e.call(t,r)}},9247:(t,e,r)=>{var n=r(5234),i=r(9933);t.exports=r(1329)?function(t,e,r){return n.f(t,e,i(1,r))}:function(t,e,r){return t[e]=r,t}},1847:(t,e,r)=>{var n=r(2276).document;t.exports=n&&n.documentElement},706:(t,e,r)=>{t.exports=!r(1329)&&!r(4308)((function(){return 7!=Object.defineProperty(r(7233)("div"),"a",{get:function(){return 7}}).a}))},1906:(t,e,r)=>{var n=r(9603),i=r(8860).set;t.exports=function(t,e,r){var a,o=e.constructor;return o!==r&&"function"==typeof o&&(a=o.prototype)!==r.prototype&&n(a)&&i&&i(t,a),t}},3436:t=>{t.exports=function(t,e,r){var n=void 0===r;switch(e.length){case 0:return n?t():t.call(r);case 1:return n?t(e[0]):t.call(r,e[0]);case 2:return n?t(e[0],e[1]):t.call(r,e[0],e[1]);case 3:return n?t(e[0],e[1],e[2]):t.call(r,e[0],e[1],e[2]);case 4:return n?t(e[0],e[1],e[2],e[3]):t.call(r,e[0],e[1],e[2],e[3])}return t.apply(r,e)}},3424:(t,e,r)=>{var n=r(9519);t.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==n(t)?t.split(""):Object(t)}},99:(t,e,r)=>{var n=r(479),i=r(8076)("iterator"),a=Array.prototype;t.exports=function(t){return void 0!==t&&(n.Array===t||a[i]===t)}},7375:(t,e,r)=>{var n=r(9519);t.exports=Array.isArray||function(t){return"Array"==n(t)}},8400:(t,e,r)=>{var n=r(9603),i=Math.floor;t.exports=function(t){return!n(t)&&isFinite(t)&&i(t)===t}},9603:t=>{t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},5119:(t,e,r)=>{var n=r(9603),i=r(9519),a=r(8076)("match");t.exports=function(t){var e;return n(t)&&(void 0!==(e=t[a])?!!e:"RegExp"==i(t))}},228:(t,e,r)=>{var n=r(9204);t.exports=function(t,e,r,i){try{return i?e(n(r)[0],r[1]):e(r)}catch(e){var a=t.return;throw void 0!==a&&n(a.call(t)),e}}},4434:(t,e,r)=>{"use strict";var n=r(4958),i=r(9933),a=r(6668),o={};r(9247)(o,r(8076)("iterator"),(function(){return this})),t.exports=function(t,e,r){t.prototype=n(o,{next:i(1,r)}),a(t,e+" Iterator")}},7091:(t,e,r)=>{"use strict";var n=r(5020),i=r(3350),a=r(1951),o=r(9247),s=r(479),c=r(4434),u=r(6668),l=r(9565),f=r(8076)("iterator"),d=!([].keys&&"next"in[].keys()),h="keys",p="values",m=function(){return this};t.exports=function(t,e,r,g,v,y,b){c(r,e,g);var x,w,A,E=function(t){if(!d&&t in k)return k[t];switch(t){case h:case p:return function(){return new r(this,t)}}return function(){return new r(this,t)}},S=e+" Iterator",_=v==p,M=!1,k=t.prototype,T=k[f]||k["@@iterator"]||v&&k[v],O=T||E(v),R=v?_?E("entries"):O:void 0,C="Array"==e&&k.entries||T;if(C&&(A=l(C.call(new t)))!==Object.prototype&&A.next&&(u(A,S,!0),n||"function"==typeof A[f]||o(A,f,m)),_&&T&&T.name!==p&&(M=!0,O=function(){return T.call(this)}),n&&!b||!d&&!M&&k[f]||o(k,f,O),s[e]=O,s[S]=m,v)if(x={values:_?O:E(p),keys:y?O:E(h),entries:R},b)for(w in x)w in k||a(k,w,x[w]);else i(i.P+i.F*(d||M),e,x);return x}},3490:(t,e,r)=>{var n=r(8076)("iterator"),i=!1;try{var a=[7][n]();a.return=function(){i=!0},Array.from(a,(function(){throw 2}))}catch(t){}t.exports=function(t,e){if(!e&&!i)return!1;var r=!1;try{var a=[7],o=a[n]();o.next=function(){return{done:r=!0}},a[n]=function(){return o},t(a)}catch(t){}return r}},4165:t=>{t.exports=function(t,e){return{value:e,done:!!t}}},479:t=>{t.exports={}},5020:t=>{t.exports=!1},9372:t=>{var e=Math.expm1;t.exports=!e||e(10)>22025.465794806718||e(10)<22025.465794806718||-2e-17!=e(-2e-17)?function(t){return 0==(t=+t)?t:t>-1e-6&&t<1e-6?t+t*t/2:Math.exp(t)-1}:e},5600:(t,e,r)=>{var n=r(7083),i=Math.pow,a=i(2,-52),o=i(2,-23),s=i(2,127)*(2-o),c=i(2,-126);t.exports=Math.fround||function(t){var e,r,i=Math.abs(t),u=n(t);return is||r!=r?u*(1/0):u*r}},5386:t=>{t.exports=Math.log1p||function(t){return(t=+t)>-1e-8&&t<1e-8?t-t*t/2:Math.log(1+t)}},6030:t=>{t.exports=Math.scale||function(t,e,r,n,i){return 0===arguments.length||t!=t||e!=e||r!=r||n!=n||i!=i?NaN:t===1/0||t===-1/0?t:(t-e)*(i-n)/(r-e)+n}},7083:t=>{t.exports=Math.sign||function(t){return 0==(t=+t)||t!=t?t:t<0?-1:1}},4787:(t,e,r)=>{var n=r(6835)("meta"),i=r(9603),a=r(1262),o=r(5234).f,s=0,c=Object.isExtensible||function(){return!0},u=!r(4308)((function(){return c(Object.preventExtensions({}))})),l=function(t){o(t,n,{value:{i:"O"+ ++s,w:{}}})},f=t.exports={KEY:n,NEED:!1,fastKey:function(t,e){if(!i(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!a(t,n)){if(!c(t))return"F";if(!e)return"E";l(t)}return t[n].i},getWeak:function(t,e){if(!a(t,n)){if(!c(t))return!0;if(!e)return!1;l(t)}return t[n].w},onFreeze:function(t){return u&&f.NEED&&c(t)&&!a(t,n)&&l(t),t}}},9966:(t,e,r)=>{var n=r(468),i=r(3350),a=r(3259)("metadata"),o=a.store||(a.store=new(r(7729))),s=function(t,e,r){var i=o.get(t);if(!i){if(!r)return;o.set(t,i=new n)}var a=i.get(e);if(!a){if(!r)return;i.set(e,a=new n)}return a};t.exports={store:o,map:s,has:function(t,e,r){var n=s(e,r,!1);return void 0!==n&&n.has(t)},get:function(t,e,r){var n=s(e,r,!1);return void 0===n?void 0:n.get(t)},set:function(t,e,r,n){s(r,n,!0).set(t,e)},keys:function(t,e){var r=s(t,e,!1),n=[];return r&&r.forEach((function(t,e){n.push(e)})),n},key:function(t){return void 0===t||"symbol"==typeof t?t:String(t)},exp:function(t){i(i.S,"Reflect",t)}}},6787:(t,e,r)=>{var n=r(2276),i=r(9770).set,a=n.MutationObserver||n.WebKitMutationObserver,o=n.process,s=n.Promise,c="process"==r(9519)(o);t.exports=function(){var t,e,r,u=function(){var n,i;for(c&&(n=o.domain)&&n.exit();t;){i=t.fn,t=t.next;try{i()}catch(n){throw t?r():e=void 0,n}}e=void 0,n&&n.enter()};if(c)r=function(){o.nextTick(u)};else if(!a||n.navigator&&n.navigator.standalone)if(s&&s.resolve){var l=s.resolve(void 0);r=function(){l.then(u)}}else r=function(){i.call(n,u)};else{var f=!0,d=document.createTextNode("");new a(u).observe(d,{characterData:!0}),r=function(){d.data=f=!f}}return function(n){var i={fn:n,next:void 0};e&&(e.next=i),t||(t=i,r()),e=i}}},8176:(t,e,r)=>{"use strict";var n=r(8304);function i(t){var e,r;this.promise=new t((function(t,n){if(void 0!==e||void 0!==r)throw TypeError("Bad Promise constructor");e=t,r=n})),this.resolve=n(e),this.reject=n(r)}t.exports.f=function(t){return new i(t)}},7288:(t,e,r)=>{"use strict";var n=r(1329),i=r(1720),a=r(1259),o=r(6418),s=r(6415),c=r(3424),u=Object.assign;t.exports=!u||r(4308)((function(){var t={},e={},r=Symbol(),n="abcdefghijklmnopqrst";return t[r]=7,n.split("").forEach((function(t){e[t]=t})),7!=u({},t)[r]||Object.keys(u({},e)).join("")!=n}))?function(t,e){for(var r=s(t),u=arguments.length,l=1,f=a.f,d=o.f;u>l;)for(var h,p=c(arguments[l++]),m=f?i(p).concat(f(p)):i(p),g=m.length,v=0;g>v;)h=m[v++],n&&!d.call(p,h)||(r[h]=p[h]);return r}:u},4958:(t,e,r)=>{var n=r(9204),i=r(2305),a=r(120),o=r(1606)("IE_PROTO"),s=function(){},c="prototype",u=function(){var t,e=r(7233)("iframe"),n=a.length;for(e.style.display="none",r(1847).appendChild(e),e.src="javascript:",(t=e.contentWindow.document).open(),t.write("