Adding initial support for conquering nodes.

This commit is contained in:
Sergiotarxz 2024-01-14 22:02:49 +01:00
parent 16888b9fdb
commit 389f325618
8 changed files with 166 additions and 29 deletions

View File

@ -24,6 +24,7 @@ import NewNodeUI from '@burguillosinfo/conquer/interface/new-node'
import NewTeamUI from '@burguillosinfo/conquer/interface/new-team' import NewTeamUI from '@burguillosinfo/conquer/interface/new-team'
import WebSocket from '@burguillosinfo/conquer/websocket' import WebSocket from '@burguillosinfo/conquer/websocket'
import JsonSerializer from '@burguillosinfo/conquer/serializer'; import JsonSerializer from '@burguillosinfo/conquer/serializer';
import ConquerUser from '@burguillosinfo/conquer/user'
type StylesInterface = Record<string, Style> type StylesInterface = Record<string, Style>
@ -433,13 +434,21 @@ export default class Conquer {
if (this.currentPositionFeature === null) { if (this.currentPositionFeature === null) {
return return
} }
const user = await ConquerUser.getSelfUser()
let color = 'white';
if (user !== null) {
const team = await user.getTeam();
if (team !== null) {
color = team.getColor();
}
}
const styles: StylesInterface = { const styles: StylesInterface = {
currentPositionFeature: new Style({ currentPositionFeature: new Style({
image: new CircleStyle({ image: new CircleStyle({
radius: 14, radius: 14,
fill: new Fill({color: 'white'}), fill: new Fill({color: color}),
stroke: new Stroke({ stroke: new Stroke({
color: 'blue', color: 'beige',
width: 2, width: 2,
}) })
}) })
@ -447,7 +456,7 @@ export default class Conquer {
}; };
const features = [this.currentPositionFeature] const features = [this.currentPositionFeature]
for (const key in this.getServerNodes()) { for (const key in this.getServerNodes()) {
styles[key] = this.getServerNodes()[key].getStyle() styles[key] = await this.getServerNodes()[key].getStyle()
features.push(this.getServerNodes()[key].getFeature()) features.push(this.getServerNodes()[key].getFeature())
} }
const vectorLayer = new VectorLayer<VectorSource>({ const vectorLayer = new VectorLayer<VectorSource>({

View File

@ -63,6 +63,7 @@ export default class NodeView extends AbstractTopBarInterface {
+ (this.node.isNear() + (this.node.isNear()
? 'Estas cerca y puedes interactuar con este sitio.' ? 'Estas cerca y puedes interactuar con este sitio.'
: 'Estás demasiado lejos para hacer nada aquí.'); : 'Estás demasiado lejos para hacer nada aquí.');
this.populateTeamData();
if (this.node.isNear()) { if (this.node.isNear()) {
await this.runIfNear(); await this.runIfNear();
} }
@ -70,22 +71,87 @@ export default class NodeView extends AbstractTopBarInterface {
mainNode.classList.remove('conquer-display-none') mainNode.classList.remove('conquer-display-none')
} }
private async runIfNear(): Promise<void> { private async populateTeamData() {
const team = await this.user.getTeam(); const element = document.createElement('p');
const team = await this.node.getTeam();
(() => {
if (team === null) { if (team === null) {
element.innerText = 'El nodo no pertenece a ningún equipo todavía.';
return;
}
const spanText = document.createElement('span');
spanText.innerText = 'Equipo: ';
element.append(spanText);
const spanCircle = document.createElement('span');
spanCircle.classList.add('conquer-team-circle');
spanCircle.style.backgroundColor = team.getColor();
element.append(spanCircle);
const spanTeamName = document.createElement('span');
spanTeamName.style.color = team.getColor();
spanTeamName.innerText = ' ' + team.getName();
element.append(spanTeamName);
})();
this.getView().append(element);
}
private async runIfNear(): Promise<void> {
const userTeam = await this.user.getTeam();
const nodeTeam = await this.node.getTeam();
if (userTeam === null) {
const paragraphNoTeam = document.createElement('p'); const paragraphNoTeam = document.createElement('p');
paragraphNoTeam.innerText = 'Parece que no has seleccionado equipo aun,' paragraphNoTeam.innerText = 'Parece que no has seleccionado equipo aun,'
+ ' pulsa el botón de seleccionar equipo para comenzar tu aventura,' + ' pulsa el botón de seleccionar equipo para comenzar tu aventura,'
+ ' si quieres cambiar de equipo en el futuro puedes hacerlo sin problemas.'; + ' si quieres cambiar de equipo en el futuro puedes hacerlo sin problemas.';
this.getView().append(paragraphNoTeam); this.getView().append(paragraphNoTeam);
} }
const selectTeamButton = document.createElement('button'); const selectTeamButton = document.createElement('button');
selectTeamButton.innerText = 'Seleccionar equipo'; selectTeamButton.innerText = 'Seleccionar equipo';
selectTeamButton.addEventListener('click', () => { selectTeamButton.addEventListener('click', () => {
this.runCallbacks('open-select-team'); this.runCallbacks('open-select-team');
this.runCallbacks('close'); this.runCallbacks('close');
}); });
this.getView().append(selectTeamButton); this.getView().append(selectTeamButton);
if (await this.isOpposingNode()) {
const conquerForTeamButton = document.createElement('button');
conquerForTeamButton.innerText = 'Conquistar';
conquerForTeamButton.addEventListener('click', () => {
this.conquerThisNodeForTeam();
});
this.getView().append(conquerForTeamButton);
}
}
private async conquerThisNodeForTeam() {
const urlNode = new URL('/conquer/node/' + this.node.getUUID() + '/try-conquer',
window.location.protocol + '//'
+ window.location.hostname + ':'
+ window.location.port)
const response = await fetch(urlNode, {
method: 'POST',
});
this.runCallbacks('update-nodes');
this.runCallbacks('close');
}
private async isOpposingNode(): Promise<boolean> {
const userTeam = await this.user.getTeam();
const nodeTeam = await this.node.getTeam();
if (userTeam === null) {
return false;
}
if (nodeTeam === null) {
return true;
}
if (nodeTeam.getUUID() !== userTeam.getUUID()) {
return true;
}
return false;
}
private async isNodeFree(): Promise<boolean> {
return await this.node.getTeam() === null;
} }
} }

View File

@ -9,6 +9,7 @@ import InterfaceManager from '@burguillosinfo/conquer/interface-manager'
import NodeView from '@burguillosinfo/conquer/interface/node-view' import NodeView from '@burguillosinfo/conquer/interface/node-view'
import JsonSerializer from '@burguillosinfo/conquer/serializer'; import JsonSerializer from '@burguillosinfo/conquer/serializer';
import SelectTeamUI from '@burguillosinfo/conquer/interface/select-team'; import SelectTeamUI from '@burguillosinfo/conquer/interface/select-team';
import ConquerTeam from '@burguillosinfo/conquer/team';
@JsonObject() @JsonObject()
export default class MapNode { export default class MapNode {
@ -24,9 +25,18 @@ export default class MapNode {
@JsonProperty() private description: string, @JsonProperty() private description: string,
@JsonProperty() private kind: string, @JsonProperty() private kind: string,
@JsonProperty() private is_near: boolean, @JsonProperty() private is_near: boolean,
@JsonProperty() private team: string,
) { ) {
} }
public async getTeam(): Promise<ConquerTeam | null> {
if (this.team === null) {
return null;
}
return ConquerTeam.getTeam(this.team);
}
public async fetch(): Promise<MapNode> { public async fetch(): Promise<MapNode> {
const urlNode = new URL('/conquer/node/' + this.uuid, window.location.protocol + '//' + window.location.hostname + ':' + window.location.port) const urlNode = new URL('/conquer/node/' + this.uuid, window.location.protocol + '//' + window.location.hostname + ':' + window.location.port)
const response = await fetch(urlNode); const response = await fetch(urlNode);
@ -125,11 +135,16 @@ export default class MapNode {
return this.feature; return this.feature;
} }
public getStyle(): Style { public async getStyle(): Promise<Style> {
const team = await this.getTeam();
let color = 'white';
if (team !== null) {
color = team.getColor();
}
return new Style({ return new Style({
image: new CircleStyle({ image: new CircleStyle({
radius: 14, radius: 14,
fill: new Fill({color: 'white'}), fill: new Fill({color: color}),
stroke: new Stroke({ stroke: new Stroke({
color: 'gray', color: 'gray',
width: 2, width: 2,

View File

@ -101,6 +101,7 @@ sub startup ($self) {
$r->put('/conquer/node')->to('ConquerNode#create'); $r->put('/conquer/node')->to('ConquerNode#create');
$r->get('/conquer/node/near')->to('ConquerNode#nearbyNodes'); $r->get('/conquer/node/near')->to('ConquerNode#nearbyNodes');
$r->get('/conquer/node/<uuid>')->to('ConquerNode#get'); $r->get('/conquer/node/<uuid>')->to('ConquerNode#get');
$r->post('/conquer/node/<uuid>/try-conquer')->to('ConquerNode#tryConquer');
$r->get('/conquer/user')->to('UserConquer#get_self'); $r->get('/conquer/user')->to('UserConquer#get_self');
$r->post('/conquer/user/login')->to('UserConquer#login'); $r->post('/conquer/user/login')->to('UserConquer#login');
$r->get('/conquer/tile/<zoom>/<x>/<y>.png')->to('ConquerTile#tile'); $r->get('/conquer/tile/<zoom>/<x>/<y>.png')->to('ConquerTile#tile');

View File

@ -33,6 +33,33 @@ sub get($self) {
return $self->render(json => $node->serialize()); return $self->render(json => $node->serialize());
} }
sub tryConquer($self) {
my $user = $self->current_user;
my $schema = BurguillosInfo::Schema->Schema->resultset('ConquerNode');
if (!defined $user) {
return $self->render(status => 401, json => {
error => 'You must be logged to conquer a node.',
});
}
if (!defined $user->team) {
return $self->render(status => 400, json => {
error => 'You must belong to a team to conquer a node.',
});
}
my $uuid = $self->param('uuid');
my ($node) = $schema->search({uuid => $uuid});
if (!defined $node) {
return $self->render(status => 404, json => {
error => 'No existe ese nodo.',
});
}
$node->team($user->team);
$node->update;
$self->render(json => {
ok => $JSON::true,
});
}
sub create ($self) { sub create ($self) {
my $user = $self->current_user; my $user = $self->current_user;
if ( !defined $user ) { if ( !defined $user ) {

View File

@ -37,29 +37,39 @@ __PACKAGE__->add_columns(
data_type => 'geometry', data_type => 'geometry',
is_nullable => 0, is_nullable => 0,
}, },
team => {
data_type => 'uuid',
is_nullable => 1,
},
); );
sub coordinate_2($self) { sub coordinate_2 ($self) {
require BurguillosInfo::Schema; require BurguillosInfo::Schema;
my $resultset = BurguillosInfo::Schema->Schema->resultset('ConquerNode'); my $resultset = BurguillosInfo::Schema->Schema->resultset('ConquerNode');
my ($new_self) = $resultset->search({uuid => $self->uuid}, { my ($new_self) = $resultset->search(
{ uuid => $self->uuid },
{
'+select' => { '+select' => {
ST_Y => { ST_Centroid => 'geometry' }, ST_Y => { ST_Centroid => 'geometry' },
-as => 'coordinate_2', -as => 'coordinate_2',
} }
}); }
);
return $new_self->get_column('coordinate_2'); return $new_self->get_column('coordinate_2');
} }
sub coordinate_1($self) { sub coordinate_1 ($self) {
require BurguillosInfo::Schema; require BurguillosInfo::Schema;
my $resultset = BurguillosInfo::Schema->Schema->resultset('ConquerNode'); my $resultset = BurguillosInfo::Schema->Schema->resultset('ConquerNode');
my ($new_self) = $resultset->search({uuid => $self->uuid}, { my ($new_self) = $resultset->search(
{ uuid => $self->uuid },
{
'+select' => { '+select' => {
ST_X => { ST_Centroid => 'geometry' }, ST_X => { ST_Centroid => 'geometry' },
-as => 'coordinate_1', -as => 'coordinate_1',
} }
}); }
);
return $new_self->get_column('coordinate_1'); return $new_self->get_column('coordinate_1');
} }
@ -74,6 +84,7 @@ sub serialize ( $self, $player = undef ) {
coordinate_1 => $self->coordinate_1, coordinate_1 => $self->coordinate_1,
coordinate_2 => $self->coordinate_2, coordinate_2 => $self->coordinate_2,
is_near => $self->is_near($player), is_near => $self->is_near($player),
team => $self->team,
}; };
return $return; return $return;
} }
@ -82,22 +93,29 @@ sub is_near ( $self, $player ) {
if ( !defined $player ) { if ( !defined $player ) {
return $JSON::false; return $JSON::false;
} }
# Meters # Meters
if ($self->get_distance_to_player($player) < 100) { if ( $self->get_distance_to_player($player) < 100 ) {
return $JSON::true; return $JSON::true;
} }
return $JSON::false; return $JSON::false;
} }
sub get_distance_to_player ($self, $player) { sub get_distance_to_player ( $self, $player ) {
my $longitude_player = $player->last_coordinate_1; my $longitude_player = $player->last_coordinate_1;
my $latitude_player = $player->last_coordinate_2; my $latitude_player = $player->last_coordinate_2;
my $longitude_node = $self->coordinate_1; my $longitude_node = $self->coordinate_1;
my $latitude_node = $self->coordinate_2; my $latitude_node = $self->coordinate_2;
my $gis = GIS::Distance->new; my $gis = GIS::Distance->new;
# Setting distance to meters. # Setting distance to meters.
my $distance = $gis->distance_metal( $latitude_node, $longitude_node, $latitude_player, $longitude_player) * 1000; my $distance = $gis->distance_metal(
$latitude_node, $longitude_node,
$latitude_player, $longitude_player
) * 1000;
} }
__PACKAGE__->set_primary_key('uuid'); __PACKAGE__->set_primary_key('uuid');
__PACKAGE__->belongs_to( 'team_object',
'BurguillosInfo::Schema::Result::ConquerTeam', 'team' );
1; 1;

View File

@ -39,6 +39,7 @@ __PACKAGE__->add_columns(
__PACKAGE__->set_primary_key('uuid'); __PACKAGE__->set_primary_key('uuid');
__PACKAGE__->has_many( players => 'BurguillosInfo::Schema::Result::ConquerUser', 'team'); __PACKAGE__->has_many( players => 'BurguillosInfo::Schema::Result::ConquerUser', 'team');
__PACKAGE__->has_many( nodes => 'BurguillosInfo::Schema::Result::ConquerNode', 'team');
sub serialize ($self) { sub serialize ($self) {
$self = $self->get_from_storage(); $self = $self->get_from_storage();

File diff suppressed because one or more lines are too long