closed #131 new "route search" algorithm, added current map systems to live search, added refresh/update functionality for each found route, added bulk route refresh function, added "meta map" route search (search on multiple maps), added route "filters" (restrict search on "stargates", "wormholes", "jumpbridges"), added route "filter" for wormholes (reduced/critical wormholes)
closed #89 fixed "loop connections" on same system #84 added error messages for "invalid" CREST "Client ID" added "bootboxjs" (customized styled checkboxes/radio buttons) CSS only "Font Awesome" version upgrade 4.4.0 -> 4.61 "Bootbox.js" version upgrade 4.3.0 -> 4.4.0 fixed "system dialog" (added responsive layout)
This commit is contained in:
@@ -18,10 +18,16 @@ use Model;
|
||||
class Route extends \Controller\AccessController {
|
||||
|
||||
/**
|
||||
* cache time for static jump data
|
||||
* cache time for static jump data (e.g. K-Space stargates)
|
||||
* @var int
|
||||
*/
|
||||
private $jumpDataCacheTime = 86400;
|
||||
private $staticJumpDataCacheTime = 86400;
|
||||
|
||||
/**
|
||||
* cache time for dynamic jump data (e.g. W-Space systems, Jumpbridges. ...)
|
||||
* @var int
|
||||
*/
|
||||
private $dynamicJumpDataCacheTime = 10;
|
||||
|
||||
/**
|
||||
* array system information grouped by systemId
|
||||
@@ -41,11 +47,27 @@ class Route extends \Controller\AccessController {
|
||||
*/
|
||||
private $idArray = [];
|
||||
|
||||
/**
|
||||
* set jump data for route search
|
||||
* -> this function is required for route search! (Don´t forget)
|
||||
* @param array $mapIds
|
||||
* @param array $filterData
|
||||
*/
|
||||
public function initJumpData($mapIds = [], $filterData = []){
|
||||
// add static data (e.g. K-Space stargates,..)
|
||||
$this->setStaticJumpData();
|
||||
|
||||
// add map specific data
|
||||
$this->setDynamicJumpData($mapIds, $filterData);
|
||||
}
|
||||
|
||||
/**
|
||||
* set static system jump data for this instance
|
||||
* the data is fixed and should not change
|
||||
* -> jump data includes JUST "static" connections (Stargates)
|
||||
* -> this data is equal for EACH route search (does not depend on map data)
|
||||
*/
|
||||
private function setSystemJumpData(){
|
||||
private function setStaticJumpData(){
|
||||
$cacheKey = 'staticJumpData';
|
||||
|
||||
$f3 = $this->getF3();
|
||||
@@ -59,42 +81,167 @@ class Route extends \Controller\AccessController {
|
||||
$f3->exists($cacheKeyJumpArray) &&
|
||||
$f3->exists($cacheKeyIdArray)
|
||||
){
|
||||
// get cached values
|
||||
|
||||
// get cached values
|
||||
$this->nameArray = $f3->get($cacheKeyNamedArray);
|
||||
$this->jumpArray = $f3->get($cacheKeyJumpArray);
|
||||
$this->idArray = $f3->get($cacheKeyIdArray);
|
||||
}else{
|
||||
// nothing cached
|
||||
|
||||
$pfDB = $this->getDB('PF');
|
||||
|
||||
$query = "SELECT * FROM system_neighbour";
|
||||
|
||||
$rows = $pfDB->exec($query, null, $this->jumpDataCacheTime);
|
||||
$rows = $this->getDB()->exec($query, null, $this->staticJumpDataCacheTime);
|
||||
|
||||
if(count($rows) > 0){
|
||||
foreach($rows as $row){
|
||||
$regionId = $row['regionId'];
|
||||
$constId = $row['constellationId'];
|
||||
$systemName = strtoupper($row['systemName']);
|
||||
$systemId = $row['systemId'];
|
||||
$secStatus = $row['trueSec'];
|
||||
$this->updateJumpData($rows);
|
||||
|
||||
$this->nameArray[$systemId][0] = $systemName;
|
||||
$this->nameArray[$systemId][1] = $regionId;
|
||||
$this->nameArray[$systemId][2] = $constId;
|
||||
$this->nameArray[$systemId][3] = $secStatus;
|
||||
// static data should be cached
|
||||
$f3->set($cacheKeyNamedArray, $this->nameArray, $this->staticJumpDataCacheTime);
|
||||
$f3->set($cacheKeyJumpArray, $this->jumpArray, $this->staticJumpDataCacheTime);
|
||||
$f3->set($cacheKeyIdArray, $this->idArray, $this->staticJumpDataCacheTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->idArray[strtoupper($systemName)] = $systemId;
|
||||
/**
|
||||
* set/add dynamic system jump data for specific "mapId"´s
|
||||
* -> this data is dynamic and could change on any map change
|
||||
* -> (e.g. new system added, connection added/updated, ...)
|
||||
* @param array $mapIds
|
||||
* @param array $filterData
|
||||
*/
|
||||
private function setDynamicJumpData($mapIds = [], $filterData = []){
|
||||
|
||||
$this->jumpArray[$systemName]= explode(":", strtoupper($row['jumpNodes']));
|
||||
array_push($this->jumpArray[$systemName],$systemId);
|
||||
if( !empty($mapIds) ){
|
||||
// make sure, mapIds are integers (protect against SQL injections)
|
||||
$mapIds = array_map('intval', $mapIds);
|
||||
|
||||
// connection filter --------------------------------------------------------
|
||||
$whereQuery = "";
|
||||
$includeScopes = [];
|
||||
$includeTypes = [];
|
||||
|
||||
if( $filterData['stargates'] === true){
|
||||
// include "stargates" for search
|
||||
$includeScopes[] = 'stargate';
|
||||
$includeTypes[] = 'stargate';
|
||||
|
||||
}
|
||||
|
||||
if( $filterData['jumpbridges'] === true ){
|
||||
// add jumpbridge connections for search
|
||||
$includeScopes[] = 'jumpbridge';
|
||||
$includeTypes[] = 'jumpbridge';
|
||||
}
|
||||
|
||||
if( $filterData['wormholes'] === true ){
|
||||
// add wormhole connections for search
|
||||
$includeScopes[] = 'wh';
|
||||
$includeTypes[] = 'wh_fresh';
|
||||
|
||||
|
||||
if( $filterData['wormholesReduced'] === true ){
|
||||
$includeTypes[] = 'wh_reduced';
|
||||
}
|
||||
|
||||
$f3->set($cacheKeyNamedArray, $this->nameArray, $this->jumpDataCacheTime);
|
||||
$f3->set($cacheKeyJumpArray, $this->jumpArray, $this->jumpDataCacheTime);
|
||||
$f3->set($cacheKeyIdArray, $this->idArray, $this->jumpDataCacheTime);
|
||||
if( $filterData['wormholesCritical'] === true ){
|
||||
$includeTypes[] = 'wh_critical';
|
||||
}
|
||||
}
|
||||
|
||||
// search connections -------------------------------------------------------
|
||||
|
||||
if( !empty($includeScopes) ){
|
||||
$whereQuery .= " connection.scope IN ('" . implode("', '", $includeScopes) . "') AND ";
|
||||
|
||||
if( !empty($includeTypes) ){
|
||||
$whereQuery .= " connection.type REGEXP '" . implode("|", $includeTypes) . "' AND ";
|
||||
}
|
||||
|
||||
|
||||
$query = "SELECT
|
||||
system_src.regionId regionId,
|
||||
system_src.constellationId constellationId,
|
||||
system_src.name systemName,
|
||||
system_src.systemId systemId,
|
||||
(
|
||||
SELECT
|
||||
GROUP_CONCAT( NULLIF(system_tar.name, NULL) SEPARATOR ':')
|
||||
FROM
|
||||
connection INNER JOIN
|
||||
system system_tar ON
|
||||
system_tar.id = connection.source OR
|
||||
system_tar.id = connection.target
|
||||
WHERE
|
||||
(
|
||||
connection.source = system_src.id OR
|
||||
connection.target = system_src.id
|
||||
) AND
|
||||
" . $whereQuery . "
|
||||
connection.active = 1 AND
|
||||
system_tar.id != system_src.id AND
|
||||
system_tar.active = 1
|
||||
) jumpNodes,
|
||||
system_src.trueSec trueSec
|
||||
FROM
|
||||
system system_src INNER JOIN
|
||||
map ON
|
||||
map.id = system_src.mapId
|
||||
WHERE
|
||||
system_src.mapId IN (" . implode(', ', $mapIds) . ") AND
|
||||
system_src.active = 1 AND
|
||||
map.active = 1
|
||||
HAVING
|
||||
-- skip systems without neighbors (e.g. WHs)
|
||||
jumpNodes IS NOT NULL
|
||||
";
|
||||
|
||||
$rows = $this->getDB()->exec($query, null, $this->dynamicJumpDataCacheTime);
|
||||
|
||||
if(count($rows) > 0){
|
||||
// update jump data for this instance
|
||||
$this->updateJumpData($rows);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* update jump data for this instance
|
||||
* -> data is either coming from CCPs static export OR from map specific data
|
||||
* @param array $rows
|
||||
*/
|
||||
private function updateJumpData($rows = []){
|
||||
|
||||
foreach($rows as $row){
|
||||
$regionId = (int)$row['regionId'];
|
||||
$constId = (int)$row['constellationId'];
|
||||
$systemName = strtoupper($row['systemName']);
|
||||
$systemId = (int)$row['systemId'];
|
||||
$secStatus = (float)$row['trueSec'];
|
||||
|
||||
// fill "nameArray" data ----------------------------------------------------
|
||||
if( !isset($this->nameArray[$systemId]) ){
|
||||
$this->nameArray[$systemId][0] = $systemName;
|
||||
$this->nameArray[$systemId][1] = $regionId;
|
||||
$this->nameArray[$systemId][2] = $constId;
|
||||
$this->nameArray[$systemId][3] = $secStatus;
|
||||
}
|
||||
|
||||
// fill "idArray" data ------------------------------------------------------
|
||||
if( !isset($this->idArray[$systemName]) ){
|
||||
$this->idArray[$systemName] = $systemId;
|
||||
}
|
||||
|
||||
// fill "jumpArray" data ----------------------------------------------------
|
||||
if( !is_array($this->jumpArray[$systemName]) ){
|
||||
$this->jumpArray[$systemName] = [];
|
||||
}
|
||||
$this->jumpArray[$systemName] = array_merge( explode(':', strtoupper($row['jumpNodes'])), $this->jumpArray[$systemName] );
|
||||
|
||||
// add systemId to end (if not already there)
|
||||
if(end($this->jumpArray[$systemName]) != $systemId){
|
||||
array_push($this->jumpArray[$systemName],$systemId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -284,8 +431,6 @@ class Route extends \Controller\AccessController {
|
||||
!empty($systemTo)
|
||||
){
|
||||
|
||||
$this->setSystemJumpData();
|
||||
|
||||
$from = strtoupper( $systemFrom );
|
||||
$to = strtoupper( $systemTo );
|
||||
|
||||
@@ -294,7 +439,6 @@ class Route extends \Controller\AccessController {
|
||||
|
||||
if( isset($this->jumpArray[$from]) ){
|
||||
|
||||
|
||||
// check if the system we are looking for is a direct neighbour
|
||||
foreach( $this->jumpArray[$from] as $n ) {
|
||||
|
||||
@@ -352,45 +496,146 @@ class Route extends \Controller\AccessController {
|
||||
return $routeData;
|
||||
}
|
||||
|
||||
/**
|
||||
* get key for route cache
|
||||
* @param $mapIds
|
||||
* @param $systemFrom
|
||||
* @param $systemTo
|
||||
* @param array $filterData
|
||||
* @return string
|
||||
*/
|
||||
private function getRouteCacheKey($mapIds, $systemFrom, $systemTo, $filterData = []){
|
||||
|
||||
$keyParts = [
|
||||
implode('_', $mapIds),
|
||||
self::formatHiveKey($systemFrom),
|
||||
self::formatHiveKey($systemTo)
|
||||
];
|
||||
|
||||
$keyParts += $filterData;
|
||||
$key = 'route_' . hash('md5', implode('_', $keyParts));
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* search multiple route between two systems
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function search($f3){
|
||||
$routesData = $data = (array)$f3->get('POST.routeData');
|
||||
$requestData = (array)$f3->get('POST');
|
||||
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
$return->routesData = [];
|
||||
|
||||
foreach($routesData as $routeData){
|
||||
$cacheKey = self::formatHiveKey($routeData['systemFrom']) . '_' . self::formatHiveKey($routeData['systemTo']);
|
||||
if(
|
||||
$activeCharacter &&
|
||||
!empty($requestData['routeData'])
|
||||
){
|
||||
|
||||
if($f3->exists($cacheKey)){
|
||||
// get data from cache
|
||||
$return->routesData[] = $f3->get($cacheKey);
|
||||
}else{
|
||||
// no cached route data found
|
||||
$foundRoutData = $this->findRoute($routeData['systemFrom'], $routeData['systemTo']);
|
||||
$routesData = (array)$requestData['routeData'];
|
||||
|
||||
// cache if route was found
|
||||
if(
|
||||
isset($foundRoutData['routePossible']) &&
|
||||
$foundRoutData['routePossible'] === true
|
||||
){
|
||||
$f3->set($cacheKey, $foundRoutData, $this->jumpDataCacheTime);
|
||||
// map data where access was already checked -> cached data
|
||||
$validMaps = [];
|
||||
|
||||
/**
|
||||
* @var $map Model\MapModel
|
||||
*/
|
||||
$map = Model\BasicModel::getNew('MapModel');
|
||||
|
||||
foreach($routesData as $key => $routeData){
|
||||
// mapIds are optional. If mapIds is empty or not set
|
||||
// route search is limited to CCPs static data
|
||||
$mapData = (array)$routeData['mapIds'];
|
||||
$mapData = array_flip( array_map('intval', $mapData) );
|
||||
|
||||
// check map access (filter requested mapIDs and format) --------------------
|
||||
array_walk($mapData, function(&$item, &$key, $data){
|
||||
|
||||
if( isset($data[1][$key]) ){
|
||||
// character has mas access -> do not check again
|
||||
$item = $data[1][$key];
|
||||
}else{
|
||||
// check map access for current character
|
||||
$data[0]->getById($key);
|
||||
|
||||
if( $data[0]->hasAccess($data[2]) ){
|
||||
$item = ['id' => $key, 'name' => $data[0]->name];
|
||||
}else{
|
||||
$item = false;
|
||||
}
|
||||
$data[0]->reset();
|
||||
|
||||
}
|
||||
|
||||
}, [$map, $validMaps, $activeCharacter]);
|
||||
|
||||
// filter maps with NO access right
|
||||
$mapData = array_filter($mapData);
|
||||
$mapIds = array_column($mapData, 'id');
|
||||
|
||||
// add map data to cache array
|
||||
$validMaps += $mapData;
|
||||
|
||||
// search route with filter options
|
||||
$filterData = [
|
||||
'stargates' => (bool) $routeData['stargates'],
|
||||
'jumpbridges' => (bool) $routeData['jumpbridges'],
|
||||
'wormholes' => (bool) $routeData['wormholes'],
|
||||
'wormholesReduced' => (bool) $routeData['wormholesReduced'],
|
||||
'wormholesCritical' => (bool) $routeData['wormholesCritical']
|
||||
];
|
||||
|
||||
$returnRoutData = [
|
||||
'systemFrom' => $routeData['systemFrom'],
|
||||
'systemTo' => $routeData['systemTo'],
|
||||
'maps' => $mapData,
|
||||
'mapIds' => $mapIds
|
||||
];
|
||||
|
||||
// add filter options for each route as well
|
||||
$returnRoutData += $filterData;
|
||||
|
||||
if(count($mapIds) > 0){
|
||||
$cacheKey = $this->getRouteCacheKey(
|
||||
$mapIds,
|
||||
$routeData['systemFrom'],
|
||||
$routeData['systemTo'],
|
||||
$filterData
|
||||
);
|
||||
|
||||
if($f3->exists($cacheKey)){
|
||||
// get data from cache
|
||||
$returnRoutData = $f3->get($cacheKey);
|
||||
}else{
|
||||
// set jump data for following route search
|
||||
$this->initJumpData($mapIds, $filterData);
|
||||
|
||||
// no cached route data found
|
||||
$foundRoutData = $this->findRoute($routeData['systemFrom'], $routeData['systemTo']);
|
||||
$returnRoutData = array_merge($returnRoutData, $foundRoutData);
|
||||
|
||||
// cache if route was found
|
||||
if(
|
||||
isset($returnRoutData['routePossible']) &&
|
||||
$returnRoutData['routePossible'] === true
|
||||
){
|
||||
$f3->set($cacheKey, $returnRoutData, $this->dynamicJumpDataCacheTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$return->routesData[] = $foundRoutData;
|
||||
$return->routesData[] = $returnRoutData;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
echo json_encode($return);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user