BangleApps/apps/golfview/custom.html

206 lines
7.1 KiB
HTML
Raw Normal View History

<html>
<head>
<link rel="stylesheet" href="../../css/spectre.min.css">
2022-04-03 05:52:47 +00:00
<script src="https://cdn.jsdelivr.net/gh/mourner/simplify-js@1.2.4/simplify.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
</head>
2022-04-26 05:55:58 +00:00
<style>
#searchresults ul {
list-style-type: none;
margin: 0;
padding: 0;
}
#searchresults ul li a {
display: block;
width: 100%;
text-decoration: none;
padding: 5px;
}
#searchresults ul li a:hover {
background-color: #ccc;
}
</style>
<body>
2022-04-05 18:18:21 +00:00
<div>
2022-04-26 05:55:58 +00:00
<input type="text" placeholder="Whistling Straits" id="course_id">
2022-04-09 00:30:34 +00:00
<button type="button" onclick="courseSearch();">Search</button>
2022-04-26 05:55:58 +00:00
<ul id="searchresults"></ul>
2022-04-09 00:30:34 +00:00
<div>
2022-04-26 05:55:58 +00:00
<p id="status">No course loaded.</p>
2022-04-09 00:30:34 +00:00
<button id="upload" class="btn btn-primary" disabled="true">Upload to Device</button>
<button id="download" class="btn btn-primary" disabled="true">Download Course</button>
</div>
2022-04-26 05:55:58 +00:00
<div>
<p>A course needs a few things to be parsed correctly by this tool.</p>
<ul>
<li>See official mapping guidelines <a
href="https://wiki.openstreetmap.org/wiki/Tag:leisure%3Dgolf_course">here</a>.</li>
<li>All holes and features must be within the target course's area.</li>
<li>Supported features are greens, fairways, tees, bunkers, water hazards and holes.</li>
<li>All features for a given hole should have the "ref" tag with the hole number as value. Shared features
should
list ref values separated by ';'. <a href="https://www.openstreetmap.org/way/36896320">example</a>.</li>
<li>There must be 18 holes and they must have the following tags: handicap, par, ref, dist</li>
<li>For any mapping assistance or issues, please file in the <a
href="https://github.com/espruino/BangleApps/issues/new?assignees=&labels=bug&template=bangle-bug-report-custom-form.yaml&title=[golfview]+Short+description+of+bug">official
repo</a></li>
</ul>
<a href="https://www.openstreetmap.org/way/25447898">Example Course</a>
</div>
<footer>
<hr />
<a href="https://www.openstreetmap.org/copyright">© OpenStreetMap contributors</p>
</footer>
2022-04-05 18:18:21 +00:00
</div>
<script src="../../core/lib/customize.js"></script>
<script src="./maptools.js"></script>
<script>
const url = "https://overpass-api.de/api/interpreter";
2022-04-26 05:55:58 +00:00
const search_url = "https://nominatim.openstreetmap.org/search";
let search_query = null;
let course_input = null;
2022-04-26 05:55:58 +00:00
let search_results = $("#searchresults");
2022-04-09 00:30:34 +00:00
function courseSearch() {
let inputVal = document.getElementById("course_id").value;
2022-04-26 05:55:58 +00:00
search_query = {
"format": "jsonv2",
"q": inputVal,
};
doSearch();
// query = `[out:json][timeout:5];way(${inputVal});map_to_area ->.golfcourse;way["golf"="hole"](area.golfcourse)->.holes;(relation["golf"="fairway"](area.golfcourse);way["golf"~"^(green|tee|water_hazard|bunker|fairway)"](area.golfcourse);)->.features;.holes out geom;.features out geom;`;
// doQuery();
2022-04-09 00:30:34 +00:00
}
function processFeatures(course_verbose) {
let course_processed = {
holes: {}
};
for (let i = 0; i < course_verbose.length; i++) {
const element = course_verbose[i];
2022-04-07 19:56:53 +00:00
if (element.tags.golf === "hole") {
// if we find a high-level hole feature
2022-04-07 19:56:53 +00:00
// todo check if hole exists
let current_hole = parseInt(element.tags.ref); //subsequent way features should be applied to the current hole
let tees = []
Object.keys(element.tags).forEach((key) => {
if (key.includes("dist")) {
tees.push(Math.round(element.tags[key]));
}
2022-04-07 19:56:53 +00:00
})
var hole = {
hole_number: current_hole,
handicap: parseInt(element.tags.handicap),
par: parseInt(element.tags.par),
nodesXY: preprocessCoords(element.geometry, element.geometry[0]),
tees: tees.sort(),
way: element.geometry,
features: [],
angle: 0,
}
2022-04-07 19:56:53 +00:00
hole.angle = angle(hole.nodesXY[0], hole.nodesXY[hole.nodesXY.length - 1])
course_processed.holes[current_hole.toString()] = hole;
}
2022-04-07 20:20:56 +00:00
else {
2022-04-07 19:56:53 +00:00
if (!("ref" in element.tags)) continue;
2022-04-08 00:29:21 +00:00
if (element.type === "relation") {
2022-04-07 20:20:56 +00:00
for (member of element.members) {
if (member.role === "outer") break; // only use the outer because it is overwritten anyway
}
Object.assign(element, { "geometry": member.geometry });
}
// if we find a feature add it to the corresponding hole
2022-04-07 19:56:53 +00:00
let active_holes = element.tags.ref.split(";"); // a feature can be on more than one hole
for (feature_hole of active_holes) {
let new_feature = {
2022-04-07 20:52:59 +00:00
nodesXY: preprocessCoords(element.geometry, course_processed.holes[feature_hole].way[0]),
type: element.tags.golf,
id: element.id,
}
2022-04-07 19:56:53 +00:00
course_processed.holes[feature_hole].features.push(new_feature);
}
}
}
return course_processed;
}
2022-04-07 19:56:53 +00:00
function preprocessCoords(coord_array, origin) {
let many_points = arraytoXY(coord_array, origin);
let less_points = simplify(many_points, 2, true); // from simplify-js
2022-04-07 19:56:53 +00:00
// convert to int to save some memory
less_points = less_points.map(function (pt) {
return { x: Math.round(pt.x), y: Math.round(pt.y) }
});
return less_points;
}
2022-04-05 20:31:24 +00:00
var courses = [];
2022-04-05 19:59:09 +00:00
var course_name = "Davis";
2022-04-05 18:18:21 +00:00
$("#upload").click(function () {
sendCustomizedApp({
2022-04-07 21:35:57 +00:00
storage: courses,
2022-04-05 18:18:21 +00:00
});
});
$("#download").click(function () {
2022-04-07 20:29:54 +00:00
downloadObjectAsJSON(courses[0].content, "golfcourse-" + course_name);
2022-04-05 18:18:21 +00:00
});
2022-04-26 05:55:58 +00:00
// download info from the course
function doSearch() {
$.get(search_url, search_query, function (result) {
if (result.length === 0) {
$('#status').text("Course not found!");
return;
}
search_results.empty();
for (let index = 0; index < result.length; index++) {
const element = result[index];
if (element.type != "golf_course") continue;
search_results.append($("<li>").append($("<a>").attr('href', 'google.com').text(element.display_name)));
}
})
}
// download info from the course
2022-04-09 00:30:34 +00:00
function doQuery() {
$.post(url, query, function (result) {
if (result.elements.length === 0) {
$('#status').text("Course not found!");
return;
}
course_input = result;
console.log(course_input);
out = processFeatures(course_input.elements);
console.log(out);
courses.push({
name: "golfcourse-" + course_name + ".json",
content: JSON.stringify(out),
});
$('#status').text("Course retrieved!");
$('#upload').attr("disabled", false);
$('#download').attr("disabled", false);
})
}
</script>
</body>
</html>