import Map from "ol/Map"; import View from "ol/View"; import Projection from "ol/proj/Projection.js"; import TileLayer from 'ol/layer/Tile' import OSM from 'ol/source/OSM' import * as olProj from "ol/proj"; export default class Conquer { private conquerContainer: HTMLDivElement; private map: Map; private currentLongitude: number; private currentLatitude: number; private rotationOffset = 0; private heading = 0 private disableSetRotationOffset = false private conquerLogin: HTMLDivElement private conquerLoginGoToRegister: HTMLAnchorElement private conquerLoginError: HTMLParagraphElement private conquerLoginSuccess: HTMLParagraphElement private conquerRegisterGoToLogin: HTMLAnchorElement private conquerRegister: HTMLDivElement private conquerRegisterUsername: HTMLInputElement private conquerRegisterPassword: HTMLInputElement private conquerRegisterRepeatPassword: HTMLInputElement private conquerRegisterSubmit: HTMLButtonElement private conquerRegisterError: HTMLParagraphElement private alpha = 0; private beta = 0; private gamma = 0; static start() { const conquerContainer = document.querySelector(".conquer-container"); if (conquerContainer !== null) { if (!(conquerContainer instanceof HTMLDivElement)) { console.error(".conquer-container is not a div."); return; } const conquer = new Conquer(conquerContainer); conquer.run(); } } setCenterDisplaced(lat: number, lon: number) { const olCoordinates = this.realCoordinatesToOl(lat, lon) const size = this.map.getSize() if (size === undefined) { return } this.map.getView().centerOn(olCoordinates, size, [size[0]/2, size[1]-60]) } static fail(error: string): never { alert('Error de interfaz') throw new Error(error) } fillConquerLogin() { const conquerLogin = document.querySelector('.conquer-login') if (conquerLogin === null || !(conquerLogin instanceof HTMLDivElement)) { Conquer.fail('conquerLogin is invalid') } this.conquerLogin = conquerLogin const conquerLoginGoToRegister = document.querySelector('.conquer-login-go-to-register') if (conquerLoginGoToRegister === null || !(conquerLoginGoToRegister instanceof HTMLAnchorElement)) { Conquer.fail('Link to go to register from login is invalid.') } this.conquerLoginGoToRegister = conquerLoginGoToRegister this.conquerLoginGoToRegister.addEventListener('click', () => { this.goToRegister() }) const conquerLoginError = document.querySelector('.conquer-login-error') if (conquerLoginError === null || !(conquerLoginError instanceof HTMLParagraphElement)) { Conquer.fail('Unable to find conquer login error.') } this.conquerLoginError = conquerLoginError const conquerLoginSuccess = document.querySelector('.conquer-login-success') if (conquerLoginSuccess === null || !(conquerLoginSuccess instanceof HTMLParagraphElement)) { Conquer.fail('Unable to find conquer login success.') } this.conquerLoginSuccess = conquerLoginSuccess } async goToRegister(): Promise { const isLogged = await this.isLogged(); await this.removeLoginRegisterCombo() if (!isLogged) { this.conquerRegister.classList.remove('conquer-display-none') } } async goToLogin(): Promise { const isLogged = await this.isLogged(); await this.removeLoginRegisterCombo() if (!isLogged) { this.conquerLogin.classList.remove('conquer-display-none') } } async removeLoginRegisterCombo(): Promise { this.conquerLogin.classList.add('conquer-display-none') this.conquerRegister.classList.add('conquer-display-none') } fillConquerRegister() { const conquerRegister = document.querySelector('.conquer-register') if (conquerRegister === null || !(conquerRegister instanceof HTMLDivElement)) { Conquer.fail('conquerRegister is invalid') } this.conquerRegister = conquerRegister const conquerRegisterGoToLogin = document.querySelector('.conquer-register-go-to-login') if (conquerRegisterGoToLogin === null || !(conquerRegisterGoToLogin instanceof HTMLAnchorElement)) { Conquer.fail('Link to go to login from register is invalid.') } this.conquerRegisterGoToLogin = conquerRegisterGoToLogin this.conquerRegisterGoToLogin.addEventListener('click', () => { this.goToLogin() }) const conquerRegisterUsername = document.querySelector('.conquer-register-username') if (conquerRegisterUsername === null || !(conquerRegisterUsername instanceof HTMLInputElement)) { Conquer.fail('No username field in conquer register.') } this.conquerRegisterUsername = conquerRegisterUsername const conquerRegisterPassword = document.querySelector('.conquer-register-password') if (conquerRegisterPassword === null || !(conquerRegisterPassword instanceof HTMLInputElement)) { Conquer.fail('No password field in conquer register.') } this.conquerRegisterPassword = conquerRegisterPassword const conquerRegisterRepeatPassword = document.querySelector('.conquer-register-repeat-password') if (conquerRegisterRepeatPassword === null || !(conquerRegisterRepeatPassword instanceof HTMLInputElement)) { Conquer.fail('No repeat password field in conquer register.') } this.conquerRegisterRepeatPassword = conquerRegisterRepeatPassword const conquerRegisterSubmit = document.querySelector('.conquer-register-submit') if (conquerRegisterSubmit === null || !(conquerRegisterSubmit instanceof HTMLButtonElement)) { Conquer.fail('No register submit button found.') } this.conquerRegisterSubmit = conquerRegisterSubmit this.conquerRegisterSubmit.addEventListener('click', (event: Event) => { event.preventDefault() this.onRegisterRequest() }) const conquerRegisterError = document.querySelector('.conquer-register-error') if (conquerRegisterError === null || !(conquerRegisterError instanceof HTMLParagraphElement)) { Conquer.fail('Unable to find the conquer error element.') } this.conquerRegisterError = conquerRegisterError } unsetLoginAndRegisterErrors() { this.conquerRegisterError.classList.add('conquer-display-none') this.conquerLoginError.classList.add('conquer-display-none') } async onRegisterRequest(): Promise { const username = this.conquerRegisterUsername.value const password = this.conquerRegisterPassword.value const repeatPassword = this.conquerRegisterRepeatPassword.value const urlUser = new URL('/conquer/user', window.location.protocol + '//' + window.location.hostname + ':' + window.location.port) const response = await fetch(urlUser, { method: 'PUT', body: JSON.stringify({ username: username, password: password, repeat_password: repeatPassword }) }) let responseJson try { responseJson = await response.json() } catch(e) { console.error(e) return; } if (response.status !== 200) { this.addNewRegisterError(responseJson.error) return } this.addNewLoginSuccessText(`Usuario registrado ${username}.`) this.goToLogin() } addNewLoginSuccessText(message: string): void { this.unsetLoginAndRegisterErrors() this.conquerLoginSuccess.innerText = message this.conquerLoginSuccess.classList.remove('conquer-display-none') } addNewRegisterError(error: string): void { this.unsetLoginAndRegisterErrors() this.conquerLoginSuccess.classList.add('conquer-display-none') this.conquerRegisterError.innerText = error this.conquerRegisterError.classList.remove('conquer-display-none') } async run() { this.fillConquerLogin() this.fillConquerRegister() const isLogged = await this.isLogged(); if (!isLogged) { this.conquerLogin.classList.remove('conquer-display-none') } const conquerContainer = this.conquerContainer; //layer.on('prerender', (evt) => { // // return // if (evt.context) { // const context = evt.context as CanvasRenderingContext2D; // context.filter = 'grayscale(80%) invert(100%) '; // context.globalCompositeOperation = 'source-over'; // } //}); //layer.on('postrender', (evt) => { // if (evt.context) { // const context = evt.context as CanvasRenderingContext2D; // context.filter = 'none'; // } //}); olProj.useGeographic(); this.map = new Map({ target: conquerContainer, layers: [ new TileLayer({ source: new OSM() }) ], view: new View({ zoom: 21, maxZoom: 22, }), }); const proccessLocation = (location: GeolocationPosition) => { this.currentLatitude = location.coords.latitude this.currentLongitude = location. coords.longitude if (location.coords.heading !== null && (this.alpha != 0 || this.beta != 0 || this.gamma != 0) && !this.disableSetRotationOffset) { this.disableSetRotationOffset = true this.heading = location.coords.heading this.rotationOffset = this.compassHeading(this.alpha, this.beta, this.gamma) + (location.coords.heading*Math.PI*2)/360 } this.setCenterDisplaced(this.currentLatitude, this.currentLongitude) } this.setCenterDisplaced(37.58237, -5.96766) navigator.geolocation.watchPosition((location) => { proccessLocation(location) }, (err) => { return }, { enableHighAccuracy: true, maximumAge: 0 }); window.setInterval(() => { this.disableSetRotationOffset = false }, 10000); window.setTimeout(() => { window.setInterval(() => { navigator.geolocation.getCurrentPosition((location) => { proccessLocation(location) }, () => { return }, { enableHighAccuracy: true, maximumAge: 0 }) }, 1000) }, 1000) if (window.DeviceOrientationEvent) { window.addEventListener("deviceorientation", (event) => { if (event.alpha !== null && event.beta !== null && event.gamma !== null) { this.onRotate(event.alpha, event.beta, event.gamma); } }, true); } } realCoordinatesToOl(lat: number, lon: number): number[] { return olProj.transform( [lon, lat], new Projection({ code: "WGS84" }), new Projection({ code: "EPSG:900913" }), ); } compassHeading(alpha:number, beta:number, gamma:number): number { const alphaRad = alpha * (Math.PI / 180); return alphaRad let betaRad = beta * (Math.PI / 180); const gammaRad = gamma * (Math.PI / 180); betaRad = 1.5707963268; const cA = Math.cos(alphaRad); const sA = Math.sin(alphaRad); const sB = Math.sin(betaRad); const cG = Math.cos(gammaRad); const sG = Math.sin(gammaRad); const rA = - cA * sG - sA * sB * cG; const rB = - sA * sG + cA * sB * cG; return Math.atan2(rA, rB) } logToServer(logValue: string) { const urlLog = new URL('/conquer/log', window.location.protocol + '//' + window.location.hostname + ':' + window.location.port) urlLog.searchParams.append('log', logValue) fetch(urlLog).then(() => { return }).catch((error) => { console.error(error) }) } enabledOnRotate = true; onRotate(alpha: number, beta: number, gamma: number) { if (this.enabledOnRotate) { this.alpha = alpha this.beta = beta this.gamma = gamma this.enabledOnRotate = false this.map.getView().setRotation((this.compassHeading(alpha, beta, gamma) - this.rotationOffset)) window.setTimeout(() => { this.enabledOnRotate = true }, 10) } this.setCenterDisplaced(this.currentLatitude, this.currentLongitude) } constructor(conquerContainer: HTMLDivElement) { this.conquerContainer = conquerContainer; } private async isLogged(): Promise { return false // return fetch("/conquer/user") // .then(async (res): Promise => { // const data = await res.json(); // if (data === null) { // return false; // } // return true; // }) // .catch((error) => { // console.error(error); // return false; // }); } }