commit
7531f29218
|
@ -16,3 +16,4 @@ npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
|
.vercel
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JavaScriptSettings">
|
||||||
|
<option name="languageLevel" value="ES6" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/frontend.iml" filepath="$PROJECT_DIR$/.idea/frontend.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -1,62 +1,58 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="AutoImportSettings">
|
||||||
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="3c7078e7-6f30-4d92-9696-11496f9e6dff" name="Changes" comment="">
|
<list default="true" id="3c7078e7-6f30-4d92-9696-11496f9e6dff" name="Changes" comment="">
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/.idea/.gitignore" beforeDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/.idea/jsLibraryMappings.xml" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/.idea/modules.xml" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/.idea/nanomap.iml" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/.idea/vcs.xml" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/.gitignore" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/README.md" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/package-lock.json" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/package.json" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/public/favicon.ico" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/public/index.html" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/App.css" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/App.js" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/App.test.js" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/Networking.js" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/SimulateClick.js" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/UMap.js" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/index.css" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/index.js" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/nanomap/nanomap/src/logo.svg" beforeDir="false" />
|
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="FileTemplateManagerImpl">
|
||||||
|
<option name="RECENT_TEMPLATES">
|
||||||
|
<list>
|
||||||
|
<option value="JavaScript File" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
<component name="Git.Settings">
|
<component name="Git.Settings">
|
||||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
</component>
|
</component>
|
||||||
<component name="MarkdownSettingsMigration">
|
<component name="MarkdownSettingsMigration">
|
||||||
<option name="stateVersion" value="1" />
|
<option name="stateVersion" value="1" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectColorInfo"><![CDATA[{
|
<component name="ProjectColorInfo">{
|
||||||
"associatedIndex": 3
|
"associatedIndex": 3
|
||||||
}]]></component>
|
}</component>
|
||||||
<component name="ProjectId" id="2Yc9rUDmr9wvYpz7Xdq1eJVJoJy" />
|
<component name="ProjectId" id="2Yc9rUDmr9wvYpz7Xdq1eJVJoJy" />
|
||||||
<component name="ProjectViewState">
|
<component name="ProjectViewState">
|
||||||
<option name="hideEmptyMiddlePackages" value="true" />
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
<option name="showLibraryContents" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent"><![CDATA[{
|
<component name="PropertiesComponent">{
|
||||||
"keyToString": {
|
"keyToString": {
|
||||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
"Node.js.test.js.executor": "Run",
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||||
"WebServerToolWindowFactoryState": "false",
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
"git-widget-placeholder": "dev",
|
"WebServerToolWindowFactoryState": "false",
|
||||||
"last_opened_file_path": "/home/user/Documents/fd_data-structures/pj/nanomap-frontend",
|
"git-widget-placeholder": "dev",
|
||||||
"node.js.detected.package.eslint": "true",
|
"last_opened_file_path": "/home/user/Documents/fd_data-structures/pj/frontend",
|
||||||
"node.js.detected.package.tslint": "true",
|
"node.js.detected.package.eslint": "true",
|
||||||
"node.js.selected.package.eslint": "(autodetect)",
|
"node.js.detected.package.tslint": "true",
|
||||||
"node.js.selected.package.tslint": "(autodetect)",
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
"nodejs_package_manager_path": "npm",
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
"vue.rearranger.settings.migration": "true"
|
"nodejs_interpreter_path": "/home/user/.nvm/versions/node/v20.10.0/bin/node",
|
||||||
|
"nodejs_package_manager_path": "npm",
|
||||||
|
"npm.start.executor": "Run",
|
||||||
|
"settings.editor.selected.configurable": "editor.preferences.fonts.default",
|
||||||
|
"ts.external.directory.path": "/home/user/.local/share/JetBrains/Toolbox/apps/webstorm/plugins/javascript-impl/jsLanguageServicesImpl/external",
|
||||||
|
"vue.rearranger.settings.migration": "true"
|
||||||
}
|
}
|
||||||
}]]></component>
|
}</component>
|
||||||
<component name="RunManager">
|
<component name="RunManager">
|
||||||
<configuration name="start" type="js.build_tools.npm" temporary="true" nameIsGenerated="true">
|
<configuration name="start" type="js.build_tools.npm" temporary="true" nameIsGenerated="true">
|
||||||
<package-json value="$PROJECT_DIR$/package.json" />
|
<package-json value="$PROJECT_DIR$/package.json" />
|
||||||
|
@ -83,6 +79,16 @@
|
||||||
<option name="presentableId" value="Default" />
|
<option name="presentableId" value="Default" />
|
||||||
<updated>1700814200305</updated>
|
<updated>1700814200305</updated>
|
||||||
<workItem from="1700814201341" duration="315000" />
|
<workItem from="1700814201341" duration="315000" />
|
||||||
|
<workItem from="1700814808669" duration="47000" />
|
||||||
|
<workItem from="1700822693197" duration="9493000" />
|
||||||
|
<workItem from="1701004587189" duration="3578000" />
|
||||||
|
<workItem from="1701042611758" duration="10222000" />
|
||||||
|
<workItem from="1701056208994" duration="5687000" />
|
||||||
|
<workItem from="1701847206194" duration="6179000" />
|
||||||
|
<workItem from="1702448962541" duration="5620000" />
|
||||||
|
<workItem from="1703419885970" duration="13073000" />
|
||||||
|
<workItem from="1703582457934" duration="210000" />
|
||||||
|
<workItem from="1703642799206" duration="22143000" />
|
||||||
</task>
|
</task>
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
// no dependencies
|
||||||
|
|
||||||
|
export const __DEBUG__ = 0;
|
||||||
|
export const __APP_VERSION__ = 'v0.3.1-beta';
|
||||||
|
|
||||||
|
export const __APP_INTRO__ = `
|
||||||
|
<b>Algorithm improvement.</b><br>
|
||||||
|
Our new routing solution is based on the Obvious A-Star algorithm now, with 2~10x faster speed in calculations.<br>
|
||||||
|
<b>Support concatenating paths.</b><br>
|
||||||
|
You can add points sequentially on the map.<br>
|
||||||
|
<b>Clear the map.</b><br>
|
||||||
|
Clear all markers with one click.<br>
|
||||||
|
`;
|
|
@ -0,0 +1,172 @@
|
||||||
|
import {dijkstra, haversine_distance, obvious_dijkstra, obvious_a_star} from "../tools/ShortestPath";
|
||||||
|
import {sill, sill_unwrap, noexcept} from "../tools/Debug";
|
||||||
|
import {get_row} from "../tools/Misc";
|
||||||
|
import benchmark from "../tools/PathBench";
|
||||||
|
|
||||||
|
const __spa = obvious_a_star;
|
||||||
|
|
||||||
|
function find_nearest_node_id(nodes, point) {
|
||||||
|
const [lat, lon] = point;
|
||||||
|
let min_distance = 1e100;
|
||||||
|
let res = '';
|
||||||
|
for (let node_id in nodes) {
|
||||||
|
const curr_distance = haversine_distance(nodes[node_id], point);
|
||||||
|
if (curr_distance < min_distance) {
|
||||||
|
min_distance = curr_distance;
|
||||||
|
res = node_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
const shortest_path = noexcept((nodes, ways, start_point, end_point) => {
|
||||||
|
// const clean_nodes = nodes;
|
||||||
|
const count = {};
|
||||||
|
const aff = {};
|
||||||
|
const location = {};
|
||||||
|
const clean_nodes = {};
|
||||||
|
// TODO: delete this
|
||||||
|
let count1 = 0, tot = 0;
|
||||||
|
for (const way_id in ways) {
|
||||||
|
// sill_unwrap(way_id);
|
||||||
|
const st = new Set();
|
||||||
|
const [l, n] = get_row(ways, way_id);
|
||||||
|
for (let i = 0; i < n; ++i) {
|
||||||
|
l[i] = l[i].toString(); // critical
|
||||||
|
const curr = l[i];
|
||||||
|
if (st.has(curr)) continue;
|
||||||
|
st.add(curr);
|
||||||
|
if (location[curr]) {
|
||||||
|
location[curr][way_id] = i;
|
||||||
|
} else {
|
||||||
|
location[curr] = {[way_id]: i};
|
||||||
|
}
|
||||||
|
clean_nodes[curr] = nodes[curr];
|
||||||
|
if (count[curr]) {
|
||||||
|
if (count[curr] === 1) {
|
||||||
|
count1 -= 1;
|
||||||
|
}
|
||||||
|
++count[curr];
|
||||||
|
} else {
|
||||||
|
count[curr] = 1;
|
||||||
|
count1 += 1;
|
||||||
|
tot += 1;
|
||||||
|
}
|
||||||
|
if (aff[curr]) {
|
||||||
|
aff[curr][way_id] = true;
|
||||||
|
} else {
|
||||||
|
aff[curr] = {[way_id]: true};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sill(`One ratio: ${count1} / ${tot}`);
|
||||||
|
// sill_unwrap(aff);
|
||||||
|
const actual_start_node_id = find_nearest_node_id(clean_nodes, start_point);
|
||||||
|
const actual_end_node_id = find_nearest_node_id(clean_nodes, end_point);
|
||||||
|
// sill_unwrap(typeof (actual_start_node_id));
|
||||||
|
// sill(count);
|
||||||
|
const ch_dict = {};
|
||||||
|
const ch_dict_bench = {};
|
||||||
|
let f = 1;
|
||||||
|
for (const t in ways) {
|
||||||
|
// if (t === ways[aff[actual_start_node_id]]) sill('yes');
|
||||||
|
const [l, n] = get_row(ways, t);
|
||||||
|
// // TODO: delete this
|
||||||
|
// for (let i = 1; i < n; ++i) {
|
||||||
|
// const curr = l[i];
|
||||||
|
// const prev = l[i-1];
|
||||||
|
// const distance = haversine_distance(nodes[curr], nodes[prev]);
|
||||||
|
// if (ch_dict_bench[curr]) {
|
||||||
|
// ch_dict_bench[curr].push([prev, distance]);
|
||||||
|
// } else {
|
||||||
|
// ch_dict_bench[curr] = [[prev, distance]];
|
||||||
|
// }
|
||||||
|
// if (ch_dict_bench[prev]) {
|
||||||
|
// ch_dict_bench[prev].push([curr, distance]);
|
||||||
|
// } else {
|
||||||
|
// ch_dict_bench[prev] = [[curr, distance]];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
let prev = '';
|
||||||
|
let distance = 0;
|
||||||
|
for (let i = 0; i < n; ++i) {
|
||||||
|
const curr = l[i];
|
||||||
|
if (i) distance += haversine_distance(nodes[curr], nodes[l[i-1]]);
|
||||||
|
// if(true) {
|
||||||
|
if (count[curr] > 1 || curr === actual_end_node_id || curr === actual_start_node_id) {
|
||||||
|
// if (curr === actual_start_node_id) sill(curr === actual_start_node_id);
|
||||||
|
if (prev !== '') {
|
||||||
|
if (ch_dict[curr]) {
|
||||||
|
ch_dict[curr].push([prev, distance]);
|
||||||
|
} else {
|
||||||
|
ch_dict[curr] = [[prev, distance]];
|
||||||
|
}
|
||||||
|
if (ch_dict[prev]) {
|
||||||
|
ch_dict[prev].push([curr, distance]);
|
||||||
|
} else {
|
||||||
|
ch_dict[prev] = [[curr, distance]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev = curr;
|
||||||
|
distance = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// const clean_nodes = {};
|
||||||
|
// Object.keys(nodes).forEach((node_id) => {
|
||||||
|
// if (ch_dict[node_id]) clean_nodes[node_id] = nodes[node_id];
|
||||||
|
// });
|
||||||
|
sill(`start distance: ${haversine_distance(nodes[actual_start_node_id], start_point)}`);
|
||||||
|
sill(`dest distance: ${haversine_distance(nodes[actual_end_node_id], end_point)}`);
|
||||||
|
sill("calling __spa...");
|
||||||
|
// // TODO: delete this
|
||||||
|
// const seq = __spa(nodes, clean_nodes, ways, location, ch_dict, ch_dict_bench, count, aff, actual_start_node_id, actual_end_node_id);
|
||||||
|
const seq = __spa(clean_nodes, ways, location, ch_dict, count, aff, actual_start_node_id, actual_end_node_id);
|
||||||
|
const res = [end_point];
|
||||||
|
seq.forEach((node_id) => {
|
||||||
|
if (clean_nodes[node_id]) res.push(clean_nodes[node_id]);
|
||||||
|
});
|
||||||
|
res.push(start_point);
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
export default function handler(req, res) {
|
||||||
|
const pts = JSON.parse(req.body);
|
||||||
|
const latRange = pts.map((row) => row[0]),
|
||||||
|
lonRange = pts.map((row) => row[1]);
|
||||||
|
const minlon = Math.min(...lonRange) - 0.01, minlat = Math.min(...latRange) - 0.01,
|
||||||
|
maxlon = Math.max(...lonRange) + 0.01, maxlat = Math.max(...latRange) + 0.01;
|
||||||
|
if (haversine_distance([minlat, minlon], [maxlat, maxlon]) > 100) {
|
||||||
|
res.status(500);
|
||||||
|
sill('rejected');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const request_uri = `https://www.overpass-api.de/api/interpreter?data=[out:json];way[highway](${minlat},${minlon},${maxlat},${maxlon});(._;>;);out body;`;
|
||||||
|
sill(`Requesting ${request_uri}`);
|
||||||
|
const fetch_debug_response = fetch(request_uri).then((response) => {
|
||||||
|
return response.json();
|
||||||
|
});
|
||||||
|
fetch_debug_response.then((debug_response) => {
|
||||||
|
// sill(debug_response);
|
||||||
|
let ps = {};
|
||||||
|
let ws = {};
|
||||||
|
debug_response.elements.forEach((it) => {
|
||||||
|
if (it.type === "node") {
|
||||||
|
ps[it.id] = [it.lat, it.lon];
|
||||||
|
} else if (it.type === "way") {
|
||||||
|
ws[it.id] = it.nodes;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const path_found = shortest_path(ps, ws, pts[0], pts[pts.length - 1]);
|
||||||
|
res.status(200).json({
|
||||||
|
log: `Method: click\nArgs: ${pts}\nStatus: requested "${request_uri}", got response ${JSON.stringify(debug_response.elements)}`,
|
||||||
|
multipolyline: JSON.stringify(path_found),
|
||||||
|
// __debug_pts: ps
|
||||||
|
});
|
||||||
|
}).catch(e => {
|
||||||
|
console.debug(e);
|
||||||
|
res.status(500);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
import {__APP_VERSION__, __APP_INTRO__} from "../PublicProperty";
|
||||||
|
|
||||||
|
export default function handler(req,res){
|
||||||
|
res.status(200).json({
|
||||||
|
log: 'Method: handshake\nStatus: responded handshake request',
|
||||||
|
version: __APP_VERSION__,
|
||||||
|
intro: __APP_INTRO__,
|
||||||
|
});
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
|
@ -1,13 +1,14 @@
|
||||||
{
|
{
|
||||||
"name": "nanomap",
|
"name": "nanomap",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "nanomap",
|
"name": "nanomap",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@datastructures-js/priority-queue": "^6.3.0",
|
||||||
"@emotion/react": "^11.11.1",
|
"@emotion/react": "^11.11.1",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@mui/icons-material": "^5.14.18",
|
"@mui/icons-material": "^5.14.18",
|
||||||
|
@ -18,6 +19,12 @@
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-leaflet": "^4.2.1",
|
"react-leaflet": "^4.2.1",
|
||||||
"react-scripts": "5.0.1"
|
"react-scripts": "5.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "^7.23.4",
|
||||||
|
"@babel/core": "^7.23.5",
|
||||||
|
"@babel/plugin-proposal-private-property-in-object": "latest",
|
||||||
|
"@babel/preset-flow": "^7.23.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aashutoshrathi/word-wrap": {
|
"node_modules/@aashutoshrathi/word-wrap": {
|
||||||
|
@ -51,12 +58,90 @@
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/code-frame": {
|
"node_modules/@babel/cli": {
|
||||||
"version": "7.22.13",
|
"version": "7.23.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.23.4.tgz",
|
||||||
"integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
|
"integrity": "sha512-j3luA9xGKCXVyCa5R7lJvOMM+Kc2JEnAEIgz2ggtjQ/j5YUVgfsg/WsG95bbsgq7YLHuiCOzMnoSasuY16qiCw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/highlight": "^7.22.13",
|
"@jridgewell/trace-mapping": "^0.3.17",
|
||||||
|
"commander": "^4.0.1",
|
||||||
|
"convert-source-map": "^2.0.0",
|
||||||
|
"fs-readdir-recursive": "^1.1.0",
|
||||||
|
"glob": "^7.2.0",
|
||||||
|
"make-dir": "^2.1.0",
|
||||||
|
"slash": "^2.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"babel": "bin/babel.js",
|
||||||
|
"babel-external-helpers": "bin/babel-external-helpers.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3",
|
||||||
|
"chokidar": "^3.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/core": "^7.0.0-0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/cli/node_modules/commander": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/cli/node_modules/make-dir": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"pify": "^4.0.1",
|
||||||
|
"semver": "^5.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/cli/node_modules/pify": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/cli/node_modules/semver": {
|
||||||
|
"version": "5.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||||
|
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/cli/node_modules/slash": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/code-frame": {
|
||||||
|
"version": "7.23.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
|
||||||
|
"integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/highlight": "^7.23.4",
|
||||||
"chalk": "^2.4.2"
|
"chalk": "^2.4.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -72,20 +157,20 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/core": {
|
"node_modules/@babel/core": {
|
||||||
"version": "7.23.3",
|
"version": "7.23.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.5.tgz",
|
||||||
"integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==",
|
"integrity": "sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ampproject/remapping": "^2.2.0",
|
"@ampproject/remapping": "^2.2.0",
|
||||||
"@babel/code-frame": "^7.22.13",
|
"@babel/code-frame": "^7.23.5",
|
||||||
"@babel/generator": "^7.23.3",
|
"@babel/generator": "^7.23.5",
|
||||||
"@babel/helper-compilation-targets": "^7.22.15",
|
"@babel/helper-compilation-targets": "^7.22.15",
|
||||||
"@babel/helper-module-transforms": "^7.23.3",
|
"@babel/helper-module-transforms": "^7.23.3",
|
||||||
"@babel/helpers": "^7.23.2",
|
"@babel/helpers": "^7.23.5",
|
||||||
"@babel/parser": "^7.23.3",
|
"@babel/parser": "^7.23.5",
|
||||||
"@babel/template": "^7.22.15",
|
"@babel/template": "^7.22.15",
|
||||||
"@babel/traverse": "^7.23.3",
|
"@babel/traverse": "^7.23.5",
|
||||||
"@babel/types": "^7.23.3",
|
"@babel/types": "^7.23.5",
|
||||||
"convert-source-map": "^2.0.0",
|
"convert-source-map": "^2.0.0",
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"gensync": "^1.0.0-beta.2",
|
"gensync": "^1.0.0-beta.2",
|
||||||
|
@ -142,11 +227,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/generator": {
|
"node_modules/@babel/generator": {
|
||||||
"version": "7.23.3",
|
"version": "7.23.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.5.tgz",
|
||||||
"integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==",
|
"integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.23.3",
|
"@babel/types": "^7.23.5",
|
||||||
"@jridgewell/gen-mapping": "^0.3.2",
|
"@jridgewell/gen-mapping": "^0.3.2",
|
||||||
"@jridgewell/trace-mapping": "^0.3.17",
|
"@jridgewell/trace-mapping": "^0.3.17",
|
||||||
"jsesc": "^2.5.1"
|
"jsesc": "^2.5.1"
|
||||||
|
@ -425,9 +510,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-string-parser": {
|
"node_modules/@babel/helper-string-parser": {
|
||||||
"version": "7.22.5",
|
"version": "7.23.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz",
|
||||||
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
|
"integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
|
@ -462,22 +547,22 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helpers": {
|
"node_modules/@babel/helpers": {
|
||||||
"version": "7.23.2",
|
"version": "7.23.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.5.tgz",
|
||||||
"integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==",
|
"integrity": "sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/template": "^7.22.15",
|
"@babel/template": "^7.22.15",
|
||||||
"@babel/traverse": "^7.23.2",
|
"@babel/traverse": "^7.23.5",
|
||||||
"@babel/types": "^7.23.0"
|
"@babel/types": "^7.23.5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/highlight": {
|
"node_modules/@babel/highlight": {
|
||||||
"version": "7.22.20",
|
"version": "7.23.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz",
|
||||||
"integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
|
"integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-validator-identifier": "^7.22.20",
|
"@babel/helper-validator-identifier": "^7.22.20",
|
||||||
"chalk": "^2.4.2",
|
"chalk": "^2.4.2",
|
||||||
|
@ -488,9 +573,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/parser": {
|
"node_modules/@babel/parser": {
|
||||||
"version": "7.23.3",
|
"version": "7.23.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz",
|
||||||
"integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==",
|
"integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==",
|
||||||
"bin": {
|
"bin": {
|
||||||
"parser": "bin/babel-parser.js"
|
"parser": "bin/babel-parser.js"
|
||||||
},
|
},
|
||||||
|
@ -1896,6 +1981,23 @@
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/preset-flow": {
|
||||||
|
"version": "7.23.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.23.3.tgz",
|
||||||
|
"integrity": "sha512-7yn6hl8RIv+KNk6iIrGZ+D06VhVY35wLVf23Cz/mMu1zOr7u4MMP4j0nZ9tLf8+4ZFpnib8cFYgB/oYg9hfswA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-plugin-utils": "^7.22.5",
|
||||||
|
"@babel/helper-validator-option": "^7.22.15",
|
||||||
|
"@babel/plugin-transform-flow-strip-types": "^7.23.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/core": "^7.0.0-0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/preset-modules": {
|
"node_modules/@babel/preset-modules": {
|
||||||
"version": "0.1.6-no-external-plugins",
|
"version": "0.1.6-no-external-plugins",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
|
||||||
|
@ -1976,18 +2078,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/traverse": {
|
"node_modules/@babel/traverse": {
|
||||||
"version": "7.23.3",
|
"version": "7.23.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.5.tgz",
|
||||||
"integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==",
|
"integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.22.13",
|
"@babel/code-frame": "^7.23.5",
|
||||||
"@babel/generator": "^7.23.3",
|
"@babel/generator": "^7.23.5",
|
||||||
"@babel/helper-environment-visitor": "^7.22.20",
|
"@babel/helper-environment-visitor": "^7.22.20",
|
||||||
"@babel/helper-function-name": "^7.23.0",
|
"@babel/helper-function-name": "^7.23.0",
|
||||||
"@babel/helper-hoist-variables": "^7.22.5",
|
"@babel/helper-hoist-variables": "^7.22.5",
|
||||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||||
"@babel/parser": "^7.23.3",
|
"@babel/parser": "^7.23.5",
|
||||||
"@babel/types": "^7.23.3",
|
"@babel/types": "^7.23.5",
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"globals": "^11.1.0"
|
"globals": "^11.1.0"
|
||||||
},
|
},
|
||||||
|
@ -1996,11 +2098,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.23.3",
|
"version": "7.23.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.5.tgz",
|
||||||
"integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==",
|
"integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-string-parser": "^7.22.5",
|
"@babel/helper-string-parser": "^7.23.4",
|
||||||
"@babel/helper-validator-identifier": "^7.22.20",
|
"@babel/helper-validator-identifier": "^7.22.20",
|
||||||
"to-fast-properties": "^2.0.0"
|
"to-fast-properties": "^2.0.0"
|
||||||
},
|
},
|
||||||
|
@ -2283,6 +2385,19 @@
|
||||||
"postcss-selector-parser": "^6.0.10"
|
"postcss-selector-parser": "^6.0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@datastructures-js/heap": {
|
||||||
|
"version": "4.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@datastructures-js/heap/-/heap-4.3.2.tgz",
|
||||||
|
"integrity": "sha512-7/9QSsIZ+wMG3C9++mz9iOjdtTp9C036PISHvNjG3eyFO8nXOBJQFKgeV7M6/+EPl+oXXFRGBb8Ue60LsqTqGw=="
|
||||||
|
},
|
||||||
|
"node_modules/@datastructures-js/priority-queue": {
|
||||||
|
"version": "6.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@datastructures-js/priority-queue/-/priority-queue-6.3.0.tgz",
|
||||||
|
"integrity": "sha512-bJkryPys8zVYMCSjyBPYzJlw5V2kMeOYzGHRBXiGkwqTv8vZ/Ux5RO736T8Y6l3cH+ocbQV9UxlsFwA9qI4VhA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@datastructures-js/heap": "^4.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@emotion/babel-plugin": {
|
"node_modules/@emotion/babel-plugin": {
|
||||||
"version": "11.11.0",
|
"version": "11.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz",
|
||||||
|
@ -3617,6 +3732,13 @@
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
|
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@nicolo-ribaudo/chokidar-2": {
|
||||||
|
"version": "2.1.8-no-fsevents.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz",
|
||||||
|
"integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
|
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
|
||||||
"version": "5.1.1-v1",
|
"version": "5.1.1-v1",
|
||||||
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
|
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
|
||||||
|
@ -8477,6 +8599,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz",
|
||||||
"integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew=="
|
"integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew=="
|
||||||
},
|
},
|
||||||
|
"node_modules/fs-readdir-recursive": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/fs.realpath": {
|
"node_modules/fs.realpath": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
{
|
{
|
||||||
"name": "nanomap",
|
"name": "nanomap",
|
||||||
"version": "0.1.0",
|
"version": "0.1.4a",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@datastructures-js/priority-queue": "^6.3.0",
|
||||||
"@emotion/react": "^11.11.1",
|
"@emotion/react": "^11.11.1",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@mui/icons-material": "^5.14.18",
|
"@mui/icons-material": "^5.14.18",
|
||||||
|
@ -14,6 +15,12 @@
|
||||||
"react-leaflet": "^4.2.1",
|
"react-leaflet": "^4.2.1",
|
||||||
"react-scripts": "5.0.1"
|
"react-scripts": "5.0.1"
|
||||||
},
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "^7.23.4",
|
||||||
|
"@babel/core": "^7.23.5",
|
||||||
|
"@babel/plugin-proposal-private-property-in-object": "latest",
|
||||||
|
"@babel/preset-flow": "^7.23.3"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
"build": "react-scripts build",
|
"build": "react-scripts build",
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 63 KiB |
|
@ -6,7 +6,7 @@
|
||||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
|
||||||
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
|
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
|
||||||
crossorigin=""/>
|
crossorigin=""/>
|
||||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
<link rel="shortcut icon" href="%PUBLIC_URL%/icon.jpeg">
|
||||||
<!--
|
<!--
|
||||||
Notice the use of %PUBLIC_URL% in the tag above.
|
Notice the use of %PUBLIC_URL% in the tag above.
|
||||||
It will be replaced with the URL of the `public` folder during the build.
|
It will be replaced with the URL of the `public` folder during the build.
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
work correctly both with client-side routing and a non-root public URL.
|
work correctly both with client-side routing and a non-root public URL.
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
-->
|
-->
|
||||||
<title>React App</title>
|
<title>nanoMap</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|
124
src/App.js
124
src/App.js
|
@ -1,18 +1,126 @@
|
||||||
import React, { Component } from 'react';
|
import React, {Component, useState} from 'react';
|
||||||
import logo from './logo.svg';
|
import {Transition} from 'react-transition-group';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import UMap from "./UMap";
|
import UMap from "./UMap";
|
||||||
|
import {
|
||||||
|
Alert,
|
||||||
|
Box, Button,
|
||||||
|
CircularProgress,
|
||||||
|
DialogContent,
|
||||||
|
DialogTitle,
|
||||||
|
Modal, ModalClose,
|
||||||
|
ModalDialog,
|
||||||
|
Sheet,
|
||||||
|
Typography
|
||||||
|
} from "@mui/joy";
|
||||||
|
import {WebhookOutlined} from "@mui/icons-material";
|
||||||
|
import {post} from "./Networking";
|
||||||
|
|
||||||
class App extends Component {
|
export default function App() {
|
||||||
render() {
|
const [featureOpen, setFeatureOpen] = useState(true);
|
||||||
|
const [version, setVersion] = useState('');
|
||||||
|
const [intro, setIntro] = useState('');
|
||||||
|
const hs = setInterval(() => {
|
||||||
|
post('GET','handshake', []).then((response) => {
|
||||||
|
const {version, intro} = response;
|
||||||
|
setVersion(version);
|
||||||
|
setIntro(intro);
|
||||||
|
clearInterval(hs);
|
||||||
|
}).catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
setVersion('');
|
||||||
|
});
|
||||||
|
}, 2000);
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App" style={{pointerEvents: version !== '' ? 'all' : 'none'}}>
|
||||||
<div style={{display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
|
<div style={{display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
|
||||||
<UMap/>
|
<UMap/>
|
||||||
|
<Transition in={featureOpen} timeout={400}>
|
||||||
|
{(state) => (
|
||||||
|
<Modal style={{pointerEvents: version !== '' ? 'all' : 'none'}}
|
||||||
|
keepMounted
|
||||||
|
open={!['exited', 'exiting'].includes(state)}
|
||||||
|
onClose={() => setFeatureOpen(false)}
|
||||||
|
slotProps={{
|
||||||
|
backdrop: {
|
||||||
|
sx: {
|
||||||
|
opacity: 0,
|
||||||
|
backdropFilter: 'none',
|
||||||
|
transition: `opacity 400ms, backdrop-filter 400ms`,
|
||||||
|
...{
|
||||||
|
entering: {opacity: 1, backdropFilter: 'blur(8px)'},
|
||||||
|
entered: {opacity: 1, backdropFilter: 'blur(8px)'},
|
||||||
|
}[state],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
visibility: state === 'exited' ? 'hidden' : 'visible',
|
||||||
|
zIndex: 'tooltip'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ModalDialog
|
||||||
|
sx={{
|
||||||
|
opacity: 0,
|
||||||
|
transition: `opacity 300ms`,
|
||||||
|
...{
|
||||||
|
entering: {opacity: 1},
|
||||||
|
entered: {opacity: 1},
|
||||||
|
}[state],
|
||||||
|
display: 'flex',
|
||||||
|
width: version !== '' ? '60%' : 'auto',
|
||||||
|
height: 'auto',
|
||||||
|
maxWidth: '50vw',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Sheet sx={{display: 'flex',marginTop: version!==''?'5%':0, flexDirection: 'column'}}>
|
||||||
|
<Alert style={{display: version !== '' ? 'none' : 'flex'}}
|
||||||
|
variant="soft"
|
||||||
|
color="warning"
|
||||||
|
invertedColors
|
||||||
|
startDecorator={
|
||||||
|
<CircularProgress size="lg" color="warning">
|
||||||
|
<WebhookOutlined/>
|
||||||
|
</CircularProgress>
|
||||||
|
}
|
||||||
|
sx={{alignItems: 'flex-start', gap: '1rem'}}
|
||||||
|
>
|
||||||
|
<Box sx={{flex: 1}}>
|
||||||
|
<Typography level="title-lg">Still connecting...</Typography>
|
||||||
|
<Typography level="body-md">
|
||||||
|
nanoMap requires a valid backend to work. If it takes too long, please
|
||||||
|
check
|
||||||
|
your connection or see our status page.
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Alert>
|
||||||
|
<Sheet style={{display: version !== '' ? 'flex' : 'none'}}>
|
||||||
|
<img src={'icon.jpeg'}
|
||||||
|
style={{
|
||||||
|
height: '150px',
|
||||||
|
display: 'flex',
|
||||||
|
margin: 'auto',
|
||||||
|
borderRadius: '50%'
|
||||||
|
}}
|
||||||
|
alt={'nanoMap'}/>
|
||||||
|
</Sheet>
|
||||||
|
<DialogTitle style={{display: version !== '' ? 'flex' : 'none'}}
|
||||||
|
sx={{margin: 'auto', fontSize: '200%', textAlign: 'center'}}>What's new
|
||||||
|
in
|
||||||
|
nanoMap {version}</DialogTitle>
|
||||||
|
<DialogContent style={{display: version !== '' ? 'flex' : 'none'}}
|
||||||
|
sx={{margin: 'auto', maxWidth: '80%'}}>
|
||||||
|
<div dangerouslySetInnerHTML={{__html: intro}}/>
|
||||||
|
</DialogContent>
|
||||||
|
</Sheet>
|
||||||
|
<Sheet onClick={()=>setFeatureOpen(false)} sx={{display: version!==''?'flex':'none', bottom: '10%', width: '100%'}}>
|
||||||
|
<Button size="lg" sx={{width: '50%', maxWidth: '20vw', display: 'flex', margin: 'auto'}}>Done</Button>
|
||||||
|
</Sheet>
|
||||||
|
</ModalDialog>
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
export function post(method,args) {
|
import {sill} from "./tools/Debug";
|
||||||
const data = new FormData();
|
|
||||||
data.append('method', method)
|
export function post(type,method,args) {
|
||||||
data.append('payload', args.join(','));
|
|
||||||
let res = '';
|
|
||||||
let ft = async () => {
|
let ft = async () => {
|
||||||
const response = await fetch('http://127.0.0.1:825/', {
|
let response;
|
||||||
method: 'POST',
|
if(type==='GET'){
|
||||||
body: data
|
const payload=args.join('@@');
|
||||||
|
response = await fetch(`/api/${method}${payload.length?"?query=":""}${payload}`, {
|
||||||
|
method: 'GET',
|
||||||
});
|
});
|
||||||
const response_data = await response.text();
|
}else if(type==='POST'){
|
||||||
console.log(`Received: ${response_data}`);
|
response = await fetch(`/api/${method}`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(args),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const response_data = await response.json();
|
||||||
|
sill(`Request "${method}" finished:\n ${response_data.log.replaceAll('\n','\n ')}`);
|
||||||
return response_data;
|
return response_data;
|
||||||
};
|
};
|
||||||
return ft();
|
return ft();
|
||||||
};
|
}
|
|
@ -1,12 +1,13 @@
|
||||||
import {Button, IconButton, ButtonGroup, Menu, MenuItem, Stack} from "@mui/joy";
|
import {Button, IconButton, ButtonGroup, Menu, MenuItem, Stack} from "@mui/joy";
|
||||||
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
|
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import {Delete, LocationOn} from "@mui/icons-material";
|
||||||
|
|
||||||
export default function SimulateClick() {
|
export default function SimulateClick({isLocated,isMarkersEmpty,relocator,clearMarkers}) {
|
||||||
return (
|
return (
|
||||||
<ButtonGroup buttonFlex={1} aria-label="flex button group" sx={{zIndex: 'modal'}}>
|
<ButtonGroup buttonFlex={1} aria-label="flex button group" sx={{zIndex: 'modal'}}>
|
||||||
<Button variant={'solid'} color={'success'}>Starting</Button>
|
<Button disabled={isLocated} variant={'solid'} color={'warning'} startDecorator={<LocationOn />} onClick={relocator}>Relocate</Button>
|
||||||
<Button variant={'solid'} color={'primary'}>Destination</Button>
|
<Button disabled={isMarkersEmpty} variant={'solid'} color={'danger'} startDecorator={<Delete />} onClick={clearMarkers}>Clear</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
);
|
);
|
||||||
}
|
}
|
165
src/UMap.js
165
src/UMap.js
|
@ -1,34 +1,48 @@
|
||||||
import React, {Component, useEffect, useRef, useState} from 'react';
|
import React, {Component, useEffect, useRef, useState} from 'react';
|
||||||
import SearchIcon from '@mui/icons-material/Search';
|
import SearchIcon from '@mui/icons-material/Search';
|
||||||
import {MapContainer, TileLayer, Marker, Popup, useMap} from 'react-leaflet';
|
import {MapContainer, TileLayer, Marker, useMap, Polyline} from 'react-leaflet';
|
||||||
import {useMapEvents} from 'react-leaflet/hooks';
|
import {useMapEvents} from 'react-leaflet/hooks';
|
||||||
import {post} from './Networking';
|
import {post} from './Networking';
|
||||||
import {Autocomplete, CircularProgress, Sheet} from "@mui/joy";
|
import {Autocomplete, CircularProgress, Sheet} from "@mui/joy";
|
||||||
import SimulateClick from "./SimulateClick";
|
import SimulateClick from "./SimulateClick";
|
||||||
|
import {NearMe} from "@mui/icons-material";
|
||||||
|
import {sill} from "./tools/Debug";
|
||||||
|
|
||||||
const AppleParkLoc=[37.334835049999995,-122.01139165956805];
|
const defaultZoomLevel=16;
|
||||||
|
const defaultLocationName = 'Apple Park';
|
||||||
|
const defaultLocation = [37.334835049999995, -122.01139165956805];
|
||||||
|
|
||||||
class Markers extends Component {
|
class Markers extends Component {
|
||||||
|
// A location is a [lat,lon] pair.
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {markers: [], candMarkers: []};
|
this.state = {markers: [], candMarkers: [], mksEmpty: true, candEmpty: true, polylines: []};
|
||||||
|
this.clearMarkers = this.clearMarkers.bind(this);
|
||||||
|
this.clearCandMarkers = this.clearCandMarkers.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const fillBlueOptions = {fillColor: 'blue'};
|
||||||
|
const pl = this.state.polylines;
|
||||||
const mks = this.state.markers.map((p, i) => (
|
const mks = this.state.markers.map((p, i) => (
|
||||||
<Marker position={[p[0], p[1]]} opacity={1.0}><Popup>Generated
|
<Marker key={`m` + i} interactive={false} position={[p[0], p[1]]} opacity={1.0}/>
|
||||||
by <code>Markers()</code></Popup></Marker>
|
|
||||||
));
|
));
|
||||||
const cmks = this.state.candMarkers.map((p, i) => (
|
const cmks = this.state.candMarkers.map((p, i) => (
|
||||||
<Marker interactive={false} position={[p[0], p[1]]} opacity={0.5}><Popup>Generated
|
<Marker key={`c` + i} interactive={false} position={[p[0], p[1]]} opacity={0.5}/>
|
||||||
by <code>Markers()</code></Popup></Marker>
|
|
||||||
));
|
));
|
||||||
return mks.concat(cmks);
|
return [
|
||||||
|
...mks.concat(cmks),
|
||||||
|
pl && pl.length > 1 ? <Polyline pathOptions={fillBlueOptions} positions={pl}/> : <div/>
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
addMarker(lat, lng) {
|
addMarker(lat, lng) {
|
||||||
this.setState((prev) => ({
|
this.setState((prev) => ({
|
||||||
markers: [...prev.markers, [lat, lng]], candMarkers: prev.candMarkers,
|
markers: [...prev.markers, [lat, lng]],
|
||||||
|
candMarkers: prev.candMarkers,
|
||||||
|
mksEmpty: false,
|
||||||
|
candEmpty: prev.candEmpty,
|
||||||
|
polylines: prev.polylines,
|
||||||
}));
|
}));
|
||||||
this.getFocus();
|
this.getFocus();
|
||||||
}
|
}
|
||||||
|
@ -37,41 +51,85 @@ class Markers extends Component {
|
||||||
this.setState((prev) => ({
|
this.setState((prev) => ({
|
||||||
candMarkers: [...prev.candMarkers, [lat, lng]],
|
candMarkers: [...prev.candMarkers, [lat, lng]],
|
||||||
markers: prev.markers,
|
markers: prev.markers,
|
||||||
|
mksEmpty: prev.mksEmpty,
|
||||||
|
candEmpty: false,
|
||||||
|
polylines: prev.polylines,
|
||||||
|
}));
|
||||||
|
this.getFocus(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
clearMarkers() {
|
||||||
|
this.setState((prev) => ({
|
||||||
|
markers: [],
|
||||||
|
candMarkers: prev.candMarkers,
|
||||||
|
mksEmpty: true,
|
||||||
|
candEmpty: prev.candEmpty,
|
||||||
|
polylines: [],
|
||||||
}));
|
}));
|
||||||
this.getFocus();
|
this.getFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
clearMarkers() {
|
|
||||||
this.setState((prev) => ({markers: [], candMarkers: prev.candMarkers}));
|
|
||||||
this.getFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
clearCandMarkers() {
|
clearCandMarkers() {
|
||||||
this.setState((prev) => ({markers: prev.markers, candMarkers: []}));
|
this.setState((prev) => ({
|
||||||
|
markers: prev.markers,
|
||||||
|
candMarkers: [],
|
||||||
|
mksEmpty: prev.mksEmpty,
|
||||||
|
candEmpty: true,
|
||||||
|
polylines: prev.polylines,
|
||||||
|
}));
|
||||||
this.getFocus();
|
this.getFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
getFocus() {
|
getFocus(virtual=false) {
|
||||||
let currentFocus = [];
|
let currentFocus = [];
|
||||||
if (this.state.candMarkers.length) {
|
if (this.state.candMarkers.length) {
|
||||||
currentFocus = this.state.candMarkers.at(-1);
|
currentFocus = this.state.candMarkers.at(-1);
|
||||||
} else if (this.state.markers.length) {
|
} else if (this.state.markers.length) {
|
||||||
currentFocus = this.state.markers.at(-1);
|
currentFocus = this.state.markers.at(-1);
|
||||||
} else {
|
} else {
|
||||||
currentFocus=AppleParkLoc;
|
currentFocus = defaultLocation;
|
||||||
}
|
}
|
||||||
this.props.focusUpdater(currentFocus);
|
this.props.focusUpdater(currentFocus);
|
||||||
|
if(virtual){
|
||||||
|
this.props.locator(currentFocus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function MapClickHandler({mks}) {
|
flushPolylines(pl, clear=true) {
|
||||||
|
this.setState((prev) => ({
|
||||||
|
markers: prev.markers,
|
||||||
|
candMarkers: prev.candMarkers,
|
||||||
|
mksEmpty: prev.mksEmpty,
|
||||||
|
candEmpty: prev.candEmpty,
|
||||||
|
polylines: clear ? pl : [...pl, ...prev.polylines], // mind the ordering
|
||||||
|
}));
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function MapClickHandler({mks,focusUpdater,locator,locker}) {
|
||||||
const map = useMapEvents({
|
const map = useMapEvents({
|
||||||
click: (e) => {
|
click: (e) => {
|
||||||
map.locate();
|
map.locate();
|
||||||
const lat = e.latlng.lat, lng = e.latlng.lng;
|
const {lat,lng}=e.latlng;
|
||||||
console.info(`Clicking on ${lat} ${lng}`);
|
sill(`Clicking on ${lat} ${lng}`);
|
||||||
mks.current.addMarker(lat, lng);
|
mks.current.addMarker(lat, lng);
|
||||||
post('click', [lat, lng]);
|
post('POST', 'click', mks.current.state.markers.slice(-2)).then((response) => {
|
||||||
|
// TODO: real functionality
|
||||||
|
const pl = JSON.parse(response.multipolyline);
|
||||||
|
// DEBUG
|
||||||
|
// response.__debug_pts.forEach(({lat,lon})=>{
|
||||||
|
// mks.current.addCandMarker(lat,lon);
|
||||||
|
// });
|
||||||
|
sill(`pl = ${JSON.stringify(pl)}`);
|
||||||
|
if (pl.length > 1) mks.current.flushPolylines(pl, false);
|
||||||
|
focusUpdater([lat,lng]);
|
||||||
|
locator([lat,lng]);
|
||||||
|
locker(true);
|
||||||
|
}).catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
// location.reload();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
// TODO
|
// TODO
|
||||||
locationfound: (location) => {
|
locationfound: (location) => {
|
||||||
|
@ -81,11 +139,21 @@ function MapClickHandler({mks}) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LocationSearch = ({mks}) => {
|
const LocationSearch = ({mks, focus, nb}) => {
|
||||||
const [query, setQuery] = useState('');
|
const [query, setQuery] = useState('');
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [suggestedLocations, setSuggestedLocations] = useState([]);
|
const [suggestedLocations, setSuggestedLocations] = useState([]);
|
||||||
const [controller, setController] = useState(new AbortController());
|
const [controller, setController] = useState(new AbortController());
|
||||||
|
const [everywhere,setEverywhere]=useState(false);
|
||||||
|
|
||||||
|
const SearchLogo=()=>{
|
||||||
|
const cf=()=>setEverywhere(!everywhere);
|
||||||
|
if(everywhere){
|
||||||
|
return <SearchIcon onClick={cf}/>;
|
||||||
|
} else{
|
||||||
|
return <NearMe onClick={cf}/>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => controller.abort();
|
return () => controller.abort();
|
||||||
|
@ -103,7 +171,7 @@ const LocationSearch = ({mks}) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`https://nominatim.openstreetmap.org/search?format=json&q=${v}`,
|
`https://nominatim.openstreetmap.org/search?format=json&q=${v}${everywhere?'':' '+focus[0]+','+focus[1]}`,
|
||||||
{signal: newController.signal}
|
{signal: newController.signal}
|
||||||
);
|
);
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
@ -130,9 +198,11 @@ const LocationSearch = ({mks}) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return <Autocomplete sx={{zIndex: 'snackbar'}} loading={loading} loadingText={"Searching..."} startDecorator={<SearchIcon/>}
|
return <Autocomplete sx={{zIndex: 'snackbar'}} loading={loading} loadingText={"Searching..."}
|
||||||
placeholder={'Find a location...'} onInputChange={handleSearch}
|
startDecorator={<SearchLogo/>}
|
||||||
options={suggestedLocations} isOptionEqualToValue={(option, value) => option.value === value.value} endDecorator={
|
placeholder={everywhere?'Search everywhere...':`Search near${nb}`} onInputChange={handleSearch}
|
||||||
|
options={suggestedLocations}
|
||||||
|
isOptionEqualToValue={(option, value) => option.value === value.value} endDecorator={
|
||||||
loading ? (
|
loading ? (
|
||||||
<CircularProgress size="sm" sx={{bgcolor: 'background.surface'}}/>
|
<CircularProgress size="sm" sx={{bgcolor: 'background.surface'}}/>
|
||||||
) : null
|
) : null
|
||||||
|
@ -146,9 +216,35 @@ function ChangeView({center,zoom}){
|
||||||
|
|
||||||
export default function UMap() {
|
export default function UMap() {
|
||||||
const markersRef = useRef(null);
|
const markersRef = useRef(null);
|
||||||
const [focus, setFocus]=useState([37.334835049999995,-122.01139165956805]);
|
const [focus, setFocus] = useState(defaultLocation);
|
||||||
const zoom=13;
|
const [located,setLocated]=useState(true);
|
||||||
const sf=(a)=>{setFocus(a);console.log(`triggered focus update, new focus is ${focus}`);};
|
const [locatedFocus,setLocatedFocus]=useState(defaultLocation);
|
||||||
|
const [nearbyName, setNearbyName] = useState(' ' + defaultLocationName);
|
||||||
|
const [zoom,setZoom] = useState(defaultZoomLevel);
|
||||||
|
const sf = (a) => {
|
||||||
|
setFocus(a);
|
||||||
|
sill(`triggered focus update, new focus is ${focus}`);
|
||||||
|
const ft = fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${a[0]}&lon=${a[1]}&zoom=${zoom}&addressdetails=0`).then(response => response.json());
|
||||||
|
ft.then((response) => setNearbyName(' ' + response.name)).catch(() => setNearbyName('by'));
|
||||||
|
};
|
||||||
|
const relo=()=> {
|
||||||
|
sf(locatedFocus);
|
||||||
|
setLocated(true);
|
||||||
|
};
|
||||||
|
const ViewportChange = () => {
|
||||||
|
const map = useMapEvents({
|
||||||
|
dragend: (e) => {
|
||||||
|
const center = e.target.getCenter();
|
||||||
|
sf([center.lat, center.lng]);
|
||||||
|
setLocated(false);
|
||||||
|
},
|
||||||
|
zoomend: (e)=>{
|
||||||
|
setZoom(e.target.getZoom());
|
||||||
|
sf(focus);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<Sheet>
|
<Sheet>
|
||||||
<MapContainer style={{height: '100vh', width: '100vw',}} sx={{zIndex: 'fab'}} center={focus} zoom={zoom}
|
<MapContainer style={{height: '100vh', width: '100vw',}} sx={{zIndex: 'fab'}} center={focus} zoom={zoom}
|
||||||
|
@ -158,12 +254,13 @@ export default function UMap() {
|
||||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||||
/>
|
/>
|
||||||
<Markers ref={markersRef} focusUpdater={sf}/>
|
<Markers ref={markersRef} focusUpdater={sf} locator={setLocatedFocus} />
|
||||||
<MapClickHandler mks={markersRef}/>
|
<MapClickHandler mks={markersRef} focusUpdater={setFocus} locator={setLocatedFocus} locker={setLocated}/>
|
||||||
|
<ViewportChange/>
|
||||||
</MapContainer>
|
</MapContainer>
|
||||||
<Sheet sx={{position: 'absolute', top: '20px', left: '10vw', zIndex: 'modal'}}>
|
<Sheet sx={{position: 'absolute', top: '20px', right: '10vw', zIndex: 'modal'}}>
|
||||||
<SimulateClick />
|
<SimulateClick isLocated={located} relocator={relo} isMarkersEmpty={markersRef.current ? markersRef.current.state.mksEmpty : true} clearMarkers={markersRef.current ? markersRef.current.clearMarkers : null}/>
|
||||||
<LocationSearch mks={markersRef}/>
|
<LocationSearch nb={nearbyName} mks={markersRef} focus={focus}/>
|
||||||
</Sheet>
|
</Sheet>
|
||||||
</Sheet>
|
</Sheet>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
import shortestPath from "../comp/ShortestPath.js";
|
||||||
|
console.log('Hello!');
|
|
@ -0,0 +1,28 @@
|
||||||
|
// no dependencies
|
||||||
|
import {__DEBUG__} from "../PublicProperty";
|
||||||
|
|
||||||
|
export function noexcept(_f) {
|
||||||
|
/**
|
||||||
|
* No exceptions.
|
||||||
|
* @returns {*}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function _wrap() {
|
||||||
|
try {
|
||||||
|
return _f.apply(this, arguments);
|
||||||
|
} catch (e) {
|
||||||
|
console.debug(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const sill = noexcept((_x) => {
|
||||||
|
if(__DEBUG__) {
|
||||||
|
console.log(_x);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const sill_unwrap = noexcept((_x) => {
|
||||||
|
sill(JSON.stringify(_x));
|
||||||
|
});
|
|
@ -0,0 +1,14 @@
|
||||||
|
import {noexcept, sill, sill_unwrap} from "./Debug";
|
||||||
|
|
||||||
|
export const get_row = noexcept((_a,_i) => {
|
||||||
|
const row = _a[_i];
|
||||||
|
return [row, row.length];
|
||||||
|
});
|
||||||
|
|
||||||
|
export const find_common = noexcept((_iterable_1, _iterable_2) => {
|
||||||
|
for(const [k,_] of Object.entries(_iterable_2)) {
|
||||||
|
if (_iterable_1[k] === true) {
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,31 @@
|
||||||
|
import * as SP from "./ShortestPath";
|
||||||
|
import {sill} from "./Debug";
|
||||||
|
import {get_row} from "./Misc";
|
||||||
|
|
||||||
|
export default function benchmark(nodes, clean_nodes, ways, location, ch_dict, ch_dict_bench, count, aff, actual_start_node_id, actual_end_node_id) {
|
||||||
|
sill(`==========PathBench==========`);
|
||||||
|
let start_time, end_time;
|
||||||
|
let res, _;
|
||||||
|
//benchmark Obvious-Dijkstra
|
||||||
|
start_time = performance.now();
|
||||||
|
res = SP.obvious_dijkstra(clean_nodes, ways, location, ch_dict, count, aff, actual_start_node_id, actual_end_node_id);
|
||||||
|
end_time = performance.now();
|
||||||
|
sill(`Obvious-Dijkstra run-time: ${end_time - start_time} ms`);
|
||||||
|
// benchmark Obvious-A-Star
|
||||||
|
start_time = performance.now();
|
||||||
|
res = SP.obvious_a_star(clean_nodes, ways, location, ch_dict, count, aff, actual_start_node_id, actual_end_node_id);
|
||||||
|
end_time = performance.now();
|
||||||
|
sill(`Obvious-A-Star run-time: ${end_time - start_time} ms`);
|
||||||
|
// benchmark Obvious-Adaptive-A-Star
|
||||||
|
start_time = performance.now();
|
||||||
|
_ = SP.obvious_a_star(clean_nodes, ways, location, ch_dict, count, aff, actual_start_node_id, actual_end_node_id, true);
|
||||||
|
end_time = performance.now();
|
||||||
|
sill(`Obvious-Adaptive-A-Star run-time: ${end_time - start_time} ms`);
|
||||||
|
// benchmark Dijkstra
|
||||||
|
start_time = performance.now();
|
||||||
|
res = SP.dijkstra(nodes, ways, location, ch_dict_bench, count, aff, actual_start_node_id, actual_end_node_id);
|
||||||
|
end_time = performance.now();
|
||||||
|
sill(`Dijkstra run-time: ${end_time - start_time} ms`);
|
||||||
|
sill(`==============================`);
|
||||||
|
return res;
|
||||||
|
}
|
|
@ -0,0 +1,250 @@
|
||||||
|
import {MinPriorityQueue} from "@datastructures-js/priority-queue";
|
||||||
|
import {sill, noexcept, sill_unwrap} from "./Debug";
|
||||||
|
import {find_common} from "./Misc";
|
||||||
|
|
||||||
|
function __haversine_distance(p1, p2) {
|
||||||
|
const toRadians = (degrees) => {
|
||||||
|
return degrees * Math.PI / 180;
|
||||||
|
};
|
||||||
|
const [lat1, lon1] = p1;
|
||||||
|
const [lat2, lon2] = p2;
|
||||||
|
const R = 6371;
|
||||||
|
const dLat = toRadians(lat2 - lat1);
|
||||||
|
const dLon = toRadians(lon2 - lon1);
|
||||||
|
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||||||
|
Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
|
||||||
|
Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
||||||
|
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||||
|
if (R * c < 0) console.warn("WARNING!!!");
|
||||||
|
return R * c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use Dijkstra algorithm to find the shortest path.
|
||||||
|
* @param nodes node index list
|
||||||
|
* @param ways unused in this implementation
|
||||||
|
* @param loc unused in this implementation
|
||||||
|
* @param ch adjacent table
|
||||||
|
* @param count unused in this implementation
|
||||||
|
* @param aff unused in this implementation
|
||||||
|
* @param u start node id
|
||||||
|
* @param p destination node id
|
||||||
|
*/
|
||||||
|
function __dijkstra(nodes, ways, loc, ch, count, aff, u, p) {
|
||||||
|
// sill(`node count: ${Object.keys(nodes).length}`);
|
||||||
|
const dis = {};
|
||||||
|
const fa = {};
|
||||||
|
const vis = new Set();
|
||||||
|
const pq = new MinPriorityQueue();
|
||||||
|
dis[u] = 0;
|
||||||
|
pq.push([0, u]);
|
||||||
|
while (!pq.isEmpty()) {
|
||||||
|
const [d, v] = pq.pop();
|
||||||
|
if (vis.has(v) || !ch[v]) continue;
|
||||||
|
if (v === p) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vis.add(v);
|
||||||
|
const t = ch[v].length;
|
||||||
|
for (let j = 0; j < t; ++j) {
|
||||||
|
const [c, w] = ch[v][j];
|
||||||
|
if (!nodes[c]) continue;
|
||||||
|
// const w = get_weight(v, c);
|
||||||
|
if (!dis[c] || d + w < dis[c]) {
|
||||||
|
dis[c] = d + w;
|
||||||
|
pq.push([dis[c], c]);
|
||||||
|
fa[c] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let curr = p;
|
||||||
|
const res = [p];
|
||||||
|
vis.clear();
|
||||||
|
while (fa[curr]) {
|
||||||
|
curr = fa[curr].toString();
|
||||||
|
if (vis.has(curr)) {
|
||||||
|
// sill(`Cycle at ${curr}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vis.add(curr);
|
||||||
|
res.push(curr);
|
||||||
|
}
|
||||||
|
// sill("finished Dijkstra.");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use Dijkstra algorithm with Obvious optimization to find the shortest path.
|
||||||
|
* @param nodes node index list
|
||||||
|
* @param ways node list for each way
|
||||||
|
* @param loc relative location in the way
|
||||||
|
* @param ch adjacent table
|
||||||
|
* @param count determine isolated nodes
|
||||||
|
* @param aff affiliation of isolated nodes
|
||||||
|
* @param u start node id
|
||||||
|
* @param p destination node id
|
||||||
|
*/
|
||||||
|
function __obvious_dijkstra(nodes, ways, loc, ch, count, aff, u, p) {
|
||||||
|
// sill(`node count: ${Object.keys(nodes).length}`);
|
||||||
|
const dis = {};
|
||||||
|
const fa = {};
|
||||||
|
const vis = new Map();
|
||||||
|
const pq = new MinPriorityQueue();
|
||||||
|
dis[u] = 0;
|
||||||
|
pq.push([0, u]);
|
||||||
|
while (!pq.isEmpty()) {
|
||||||
|
const [d, v] = pq.pop();
|
||||||
|
if (vis.has(v) || !ch[v]) {
|
||||||
|
// sill(!ch[v]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (v === p) {
|
||||||
|
// sill('break');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// sill('loop');
|
||||||
|
vis.set(v,true);
|
||||||
|
const t = ch[v].length;
|
||||||
|
for (let j = 0; j < t; ++j) {
|
||||||
|
const [c, w] = ch[v][j];
|
||||||
|
if (!nodes[c]) continue;
|
||||||
|
// sill(w);
|
||||||
|
if ((!dis[c] || d + w < dis[c])) {
|
||||||
|
dis[c] = d + w;
|
||||||
|
pq.push([dis[c], c]);
|
||||||
|
fa[c] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// sill_unwrap(fa);
|
||||||
|
let curr = p;
|
||||||
|
const res = [p];
|
||||||
|
vis.clear();
|
||||||
|
while (fa[curr]) {
|
||||||
|
const prev = curr;
|
||||||
|
curr = fa[curr];
|
||||||
|
if (vis.has(curr)) {
|
||||||
|
// sill(`Cycle at ${curr}`);
|
||||||
|
// sill(res);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vis.set(curr,true);
|
||||||
|
|
||||||
|
// res.push(curr);
|
||||||
|
const way_id = find_common(aff[prev], aff[curr]);
|
||||||
|
const way = ways[way_id];
|
||||||
|
if(!way) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const p_oc = loc[prev][way_id];
|
||||||
|
const c_oc = loc[curr][way_id];
|
||||||
|
if (p_oc < c_oc) {
|
||||||
|
for (let _p = p_oc + 1; _p <= c_oc; ++_p) {
|
||||||
|
res.push(way[_p]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let _p = p_oc - 1; _p >= c_oc; --_p) {
|
||||||
|
res.push(way[_p]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// sill("finished Obvious Dijkstra.");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use A-star algorithm with Obvious optimization to find the shortest path.
|
||||||
|
* @param nodes node index list
|
||||||
|
* @param ways node list for each way
|
||||||
|
* @param loc relative location in the way
|
||||||
|
* @param ch adjacent table
|
||||||
|
* @param count determine isolated nodes
|
||||||
|
* @param aff affiliation of isolated nodes
|
||||||
|
* @param u start node id
|
||||||
|
* @param p destination node id
|
||||||
|
* @param adaptive if the coefficient is hard-coded
|
||||||
|
*/
|
||||||
|
function __obvious_a_star(nodes, ways, loc, ch, count, aff, u, p, adaptive = false) {
|
||||||
|
// sill(`node count: ${Object.keys(nodes).length}`);
|
||||||
|
const default_coefficient = 1.1;
|
||||||
|
const linear = (y) => y;
|
||||||
|
const curve = (y) => 0.8 * y * y;
|
||||||
|
const inversed_sigmoid = (y) => Math.log(y/(1.0-y));
|
||||||
|
const heuristic = (current_distance, node_id) => {
|
||||||
|
const estimate = haversine_distance(nodes[node_id], nodes[p]);
|
||||||
|
const coef = (!adaptive) ? default_coefficient : (
|
||||||
|
default_coefficient * curve(current_distance / (current_distance + estimate))
|
||||||
|
);
|
||||||
|
return coef * estimate;
|
||||||
|
};
|
||||||
|
const dis = {};
|
||||||
|
const fa = {};
|
||||||
|
const vis = new Map();
|
||||||
|
const pq = new MinPriorityQueue();
|
||||||
|
dis[u] = 0;
|
||||||
|
pq.push([0, 0, u]);
|
||||||
|
while (!pq.isEmpty()) {
|
||||||
|
const [_, d, v] = pq.pop();
|
||||||
|
if (vis.has(v) || !ch[v]) {
|
||||||
|
// sill(!ch[v]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (v === p) {
|
||||||
|
// sill('break');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// sill('loop');
|
||||||
|
vis.set(v,true);
|
||||||
|
const t = ch[v].length;
|
||||||
|
for (let j = 0; j < t; ++j) {
|
||||||
|
const [c, w] = ch[v][j];
|
||||||
|
if (!nodes[c]) continue;
|
||||||
|
// sill(w);
|
||||||
|
if ((!dis[c] || d + w < dis[c])) {
|
||||||
|
dis[c] = d + w;
|
||||||
|
pq.push([dis[c] + heuristic(dis[c], c), dis[c], c]);
|
||||||
|
fa[c] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// sill_unwrap(fa);
|
||||||
|
let curr = p;
|
||||||
|
const res = [p];
|
||||||
|
vis.clear();
|
||||||
|
while (fa[curr]) {
|
||||||
|
const prev = curr;
|
||||||
|
curr = fa[curr];
|
||||||
|
if (vis.has(curr)) {
|
||||||
|
// sill(`Cycle at ${curr}`);
|
||||||
|
// sill(res);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vis.set(curr,true);
|
||||||
|
|
||||||
|
// res.push(curr);
|
||||||
|
const way_id = find_common(aff[prev], aff[curr]);
|
||||||
|
const way = ways[way_id];
|
||||||
|
if(!way) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const p_oc = loc[prev][way_id];
|
||||||
|
const c_oc = loc[curr][way_id];
|
||||||
|
if (p_oc < c_oc) {
|
||||||
|
for (let _p = p_oc + 1; _p <= c_oc; ++_p) {
|
||||||
|
res.push(way[_p]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let _p = p_oc - 1; _p >= c_oc; --_p) {
|
||||||
|
res.push(way[_p]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// sill("finished Obvious Dijkstra.");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const haversine_distance = noexcept(__haversine_distance);
|
||||||
|
export const dijkstra = noexcept(__dijkstra);
|
||||||
|
export const obvious_dijkstra = noexcept(__obvious_dijkstra);
|
||||||
|
export const obvious_a_star = noexcept(__obvious_a_star);
|
Loading…
Reference in New Issue