/** * system route module */ define([ 'jquery', 'app/init', 'app/util', 'bootbox' ], function($, Init, Util, bootbox) { 'use strict'; var config = { // module info moduleClass: 'pf-module', // class for each module routeCacheTTL: 10, // route cache timer (client) in seconds // system route module systemRouteModuleClass: 'pf-system-route-module', // class for this module // headline toolbar systemModuleHeadlineIcon: 'pf-module-icon-button', // class for toolbar icons in the head systemModuleHeadlineIconSearch: 'pf-module-icon-button-search', // class for "search" icon systemModuleHeadlineIconRefresh: 'pf-module-icon-button-refresh', // class for "refresh" icon systemSecurityClassPrefix: 'pf-system-security-', // prefix class for system security level (color) // dialog routeDialogId: 'pf-route-dialog', // id for route dialog systemDialogSelectClass: 'pf-system-dialog-select', // class for system select Element systemInfoRoutesTableClass: 'pf-system-route-table', // class for route tables mapSelectId: 'pf-route-dialog-map-select', // id for "map" select sigTableActionCellClass: 'pf-table-action-cell' // class for "action" cells }; // cache for system routes var cache = { systemRoutes: {} // jump information between solar systems }; /** * callback function, adds new row to a dataTable with jump information for a route * @param context * @param routesData */ var callbackAddRouteRow = function(context, routesData){ if(routesData.length > 0){ for(var i = 0; i < routesData.length; i++){ var routeData = routesData[i]; // format routeData var rowData = formatRouteData(routeData); if(rowData.route){ var cacheKey = routeData.systemFrom.toLowerCase() + '_' + routeData.systemTo.toLowerCase(); // update route cache cache.systemRoutes[cacheKey] = { data: rowData, updated: Util.getServerTime().getTime() / 1000 }; var rowElement = addRow(context, rowData); rowElement.initTooltips({ container: 'body' }); } } // redraw dataTable context.dataTable.draw(); } }; /** * add a new dataTable row to the routes table * @param context * @param rowData * @returns {*} */ var addRow = function(context, rowData){ var dataTable = context.dataTable; var rowElement = null; var row = null; var animationStatus = 'changed'; // search for an existing row (e.g. on mass "table refresh" [all routes]) // get rowIndex where column 0 (equals to "systemTo") matches rowData.systemTo var indexes = dataTable.rows().eq(0).filter( function (rowIdx) { return (dataTable.cell(rowIdx, 0 ).data() === rowData.systemTo); }); if(indexes.length > 0){ // update row with FIRST index // -> systemFrom should be unique! row = dataTable.row( parseInt(indexes[0]) ); // update row data row.data(rowData); }else{ // no existing route found -> add new row row = dataTable.row.add( rowData ); animationStatus = 'added'; } if(row.length > 0){ rowElement = row.nodes().to$(); if(animationStatus !== null){ rowElement.data('animationStatus', animationStatus); } } return rowElement; }; /** * update complete routes table (refresh all) * @param moduleElement * @param dataTable */ var updateRoutesTable = function(moduleElement, dataTable){ var context = { moduleElement: moduleElement, dataTable: dataTable }; var routeData = []; dataTable.rows().every( function() { var data = this.data(); routeData.push({ mapIds: data.mapIds, systemFrom: data.systemFrom, systemTo: data.systemTo }); } ); getRouteData({routeData: routeData}, context, callbackAddRouteRow); }; /** * show route dialog. User can search for systems and jump-info for each system is added to a data table * @param dialogData */ var showFindRouteDialog = function(dialogData){ var mapSelectOptions = []; var currentMapData = Util.getCurrentMapData(); if(currentMapData !== false){ for(var i = 0; i < currentMapData.length; i++){ mapSelectOptions.push({ id: currentMapData[i].config.id, name: currentMapData[i].config.name, selected: (dialogData.mapId === currentMapData[i].config.id) }); } } var data = { id: config.routeDialogId, selectClass: config.systemDialogSelectClass, mapSelectId: config.mapSelectId, systemFrom: dialogData.systemFrom, mapSelectOptions: mapSelectOptions }; requirejs(['text!templates/dialog/route.html', 'mustache'], function(template, Mustache) { var content = Mustache.render(template, data); // disable modal focus event -> otherwise select2 is not working! -> quick fix $.fn.modal.Constructor.prototype.enforceFocus = function() {}; var findRouteDialog = bootbox.dialog({ title: 'Route finder', message: content, show: false, buttons: { close: { label: 'cancel', className: 'btn-default', callback: function(){ $(findRouteDialog).modal('hide'); } }, success: { label: ' search route', className: 'btn-primary', callback: function () { // add new route to route table // get form Values var form = $('#' + config.routeDialogId).find('form'); var routeDialogData = $(form).getFormValues(); // validate form form.validator('validate'); // check weather the form is valid var formValid = form.isValidForm(); if(formValid === false){ // don't close dialog return false; } var context = { moduleElement: dialogData.moduleElement, dataTable: dialogData.dataTable }; var requestData = { routeData: [{ mapIds: routeDialogData.mapIds, systemFrom: dialogData.systemFrom, systemTo: routeDialogData.systemTo, stargates: routeDialogData.hasOwnProperty('stargates') ? parseInt( routeDialogData.stargates ) : 0, jumpbridges: routeDialogData.hasOwnProperty('jumpbridges') ? parseInt( routeDialogData.jumpbridges ) : 0, wormholes: routeDialogData.hasOwnProperty('wormholes') ? parseInt( routeDialogData.wormholes ) : 0, wormholesReduced: routeDialogData.hasOwnProperty('wormholesReduced') ? parseInt( routeDialogData.wormholesReduced ) : 0, wormholesCritical: routeDialogData.hasOwnProperty('wormholesCritical') ? parseInt( routeDialogData.wormholesCritical ) : 0 }] }; getRouteData(requestData, context, callbackAddRouteRow); } } } }); findRouteDialog.on('show.bs.modal', function(e) { findRouteDialog.initTooltips(); // init some dialog/form observer setDialogObserver( $(this) ); // init map select ---------------------------------------------------------------- var mapSelect = $(this).find('#' + config.mapSelectId); mapSelect.initMapSelect(); }); findRouteDialog.on('shown.bs.modal', function(e) { // init system select live search ------------------------------------------------ // -> add some delay until modal transition has finished var systemTargetSelect = $(this).find('.' + config.systemDialogSelectClass); systemTargetSelect.delay(240).initSystemSelect({key: 'name'}); }); // show dialog findRouteDialog.modal('show'); }); }; /** * set event observer for route finder dialog * @param routeDialog */ var setDialogObserver = function(routeDialog){ var wormholeCheckbox = routeDialog.find('input[type="checkbox"][name="wormholes"]'); var wormholeReducedCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesReduced"]'); var wormholeCriticalCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesCritical"]'); // store current "checked" state for each box --------------------------------------------- var storeCheckboxStatus = function(){ wormholeReducedCheckbox.data('selectState', wormholeReducedCheckbox.prop('checked')); wormholeCriticalCheckbox.data('selectState', wormholeCriticalCheckbox.prop('checked')); }; // on wormhole checkbox change ------------------------------------------------------------ var onWormholeCheckboxChange = function(){ if( $(this).is(':checked') ){ wormholeReducedCheckbox.prop('disabled', false); wormholeCriticalCheckbox.prop('disabled', false); wormholeReducedCheckbox.prop('checked', wormholeReducedCheckbox.data('selectState')); wormholeCriticalCheckbox.prop('checked', wormholeCriticalCheckbox.data('selectState')); }else{ storeCheckboxStatus(); wormholeReducedCheckbox.prop('checked', false); wormholeReducedCheckbox.prop('disabled', true); wormholeCriticalCheckbox.prop('checked', false); wormholeCriticalCheckbox.prop('disabled', true); } }.bind(wormholeCheckbox); wormholeCheckbox.on('change', onWormholeCheckboxChange); // initial checkbox check storeCheckboxStatus(); onWormholeCheckboxChange(); }; /** * requests route data from eveCentral API and execute callback * @param requestData * @param context * @param callback */ var getRouteData = function(requestData, context, callback){ context.moduleElement.showLoadingAnimation(); $.ajax({ url: Init.path.searchRoute, type: 'POST', dataType: 'json', data: requestData, context: context }).done(function(routesData){ this.moduleElement.hideLoadingAnimation(); // execute callback callback(this, routesData.routesData); }); }; /** * format route data from API request into dataTable row format * @param routeData * @returns {{}} */ var formatRouteData = function(routeData){ var reloadButton = ''; var deleteButton = ''; // default row data (e.g. no route found) var tableRowData = { systemFrom: routeData.systemFrom, systemTo: routeData.systemTo, jumps: { value: 0, formatted: '---' }, avgTrueSec: { value: '', formatted: '' }, route: 'not found', stargates: routeData.stargates, jumpbridges: routeData.jumpbridges, wormholes: routeData.wormholes, wormholesReduced: routeData.wormholesReduced, wormholesCritical: routeData.wormholesCritical, reload: { button: reloadButton }, clear: { button: deleteButton }, maps: routeData.maps, mapIds: routeData.mapIds //map data (mapIds is "redundant") }; if( routeData.routePossible === true && routeData.route.length > 0 ){ // route data available // add route Data var jumpData = []; var avgSecTemp = 0; // loop all systems on this route for(var i = 0; i < routeData.route.length; i++){ var routeNodeData = routeData.route[i]; // format system name (camelCase) var systemName = routeNodeData.system.charAt(0).toUpperCase() + routeNodeData.system.slice(1).toLowerCase(); var systemSec = Number(routeNodeData.security).toFixed(1).toString(); var tempSystemSec = systemSec; if(tempSystemSec <= 0){ tempSystemSec = '0-0'; } var systemSecClass = config.systemSecurityClassPrefix + tempSystemSec.replace('.', '-'); var system = ''; jumpData.push( system ); avgSecTemp += Number(routeNodeData.security); } var avgSec = ( avgSecTemp / routeData.route.length).toFixed(2); var avgSecForClass = Number(avgSec).toFixed(1); if(avgSecForClass <= 0){ avgSecForClass = '0.0'; } var avgSecClass = config.systemSecurityClassPrefix + avgSecForClass.toString().replace('.', '-'); tableRowData.jumps = { value: routeData.routeJumps, formatted: routeData.routeJumps }; tableRowData.avgTrueSec = { value: avgSec, formatted: '' + avgSec + '' }; tableRowData.route = jumpData.join(' '); } return tableRowData; }; /** * get the route finder moduleElement * @returns {*} */ var getModule = function(){ // create new module container var moduleElement = $('