| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- "use strict";
- let puzzeltocht = undefined;
- window.addEventListener("DOMContentLoaded", () => {
- puzzeltocht = new Puzzeltocht();
- });
- class Puzzeltocht {
- constructor() {
- this.errorCount = 0;
- this.joinScreen = new JoinScreen();
- this.joinScreen.setJoinListener((e, t) => this.start(e, t));
- this.missionScreen = new MissionScreen();
- this.missionScreen.setAnswerListener(e => this.answer(e));
- this.location = new LocationApi();
- console.log("puzzeltocht initialised");
- }
- start(eventId, teamId) {
- this.eventId = this.joinScreen.eventId;
- this.teamId = teamId;
- document.getElementById("join").style.display = "none";
- document.getElementById("mission").style.display = "block";
- this.location.enable(p => this.updateLocation(p))
- }
- answer(a) {
- this.lastUpdate = Date.now();
- Api.sendUpdate(this.eventId, this.teamId, this.position, a)
- .then(m => {
- this.missionScreen.update(m);
- this.errorCount = 0;
- })
- .catch(e => this.onError(e));
- }
- updateLocation(position) {
- let l = document.getElementById("location");
- if (position.accuracy() > 20 && window.location.hostname !== "localhost") {
- l.innerText = "Onbetrouwbare locatie: " + position.string();
- return;
- }
- this.position = position;
- l.innerText = position.string();
- if (this.lastUpdate === undefined || Date.now() - this.lastUpdate > 5000) {
- Api.sendUpdate(this.eventId, this.teamId, position)
- .then(m => {
- this.missionScreen.update(m);
- this.lastUpdate = Date.now();
- this.errorCount = 0;
- })
- .catch(e => this.onError(e));
- }
- }
- onError(e) {
- this.errorCount++;
- if (this.errorCount > 10) {
- this.location.disable();
- let l = document.getElementById("location");
- l.innerText = "Error!";
- }
- console.log(e);
- }
- }
- class MissionScreen {
- setAnswerListener(callback) {
- document.getElementById("answerForm").addEventListener("submit", (e) => MissionScreen.answer(e, callback));
- }
- static answer(submitEvent, callback) {
- submitEvent.preventDefault();
- let form = document.getElementById("answerForm");
- let answer = form.elements["questionAnwser"].value;
- form.elements["questionAnwser"].value = "";
- document.getElementById("answerButton").disabled = true;
- callback(answer);
- }
- update(m) {
- this.mission = m;
- document.getElementById("missionTitle").innerText = m.title + " (" + m.distanceToTarget + "m)";
- document.getElementById("missionDescription").innerText = m.description;
- if (m.type === "QUESTION") {
- document.getElementById("questionMission").style.display = "block";
- document.getElementById("answerButton").disabled = false;
- } else {
- document.getElementById("questionMission").style.display = "none";
- }
- }
- }
- class JoinScreen {
- constructor() {
- Api.fetchEvents()
- .then(JoinScreen.showEvents)
- .catch(console.log);
- }
- setJoinListener(callback) {
- document.getElementById("joinForm").addEventListener("submit", (e) => this.joinEvent(e, callback));
- }
- joinEvent(submitEvent, callback) {
- submitEvent.preventDefault();
- let form = document.getElementById("joinForm");
- let teamName = form.elements["teamName"].value;
- this.eventId = form.elements["eventId"].value;
- if (this.eventId === "" || teamName === "") {
- console.log("required form field empty");
- return;
- }
- document.getElementById("joinButton").disabled = true;
- Api.join(this.eventId, teamName)
- .then(teamId => callback(this.eventId, teamId))
- .catch(r => {
- console.log(r);
- document.getElementById("joinButton").disabled = false;
- });
- }
- static showEvents(eventJson) {
- let events = document.getElementById("events");
- events.innerHTML = "";
- eventJson.forEach((e) => {
- events.innerHTML += '<label><input name="eventId" value="' + e.id + '" type="radio"><span>' + e.title + '</span></label>';
- });
- document.getElementById("joinButton").disabled = false;
- }
- }
- class Api {
- static fetchEvents() {
- return FetchJson.get("/api/event")
- }
- static join(eventId, teamName) {
- let url = "/api/event/" + encodeURIComponent(eventId) + "/team";
- return FetchJson.post(url, teamName);
- }
- static sendUpdate(eventId, teamId, position, answer = null) {
- let body = {
- location: {latitude: position.lat(), longitude: position.lon()},
- answer: answer,
- };
- let url = "/api/event/" + encodeURIComponent(eventId) + "/team/" + encodeURIComponent(teamId);
- return FetchJson.put(url, body);
- }
- }
- class FetchJson {
- static get(url) {
- return fetch(url, {method: "GET"})
- .then(FetchJson.responseBody)
- }
- static post(url, body) {
- let options = {
- method: "POST",
- headers: {"Content-Type": "application/json"},
- body: JSON.stringify(body)
- };
- return fetch(url, options)
- .then(FetchJson.responseBody)
- }
- static put(url, body) {
- let options = {
- method: "PUT",
- headers: {"Content-Type": "application/json"},
- body: JSON.stringify(body)
- };
- return fetch(url, options)
- .then(FetchJson.responseBody)
- }
- static responseBody(r) {
- if (!r.ok) {
- throw Error("HTTP " + r.status + " " + r.statusText + " " + r.url);
- }
- return r.json();
- }
- }
- class Location {
- constructor(pos) {
- this.pos = pos;
- }
- accuracy() {
- return this.pos.coords.accuracy.toFixed(1)
- }
- age() {
- return Date.now() - this.pos.timestamp;
- }
- lat() {
- return this.pos.coords.latitude.toFixed(5);
- }
- lon() {
- return this.pos.coords.longitude.toFixed(5);
- }
- string() {
- return "(" + this.lat() + ", " + this.lon() + ")"
- + " +-" + this.accuracy() + "m, " + this.age() + "s geleden"
- }
- }
- class LocationApi {
- constructor() {
- if ("geolocation" in navigator) {
- console.log("Geolocation API available");
- } else {
- console.log("Geolocation API not available");
- document.getElementById("unsupported").style.display = "block";
- }
- if (window.isSecureContext) {
- console.log("Secure context available");
- } else {
- console.log("Secure context not available");
- document.getElementById("unsupported").style.display = "block";
- }
- }
- disable() {
- console.log("disabling geolocation watch " + this.watchId);
- navigator.geolocation.clearWatch(this.watchId);
- }
- enable(callback) {
- const geoOpts = {
- enableHighAccuracy: true,
- maximumAge: 10000,
- timeout: 9500
- };
- this.watchId = navigator.geolocation.watchPosition(
- (pos) => callback(new Location(pos)),
- (err) => console.log(err),
- geoOpts);
- }
- }
|