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,
|
||||
'DBIx::Class::TimeStamp' => 0,
|
||||
'DateTime::Format::HTTP' => 0,
|
||||
'GIS::Distance' => 0,
|
||||
},
|
||||
);
|
||||
$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)
|
||||
fetch(urlNodes).then(async (response) => {
|
||||
let responseBody;
|
||||
try {
|
||||
responseBody = await response.json();
|
||||
} catch (error) {
|
||||
console.error('Error parseando json: ' + responseBody);
|
||||
console.error(error);
|
||||
return;
|
||||
let response;
|
||||
try {
|
||||
response = await fetch(urlNodes);
|
||||
} catch (error) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
serverNodes[node.getId()] = node;
|
||||
}
|
||||
this.serverNodes = serverNodes;
|
||||
this.refreshLayers();
|
||||
});
|
||||
node.on('update-nodes', async () => {
|
||||
await this.sendCoordinatesToServer();
|
||||
this.getNearbyNodes();
|
||||
});
|
||||
serverNodes[node.getId()] = node;
|
||||
}
|
||||
this.serverNodes = serverNodes;
|
||||
this.refreshLayers();
|
||||
}
|
||||
|
||||
private createIntervalPollNearbyNodes(): void {
|
||||
@ -284,29 +293,31 @@ export default class Conquer {
|
||||
}, 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)
|
||||
fetch(urlLog, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify([
|
||||
this.coordinate_1,
|
||||
this.coordinate_2,
|
||||
]),
|
||||
}).then(async (res) => {
|
||||
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);
|
||||
}
|
||||
}).catch((error) => {
|
||||
let res;
|
||||
try {
|
||||
res = await fetch(urlLog, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify([
|
||||
this.coordinate_1,
|
||||
this.coordinate_2,
|
||||
])});
|
||||
} catch (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 {
|
||||
|
@ -24,12 +24,22 @@ export default class NodeView extends AbstractTopBarInterface {
|
||||
super()
|
||||
this.node = node;
|
||||
}
|
||||
public run() {
|
||||
public async run() {
|
||||
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')
|
||||
mainNode.append(view)
|
||||
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')
|
||||
mainNode.classList.remove('conquer-display-none')
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ 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';
|
||||
|
||||
@JsonObject()
|
||||
export default class MapNode {
|
||||
@ -21,14 +22,42 @@ export default class MapNode {
|
||||
@JsonProperty() private name: string,
|
||||
@JsonProperty() private description: 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 {
|
||||
const viewNodeInterface = new NodeView(this);
|
||||
viewNodeInterface.on('close', () => {
|
||||
interfaceManager.remove(viewNodeInterface);
|
||||
});
|
||||
viewNodeInterface.on('update-nodes', () => {
|
||||
this.runCallbacks('update-nodes');
|
||||
});
|
||||
interfaceManager.push(viewNodeInterface);
|
||||
this.runCallbacks('click');
|
||||
}
|
||||
@ -53,6 +82,10 @@ export default class MapNode {
|
||||
public getType(): string {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public isNear(): boolean {
|
||||
return this.is_near;
|
||||
}
|
||||
|
||||
public getName(): string {
|
||||
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 {
|
||||
is_admin: number
|
||||
kind: string
|
||||
@ -7,29 +11,37 @@ export interface UserData {
|
||||
uuid: string
|
||||
}
|
||||
|
||||
@JsonObject()
|
||||
export default class ConquerUser {
|
||||
private _isAdmin = false
|
||||
private kind = "ConquerUser"
|
||||
private lastActivity: string | null = null
|
||||
private registrationDate: string | null = null
|
||||
private username: string | null = null
|
||||
private uuid: string | null = null
|
||||
@JsonProperty()
|
||||
private is_admin: boolean;
|
||||
@JsonProperty()
|
||||
private kind: string;
|
||||
@JsonProperty()
|
||||
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) {
|
||||
this.lastActivity = data.last_activity ?? null;
|
||||
this.registrationDate = data.registration_date ?? null;
|
||||
if (this.kind !== data.kind) {
|
||||
throw new Error(`We cannot instance a user from a kind different to ${this.kind}.`)
|
||||
}
|
||||
this._isAdmin = !!data.is_admin || false
|
||||
this.uuid = data.uuid
|
||||
this.username = data.username
|
||||
if (this.username === null || this.username === undefined) {
|
||||
throw new Error('No username in user instance')
|
||||
}
|
||||
if (this.uuid === null || this.username === undefined) {
|
||||
throw new Error('No uuid in user instance')
|
||||
constructor(kind: string, uuid: string, username: string, is_admin = false, registration_date: string | null = null, last_activity: string | null = null) {
|
||||
this.kind = kind;
|
||||
this.uuid = uuid;
|
||||
this.username = username;
|
||||
this.is_admin = is_admin;
|
||||
this.registration_date = registration_date;
|
||||
this.last_activity = last_activity;
|
||||
}
|
||||
|
||||
public async getTeam(): Promise<ConquerTeam | null> {
|
||||
if (this.team_uuid === null) {
|
||||
return null;
|
||||
}
|
||||
return ConquerTeam.getTeam(this.team_uuid);
|
||||
}
|
||||
|
||||
public static async getSelfUser(): Promise<ConquerUser | null> {
|
||||
@ -40,7 +52,11 @@ export default class ConquerUser {
|
||||
throw new Error('Invalid response fetching user.')
|
||||
}
|
||||
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) {
|
||||
console.error(error)
|
||||
return null
|
||||
@ -53,6 +69,6 @@ export default class ConquerUser {
|
||||
return this.username
|
||||
}
|
||||
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
|
||||
sub startup ($self) {
|
||||
my $metrics = BurguillosInfo::Controller::Metrics->new;
|
||||
$self->sessions->default_expiration(0);
|
||||
$self->hook(
|
||||
around_dispatch => sub {
|
||||
my $next = shift;
|
||||
@ -91,9 +92,12 @@ sub startup ($self) {
|
||||
$r->get('/stats')->to('Metrics#stats');
|
||||
$r->get('/conquer')->to('Conquer#index');
|
||||
$r->put('/conquer/user')->to('UserConquer#create');
|
||||
$r->get('/conquer/user/team')->to('UserConquer#getSelfTeam');
|
||||
$r->post('/conquer/user/coordinates')->to('UserConquer#setCoordinates');
|
||||
$r->get('/conquer/team/<uuid>')->to('ConquerTeam#get');
|
||||
$r->put('/conquer/node')->to('ConquerNode#create');
|
||||
$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->post('/conquer/user/login')->to('UserConquer#login');
|
||||
$r->get('/conquer/tile/<zoom>/<x>/<y>.png')->to('ConquerTile#tile');
|
||||
|
@ -9,7 +9,30 @@ use utf8;
|
||||
|
||||
use Mojo::Base 'Mojolicious::Controller', '-signatures';
|
||||
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) {
|
||||
my $user = $self->current_user;
|
||||
if ( !defined $user ) {
|
||||
@ -118,7 +141,7 @@ sub nearbyNodes($self) {
|
||||
});
|
||||
}
|
||||
my @nodes = BurguillosInfo::Schema->Schema->resultset('ConquerNode')->search({});
|
||||
@nodes = map { $_->serialize } @nodes;
|
||||
@nodes = map { $_->serialize($user) } @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,
|
||||
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 requests ADD PRIMARY KEY (uuid)',
|
||||
'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);',
|
||||
'ALTER TABLE requests ADD COLUMN country TEXT;',
|
||||
'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 ADD COLUMN last_coordinate_2 REAL NOT NULL DEFAULT 0;',
|
||||
'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 JSON;
|
||||
use GIS::Distance;
|
||||
|
||||
__PACKAGE__->table('conquer_node');
|
||||
__PACKAGE__->load_components("TimeStamp");
|
||||
|
||||
@ -40,9 +43,9 @@ __PACKAGE__->add_columns(
|
||||
}
|
||||
);
|
||||
|
||||
sub serialize ($self) {
|
||||
sub serialize ( $self, $player = undef ) {
|
||||
$self = $self->get_from_storage();
|
||||
return {
|
||||
my $return = {
|
||||
kind => 'ConquerNode',
|
||||
uuid => $self->uuid,
|
||||
name => $self->name,
|
||||
@ -50,7 +53,31 @@ sub serialize ($self) {
|
||||
type => $self->type,
|
||||
coordinate_1 => $self->coordinate_1,
|
||||
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');
|
||||
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 JSON;
|
||||
|
||||
__PACKAGE__->table('conquer_user');
|
||||
__PACKAGE__->load_components("TimeStamp");
|
||||
|
||||
@ -17,6 +19,10 @@ __PACKAGE__->add_columns(
|
||||
data_type => 'uuid',
|
||||
is_nullable => 0,
|
||||
},
|
||||
team => {
|
||||
data_type => 'uuid',
|
||||
is_nullable => 1,
|
||||
},
|
||||
username => {
|
||||
data_type => 'text',
|
||||
is_nullable => 0,
|
||||
@ -52,16 +58,16 @@ __PACKAGE__->add_columns(
|
||||
},
|
||||
);
|
||||
|
||||
sub coordinates($self, $coordinates = undef) {
|
||||
if (defined $coordinates) {
|
||||
if (ref $coordinates ne 'ARRAY' || scalar $coordinates->@* != 2) {
|
||||
sub coordinates ( $self, $coordinates = undef ) {
|
||||
if ( defined $coordinates ) {
|
||||
if ( ref $coordinates ne 'ARRAY' || scalar $coordinates->@* != 2 ) {
|
||||
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_2($coordinates->[1]);
|
||||
$self->last_coordinate_1( $coordinates->[0] );
|
||||
$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) {
|
||||
@ -69,8 +75,9 @@ sub serialize_to_owner ($self) {
|
||||
return {
|
||||
kind => 'ConquerUser',
|
||||
uuid => $self->uuid,
|
||||
team => $self->team,
|
||||
username => $self->username,
|
||||
is_admin => $self->is_admin,
|
||||
is_admin => $self->is_admin ? $JSON::true : $JSON::false,
|
||||
last_activity => $self->last_activity,
|
||||
registration_date => $self->registration_date,
|
||||
};
|
||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user