Adding initial team support.
This commit is contained in:
parent
c38474614d
commit
9279e6388a
1
Build.PL
1
Build.PL
@ -33,6 +33,7 @@ my $build = Module::Build->new(
|
|||||||
'Crypt::Bcrypt' => 0,
|
'Crypt::Bcrypt' => 0,
|
||||||
'DBIx::Class::TimeStamp' => 0,
|
'DBIx::Class::TimeStamp' => 0,
|
||||||
'DateTime::Format::HTTP' => 0,
|
'DateTime::Format::HTTP' => 0,
|
||||||
|
'GIS::Distance' => 0,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
$build->create_build_script;
|
$build->create_build_script;
|
||||||
|
@ -238,37 +238,46 @@ export default class Conquer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getNearbyNodes(): void {
|
private async getNearbyNodes(): Promise<void> {
|
||||||
const urlNodes = new URL('/conquer/node/near', window.location.protocol + '//' + window.location.hostname + ':' + window.location.port)
|
const urlNodes = new URL('/conquer/node/near', window.location.protocol + '//' + window.location.hostname + ':' + window.location.port)
|
||||||
fetch(urlNodes).then(async (response) => {
|
let response;
|
||||||
let responseBody;
|
try {
|
||||||
try {
|
response = await fetch(urlNodes);
|
||||||
responseBody = await response.json();
|
} catch (error) {
|
||||||
} catch (error) {
|
console.error(error);
|
||||||
console.error('Error parseando json: ' + responseBody);
|
return;
|
||||||
console.error(error);
|
}
|
||||||
return;
|
let responseBody;
|
||||||
|
try {
|
||||||
|
responseBody = await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error parseando json: ' + responseBody);
|
||||||
|
console.error(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (response.status !== 200) {
|
||||||
|
console.error(responseBody.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const serverNodes: Record<string, MapNode> = {};
|
||||||
|
const nodes = JsonSerializer.deserialize(responseBody, MapNode);
|
||||||
|
if (!(nodes instanceof Array)) {
|
||||||
|
console.error('Received null instead of node list.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const node of nodes) {
|
||||||
|
if (!(node instanceof MapNode)) {
|
||||||
|
console.error('Received node is not a MapNode.');
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (response.status !== 200) {
|
node.on('update-nodes', async () => {
|
||||||
console.error(responseBody.error);
|
await this.sendCoordinatesToServer();
|
||||||
return;
|
this.getNearbyNodes();
|
||||||
}
|
});
|
||||||
const serverNodes: Record<string, MapNode> = {};
|
serverNodes[node.getId()] = node;
|
||||||
const nodes = JsonSerializer.deserialize(responseBody, MapNode);
|
}
|
||||||
if (!(nodes instanceof Array)) {
|
this.serverNodes = serverNodes;
|
||||||
console.error('Received null instead of node list.');
|
this.refreshLayers();
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (const node of nodes) {
|
|
||||||
if (!(node instanceof MapNode)) {
|
|
||||||
console.error('Received node is not a MapNode.');
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
serverNodes[node.getId()] = node;
|
|
||||||
}
|
|
||||||
this.serverNodes = serverNodes;
|
|
||||||
this.refreshLayers();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private createIntervalPollNearbyNodes(): void {
|
private createIntervalPollNearbyNodes(): void {
|
||||||
@ -284,29 +293,31 @@ export default class Conquer {
|
|||||||
}, 40000);
|
}, 40000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private sendCoordinatesToServer(): void {
|
private async sendCoordinatesToServer(): Promise<void> {
|
||||||
const urlLog = new URL('/conquer/user/coordinates', window.location.protocol + '//' + window.location.hostname + ':' + window.location.port)
|
const urlLog = new URL('/conquer/user/coordinates', window.location.protocol + '//' + window.location.hostname + ':' + window.location.port)
|
||||||
fetch(urlLog, {
|
let res;
|
||||||
method: 'POST',
|
try {
|
||||||
body: JSON.stringify([
|
res = await fetch(urlLog, {
|
||||||
this.coordinate_1,
|
method: 'POST',
|
||||||
this.coordinate_2,
|
body: JSON.stringify([
|
||||||
]),
|
this.coordinate_1,
|
||||||
}).then(async (res) => {
|
this.coordinate_2,
|
||||||
let responseBody;
|
])});
|
||||||
try {
|
} catch (error) {
|
||||||
responseBody = await res.json();
|
|
||||||
} catch(error) {
|
|
||||||
console.error('Error parseando json: ' + responseBody);
|
|
||||||
console.error(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (res.status !== 200) {
|
|
||||||
console.error(responseBody.error);
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error)
|
console.error(error)
|
||||||
});
|
return;
|
||||||
|
}
|
||||||
|
let responseBody;
|
||||||
|
try {
|
||||||
|
responseBody = await res.json();
|
||||||
|
} catch(error) {
|
||||||
|
console.error('Error parseando json: ' + responseBody);
|
||||||
|
console.error(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (res.status !== 200) {
|
||||||
|
console.error(responseBody.error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private runPreStartState(): void {
|
private runPreStartState(): void {
|
||||||
|
@ -24,12 +24,22 @@ export default class NodeView extends AbstractTopBarInterface {
|
|||||||
super()
|
super()
|
||||||
this.node = node;
|
this.node = node;
|
||||||
}
|
}
|
||||||
public run() {
|
public async run() {
|
||||||
const mainNode = this.getMainNode()
|
const mainNode = this.getMainNode()
|
||||||
|
this.runCallbacks('update-nodes');
|
||||||
|
try {
|
||||||
|
this.node = await this.node.fetch();
|
||||||
|
} catch (error) {
|
||||||
|
this.runCallbacks('close');
|
||||||
|
}
|
||||||
const view = this.getNodeFromTemplateId('conquer-view-node-template')
|
const view = this.getNodeFromTemplateId('conquer-view-node-template')
|
||||||
mainNode.append(view)
|
mainNode.append(view)
|
||||||
this.getNodeNameH2().innerText = this.node.getName();
|
this.getNodeNameH2().innerText = this.node.getName();
|
||||||
this.getNodeDescriptionParagraph().innerText = this.node.getDescription();
|
this.getNodeDescriptionParagraph().innerText = this.node.getDescription()
|
||||||
|
+ "\n"
|
||||||
|
+ (this.node.isNear()
|
||||||
|
? 'Estas cerca y puedes interactuar con este sitio.'
|
||||||
|
: 'Estás demasiado lejos para hacer nada aquí.');
|
||||||
view.classList.remove('conquer-display-none')
|
view.classList.remove('conquer-display-none')
|
||||||
mainNode.classList.remove('conquer-display-none')
|
mainNode.classList.remove('conquer-display-none')
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import Fill from 'ol/style/Fill'
|
|||||||
import Stroke from 'ol/style/Stroke'
|
import Stroke from 'ol/style/Stroke'
|
||||||
import InterfaceManager from '@burguillosinfo/conquer/interface-manager'
|
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';
|
||||||
|
|
||||||
@JsonObject()
|
@JsonObject()
|
||||||
export default class MapNode {
|
export default class MapNode {
|
||||||
@ -21,14 +22,42 @@ export default class MapNode {
|
|||||||
@JsonProperty() private name: string,
|
@JsonProperty() private name: string,
|
||||||
@JsonProperty() private description: string,
|
@JsonProperty() private description: string,
|
||||||
@JsonProperty() private kind: string,
|
@JsonProperty() private kind: string,
|
||||||
|
@JsonProperty() private is_near: boolean,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
public click(interfaceManager: InterfaceManager): void {
|
||||||
const viewNodeInterface = new NodeView(this);
|
const viewNodeInterface = new NodeView(this);
|
||||||
viewNodeInterface.on('close', () => {
|
viewNodeInterface.on('close', () => {
|
||||||
interfaceManager.remove(viewNodeInterface);
|
interfaceManager.remove(viewNodeInterface);
|
||||||
});
|
});
|
||||||
|
viewNodeInterface.on('update-nodes', () => {
|
||||||
|
this.runCallbacks('update-nodes');
|
||||||
|
});
|
||||||
interfaceManager.push(viewNodeInterface);
|
interfaceManager.push(viewNodeInterface);
|
||||||
this.runCallbacks('click');
|
this.runCallbacks('click');
|
||||||
}
|
}
|
||||||
@ -53,6 +82,10 @@ export default class MapNode {
|
|||||||
public getType(): string {
|
public getType(): string {
|
||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public isNear(): boolean {
|
||||||
|
return this.is_near;
|
||||||
|
}
|
||||||
|
|
||||||
public getName(): string {
|
public getName(): string {
|
||||||
return this.name;
|
return this.name;
|
||||||
|
71
js-src/conquer/team.ts
Normal file
71
js-src/conquer/team.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import JsonSerializer from '@burguillosinfo/conquer/serializer';
|
||||||
|
import { JsonObject, JsonProperty } from 'typescript-json-serializer';
|
||||||
|
|
||||||
|
@JsonObject()
|
||||||
|
export default class ConquerTeam {
|
||||||
|
@JsonProperty()
|
||||||
|
private kind: string;
|
||||||
|
@JsonProperty()
|
||||||
|
private uuid: string;
|
||||||
|
@JsonProperty()
|
||||||
|
private name: string;
|
||||||
|
@JsonProperty()
|
||||||
|
private description: string;
|
||||||
|
@JsonProperty()
|
||||||
|
private points: number;
|
||||||
|
@JsonProperty()
|
||||||
|
private color: string;
|
||||||
|
|
||||||
|
constructor(uuid: string, name: string, description: string, points: number, color: string) {
|
||||||
|
this.kind = 'ConquerTeam';
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.name = name;
|
||||||
|
this.description = description;
|
||||||
|
this.points = points;
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async getTeam(uuid: string): Promise<ConquerTeam> {
|
||||||
|
const urlTeam = new URL('/conquer/team/' + uuid, window.location.protocol + '//' + window.location.hostname + ':' + window.location.port)
|
||||||
|
try {
|
||||||
|
const response = await fetch(urlTeam)
|
||||||
|
if (response.status !== 200) {
|
||||||
|
throw new Error('Invalid response fetching team.')
|
||||||
|
}
|
||||||
|
const teamData = await response.json()
|
||||||
|
let team = JsonSerializer.deserialize(teamData, ConquerTeam);
|
||||||
|
if (team === undefined) {
|
||||||
|
team = null;
|
||||||
|
}
|
||||||
|
if (!(team instanceof ConquerTeam)) {
|
||||||
|
throw new Error('Unable to parse team.');
|
||||||
|
}
|
||||||
|
return team;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
throw new Error('Unable to fetch Team.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async getSelfTeam(): Promise<ConquerTeam | null> {
|
||||||
|
const urlTeam = new URL('/conquer/user/team', window.location.protocol + '//' + window.location.hostname + ':' + window.location.port)
|
||||||
|
try {
|
||||||
|
const response = await fetch(urlTeam)
|
||||||
|
if (response.status !== 200) {
|
||||||
|
throw new Error('Invalid response fetching team.')
|
||||||
|
}
|
||||||
|
const teamData = await response.json()
|
||||||
|
let team = JsonSerializer.deserialize(teamData, ConquerTeam);
|
||||||
|
if (team === undefined) {
|
||||||
|
team = null;
|
||||||
|
}
|
||||||
|
if (team !== null && !(team instanceof ConquerTeam)) {
|
||||||
|
throw new Error('Unable to parse team.');
|
||||||
|
}
|
||||||
|
return team;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
throw new Error('Unable to fetch Team.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,7 @@
|
|||||||
|
import JsonSerializer from '@burguillosinfo/conquer/serializer';
|
||||||
|
import { JsonObject, JsonProperty } from 'typescript-json-serializer';
|
||||||
|
import ConquerTeam from '@burguillosinfo/conquer/team';
|
||||||
|
|
||||||
export interface UserData {
|
export interface UserData {
|
||||||
is_admin: number
|
is_admin: number
|
||||||
kind: string
|
kind: string
|
||||||
@ -7,29 +11,37 @@ export interface UserData {
|
|||||||
uuid: string
|
uuid: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonObject()
|
||||||
export default class ConquerUser {
|
export default class ConquerUser {
|
||||||
private _isAdmin = false
|
@JsonProperty()
|
||||||
private kind = "ConquerUser"
|
private is_admin: boolean;
|
||||||
private lastActivity: string | null = null
|
@JsonProperty()
|
||||||
private registrationDate: string | null = null
|
private kind: string;
|
||||||
private username: string | null = null
|
@JsonProperty()
|
||||||
private uuid: string | null = null
|
private last_activity: string | null;
|
||||||
|
@JsonProperty()
|
||||||
|
private registration_date: string | null;
|
||||||
|
@JsonProperty()
|
||||||
|
private username: string;
|
||||||
|
@JsonProperty()
|
||||||
|
private uuid: string;
|
||||||
|
@JsonProperty({name: 'team'})
|
||||||
|
private team_uuid: string | null;
|
||||||
|
|
||||||
constructor(data: UserData) {
|
constructor(kind: string, uuid: string, username: string, is_admin = false, registration_date: string | null = null, last_activity: string | null = null) {
|
||||||
this.lastActivity = data.last_activity ?? null;
|
this.kind = kind;
|
||||||
this.registrationDate = data.registration_date ?? null;
|
this.uuid = uuid;
|
||||||
if (this.kind !== data.kind) {
|
this.username = username;
|
||||||
throw new Error(`We cannot instance a user from a kind different to ${this.kind}.`)
|
this.is_admin = is_admin;
|
||||||
}
|
this.registration_date = registration_date;
|
||||||
this._isAdmin = !!data.is_admin || false
|
this.last_activity = last_activity;
|
||||||
this.uuid = data.uuid
|
}
|
||||||
this.username = data.username
|
|
||||||
if (this.username === null || this.username === undefined) {
|
public async getTeam(): Promise<ConquerTeam | null> {
|
||||||
throw new Error('No username in user instance')
|
if (this.team_uuid === null) {
|
||||||
}
|
return null;
|
||||||
if (this.uuid === null || this.username === undefined) {
|
|
||||||
throw new Error('No uuid in user instance')
|
|
||||||
}
|
}
|
||||||
|
return ConquerTeam.getTeam(this.team_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async getSelfUser(): Promise<ConquerUser | null> {
|
public static async getSelfUser(): Promise<ConquerUser | null> {
|
||||||
@ -40,7 +52,11 @@ export default class ConquerUser {
|
|||||||
throw new Error('Invalid response fetching user.')
|
throw new Error('Invalid response fetching user.')
|
||||||
}
|
}
|
||||||
const userData = await response.json()
|
const userData = await response.json()
|
||||||
return new ConquerUser(userData)
|
const user = JsonSerializer.deserialize(userData, ConquerUser);
|
||||||
|
if (!(user instanceof ConquerUser)) {
|
||||||
|
throw new Error('Unable to parse user.');
|
||||||
|
}
|
||||||
|
return user;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
return null
|
return null
|
||||||
@ -53,6 +69,6 @@ export default class ConquerUser {
|
|||||||
return this.username
|
return this.username
|
||||||
}
|
}
|
||||||
public isAdmin(): boolean {
|
public isAdmin(): boolean {
|
||||||
return this._isAdmin
|
return this.is_admin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ use Mojo::Base 'Mojolicious', -signatures;
|
|||||||
# This method will run once at server start
|
# This method will run once at server start
|
||||||
sub startup ($self) {
|
sub startup ($self) {
|
||||||
my $metrics = BurguillosInfo::Controller::Metrics->new;
|
my $metrics = BurguillosInfo::Controller::Metrics->new;
|
||||||
|
$self->sessions->default_expiration(0);
|
||||||
$self->hook(
|
$self->hook(
|
||||||
around_dispatch => sub {
|
around_dispatch => sub {
|
||||||
my $next = shift;
|
my $next = shift;
|
||||||
@ -91,9 +92,12 @@ sub startup ($self) {
|
|||||||
$r->get('/stats')->to('Metrics#stats');
|
$r->get('/stats')->to('Metrics#stats');
|
||||||
$r->get('/conquer')->to('Conquer#index');
|
$r->get('/conquer')->to('Conquer#index');
|
||||||
$r->put('/conquer/user')->to('UserConquer#create');
|
$r->put('/conquer/user')->to('UserConquer#create');
|
||||||
|
$r->get('/conquer/user/team')->to('UserConquer#getSelfTeam');
|
||||||
$r->post('/conquer/user/coordinates')->to('UserConquer#setCoordinates');
|
$r->post('/conquer/user/coordinates')->to('UserConquer#setCoordinates');
|
||||||
|
$r->get('/conquer/team/<uuid>')->to('ConquerTeam#get');
|
||||||
$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/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');
|
||||||
|
@ -9,7 +9,30 @@ use utf8;
|
|||||||
|
|
||||||
use Mojo::Base 'Mojolicious::Controller', '-signatures';
|
use Mojo::Base 'Mojolicious::Controller', '-signatures';
|
||||||
use UUID::URandom qw/create_uuid_string/;
|
use UUID::URandom qw/create_uuid_string/;
|
||||||
|
use BurguillosInfo::Schema;
|
||||||
|
|
||||||
|
sub get($self) {
|
||||||
|
my $uuid = $self->param('uuid');
|
||||||
|
my $user = $self->current_user;
|
||||||
|
if (!defined $uuid || !$uuid) {
|
||||||
|
return $self->render(status => 400, json => {
|
||||||
|
error => 'UUID de nodo invalido.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
my $schema = BurguillosInfo::Schema->Schema->resultset('ConquerNode');
|
||||||
|
my @nodes = $schema->search({uuid => $uuid});
|
||||||
|
if (!scalar @nodes) {
|
||||||
|
return $self->render(status => 404, json => {
|
||||||
|
error => 'Nodo no encontrado',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
my $node = $nodes[0];
|
||||||
|
if (defined $user) {
|
||||||
|
return $self->render(json => $node->serialize($user));
|
||||||
|
}
|
||||||
|
return $self->render(json => $node->serialize());
|
||||||
|
}
|
||||||
|
|
||||||
sub create ($self) {
|
sub create ($self) {
|
||||||
my $user = $self->current_user;
|
my $user = $self->current_user;
|
||||||
if ( !defined $user ) {
|
if ( !defined $user ) {
|
||||||
@ -118,7 +141,7 @@ sub nearbyNodes($self) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
my @nodes = BurguillosInfo::Schema->Schema->resultset('ConquerNode')->search({});
|
my @nodes = BurguillosInfo::Schema->Schema->resultset('ConquerNode')->search({});
|
||||||
@nodes = map { $_->serialize } @nodes;
|
@nodes = map { $_->serialize($user) } @nodes;
|
||||||
return $self->render(json => \@nodes);
|
return $self->render(json => \@nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
57
lib/BurguillosInfo/Controller/ConquerTeam.pm
Normal file
57
lib/BurguillosInfo/Controller/ConquerTeam.pm
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package BurguillosInfo::Controller::ConquerTeam;
|
||||||
|
|
||||||
|
use v5.34.1;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use utf8;
|
||||||
|
|
||||||
|
use Mojo::Base 'Mojolicious::Controller', '-signatures';
|
||||||
|
|
||||||
|
use UUID::URandom qw/create_uuid_string/;
|
||||||
|
use JSON;
|
||||||
|
|
||||||
|
use BurguillosInfo::Schema;
|
||||||
|
|
||||||
|
sub get($self) {
|
||||||
|
my $user = $self->current_user;
|
||||||
|
if (!defined $user) {
|
||||||
|
return $self->render(status => 401, json => {
|
||||||
|
error => 'You must be logged to fetch a team.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
my $uuid = $self->param('uuid');
|
||||||
|
my $resultset = BurguillosInfo::Schema->Schema->resultset('ConquerTeam');
|
||||||
|
my @teams = $resultset->search({
|
||||||
|
'uuid' => $uuid,
|
||||||
|
});
|
||||||
|
if (scalar @teams <= 0) {
|
||||||
|
return $self->render( status => 404, json => {
|
||||||
|
error => 'This team does not exist.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
my $team = $teams[0];
|
||||||
|
return $self->render(json => $team);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub getSelfTeam($self) {
|
||||||
|
my $user = $self->current_user;
|
||||||
|
if (!defined $user) {
|
||||||
|
return $self->render(status => 401, json => {
|
||||||
|
error => 'You must be logged to fetch your Team.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
my $resultset = BurguillosInfo::Schema->Schema->resultset('ConquerTeam');
|
||||||
|
my @teams = $resultset->search({
|
||||||
|
'players.uuid' => $user->uuid
|
||||||
|
}, {
|
||||||
|
join => 'players',
|
||||||
|
});
|
||||||
|
if (scalar @teams <= 0) {
|
||||||
|
return $self->render(json => undef);
|
||||||
|
}
|
||||||
|
my $team = $teams[0];
|
||||||
|
return $self->render(json => $team);
|
||||||
|
}
|
||||||
|
1;
|
@ -28,11 +28,11 @@ sub MIGRATIONS {
|
|||||||
path TEXT,
|
path TEXT,
|
||||||
FOREIGN KEY (path) REFERENCES paths(path)
|
FOREIGN KEY (path) REFERENCES paths(path)
|
||||||
)',
|
)',
|
||||||
'ALTER TABLE paths ADD column last_seen TIMESTAMP;',
|
'ALTER TABLE paths ADD COLUMN last_seen TIMESTAMP;',
|
||||||
'ALTER TABLE paths ALTER COLUMN last_seen SET DEFAULT NOW();',
|
'ALTER TABLE paths ALTER COLUMN last_seen SET DEFAULT NOW();',
|
||||||
'ALTER TABLE requests ADD PRIMARY KEY (uuid)',
|
'ALTER TABLE requests ADD PRIMARY KEY (uuid)',
|
||||||
'CREATE INDEX request_extra_index on requests (date, path);',
|
'CREATE INDEX request_extra_index on requests (date, path);',
|
||||||
'ALTER TABLE requests ADD column referer text;',
|
'ALTER TABLE requests ADD COLUMN referer text;',
|
||||||
'CREATE INDEX request_referer_index on requests (referer);',
|
'CREATE INDEX request_referer_index on requests (referer);',
|
||||||
'ALTER TABLE requests ADD COLUMN country TEXT;',
|
'ALTER TABLE requests ADD COLUMN country TEXT;',
|
||||||
'CREATE INDEX request_country_index on requests (country);',
|
'CREATE INDEX request_country_index on requests (country);',
|
||||||
@ -71,6 +71,17 @@ sub MIGRATIONS {
|
|||||||
'ALTER TABLE conquer_user ALTER COLUMN last_coordinate_1 DROP DEFAULT;',
|
'ALTER TABLE conquer_user ALTER COLUMN last_coordinate_1 DROP DEFAULT;',
|
||||||
'ALTER TABLE conquer_user ADD COLUMN last_coordinate_2 REAL NOT NULL DEFAULT 0;',
|
'ALTER TABLE conquer_user ADD COLUMN last_coordinate_2 REAL NOT NULL DEFAULT 0;',
|
||||||
'ALTER TABLE conquer_user ALTER COLUMN last_coordinate_2 DROP DEFAULT;',
|
'ALTER TABLE conquer_user ALTER COLUMN last_coordinate_2 DROP DEFAULT;',
|
||||||
|
'CREATE TABLE conquer_teams (
|
||||||
|
uuid UUID NOT NULL PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
description TEXT NOT NULL DEFAULT \'\',
|
||||||
|
points INTEGER NOT NULL DEFAULT 0
|
||||||
|
);',
|
||||||
|
'ALTER TABLE conquer_user ADD COLUMN team UUID REFERENCES conquer_teams (uuid);',
|
||||||
|
'ALTER TABLE conquer_node ADD COLUMN team UUID REFERENCES conquer_teams (uuid);',
|
||||||
|
'ALTER TABLE conquer_teams ADD COLUMN color TEXT NOT NULL DEFAULT \'#000\';',
|
||||||
|
'ALTER TABLE conquer_teams ALTER COLUMN color SET DEFAULT \'#555\';',
|
||||||
|
'ALTER TABLE conquer_teams ALTER COLUMN color SET DEFAULT \'#aaa\';',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,9 @@ use parent 'DBIx::Class::Core';
|
|||||||
|
|
||||||
use feature 'signatures';
|
use feature 'signatures';
|
||||||
|
|
||||||
|
use JSON;
|
||||||
|
use GIS::Distance;
|
||||||
|
|
||||||
__PACKAGE__->table('conquer_node');
|
__PACKAGE__->table('conquer_node');
|
||||||
__PACKAGE__->load_components("TimeStamp");
|
__PACKAGE__->load_components("TimeStamp");
|
||||||
|
|
||||||
@ -40,9 +43,9 @@ __PACKAGE__->add_columns(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
sub serialize ($self) {
|
sub serialize ( $self, $player = undef ) {
|
||||||
$self = $self->get_from_storage();
|
$self = $self->get_from_storage();
|
||||||
return {
|
my $return = {
|
||||||
kind => 'ConquerNode',
|
kind => 'ConquerNode',
|
||||||
uuid => $self->uuid,
|
uuid => $self->uuid,
|
||||||
name => $self->name,
|
name => $self->name,
|
||||||
@ -50,7 +53,31 @@ sub serialize ($self) {
|
|||||||
type => $self->type,
|
type => $self->type,
|
||||||
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),
|
||||||
};
|
};
|
||||||
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub is_near ( $self, $player ) {
|
||||||
|
if ( !defined $player ) {
|
||||||
|
return $JSON::false;
|
||||||
|
}
|
||||||
|
# Meters
|
||||||
|
if ($self->get_distance_to_player($player) < 100) {
|
||||||
|
return $JSON::true;
|
||||||
|
}
|
||||||
|
return $JSON::false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_distance_to_player ($self, $player) {
|
||||||
|
my $longitude_player = $player->last_coordinate_1;
|
||||||
|
my $latitude_player = $player->last_coordinate_2;
|
||||||
|
my $longitude_node = $self->coordinate_1;
|
||||||
|
my $latitude_node = $self->coordinate_2;
|
||||||
|
my $gis = GIS::Distance->new;
|
||||||
|
# Setting distance to meters.
|
||||||
|
my $distance = $gis->distance_metal( $latitude_node, $longitude_node, $latitude_player, $longitude_player) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
__PACKAGE__->set_primary_key('uuid');
|
__PACKAGE__->set_primary_key('uuid');
|
||||||
1;
|
1;
|
||||||
|
53
lib/BurguillosInfo/Schema/Result/ConquerTeam.pm
Normal file
53
lib/BurguillosInfo/Schema/Result/ConquerTeam.pm
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package BurguillosInfo::Schema::Result::ConquerTeam;
|
||||||
|
|
||||||
|
use v5.36.0;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use parent 'DBIx::Class::Core';
|
||||||
|
|
||||||
|
use feature 'signatures';
|
||||||
|
|
||||||
|
use JSON;
|
||||||
|
|
||||||
|
__PACKAGE__->table('conquer_teams');
|
||||||
|
__PACKAGE__->load_components("TimeStamp");
|
||||||
|
|
||||||
|
__PACKAGE__->add_columns(
|
||||||
|
uuid => {
|
||||||
|
data_type => 'uuid',
|
||||||
|
is_nullable => 0,
|
||||||
|
},
|
||||||
|
name => {
|
||||||
|
data_type => 'text',
|
||||||
|
is_nullable => 0,
|
||||||
|
},
|
||||||
|
description => {
|
||||||
|
data_type => 'text',
|
||||||
|
is_nullable => 0,
|
||||||
|
},
|
||||||
|
points => {
|
||||||
|
data_type => 'integer',
|
||||||
|
is_nullable => 0,
|
||||||
|
},
|
||||||
|
color => {
|
||||||
|
data_type => 'text',
|
||||||
|
is_nullable => 0,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
sub serialize ($self) {
|
||||||
|
$self = $self->get_from_storage();
|
||||||
|
return {
|
||||||
|
kind => 'ConquerTeam',
|
||||||
|
uuid => $self->uuid,
|
||||||
|
name => $self->name,
|
||||||
|
description => $self->description,
|
||||||
|
points => $self->points,
|
||||||
|
color => $self->color,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
__PACKAGE__->has_many( players => 'BurguillosInfo::Schema::Result::ConquerUser', 'team');
|
||||||
|
__PACKAGE__->set_primary_key('uuid');
|
||||||
|
1;
|
@ -9,6 +9,8 @@ use parent 'DBIx::Class::Core';
|
|||||||
|
|
||||||
use feature 'signatures';
|
use feature 'signatures';
|
||||||
|
|
||||||
|
use JSON;
|
||||||
|
|
||||||
__PACKAGE__->table('conquer_user');
|
__PACKAGE__->table('conquer_user');
|
||||||
__PACKAGE__->load_components("TimeStamp");
|
__PACKAGE__->load_components("TimeStamp");
|
||||||
|
|
||||||
@ -17,6 +19,10 @@ __PACKAGE__->add_columns(
|
|||||||
data_type => 'uuid',
|
data_type => 'uuid',
|
||||||
is_nullable => 0,
|
is_nullable => 0,
|
||||||
},
|
},
|
||||||
|
team => {
|
||||||
|
data_type => 'uuid',
|
||||||
|
is_nullable => 1,
|
||||||
|
},
|
||||||
username => {
|
username => {
|
||||||
data_type => 'text',
|
data_type => 'text',
|
||||||
is_nullable => 0,
|
is_nullable => 0,
|
||||||
@ -52,16 +58,16 @@ __PACKAGE__->add_columns(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
sub coordinates($self, $coordinates = undef) {
|
sub coordinates ( $self, $coordinates = undef ) {
|
||||||
if (defined $coordinates) {
|
if ( defined $coordinates ) {
|
||||||
if (ref $coordinates ne 'ARRAY' || scalar $coordinates->@* != 2) {
|
if ( ref $coordinates ne 'ARRAY' || scalar $coordinates->@* != 2 ) {
|
||||||
die 'The second parameter of this subroutine '
|
die 'The second parameter of this subroutine '
|
||||||
. 'must be an ARRAYREF of exactly two elements.';
|
. 'must be an ARRAYREF of exactly two elements.';
|
||||||
}
|
}
|
||||||
$self->last_coordinate_1($coordinates->[0]);
|
$self->last_coordinate_1( $coordinates->[0] );
|
||||||
$self->last_coordinate_2($coordinates->[1]);
|
$self->last_coordinate_2( $coordinates->[1] );
|
||||||
}
|
}
|
||||||
return [$self->last_coordinate_1, $self->last_coordinate_2];
|
return [ $self->last_coordinate_1, $self->last_coordinate_2 ];
|
||||||
}
|
}
|
||||||
|
|
||||||
sub serialize_to_owner ($self) {
|
sub serialize_to_owner ($self) {
|
||||||
@ -69,8 +75,9 @@ sub serialize_to_owner ($self) {
|
|||||||
return {
|
return {
|
||||||
kind => 'ConquerUser',
|
kind => 'ConquerUser',
|
||||||
uuid => $self->uuid,
|
uuid => $self->uuid,
|
||||||
|
team => $self->team,
|
||||||
username => $self->username,
|
username => $self->username,
|
||||||
is_admin => $self->is_admin,
|
is_admin => $self->is_admin ? $JSON::true : $JSON::false,
|
||||||
last_activity => $self->last_activity,
|
last_activity => $self->last_activity,
|
||||||
registration_date => $self->registration_date,
|
registration_date => $self->registration_date,
|
||||||
};
|
};
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user