Files
pathfinder/app/Model/Universe/SystemModel.php
Mark Friedrich a5f29ee2eb - NEW "Thera connections" UI module, closed #829
- Upgraded "[_pathfinder_esi_](https://github.com/exodus4d/pathfinder_esi)" Web API client`v1.3.2` → `v2.0.0`
- Fixed a js bug where current active(selected) system becomes deselected after system was dragged on map
- Fixed a js bug where new auto mapped systems (e.g. after jump) were positioned outside current map scroll viewport
- Fixed a js bug where map sync failed after map tabs switch
- Fixed blurry map when map zoom was changed
- Fixed multiple minor JS bugs where map render/update failed
2020-03-02 16:42:36 +01:00

577 lines
18 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Created by PhpStorm.
* User: Exodus 4D
* Date: 14.05.2018
* Time: 19:29
*/
namespace Exodus4D\Pathfinder\Model\Universe;
use DB\SQL\Schema;
class SystemModel extends AbstractUniverseModel {
/**
* @var string
*/
protected $table = 'system';
/**
* @var array
*/
protected $fieldConf = [
'name' => [
'type' => Schema::DT_VARCHAR128,
'nullable' => false,
'default' => ''
],
'constellationId' => [
'type' => Schema::DT_INT,
'index' => true,
'belongs-to-one' => 'Exodus4D\Pathfinder\Model\Universe\ConstellationModel',
'constraint' => [
[
'table' => 'constellation',
'on-delete' => 'CASCADE'
]
],
'validate' => 'notDry'
],
'starId' => [
'type' => Schema::DT_INT,
'index' => true,
'belongs-to-one' => 'Exodus4D\Pathfinder\Model\Universe\StarModel',
'constraint' => [
[
'table' => 'star',
'on-delete' => 'CASCADE'
]
],
'validate' => 'notDry'
],
'security' => [
'type' => Schema::DT_VARCHAR128
],
'trueSec' => [
'type' => Schema::DT_FLOAT,
'nullable' => false,
'default' => 1
],
'securityStatus' => [
'type' => Schema::DT_DOUBLE,
'nullable' => false,
'default' => 1
],
'securityClass' => [
'type' => Schema::DT_VARCHAR128,
],
'effect' => [
'type' => Schema::DT_VARCHAR128
],
'x' => [
'type' => Schema::DT_BIGINT,
'nullable' => false,
'default' => 0
],
'y' => [
'type' => Schema::DT_BIGINT,
'nullable' => false,
'default' => 0
],
'z' => [
'type' => Schema::DT_BIGINT,
'nullable' => false,
'default' => 0
],
'planets' => [
'has-many' => ['Exodus4D\Pathfinder\Model\Universe\PlanetModel', 'systemId']
],
'statics' => [
'has-many' => ['Exodus4D\Pathfinder\Model\Universe\SystemStaticModel', 'systemId']
],
'stargates' => [
'has-many' => ['Exodus4D\Pathfinder\Model\Universe\StargateModel', 'systemId']
],
'stations' => [
'has-many' => ['Exodus4D\Pathfinder\Model\Universe\StationModel', 'systemId']
],
'structures' => [
'has-many' => ['Exodus4D\Pathfinder\Model\Universe\StructureModel', 'systemId']
],
'neighbour' => [
'has-one' => ['Exodus4D\Pathfinder\Model\Universe\SystemNeighbourModel', 'systemId']
],
'sovereignty' => [
'has-one' => ['Exodus4D\Pathfinder\Model\Universe\SovereigntyMapModel', 'systemId']
],
'factionWar' => [
'has-one' => ['Exodus4D\Pathfinder\Model\Universe\FactionWarSystemModel', 'systemId']
]
];
/**
* get system data
* -> this includes constellation, region, star, planets as well
* @return \stdClass
*/
public function getData(){
$data = (object) [];
$data->id = $this->_id;
$data->name = $this->name;
$data->constellation = $this->constellationId->getData();
$data->security = $this->security;
$data->trueSec = (float)$this->trueSec;
$data->effect = $this->effect;
$data->shattered = false;
if($this->starId){
$data->star = $this->starId->getData();
}
if($this->sovereignty){
$data->sovereignty = $this->sovereignty->getData();
}
if($this->factionWar){
$data->factionWar = $this->factionWar->getData();
}
if( !empty($planetsData = $this->getPlanetsData()) ){
$data->planets = $planetsData;
// 'Shattered' systems have ONLY planets named with '(shattered)'
// -> system 'Thera' has '(shattered)' AND other planets -> not shattered.
// -> system 'J164104, 'J115422' - the only non-shattered wormholes which have a shattered planet -> not shattered.
$data->shattered = count(array_filter($planetsData, function($planetData){
return property_exists($planetData, 'type') &&
(strpos(strtolower($planetData->type->name), '(shattered)') !== false);
})) == count($planetsData);
}
if( !empty($staticsData = $this->getStaticsData()) ){
$data->statics = $staticsData;
}
if( !empty($stargatesData = $this->getStargatesData()) ){
$data->stargates = $stargatesData;
}
if( !empty($stationsData = $this->getStationsData()) ){
$data->stations = $stationsData;
}
return $data;
}
/**
* setter for system name
* @param $name
* @return mixed
*/
public function set_name($name){
// name should never change
// -> important for "Abyssal" systems where ESI don´t have correct system name
if(!empty($this->name)){
$name = $this->name;
}
return $name;
}
/**
* setter for row (un-formatted) trueSec
* @param $secStatus
* @return double
*/
public function set_securityStatus($secStatus){
$secStatus = (double)$secStatus;
// round for trueSec
$positive = ($secStatus > 0);
$trueSec = round($secStatus, 1, PHP_ROUND_HALF_DOWN);
if($positive && $trueSec <= 0){
$trueSec = 0.1;
}
$this->trueSec = $trueSec;
// set 'security' for NON wormhole systems! -> those get updated from csv import
// 'J1226-0' is also a wormhole with a '-' in the name! (single system)
if(
!preg_match('/^j(\d{6}|\d{4}-\d)$/i', $this->name) &&
$this->name != 'Thera'
){
$constellationId = (int)$this->get('constellationId', true);
if($constellationId == 23000001){
// "Pocket" system
$security = 'P';
}elseif(
$constellationId >= 22000001 &&
$constellationId <= 22000025
){
// "Abyssal" system
$security = 'A';
}else{
// k-space system
if($trueSec <= 0){
$security = '0.0';
}elseif($trueSec < 0.5){
$security = 'L';
}else{
$security = 'H';
}
}
$this->security = $security;
}
return $secStatus;
}
/**
* setter for wormhole effect name
* @param $effect
* @return string|null
*/
public function set_effect($effect){
$effect = (string)$effect;
return $effect ? : null;
}
/**
* @param array $sovData
* @return bool true if sovereignty data changed
*/
public function updateSovereigntyData(array $sovData = []) : bool {
$hasChanged = false;
$systemId = (int)$sovData['systemId'];
$factionId = (int)$sovData['factionId'];
$allianceId = (int)$sovData['allianceId'];
$corporationId = (int)$sovData['corporationId'];
if($this->valid()){
if($systemId === $this->_id){
// sov data belongs to this system
$validSovData = (bool)max($factionId, $allianceId, $corporationId);
if($validSovData){
// at least one of these Ids must exist for a sovereignty relation
/**
* @var $sovereignty SovereigntyMapModel
*/
if(!$sovereignty = $this->sovereignty){
// insert new sovereignty data
$sovereignty = $this->rel('sovereignty');
}
$sovData['systemId'] = $this;
if($factionId){
// HS, L - systems have "faction war"
$sovData['allianceId'] = null;
$sovData['corporationId'] = null;
/**
* @var $faction FactionModel
*/
$faction = $sovereignty->rel('factionId');
$faction->loadById($factionId);
$sovData['factionId'] = $faction;
}else{
// 0.0 - systems have sovereignty data by corp and/or ally
$sovData['factionId'] = null;
/**
* @var $alliance AllianceModel|null
*/
$alliance = null;
if($allianceId){
$alliance = $sovereignty->rel('allianceId');
$alliance->loadById($allianceId);
}
/**
* @var $corporation CorporationModel|null
*/
$corporation = null;
if($corporationId){
$corporation = $sovereignty->rel('corporationId');
$corporation->loadById($corporationId);
}
$sovData['allianceId'] = $alliance;
$sovData['corporationId'] = $corporation;
}
$sovereignty->copyfrom($sovData, ['systemId', 'factionId', 'allianceId', 'corporationId']);
// must be called before save(). Changed fields get reset after save() is called!
if($sovereignty->changed()){
$hasChanged = true;
}
$sovereignty->save();
}elseif($this->sovereignty){
// delete existing sov data
// -> hint: WH - systems never have sovereignty data
$this->sovereignty->erase();
$hasChanged = true;
}
}
}
return $hasChanged;
}
/**
* @param array $fwData
* @return bool true if faction warfare data changed
*/
public function updateFactionWarData(array $fwData = []) : bool {
$hasChanged = false;
$systemId = (int)$fwData['systemId'];
$ownerFactionId = (int)$fwData['ownerFactionId'];
$occupierFactionId = (int)$fwData['occupierFactionId'];
if($this->valid()){
if($systemId === $this->_id){
/**
* @var $factionWar FactionWarSystemModel
*/
if(!$factionWar = $this->factionWar){
// insert new faction war data
$factionWar = $this->rel('factionWar');
}
$fwData['systemId'] = $this;
if($ownerFactionId){
/**
* @var $ownerFaction FactionModel
*/
$ownerFaction = $factionWar->rel('ownerFactionId');
$ownerFaction->loadById($ownerFactionId);
$fwData['ownerFactionId'] = $ownerFaction;
}
if($occupierFactionId){
/**
* @var $occupierFaction FactionModel
*/
$occupierFaction = $factionWar->rel('occupierFactionId');
$occupierFaction->loadById($occupierFactionId);
$fwData['occupierFactionId'] = $occupierFaction;
}
$factionWar->copyfrom($fwData, ['systemId', 'ownerFactionId', 'occupierFactionId', 'contested', 'victoryPoints', 'victoryPointsThreshold']);
// must be called before save(). Changed fields get reset after save() is called!
if($factionWar->changed()){
$hasChanged = true;
}
$factionWar->save();
}
}
return $hasChanged;
}
/**
* Event "Hook" function
* return false will stop any further action
* @param self $self
* @param $pkeys
*/
public function afterUpdateEvent($self, $pkeys){
// build search index
$self->buildIndex();
return parent::afterUpdateEvent($self, $pkeys);
}
/**
* get data from all planets
* @return array
*/
protected function getPlanetsData() : array {
$planetsData = [];
if($this->planets){
/**
* @var $planet PlanetModel
*/
foreach($this->planets as &$planet){
$planetsData[] = $planet->getData();
}
}
return $planetsData;
}
/**
* get data from all static wormholes
* @return array
*/
protected function getStaticsData() : array {
$staticsData = [];
if($this->statics){
/**
* @var $static SystemStaticModel
*/
foreach($this->statics as &$static){
$staticsData[] = $static->getData();
}
}
return $staticsData;
}
/**
* get data from all stargates
* @return array
*/
protected function getStargatesData() : array {
$stargatesData = [];
if($this->stargates){
/**
* @var $stargate StargateModel
*/
foreach($this->stargates as &$stargate){
$stargatesData[] = $stargate->getData();
}
}
return $stargatesData;
}
/**
* get data from all stations
* @return array
*/
protected function getStationsData() : array {
$stationsData = [];
if($this->stations){
/**
* @var $station StationModel
*/
foreach($this->stations as &$station){
$data = $station->getData();
if(!$data->race){
// should never happen NPC stations always have a owning race
$data->race = (object) [];
$data->race->id = 0;
$data->race->name = 'unknown';
$data->race->faction = (object) [];
$data->race->faction->id = 0;
$data->race->faction->name = 'unknown';
}
if(!array_key_exists($data->race->faction->id, $stationsData)){
$stationsData[$data->race->faction->id] = [
'id' => $data->race->faction->id,
'name' => $data->race->name,
'stations' => []
];
}
$stationsData[$data->race->faction->id]['stations'][] = $data;
}
}
return $stationsData;
}
/**
* update system from ESI
*/
public function updateModel(){
if($this->valid()){
$this->loadData($this->_id);
$this->loadPlanetsData();
}
}
/**
* @param int $id
* @param string $accessToken
* @param array $additionalOptions
*/
protected function loadData(int $id, string $accessToken = '', array $additionalOptions = []){
$data = self::getF3()->ccpClient()->send('getUniverseSystem', $id);
if(!empty($data)){
/**
* @var $constellation ConstellationModel
*/
$constellation = $this->rel('constellationId');
$constellation->loadById($data['constellationId'], $accessToken, $additionalOptions);
$data['constellationId'] = $constellation;
// starId is optional since ESI v4 (e.g. Abyssal systems)
if($data['starId']){
/**
* @var $star StarModel
*/
$star = $this->rel('starId');
$star->loadById($data['starId'], $accessToken, $additionalOptions);
$data['starId'] = $star;
}
$this->copyfrom($data, ['id', 'name', 'constellationId', 'starId', 'securityStatus', 'securityClass', 'position']);
$this->save();
}
}
/**
* load planets data for this system
*/
public function loadPlanetsData(){
if($this->valid()){
$data = self::getF3()->ccpClient()->send('getUniverseSystem', $this->_id);
if($data['planets']){
// planets are optional since ESI v4 (e.g. Abyssal systems)
foreach((array)$data['planets'] as $planetData){
/**
* @var $planet PlanetModel
*/
$planet = $this->rel('planets');
$planet->loadById($planetData->planet_id);
$planet->reset();
}
}
}
}
/**
* load stargates for this system
* -> stargates to destination system which is not in DB get ignored
*/
public function loadStargatesData(){
if($this->valid()){
$data = self::getF3()->ccpClient()->send('getUniverseSystem', $this->_id);
if($data['stargates']){
foreach((array)$data['stargates'] as $stargateId){
/**
* @var $stargate StargateModel
*/
$stargate = $this->rel('stargates');
$stargate->loadById($stargateId);
$stargate->reset();
}
}
}
}
/**
* load NPC owned stations for this system
*/
public function loadStationsData(){
if($this->valid()){
$data = self::getF3()->ccpClient()->send('getUniverseSystem', $this->_id);
if($data['stations']){
foreach((array)$data['stations'] as $stationId){
/**
* @var $station SystemModel
*/
$station = $this->rel('stations');
$station->loadById($stationId);
$station->reset();
}
}
}
}
}