405 lines
16 KiB
TypeScript
405 lines
16 KiB
TypeScript
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"
|
|
import Feature from 'ol/Feature'
|
|
import Point from 'ol/geom/Point'
|
|
|
|
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 conquerLoginUsername: HTMLInputElement
|
|
private conquerLoginPassword: HTMLInputElement
|
|
private conquerLoginSubmit: HTMLButtonElement
|
|
private conquerRegisterGoToLogin: HTMLAnchorElement
|
|
private conquerRegister: HTMLDivElement
|
|
private conquerRegisterUsername: HTMLInputElement
|
|
private conquerRegisterPassword: HTMLInputElement
|
|
private conquerRegisterRepeatPassword: HTMLInputElement
|
|
private conquerRegisterSubmit: HTMLButtonElement
|
|
private conquerRegisterError: HTMLParagraphElement
|
|
private currentPositionFeature: Feature | null
|
|
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
|
|
const conquerLoginUsername = document.querySelector('.conquer-login-username')
|
|
if (conquerLoginUsername === null || !(conquerLoginUsername instanceof HTMLInputElement)) {
|
|
Conquer.fail('Unable to find conquer login username field.')
|
|
}
|
|
this.conquerLoginUsername = conquerLoginUsername
|
|
const conquerLoginPassword = document.querySelector('.conquer-login-password')
|
|
if (conquerLoginPassword === null || !(conquerLoginPassword instanceof HTMLInputElement)) {
|
|
Conquer.fail('Unable to find conquer login password field.')
|
|
}
|
|
this.conquerLoginPassword = conquerLoginPassword
|
|
const conquerLoginSubmit = document.querySelector('.conquer-login-submit')
|
|
if (conquerLoginSubmit === null || !(conquerLoginSubmit instanceof HTMLButtonElement)) {
|
|
Conquer.fail('Unable to find the submit button for the login.')
|
|
}
|
|
this.conquerLoginSubmit = conquerLoginSubmit
|
|
this.conquerLoginSubmit.addEventListener('click', (event: Event) => {
|
|
event.preventDefault()
|
|
this.onLoginRequested()
|
|
})
|
|
}
|
|
|
|
async onLoginRequested(): Promise<void> {
|
|
const username = this.conquerLoginUsername.value
|
|
const password = this.conquerLoginPassword.value
|
|
const urlUser = new URL('/conquer/user/login', window.location.protocol + '//' + window.location.hostname + ':' + window.location.port)
|
|
let responseJson
|
|
let status
|
|
try {
|
|
const response = await fetch(urlUser, {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
username: username,
|
|
password: password,
|
|
})
|
|
})
|
|
responseJson = await response.json()
|
|
status = response.status
|
|
} catch(e) {
|
|
console.error(e)
|
|
this.addNewLoginError('El servidor ha enviado datos inesperados.')
|
|
return
|
|
}
|
|
if (status !== 200) {
|
|
this.addNewLoginError(responseJson.error)
|
|
return
|
|
}
|
|
this.unsetLoginAndRegisterErrors()
|
|
const isLogged = await this.isLogged()
|
|
if (isLogged) {
|
|
await this.removeLoginRegisterCombo()
|
|
}
|
|
}
|
|
|
|
async goToRegister(): Promise<void> {
|
|
const isLogged = await this.isLogged()
|
|
await this.removeLoginRegisterCombo()
|
|
if (!isLogged) {
|
|
this.conquerRegister.classList.remove('conquer-display-none')
|
|
}
|
|
}
|
|
async goToLogin(): Promise<void> {
|
|
const isLogged = await this.isLogged()
|
|
await this.removeLoginRegisterCombo()
|
|
if (!isLogged) {
|
|
this.conquerLogin.classList.remove('conquer-display-none')
|
|
}
|
|
}
|
|
|
|
async removeLoginRegisterCombo(): Promise<void> {
|
|
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<void> {
|
|
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)
|
|
let responseJson
|
|
let status
|
|
try {
|
|
const response = await fetch(urlUser, {
|
|
method: 'PUT',
|
|
body: JSON.stringify({
|
|
username: username,
|
|
password: password,
|
|
repeat_password: repeatPassword
|
|
})
|
|
})
|
|
responseJson = await response.json()
|
|
status = response.status
|
|
} catch(e) {
|
|
console.error(e)
|
|
this.addNewRegisterError('El servidor ha enviado datos inesperados.')
|
|
return
|
|
}
|
|
if (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')
|
|
|
|
}
|
|
addNewLoginError(error: string): void {
|
|
this.unsetLoginAndRegisterErrors()
|
|
this.conquerLoginSuccess.classList.add('conquer-display-none')
|
|
this.conquerLoginError.innerText = error
|
|
this.conquerLoginError.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,
|
|
}),
|
|
})
|
|
this.setLocationChangeTriggers()
|
|
this.setRotationChangeTriggers()
|
|
}
|
|
|
|
setRotationChangeTriggers(): void {
|
|
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)
|
|
}
|
|
}
|
|
|
|
processLocation(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)
|
|
const currentPositionFeature = new Feature({
|
|
type: 'currentPositionFeature',
|
|
geometry: new Point([this.currentLatitude, this.currentLongitude])
|
|
})
|
|
this.currentPositionFeature = currentPositionFeature
|
|
}
|
|
}
|
|
setLocationChangeTriggers(): void {
|
|
window.setInterval(() => {
|
|
this.disableSetRotationOffset = false
|
|
}, 10000)
|
|
this.currentPositionFeature = null
|
|
window.setTimeout(() => {
|
|
window.setInterval(() => {
|
|
navigator.geolocation.getCurrentPosition((location) => {
|
|
this.processLocation(location)
|
|
}, () => {
|
|
return
|
|
}, {
|
|
enableHighAccuracy: true,
|
|
maximumAge: 0
|
|
})
|
|
}, 1000)
|
|
}, 1000)
|
|
this.setCenterDisplaced(37.58237, -5.96766)
|
|
navigator.geolocation.watchPosition((location) => {
|
|
this.processLocation(location)
|
|
}, (err) => {
|
|
return
|
|
}, {
|
|
enableHighAccuracy: true,
|
|
maximumAge: 0
|
|
})
|
|
}
|
|
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
|
|
}
|
|
|
|
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 addNewLoginRegisterError(message: string): Promise<void> {
|
|
this.addNewRegisterError(message)
|
|
this.addNewLoginError(message)
|
|
}
|
|
private async isLogged(): Promise<boolean> {
|
|
const urlUser = new URL('/conquer/user', window.location.protocol + '//' + window.location.hostname + ':' + window.location.port)
|
|
let responseJson
|
|
let status
|
|
try {
|
|
const response = await fetch(urlUser)
|
|
status = response.status
|
|
} catch {
|
|
this.addNewLoginRegisterError('Error del servidor')
|
|
return false
|
|
}
|
|
return status === 200
|
|
}
|
|
}
|