- new route search ESI endpoint implemented, closed #590

This commit is contained in:
Mark Friedrich
2018-03-16 22:08:28 +01:00
parent f2fc821181
commit d1b58d8df5
8 changed files with 254 additions and 155 deletions

View File

@@ -56,24 +56,12 @@ class Connection extends Controller\AccessController {
$connection = Model\BasicModel::getNew('ConnectionModel');
$connection->getById( (int)$connectionData['id'] );
// search if systems are neighbors
$routeController = new Route();
$routeController->initJumpData();
$route = $routeController->findRoute($connectionData['sourceName'], $connectionData['targetName'], 1);
if($route['routePossible'] == true){
// systems are next to each other
$connectionData['scope'] = 'stargate';
$connectionData['type'] = ['stargate'];
}elseif($connectionData['scope'] == 'stargate'){
// connection scope changed -> this can not be a stargate
$connectionData['scope'] = 'wh';
$connectionData['type'] = ['wh_fresh'];
}
$connectionData['mapId'] = $map;
$connection->setData($connectionData);
// change the default type for the new connection
$connection->setDefaultTypeData();
if($connection->save($activeCharacter)){
$return->connectionData = $connection->getData();

View File

@@ -1042,8 +1042,7 @@ class Map extends Controller\AccessController {
// check distance between systems (in jumps)
// -> if > 1 it is !very likely! a wormhole
$routeController = new Route();
$routeController->initJumpData();
$route = $routeController->findRoute($sourceSystem->name, $targetSystem->name, 1);
$route = $routeController->searchRoute($sourceSystem->systemId, $targetSystem->systemId, 1);
if( !$route['routePossible'] ){
$addSourceSystem = true;

View File

@@ -19,6 +19,8 @@ use Model;
*/
class Route extends Controller\AccessController {
const ROUTE_SEARCH_DEPTH_DEFAULT = 1;
/**
* cache time for static jump data (e.g. K-Space stargates)
* @var int
@@ -44,27 +46,32 @@ class Route extends Controller\AccessController {
private $jumpArray = [];
/**
* array withh systemName => systemId matching
* array with systemName => systemId matching
* @var array
*/
private $idArray = [];
/**
* set jump data for route search
* -> this function is required for route search! (Don´t forget)
* @param array $mapIds
* @param array $filterData
* @param array $keepSystems
* template for routeData payload
* @var array
*/
public function initJumpData($mapIds = [], $filterData = [], $keepSystems = []){
// add static data (e.g. K-Space stargates,..)
$this->setStaticJumpData();
private $defaultRouteData = [
'routePossible' => false,
'routeJumps' => 0,
'maxDepth' => self::ROUTE_SEARCH_DEPTH_DEFAULT,
'depthSearched' => 0,
'searchType' => '',
'route' => [],
'error' => ''
];
// add map specific data
$this->setDynamicJumpData($mapIds, $filterData);
// filter jump data (e.g. remove some systems (0.0, LS)
$this->filterJumpData($filterData, $keepSystems);
/**
* reset all jump data
*/
protected function resetJumpData(){
$this->nameArray = [];
$this->jumpArray = [];
$this->idArray = [];
}
/**
@@ -74,31 +81,11 @@ class Route extends Controller\AccessController {
* -> this data is equal for EACH route search (does not depend on map data)
*/
private function setStaticJumpData(){
$cacheKey = 'staticJumpData';
$query = "SELECT * FROM system_neighbour";
$rows = $this->getDB()->exec($query, null, $this->staticJumpDataCacheTime);
$f3 = $this->getF3();
$cacheKeyNamedArray = $cacheKey . '.nameArray';
$cacheKeyJumpArray = $cacheKey . '.jumpArray';
$cacheKeyIdArray = $cacheKey . '.idArray';
if(
!$f3->exists($cacheKeyNamedArray, $this->nameArray) ||
!$f3->exists($cacheKeyJumpArray, $this->jumpArray) ||
!$f3->exists($cacheKeyIdArray, $this->idArray)
){
// nothing cached
$query = "SELECT * FROM system_neighbour";
$rows = $this->getDB()->exec($query, null, $this->staticJumpDataCacheTime);
if(count($rows) > 0){
$this->updateJumpData($rows);
// 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);
}
if(count($rows) > 0){
$this->updateJumpData($rows);
}
}
@@ -267,12 +254,12 @@ class Route extends Controller\AccessController {
}
/**
* filter systems (remove some systems) e.g. WH,LS,0.0 for "safer search"
* filter systems (remove some systems) e.g. WH,LS,0.0 for "secure search"
* @param array $filterData
* @param array $keepSystems
*/
private function filterJumpData($filterData = [], $keepSystems = []){
if($filterData['safer']){
if($filterData['flag'] == 'secure'){
// remove all systems (TrueSec < 0.5) from search arrays
$this->jumpArray = array_filter($this->jumpArray, function($jumpData) use($keepSystems) {
@@ -302,9 +289,7 @@ class Route extends Controller\AccessController {
* @return null
*/
private function getSystemInfoBySystemId($systemId, $option){
$info = null;
switch($option){
case 'systemName':
$info = $this->nameArray[ $systemId ][0];
@@ -395,65 +380,105 @@ class Route extends Controller\AccessController {
}
/**
* find a route between two systems (system names)
* $searchDepth for recursive route search (5000 would be best but slow)
* -> in reality there are no routes > 100 jumps between systems
* @param $systemFrom
* @param $systemTo
* @param int $searchDepth
* get formatted jump node data
* @param $systemName
* @return array
*/
public function findRoute($systemFrom, $systemTo, $searchDepth = 7000){
$routeData = [
'routePossible' => false,
'routeJumps' => 0,
'maxDepth' => $searchDepth,
'depthSearched' => 0,
'route' => []
protected function getJumpNodeData($systemName) : array {
return [
'system' => $systemName,
'security' => $this->getSystemInfoBySystemId($this->idArray[$systemName], 'trueSec')
];
}
if(
!empty($systemFrom) &&
!empty($systemTo)
){
/**
* search root between two systemIds
* -> function searches over ESI API, as fallback a custom search algorithm is used (no ESI)
* @param int $systemFromId
* @param int $systemToId
* @param int $searchDepth
* @param array $mapIds
* @param array $filterData
* @return array
* @throws \Exception\PathfinderException
*/
public function searchRoute(int $systemFromId, int $systemToId, $searchDepth = 0, array $mapIds = [], array $filterData = []) : array {
$from = strtoupper( $systemFrom );
$to = strtoupper( $systemTo );
// search root by ESI API
$routeData = $this->searchRouteESI($systemFromId, $systemToId, $searchDepth, $mapIds, $filterData);
self::getLogger('DEBUG')->write('NEW searchRouteESI() --------------------------------------------------');
self::getLogger('DEBUG')->write(print_r($routeData, true));
if( !empty($routeData['error']) ){
// ESI route search has errors -> fallback to custom search implementation
$routeDataTest = $this->searchRouteCustom($systemFromId, $systemToId, $searchDepth, $mapIds, $filterData);
self::getLogger('DEBUG')->write('NEW searchRouteCustom() --------------------------------------------------');
self::getLogger('DEBUG')->write(print_r($routeDataTest, true));
}
return $routeData;
}
/**
* uses a custom search algorithm to fine a route
* @param int $systemFromId
* @param int $systemToId
* @param int $searchDepth
* @param array $mapIds
* @param array $filterData
* @return array
* @throws \Exception\PathfinderException
*/
public function searchRouteCustom(int $systemFromId, int $systemToId, $searchDepth = 0, array $mapIds = [], array $filterData = []) : array {
// reset all previous set jump data
$this->resetJumpData();
$searchDepth = $searchDepth ? $searchDepth : Config::getPathfinderData('route.search_depth');
$routeData = $this->defaultRouteData;
$routeData['maxDepth'] = $searchDepth;
$routeData['searchType'] = 'custom';
if($systemFromId && $systemToId){
// prepare search data ------------------------------------------------------------------------------------
// add static data (e.g. K-Space stargates,..)
$this->setStaticJumpData();
// add map specific data
$this->setDynamicJumpData($mapIds, $filterData);
// filter jump data (e.g. remove some systems (0.0, LS)
// --> don´t filter some systems (e.g. systemFrom, systemTo) even if they are are WH,LS,0.0
$this->filterJumpData($filterData, [$systemFromId, $systemToId]);
$systemFrom = $this->getSystemInfoBySystemId($systemFromId, 'systemName');
$systemTo = $this->getSystemInfoBySystemId($systemToId, 'systemName');
// search route -------------------------------------------------------------------------------------------
// jump counter
$jumpNum = 0;
$depthSearched = 0;
if( isset($this->jumpArray[$from]) ){
if( isset($this->jumpArray[$systemFrom]) ){
// check if the system we are looking for is a direct neighbour
foreach( $this->jumpArray[$from] as $n ) {
if ($n == $to) {
foreach( $this->jumpArray[$systemFrom] as $n ) {
if ($n == $systemTo) {
$jumpNum = 2;
$jumpNode = [
'system' => $n,
'security' => $this->getSystemInfoBySystemId($this->idArray[$n], 'trueSec')
];
$routeData['route'][] = $jumpNode;
$routeData['route'][] = $this->getJumpNodeData($n);
break;
}
}
// system is not a direct neighbour -> search recursive its neighbours
if ($jumpNum == 0) {
$searchResult = $this->graph_find_path( $this->jumpArray, $from, $to, $searchDepth );
$searchResult = $this->graph_find_path( $this->jumpArray, $systemFrom, $systemTo, $searchDepth );
$depthSearched = $searchResult['depth'];
foreach( $searchResult['path'] as $systemName ) {
if ($jumpNum > 0) {
$jumpNode = [
'system' => $systemName,
'security' => $this->getSystemInfoBySystemId($this->idArray[$systemName], 'trueSec')
];
$routeData['route'][] = $jumpNode;
$routeData['route'][] = $this->getJumpNodeData($systemName);
}
$jumpNum++;
}
@@ -462,14 +487,8 @@ class Route extends Controller\AccessController {
if ($jumpNum > 0) {
// route found
$routeData['routePossible'] = true;
$jumpNode = [
'system' => $from,
'security' => $this->getSystemInfoBySystemId($this->idArray[$from], 'trueSec')
];
// insert "from" system on top
array_unshift($routeData['route'], $jumpNode);
array_unshift($routeData['route'], $this->getJumpNodeData($systemFrom));
} else {
// route not found
$routeData['routePossible'] = false;
@@ -484,6 +503,102 @@ class Route extends Controller\AccessController {
return $routeData;
}
/**
* uses ESI route search endpoint to fine a route
* @param int $systemFromId
* @param int $systemToId
* @param int $searchDepth
* @param array $mapIds
* @param array $filterData
* @return array
* @throws \Exception\PathfinderException
*/
public function searchRouteESI(int $systemFromId, int $systemToId, int $searchDepth = 0, array $mapIds = [], array $filterData = []) : array {
// reset all previous set jump data
$this->resetJumpData();
$searchDepth = $searchDepth ? $searchDepth : Config::getPathfinderData('route.search_depth');
$routeData = $this->defaultRouteData;
$routeData['maxDepth'] = $searchDepth;
$routeData['searchType'] = 'esi';
if($systemFromId && $systemToId){
// prepare search data ------------------------------------------------------------------------------------
// add map specific data
$this->setDynamicJumpData($mapIds, $filterData);
// filter jump data (e.g. remove some systems (0.0, LS)
// --> don´t filter some systems (e.g. systemFrom, systemTo) even if they are are WH,LS,0.0
$this->filterJumpData($filterData, [$systemFromId, $systemToId]);
$connections = [];
foreach($this->jumpArray as $systemSourceName => $jumpData){
$count = count($jumpData);
if($count > 1){
// ... should always > 1
$systemSourceId = (int)$this->idArray[$systemSourceName];
// loop all connections for current source system
foreach($jumpData as $systemTargetName) {
// skip last entry
if(--$count <= 0){
break;
}
$systemTargetId = (int)$this->idArray[$systemTargetName];
// systemIds exist and wer not removed before in filterJumpData()
if($systemSourceId && $systemTargetId){
$connections[] = [$systemSourceId, $systemTargetId];
}
}
}
}
// search route -------------------------------------------------------------------------------------------
$options = [
'flag' => $filterData['flag'],
'connections' => $connections
];
$result = $this->getF3()->ccpClient->getRouteData($systemFromId, $systemToId, $options);
// format result ------------------------------------------------------------------------------------------
// jump counter
$jumpNum = 0;
$depthSearched = 0;
if( !empty($result['error']) ){
$routeData['error'] = $result['error'];
}elseif( !empty($result['route']) ){
$jumpNum = count($result['route']) - 1;
// check max search depth
if($jumpNum <= $routeData['maxDepth']){
$depthSearched = $jumpNum;
$routeData['routePossible'] = true;
// Now (after search) we have to "add" static jump data information
$this->setStaticJumpData();
foreach($result['route'] as $systemId){
$systemName = $this->getSystemInfoBySystemId($systemId, 'systemName');
$routeData['route'][] = $this->getJumpNodeData($systemName);
}
}else{
$depthSearched = $routeData['maxDepth'];
}
}
// route jumps
$routeData['routeJumps'] = $jumpNum;
$routeData['depthSearched'] = $depthSearched;
}
return $routeData;
}
/**
* get key for route cache
* @param $mapIds
@@ -543,7 +658,9 @@ class Route extends Controller\AccessController {
// check map access (filter requested mapIDs and format) ----------------------------------------------
array_walk($mapData, function(&$item, &$key, $data){
/**
* @var Model\MapModel $data[0]
*/
if( isset($data[1][$key]) ){
// character has map access -> do not check again
$item = $data[1][$key];
@@ -577,7 +694,7 @@ class Route extends Controller\AccessController {
'wormholesCritical' => (bool) $routeData['wormholesCritical'],
'wormholesFrigate' => (bool) $routeData['wormholesFrigate'],
'wormholesEOL' => (bool) $routeData['wormholesEOL'],
'safer' => (bool) $routeData['safer']
'flag' => $routeData['flag']
];
$returnRoutData = [
@@ -611,16 +728,8 @@ class Route extends Controller\AccessController {
// get data from cache
$returnRoutData = $cachedData;
}else{
// max search depth for search
$searchDepth = Config::getPathfinderData('route.search_depth');
$foundRoutData = $this->searchRoute($systemFromId, $systemToId, 0, $mapIds, $filterData);
// set jump data for following route search
// --> don´t filter some systems (e.g. systemFrom, systemTo) even if they are are WH,LS,0.0
$keepSystems = [$systemFromId, $systemToId];
$this->initJumpData($mapIds, $filterData, $keepSystems);
// no cached route data found
$foundRoutData = $this->findRoute($systemFrom, $systemTo, $searchDepth);
$returnRoutData = array_merge($returnRoutData, $foundRoutData);
// cache if route was found

View File

@@ -9,6 +9,7 @@
namespace lib;
use controller\LogController;
use Exception;
class Config extends \Prefab {
@@ -378,7 +379,6 @@ class Config extends \Prefab {
}
/**
* get PATHFINDER config data
* @param string $key
* @return mixed
* @throws Exception\PathfinderException
@@ -386,8 +386,12 @@ class Config extends \Prefab {
static function getPathfinderData($key = ''){
$hiveKey = self::HIVE_KEY_PATHFINDER . ($key ? '.' . strtoupper($key) : '');
if( !\Base::instance()->exists($hiveKey, $data) ){
throw new Exception\PathfinderException(sprintf(self::ERROR_CONF_PATHFINDER, $hiveKey));
try{
if( !\Base::instance()->exists($hiveKey, $data) ){
throw new Exception\PathfinderException(sprintf(self::ERROR_CONF_PATHFINDER, $hiveKey));
}
}catch (Exception\PathfinderException $e){
LogController::getLogger('ERROR')->write($e->getMessage());
}
return $data;

View File

@@ -179,8 +179,7 @@ class ConnectionModel extends AbstractMapTrackingModel {
is_object($this->target)
){
$routeController = new Route();
$routeController->initJumpData();
$route = $routeController->findRoute($this->source->name, $this->target->name, 1);
$route = $routeController->searchRoute($this->source->systemId, $this->target->systemId, 1);
if($route['routePossible']){
$this->scope = 'stargate';

View File

@@ -123,15 +123,15 @@ SEND_RALLY_Mail_ENABLED = 0
; Route search ====================================================================================
[PATHFINDER.ROUTE]
; max recursive search depth for routes (default: 7000)
; max recursive search depth for routes (default: 9000)
; decrease it on performance problems
SEARCH_DEPTH = 9000
; default count of routes that will be checked (initial) when a system is selected (default: 2)
SEARCH_DEFAULT_COUNT = 2
; max count of routes that can be selected in "route settings" dialog (default: 4)
MAX_DEFAULT_COUNT = 4
; max count of routes that will be checked (MAX_COUNT + custom routes ) (default: 6)
LIMIT = 6
; default count of routes that will be checked (initial) when a system is selected (default: 4)
SEARCH_DEFAULT_COUNT = 4
; max count of routes that can be selected in "route settings" dialog (default: 6)
MAX_DEFAULT_COUNT = 6
; max count of routes that will be checked (MAX_COUNT + custom routes ) (default: 8)
LIMIT = 8
; Email notifications =============================================================================
; Requires SMTP configuration (see environment.ini)

View File

@@ -186,7 +186,7 @@ define([
wormholesCritical: (rowData.hasOwnProperty('wormholesCritical')) ? rowData.wormholesCritical | 0 : 1,
wormholesFrigate: (rowData.hasOwnProperty('wormholesFrigate')) ? rowData.wormholesFrigate | 0 : 1,
wormholesEOL: (rowData.hasOwnProperty('wormholesEOL')) ? rowData.wormholesEOL | 0 : 1,
safer: (rowData.hasOwnProperty('safer')) ? rowData.safer.value | 0 : 0
flag: (rowData.hasOwnProperty('flag')) ? rowData.flag.value : 'shortest'
};
};
@@ -563,10 +563,10 @@ define([
// 2: not searched
let routeStatus = routeData.skipSearch ? 2 : 0;
// button class for "safer" routes
let saferButtonClass = routeData.safer ? 'txt-color-success' : '';
// button class for flag (e.g. "secure" routes)
let flagButtonClass = routeData.flag === 'secure' ? 'txt-color-success' : '';
let saferButton = '<i class="fas ' + ['fa-shield-alt', 'txt-color', saferButtonClass].join(' ') + '"></i>';
let flagButton = '<i class="fas ' + ['fa-shield-alt', 'txt-color', flagButtonClass].join(' ') + '"></i>';
let reloadButton = '<i class="fas ' + ['fa-sync'].join(' ') + '"></i>';
let searchButton = '<i class="fas ' + ['fa-search-plus '].join(' ') + '"></i>';
let deleteButton = '<i class="fas ' + ['fa-times', 'txt-color', 'txt-color-redDarker'].join(' ') + '"></i>';
@@ -591,9 +591,9 @@ define([
wormholesCritical: routeData.wormholesCritical,
wormholesFrigate: routeData.wormholesFrigate,
wormholesEOL: routeData.wormholesEOL,
safer: {
value: routeData.safer,
button: saferButton
flag: {
value: routeData.flag,
button: flagButton
},
reload: {
button: routeData.skipSearch ? searchButton : reloadButton
@@ -694,14 +694,14 @@ define([
$('<h5>', {
class: 'pull-right'
}).append(
$('<i>', {
class: ['fas', 'fa-fw', 'fa-search', config.moduleHeadlineIconClass, config.moduleHeadlineIconSearchClass].join(' '),
title: 'find&nbsp;route'
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
$('<i>', {
class: ['fas', 'fa-fw', 'fa-sliders-h', config.moduleHeadlineIconClass, config.moduleHeadlineIconSettingsClass].join(' '),
title: 'settings'
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
$('<i>', {
class: ['fas', 'fa-fw', 'fa-search', config.moduleHeadlineIconClass, config.moduleHeadlineIconSearchClass].join(' '),
title: 'find&nbsp;route'
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
$('<i>', {
class: ['fas', 'fa-fw', 'fa-sync', config.moduleHeadlineIconClass, config.moduleHeadlineIconRefreshClass].join(' '),
title: 'refresh&nbsp;all'
@@ -794,11 +794,11 @@ define([
searchable: false,
width: '10px',
class: ['text-center', config.dataTableActionCellClass].join(' '),
data: 'safer',
data: 'flag',
render: {
_: 'button'
},
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
createdCell: function(cell, cellData, rowData, rowIndex, colIndex) {
let tempTableApi = this.api();
$(cell).on('click', function(e) {
@@ -809,7 +809,7 @@ define([
// overwrite some params
routeData.skipSearch = 0;
routeData.safer = 1 - routeData.safer; // toggle
routeData.flag = routeData.flag === 'shortest' ? 'secure' : 'shortest'; // toggle
let context = {
moduleElement: moduleElement,

View File

@@ -186,7 +186,7 @@ define([
wormholesCritical: (rowData.hasOwnProperty('wormholesCritical')) ? rowData.wormholesCritical | 0 : 1,
wormholesFrigate: (rowData.hasOwnProperty('wormholesFrigate')) ? rowData.wormholesFrigate | 0 : 1,
wormholesEOL: (rowData.hasOwnProperty('wormholesEOL')) ? rowData.wormholesEOL | 0 : 1,
safer: (rowData.hasOwnProperty('safer')) ? rowData.safer.value | 0 : 0
flag: (rowData.hasOwnProperty('flag')) ? rowData.flag.value : 'shortest'
};
};
@@ -563,10 +563,10 @@ define([
// 2: not searched
let routeStatus = routeData.skipSearch ? 2 : 0;
// button class for "safer" routes
let saferButtonClass = routeData.safer ? 'txt-color-success' : '';
// button class for flag (e.g. "secure" routes)
let flagButtonClass = routeData.flag === 'secure' ? 'txt-color-success' : '';
let saferButton = '<i class="fas ' + ['fa-shield-alt', 'txt-color', saferButtonClass].join(' ') + '"></i>';
let flagButton = '<i class="fas ' + ['fa-shield-alt', 'txt-color', flagButtonClass].join(' ') + '"></i>';
let reloadButton = '<i class="fas ' + ['fa-sync'].join(' ') + '"></i>';
let searchButton = '<i class="fas ' + ['fa-search-plus '].join(' ') + '"></i>';
let deleteButton = '<i class="fas ' + ['fa-times', 'txt-color', 'txt-color-redDarker'].join(' ') + '"></i>';
@@ -591,9 +591,9 @@ define([
wormholesCritical: routeData.wormholesCritical,
wormholesFrigate: routeData.wormholesFrigate,
wormholesEOL: routeData.wormholesEOL,
safer: {
value: routeData.safer,
button: saferButton
flag: {
value: routeData.flag,
button: flagButton
},
reload: {
button: routeData.skipSearch ? searchButton : reloadButton
@@ -694,14 +694,14 @@ define([
$('<h5>', {
class: 'pull-right'
}).append(
$('<i>', {
class: ['fas', 'fa-fw', 'fa-search', config.moduleHeadlineIconClass, config.moduleHeadlineIconSearchClass].join(' '),
title: 'find&nbsp;route'
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
$('<i>', {
class: ['fas', 'fa-fw', 'fa-sliders-h', config.moduleHeadlineIconClass, config.moduleHeadlineIconSettingsClass].join(' '),
title: 'settings'
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
$('<i>', {
class: ['fas', 'fa-fw', 'fa-search', config.moduleHeadlineIconClass, config.moduleHeadlineIconSearchClass].join(' '),
title: 'find&nbsp;route'
}).attr('data-html', 'true').attr('data-toggle', 'tooltip'),
$('<i>', {
class: ['fas', 'fa-fw', 'fa-sync', config.moduleHeadlineIconClass, config.moduleHeadlineIconRefreshClass].join(' '),
title: 'refresh&nbsp;all'
@@ -794,11 +794,11 @@ define([
searchable: false,
width: '10px',
class: ['text-center', config.dataTableActionCellClass].join(' '),
data: 'safer',
data: 'flag',
render: {
_: 'button'
},
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
createdCell: function(cell, cellData, rowData, rowIndex, colIndex) {
let tempTableApi = this.api();
$(cell).on('click', function(e) {
@@ -809,7 +809,7 @@ define([
// overwrite some params
routeData.skipSearch = 0;
routeData.safer = 1 - routeData.safer; // toggle
routeData.flag = routeData.flag === 'shortest' ? 'secure' : 'shortest'; // toggle
let context = {
moduleElement: moduleElement,