burguillos.info/js-src/conquer/map-node.ts

164 lines
5.0 KiB
TypeScript

import { JsonObject, JsonProperty } from 'typescript-json-serializer';
import Style from 'ol/style/Style'
import Feature from 'ol/Feature'
import CircleStyle from 'ol/style/Circle'
import Point from 'ol/geom/Point'
import Fill from 'ol/style/Fill'
import Stroke from 'ol/style/Stroke'
import InterfaceManager from '@burguillosinfo/conquer/interface-manager'
import NodeView from '@burguillosinfo/conquer/interface/node-view'
import JsonSerializer from '@burguillosinfo/conquer/serializer';
import SelectTeamUI from '@burguillosinfo/conquer/interface/select-team';
import ConquerTeam from '@burguillosinfo/conquer/team';
@JsonObject()
export default class MapNode {
private feature: Feature | null = null;
private callbacks: Record<string, Array<() => void>> = {}
private cachedTeam: ConquerTeam | null = null;
constructor(
@JsonProperty() private uuid: string,
@JsonProperty() private coordinate_1: number,
@JsonProperty() private coordinate_2: number,
@JsonProperty() private type: string,
@JsonProperty() private name: string,
@JsonProperty() private description: string,
@JsonProperty() private kind: string,
@JsonProperty() private is_near: boolean,
@JsonProperty() private team: string,
) {
}
public async getTeam(): Promise<ConquerTeam | null> {
if (this.cachedTeam === null) {
if (this.team === null) {
return null;
}
this.cachedTeam = await ConquerTeam.getTeam(this.team);
}
return this.cachedTeam;
}
public async fetch(): Promise<MapNode> {
const urlNode = new URL('/conquer/node/' + this.uuid, window.location.protocol + '//' + window.location.hostname + ':' + window.location.port)
const response = await fetch(urlNode);
let responseBody;
const errorThrow = new Error('Unable to fetch node updated.');
try {
responseBody = await response.json();
} catch (error) {
console.error('Error parseando json: ' + responseBody);
console.error(error);
throw errorThrow;
}
if (response.status !== 200) {
console.error(responseBody.error);
throw errorThrow;
}
const node = JsonSerializer.deserialize(responseBody, MapNode);
if (!(node instanceof MapNode)) {
console.error('Unexpected JSON value for MapNode.');
throw errorThrow;
}
return node;
}
public click(interfaceManager: InterfaceManager): void {
const viewNodeInterface = new NodeView(this);
viewNodeInterface.on('close', () => {
interfaceManager.remove(viewNodeInterface);
});
viewNodeInterface.on('update-nodes', () => {
this.runCallbacks('update-nodes');
});
viewNodeInterface.on('open-select-team', () => {
this.openSelectTeam(interfaceManager);
});
interfaceManager.push(viewNodeInterface);
this.runCallbacks('click');
}
public openSelectTeam(interfaceManager: InterfaceManager): void {
const selectTeamUI = new SelectTeamUI(this);
selectTeamUI.on('update-nodes', () => {
this.runCallbacks('update-nodes');
});
selectTeamUI.on('close', () => {
interfaceManager.remove(selectTeamUI);
});
interfaceManager.push(selectTeamUI);
}
public on(eventName: string, callback: () => void): void {
if (this.callbacks[eventName] === undefined) {
this.callbacks[eventName] = []
}
this.callbacks[eventName].push(callback)
}
protected runCallbacks(eventName: string) {
const callbacks = this.callbacks[eventName];
if (callbacks === undefined) {
return
}
for (const callback of callbacks) {
callback()
}
}
public getType(): string {
return this.type;
}
public isNear(): boolean {
return this.is_near;
}
public getName(): string {
return this.name;
}
public getDescription(): string {
return this.description;
}
public getId(): string {
return 'node-' + this.uuid;
}
public getUUID(): string {
return this.uuid;
}
public getFeature(): Feature {
if (this.feature === null) {
this.feature = new Feature({
geometry: new Point([this.coordinate_1, this.coordinate_2]),
type: 'node-' + this.uuid,
})
}
return this.feature;
}
public async getStyle(): Promise<Style> {
const team = await this.getTeam();
let color = 'white';
if (team !== null) {
color = team.getColor();
}
return new Style({
image: new CircleStyle({
radius: 14,
fill: new Fill({color: color}),
stroke: new Stroke({
color: 'black',
width: 5,
})
})
});
}
}