mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-11 08:43:02 +00:00
@@ -1 +0,0 @@
|
||||
app/js/db.js
|
||||
@@ -1,5 +1,6 @@
|
||||
angular.module('app', ['ui.router', 'ct.ui.router.extras.sticky', 'ui.sortable', 'shipyard', 'ngLodash', 'app.templates'])
|
||||
.run(['$rootScope', '$location', '$window', '$document','$state','commonArray','shipPurpose','shipSize','hardPointClass','GroupMap', 'Persist', function ($rootScope, $location, $window, $doc, $state, CArr, shipPurpose, sz, hpc, GroupMap, Persist) {
|
||||
.run(['$rootScope', '$location', '$window', '$document', '$state', 'commonArray', 'shipPurpose', 'shipSize', 'hardPointClass', 'GroupMap', 'Persist',
|
||||
function($rootScope, $location, $window, $doc, $state, CArr, shipPurpose, sz, hpc, GroupMap, Persist) {
|
||||
// App is running as a standalone web app on tablet/mobile
|
||||
var isStandAlone = $window.navigator.standalone || ($window.external && $window.external.msIsSiteMode && $window.external.msIsSiteMode());
|
||||
|
||||
@@ -48,7 +49,7 @@ angular.module('app', ['ui.router', 'ct.ui.router.extras.sticky', 'ui.sortable',
|
||||
$rootScope.fPct = d3.format('.2%');
|
||||
$rootScope.f1Pct = d3.format('.1%');
|
||||
$rootScope.fRPct = d3.format('%');
|
||||
$rootScope.fTime = function(d) { return Math.floor(d/60) + ":" + ("00" + Math.floor(d%60)).substr(-2,2); };
|
||||
$rootScope.fTime = function(d) { return Math.floor(d / 60) + ':' + ('00' + Math.floor(d % 60)).substr(-2, 2); };
|
||||
|
||||
if (isStandAlone) {
|
||||
var state = Persist.getState();
|
||||
|
||||
@@ -44,12 +44,12 @@ angular.module('app').config(['$provide','$stateProvider', '$urlRouterProvider',
|
||||
.state('error', { params: { type: null, message: null, details: null }, templateUrl: 'views/page-error.html', controller: 'ErrorController', sticky: true })
|
||||
|
||||
// Modal States and views
|
||||
.state('modal', { abstract: true, views:{ "modal": { templateUrl: "views/_modal.html", controller: 'ModalController' } } })
|
||||
.state('modal.about', { views: { "modal-content": { templateUrl: "views/modal-about.html" } } })
|
||||
.state('modal.export', { params: {title:null, data: null, promise: null}, views: { "modal-content": { templateUrl: "views/modal-export.html", controller: 'ExportController' } } })
|
||||
.state('modal.import', { params: {obj:null}, views: { "modal-content": { templateUrl: "views/modal-import.html", controller: 'ImportController' } } })
|
||||
.state('modal.link', { params: {url:null}, views: { "modal-content": { templateUrl: "views/modal-link.html", controller: 'LinkController' } } })
|
||||
.state('modal.delete', { views: { "modal-content": { templateUrl: "views/modal-delete.html", controller: 'DeleteController' } } });
|
||||
.state('modal', { abstract: true, views: { 'modal': { templateUrl: 'views/_modal.html', controller: 'ModalController' } } })
|
||||
.state('modal.about', { views: { 'modal-content': { templateUrl: 'views/modal-about.html' } } })
|
||||
.state('modal.export', { params: { title: null, data: null, promise: null }, views: { 'modal-content': { templateUrl: 'views/modal-export.html', controller: 'ExportController' } } })
|
||||
.state('modal.import', { params: { obj: null }, views: { 'modal-content': { templateUrl: 'views/modal-import.html', controller: 'ImportController' } } })
|
||||
.state('modal.link', { params: { url: null }, views: { 'modal-content': { templateUrl: 'views/modal-link.html', controller: 'LinkController' } } })
|
||||
.state('modal.delete', { views: { 'modal-content': { templateUrl: 'views/modal-delete.html', controller: 'DeleteController' } } });
|
||||
|
||||
|
||||
// Redirects
|
||||
|
||||
@@ -10,39 +10,40 @@ angular.module('app').controller('ComparisonController', ['lodash', '$rootScope'
|
||||
$scope.importObj = {}; // Used for importing comparison builds (from permalinked comparison)
|
||||
var defaultFacets = [9, 6, 4, 1, 3, 2]; // Reverse order of Armour, Shields, Speed, Jump Range, Cargo Capacity, Cost
|
||||
var facets = $scope.facets = angular.copy(ShipFacets);
|
||||
var shipId, buildName, comparisonData;
|
||||
|
||||
/**
|
||||
* Add an existing build to the comparison. The build must be saved locally.
|
||||
* @param {string} shipId The unique ship key/id
|
||||
* @param {string} buildName The build name
|
||||
* @param {string} id The unique ship key/id
|
||||
* @param {string} name The build name
|
||||
*/
|
||||
$scope.addBuild = function (shipId, buildName, code) {
|
||||
var data = Ships[shipId]; // Get ship properties
|
||||
code = code? code : Persist.builds[shipId][buildName]; // Retrieve build code if not passed
|
||||
var b = new Ship(shipId, data.properties, data.slots); // Create a new Ship instance
|
||||
$scope.addBuild = function(id, name, code) {
|
||||
var data = Ships[id]; // Get ship properties
|
||||
code = code ? code : Persist.builds[id][name]; // Retrieve build code if not passed
|
||||
var b = new Ship(id, data.properties, data.slots); // Create a new Ship instance
|
||||
Serializer.toShip(b, code); // Populate components from code
|
||||
// Extend ship instance and add properties below
|
||||
b.buildName = buildName;
|
||||
b.buildName = name;
|
||||
b.code = code;
|
||||
b.pctRetracted = b.powerRetracted / b.powerAvailable;
|
||||
b.pctDeployed = b.powerDeployed / b.powerAvailable;
|
||||
$scope.builds.push(b); // Add ship build to comparison
|
||||
$scope.builds = $filter('orderBy')($scope.builds, $scope.predicate, $scope.desc); // Resort
|
||||
_.remove($scope.unusedBuilds, function (b) { // Remove from unused builds
|
||||
return b.id == shipId && b.buildName == buildName;
|
||||
_.remove($scope.unusedBuilds, function(o) { // Remove from unused builds
|
||||
return o.id == id && o.buildName == name;
|
||||
});
|
||||
$scope.saved = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a build from the comparison
|
||||
* @param {string} shipId The unique ship key/id
|
||||
* @param {string} buildName The build name
|
||||
* @param {string} id The unique ship key/id
|
||||
* @param {string} name The build name
|
||||
*/
|
||||
$scope.removeBuild = function (shipId, buildName) {
|
||||
_.remove($scope.builds, function (b) {
|
||||
if (b.id == shipId && b.buildName == buildName) {
|
||||
$scope.unusedBuilds.push({id: shipId, buildName: buildName, name: b.name}); // Add build back to unused builds
|
||||
$scope.removeBuild = function(id, name) {
|
||||
_.remove($scope.builds, function(s) {
|
||||
if (s.id == id && s.buildName == name) {
|
||||
$scope.unusedBuilds.push({ id: id, buildName: name, name: s.name }); // Add build back to unused builds
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -68,8 +69,8 @@ angular.module('app').controller('ComparisonController', ['lodash', '$rootScope'
|
||||
var elem = angular.element(e.target);
|
||||
if (elem.attr('prop')) { // Get component ID
|
||||
$scope.sort(elem.attr('prop'));
|
||||
}
|
||||
else if (elem.attr('del')) { // Delete index
|
||||
|
||||
} else if (elem.attr('del')) { // Delete index
|
||||
$scope.removeBuild(elem.attr('del'));
|
||||
}
|
||||
};
|
||||
@@ -79,7 +80,7 @@ angular.module('app').controller('ComparisonController', ['lodash', '$rootScope'
|
||||
* @param {string} key Ship property
|
||||
*/
|
||||
$scope.sort = function(key) {
|
||||
$scope.desc = ($scope.predicate == key)? !$scope.desc : $scope.desc;
|
||||
$scope.desc = $scope.predicate == key ? !$scope.desc : $scope.desc;
|
||||
$scope.predicate = key;
|
||||
$scope.builds = $filter('orderBy')($scope.builds, $scope.predicate, $scope.desc);
|
||||
};
|
||||
@@ -150,8 +151,8 @@ angular.module('app').controller('ComparisonController', ['lodash', '$rootScope'
|
||||
function(shortUrl) {
|
||||
return Utils.comparisonBBCode(facets, $scope.builds, shortUrl);
|
||||
},
|
||||
function (e) {
|
||||
return 'Error - ' + e.statusText;
|
||||
function(err) {
|
||||
return 'Error - ' + err.statusText;
|
||||
}
|
||||
);
|
||||
$state.go('modal.export', { promise: promise, title: 'Forum BBCode' });
|
||||
@@ -184,7 +185,6 @@ angular.module('app').controller('ComparisonController', ['lodash', '$rootScope'
|
||||
});
|
||||
|
||||
/* Initialization */
|
||||
var shipId, buildName, comparisonData;
|
||||
if ($scope.compareMode) {
|
||||
if ($scope.name == 'all') {
|
||||
for (shipId in Persist.builds) {
|
||||
|
||||
@@ -21,7 +21,7 @@ angular.module('app')
|
||||
$scope.details = $p.details;
|
||||
break;
|
||||
default:
|
||||
$scope.msgPre = "Uh, Jameson, we have a problem..";
|
||||
$scope.msgPre = 'Uh, Jameson, we have a problem..';
|
||||
$scope.errorMessage = $p.message;
|
||||
$scope.details = $p.details;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ angular.module('app').controller('ImportController', ['$scope', '$stateParams',
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$scope.errorMsg = '"' + shipId + '" is not a valid Ship Id!';
|
||||
$scope.errorMsg = '"' + shipId + '"" is not a valid Ship Id!';
|
||||
return;
|
||||
}
|
||||
$scope.builds = importObj.builds;
|
||||
|
||||
@@ -166,12 +166,12 @@ angular.module('app').controller('OutfitController', ['$window','$rootScope','$s
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
$scope.sortCost = function(key) {
|
||||
$scope.costDesc = ($scope.costPredicate == key)? !$scope.costDesc : $scope.costDesc;
|
||||
$scope.costDesc = $scope.costPredicate == key ? !$scope.costDesc : $scope.costDesc;
|
||||
$scope.costPredicate = key;
|
||||
};
|
||||
|
||||
$scope.sortPwr = function(key) {
|
||||
$scope.pwrDesc = ($scope.pwrPredicate == key)? !$scope.pwrDesc : $scope.pwrDesc;
|
||||
$scope.pwrDesc = $scope.pwrPredicate == key ? !$scope.pwrDesc : $scope.pwrDesc;
|
||||
$scope.pwrPredicate = key;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
angular.module('app').directive('areaChart', ['$window', function($window) {
|
||||
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
@@ -18,57 +16,57 @@ angular.module('app').directive('areaChart', ['$window', function ($window) {
|
||||
drag = d3.behavior.drag(),
|
||||
dragging = false,
|
||||
// Define Axes
|
||||
xAxis = d3.svg.axis().outerTickSize(0).orient("bottom").tickFormat(d3.format('.2r')),
|
||||
yAxis = d3.svg.axis().ticks(6).outerTickSize(0).orient("left").tickFormat(fmt),
|
||||
xAxis = d3.svg.axis().outerTickSize(0).orient('bottom').tickFormat(d3.format('.2r')),
|
||||
yAxis = d3.svg.axis().ticks(6).outerTickSize(0).orient('left').tickFormat(fmt),
|
||||
x = d3.scale.linear(),
|
||||
y = d3.scale.linear();
|
||||
|
||||
// Create chart
|
||||
var svg = d3.select(element[0]).append("svg");
|
||||
var vis = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||
var svg = d3.select(element[0]).append('svg');
|
||||
var vis = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
|
||||
|
||||
// Define Area
|
||||
var area = d3.svg.area();
|
||||
|
||||
var gradient = vis.append("defs")
|
||||
.append("linearGradient")
|
||||
.attr("id", "gradient")
|
||||
.attr("x1", "0%").attr("y1", "0%")
|
||||
.attr("x2", "100%").attr("y2", "100%")
|
||||
.attr("spreadMethod", "pad");
|
||||
gradient.append("stop")
|
||||
.attr("offset", "0%")
|
||||
.attr("stop-color", "#ff8c0d")
|
||||
.attr("stop-opacity", 1);
|
||||
gradient.append("stop")
|
||||
.attr("offset", "100%")
|
||||
.attr("stop-color", "#ff3b00")
|
||||
.attr("stop-opacity", 1);
|
||||
var gradient = vis.append('defs')
|
||||
.append('linearGradient')
|
||||
.attr('id', 'gradient')
|
||||
.attr('x1', '0%').attr('y1', '0%')
|
||||
.attr('x2', '100%').attr('y2', '100%')
|
||||
.attr('spreadMethod', 'pad');
|
||||
gradient.append('stop')
|
||||
.attr('offset', '0%')
|
||||
.attr('stop-color', '#ff8c0d')
|
||||
.attr('stop-opacity', 1);
|
||||
gradient.append('stop')
|
||||
.attr('offset', '100%')
|
||||
.attr('stop-color', '#ff3b00')
|
||||
.attr('stop-opacity', 1);
|
||||
|
||||
// Create Y Axis SVG Elements
|
||||
var yTxt = vis.append("g").attr("class", "y axis")
|
||||
.append("text")
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("y", -50)
|
||||
.attr("dy", ".1em")
|
||||
.style("text-anchor", "middle")
|
||||
var yTxt = vis.append('g').attr('class', 'y axis')
|
||||
.append('text')
|
||||
.attr('transform', 'rotate(-90)')
|
||||
.attr('y', -50)
|
||||
.attr('dy', '.1em')
|
||||
.style('text-anchor', 'middle')
|
||||
.text(labels.yAxis.title + ' (' + labels.yAxis.unit + ')');
|
||||
// Create X Axis SVG Elements
|
||||
var xLbl = vis.append("g").attr("class", "x axis");
|
||||
var xTxt = xLbl.append("text")
|
||||
.attr("y", 30)
|
||||
.attr("dy", ".1em")
|
||||
.style("text-anchor", "middle")
|
||||
var xLbl = vis.append('g').attr('class', 'x axis');
|
||||
var xTxt = xLbl.append('text')
|
||||
.attr('y', 30)
|
||||
.attr('dy', '.1em')
|
||||
.style('text-anchor', 'middle')
|
||||
.text(labels.xAxis.title + ' (' + labels.xAxis.unit + ')');
|
||||
|
||||
// Create and Add tooltip
|
||||
var tip = vis.append("g").style("display", "none");
|
||||
tip.append("rect").attr("width","4em").attr("height", "2em").attr("x", "0.5em").attr("y","-1em").attr("class","tip");
|
||||
tip.append("circle")
|
||||
.attr("class", "marker")
|
||||
.attr("r", 4);
|
||||
tip.append("text").attr("class", 'label x').attr("y", "-0.25em");
|
||||
tip.append("text").attr("class", 'label y').attr("y", '0.85em');
|
||||
var tip = vis.append('g').style('display', 'none');
|
||||
tip.append('rect').attr('width', '4em').attr('height', '2em').attr('x', '0.5em').attr('y', '-1em').attr('class', 'tip');
|
||||
tip.append('circle')
|
||||
.attr('class', 'marker')
|
||||
.attr('r', 4);
|
||||
tip.append('text').attr('class', 'label x').attr('y', '-0.25em');
|
||||
tip.append('text').attr('class', 'label y').attr('y', '0.85em');
|
||||
|
||||
/**
|
||||
* Watch for changes in the series data (mass changes, etc)
|
||||
@@ -89,33 +87,33 @@ angular.module('app').directive('areaChart', ['$window', function ($window) {
|
||||
data.push([ series.xMin, yVal ]);
|
||||
area.x(function(d, i) { return i * w; }).y0(h).y1(function(d) { return y(d[1]); });
|
||||
} else {
|
||||
for (var d = series.xMin; d <= series.xMax; d += 1) {
|
||||
data.push([ d, func(d) ]);
|
||||
for (var val = series.xMin; val <= series.xMax; val += 1) {
|
||||
data.push([ val, func(val) ]);
|
||||
}
|
||||
area.x(function(d) { return x(d[0]); }).y0(h).y1(function(d) { return y(d[1]); });
|
||||
}
|
||||
|
||||
// Update Chart Size
|
||||
svg.attr("width", width).attr("height", height);
|
||||
svg.attr('width', width).attr('height', height);
|
||||
// Update domain and scale for axes;
|
||||
x.range([0, w]).domain([series.xMin, series.xMax]).clamp(true);
|
||||
xAxis.scale(x);
|
||||
xLbl.attr("transform", "translate(0," + h + ")");
|
||||
xTxt.attr("x", w/2);
|
||||
xLbl.attr('transform', 'translate(0,' + h + ')');
|
||||
xTxt.attr('x', w / 2);
|
||||
y.range([h, 0]).domain([series.yMin, series.yMax]);
|
||||
yAxis.scale(y);
|
||||
yTxt.attr("x", -h/2);
|
||||
vis.selectAll(".y.axis").call(yAxis);
|
||||
vis.selectAll(".x.axis").call(xAxis);
|
||||
yTxt.attr('x', -h / 2);
|
||||
vis.selectAll('.y.axis').call(yAxis);
|
||||
vis.selectAll('.x.axis').call(xAxis);
|
||||
|
||||
// Remove existing elements
|
||||
vis.selectAll('path.area').remove();
|
||||
|
||||
vis.insert("path",':first-child') // Area/Path to appear behind everything else
|
||||
vis.insert('path', ':first-child') // Area/Path to appear behind everything else
|
||||
.datum(data)
|
||||
.attr("class", "area")
|
||||
.attr('class', 'area')
|
||||
.attr('fill', 'url(#gradient)')
|
||||
.attr("d", area)
|
||||
.attr('d', area)
|
||||
.on('mouseover', showTip)
|
||||
.on('mouseout', hideTip)
|
||||
.on('mousemove', moveTip)
|
||||
@@ -127,7 +125,7 @@ angular.module('app').directive('areaChart', ['$window', function ($window) {
|
||||
moveTip.call(this);
|
||||
showTip();
|
||||
})
|
||||
.on("dragend", function() {
|
||||
.on('dragend', function() {
|
||||
dragging = false;
|
||||
hideTip();
|
||||
})
|
||||
@@ -135,20 +133,20 @@ angular.module('app').directive('areaChart', ['$window', function ($window) {
|
||||
}
|
||||
|
||||
function showTip() {
|
||||
tip.style("display", null);
|
||||
tip.style('display', null);
|
||||
}
|
||||
|
||||
function hideTip() {
|
||||
if (!dragging) {
|
||||
tip.style("display", "none");
|
||||
tip.style('display', 'none');
|
||||
}
|
||||
}
|
||||
|
||||
function moveTip() {
|
||||
var xPos = d3.mouse(this)[0], x0 = x.invert(xPos), y0 = func(x0), flip = (x0 / x.domain()[1] > 0.75);
|
||||
tip.attr("transform", "translate(" + x(x0) + "," + y(y0) + ")");
|
||||
tip.selectAll('rect').attr("x", flip? '-4.5em' : "0.5em").style("text-anchor", flip? 'end' : 'start');
|
||||
tip.selectAll('text.label').attr("x", flip? "-1em" : "1em").style("text-anchor", flip? 'end' : 'start');
|
||||
tip.attr('transform', 'translate(' + x(x0) + ',' + y(y0) + ')');
|
||||
tip.selectAll('rect').attr('x', flip ? '-4.5em' : '0.5em').style('text-anchor', flip ? 'end' : 'start');
|
||||
tip.selectAll('text.label').attr('x', flip ? '-1em' : '1em').style('text-anchor', flip ? 'end' : 'start');
|
||||
tip.select('text.label.x').text(fmtLong(x0) + ' ' + labels.xAxis.unit);
|
||||
tip.select('text.label.y').text(fmtLong(y0) + ' ' + labels.yAxis.unit);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ angular.module('app').directive('barChart', ['$window', function ($window) {
|
||||
return build.buildName + '\n' + build.name;
|
||||
}
|
||||
|
||||
var insertLinebreaks = function (d) {
|
||||
function insertLinebreaks(d) {
|
||||
var el = d3.select(this);
|
||||
var words = d.split('\n');
|
||||
el.text('').attr('y', -6);
|
||||
@@ -14,7 +14,7 @@ angular.module('app').directive('barChart', ['$window', function ($window) {
|
||||
tspan.attr('x', -9).attr('dy', 12);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
|
||||
@@ -25,11 +25,11 @@ angular.module('app').directive('powerBands', ['$window', function ($window) {
|
||||
// Create Y Axis SVG Elements
|
||||
vis.append('g').attr('class', 'watt axis');
|
||||
vis.append('g').attr('class', 'pct axis');
|
||||
vis.append("text").attr('x', -35).attr('y', 16).attr('class','primary').text('RET');
|
||||
vis.append("text").attr('x', -35).attr('y', barHeight + 18).attr('class','primary').text('DEP');
|
||||
vis.append('text').attr('x', -35).attr('y', 16).attr('class', 'primary').text('RET');
|
||||
vis.append('text').attr('x', -35).attr('y', barHeight + 18).attr('class', 'primary').text('DEP');
|
||||
|
||||
var retLbl = vis.append("text").attr('y', 16);
|
||||
var depLbl = vis.append("text").attr('y', barHeight + 18);
|
||||
var retLbl = vis.append('text').attr('y', 16);
|
||||
var depLbl = vis.append('text').attr('y', barHeight + 18);
|
||||
|
||||
// Watch for changes to data and events
|
||||
scope.$watchCollection('available', render);
|
||||
@@ -63,33 +63,34 @@ angular.module('app').directive('powerBands', ['$window', function ($window) {
|
||||
.attr('x', w + 5 )
|
||||
.attr('class', maxBand.retractedSum > available ? 'warning' : 'primary')
|
||||
.text(wattFmt(Math.max(0, maxBand.retractedSum)) + ' (' + pctFmt(Math.max(0, maxBand.retractedSum / available)) + ')');
|
||||
|
||||
depLbl
|
||||
.attr('x', w + 5 )
|
||||
.attr('class', maxBand.deployedSum > available ? 'warning' : 'primary')
|
||||
.text(wattFmt(Math.max(0, maxBand.deployedSum)) + ' (' + pctFmt(Math.max(0, maxBand.deployedSum / available)) + ')');
|
||||
|
||||
retracted.selectAll("rect").data(bands).enter().append("rect")
|
||||
.attr("height", barHeight)
|
||||
.attr("width", function(d) { return Math.max(wattScale(d.retracted) - 1, 0); })
|
||||
.attr("x", function(d) { return wattScale(d.retractedSum) - wattScale(d.retracted); })
|
||||
retracted.selectAll('rect').data(bands).enter().append('rect')
|
||||
.attr('height', barHeight)
|
||||
.attr('width', function(d) { return Math.max(wattScale(d.retracted) - 1, 0); })
|
||||
.attr('x', function(d) { return wattScale(d.retractedSum) - wattScale(d.retracted); })
|
||||
.attr('y', 1)
|
||||
.attr('class', function(d) { return (d.retractedSum > available) ? 'warning' : 'primary'; });
|
||||
|
||||
retracted.selectAll("text").data(bands).enter().append("text")
|
||||
retracted.selectAll('text').data(bands).enter().append('text')
|
||||
.attr('x', function(d) { return wattScale(d.retractedSum) - (wattScale(d.retracted) / 2); })
|
||||
.attr('y', 15)
|
||||
.style('text-anchor', 'middle')
|
||||
.attr('class', 'primary-bg')
|
||||
.text(function(d, i) { return bandText(d.retracted, i); });
|
||||
|
||||
deployed.selectAll("rect").data(bands).enter().append("rect")
|
||||
.attr("height", barHeight)
|
||||
.attr("width", function(d) { return Math.max(wattScale(d.deployed + d.retracted) - 1, 0); })
|
||||
.attr("x", function(d) { return wattScale(d.deployedSum) - wattScale(d.retracted) - wattScale(d.deployed); })
|
||||
deployed.selectAll('rect').data(bands).enter().append('rect')
|
||||
.attr('height', barHeight)
|
||||
.attr('width', function(d) { return Math.max(wattScale(d.deployed + d.retracted) - 1, 0); })
|
||||
.attr('x', function(d) { return wattScale(d.deployedSum) - wattScale(d.retracted) - wattScale(d.deployed); })
|
||||
.attr('y', barHeight + 2)
|
||||
.attr('class', function(d) { return (d.deployedSum > available) ? 'warning' : 'primary'; });
|
||||
|
||||
deployed.selectAll("text").data(bands).enter().append("text")
|
||||
deployed.selectAll('text').data(bands).enter().append('text')
|
||||
.attr('x', function(d) { return wattScale(d.deployedSum) - ((wattScale(d.retracted) + wattScale(d.deployed)) / 2); })
|
||||
.attr('y', barHeight + 17)
|
||||
.style('text-anchor', 'middle')
|
||||
|
||||
@@ -15,19 +15,19 @@ angular.module('app').directive('slider', ['$window', function ($window) {
|
||||
pct = d3.format('.1%'),
|
||||
unit = scope.unit,
|
||||
val = scope.max,
|
||||
svg = d3.select(element[0]).append("svg"),
|
||||
vis = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"),
|
||||
xAxis = vis.append("g").attr("class", "x slider-axis").attr("transform", "translate(0," + h / 2 + ")"),
|
||||
svg = d3.select(element[0]).append('svg'),
|
||||
vis = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'),
|
||||
xAxis = vis.append('g').attr('class', 'x slider-axis').attr('transform', 'translate(0,' + h / 2 + ')'),
|
||||
x = d3.scale.linear(),
|
||||
slider = vis.append("g").attr("class", "slider"),
|
||||
filled = slider.append('path').attr('class', 'filled').attr("transform", "translate(0," + h/2 + ")"),
|
||||
brush = d3.svg.brush().x(x).extent([scope.max, scope.max]).on("brush", brushed),
|
||||
handle = slider.append("circle").attr("class", "handle").attr("r", '0.6em'),
|
||||
lbl = slider.append("g").append("text").attr("y", h/2);
|
||||
slider = vis.append('g').attr('class', 'slider'),
|
||||
filled = slider.append('path').attr('class', 'filled').attr('transform', 'translate(0,' + h / 2 + ')'),
|
||||
brush = d3.svg.brush().x(x).extent([scope.max, scope.max]).on('brush', brushed),
|
||||
handle = slider.append('circle').attr('class', 'handle').attr('r', '0.6em'),
|
||||
lbl = slider.append('g').append('text').attr('y', h / 2);
|
||||
|
||||
slider.call(brush);
|
||||
slider.select(".background").attr("height", h);
|
||||
handle.attr("transform", "translate(0," + h / 2 + ")");
|
||||
slider.select('.background').attr('height', h);
|
||||
handle.attr('transform', 'translate(0,' + h / 2 + ')');
|
||||
|
||||
/**
|
||||
* Watch for changes in the max, window size
|
||||
@@ -42,21 +42,21 @@ angular.module('app').directive('slider', ['$window', function ($window) {
|
||||
function render() {
|
||||
var width = element[0].offsetWidth, w = width - margin.left - margin.right;
|
||||
|
||||
svg.attr("width", width).attr("height", height);
|
||||
svg.attr('width', width).attr('height', height);
|
||||
x.domain([0, scope.max]).range([0, w]).clamp(true);
|
||||
handle.attr("cx", x(val));
|
||||
handle.attr('cx', x(val));
|
||||
xAxis
|
||||
.call(d3.svg.axis()
|
||||
.scale(x)
|
||||
.orient("bottom")
|
||||
.orient('bottom')
|
||||
.tickFormat(function(d) { return d + unit; })
|
||||
.tickValues([0, scope.max / 4, scope.max / 2, (3 * scope.max) / 4, scope.max])
|
||||
.tickSize(0)
|
||||
.tickPadding(12))
|
||||
.select(".domain");
|
||||
.select('.domain');
|
||||
lbl.attr('x', w + 20);
|
||||
slider.call(brush.extent([val, val])).call(brush.event);
|
||||
slider.selectAll(".extent,.resize").remove();
|
||||
slider.selectAll('.extent,.resize').remove();
|
||||
}
|
||||
|
||||
function brushed() {
|
||||
@@ -67,8 +67,8 @@ angular.module('app').directive('slider', ['$window', function ($window) {
|
||||
}
|
||||
lbl.text(fmt(val) + ' ' + unit + ' ' + pct(val / scope.max));
|
||||
scope.change({ val: val });
|
||||
handle.attr("cx", x(val));
|
||||
filled.attr("d", "M0,0V0H" + x(val) + "V0");
|
||||
handle.attr('cx', x(val));
|
||||
filled.attr('d', 'M0,0V0H' + x(val) + 'V0');
|
||||
}
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
|
||||
@@ -4,7 +4,7 @@ angular.module('app').directive('slotHardpoint', ['$rootScope', function ($r) {
|
||||
scope: {
|
||||
hp: '=',
|
||||
size: '=',
|
||||
lbl: '=',
|
||||
lbl: '='
|
||||
},
|
||||
templateUrl: 'views/_slot-hardpoint.html',
|
||||
link: function(scope) {
|
||||
|
||||
@@ -36,10 +36,7 @@ angular.module('app').service('Serializer', ['lodash', function (_) {
|
||||
* @param {string} code The string to deserialize
|
||||
*/
|
||||
this.toShip = function(ship, dataString) {
|
||||
var commonCount = ship.common.length,
|
||||
hpCount = commonCount + ship.hardpoints.length,
|
||||
totalCount = hpCount + ship.internal.length,
|
||||
common = new Array(ship.common.length),
|
||||
var common = new Array(ship.common.length),
|
||||
hardpoints = new Array(ship.hardpoints.length),
|
||||
internal = new Array(ship.internal.length),
|
||||
parts = dataString.split('.'),
|
||||
@@ -61,12 +58,16 @@ angular.module('app').service('Serializer', ['lodash', function (_) {
|
||||
// - priorities
|
||||
// - enabled/disabled
|
||||
|
||||
ship.buildWith({
|
||||
ship.buildWith(
|
||||
{
|
||||
bulkheads: code.charAt(0) * 1,
|
||||
common: common,
|
||||
hardpoints: hardpoints,
|
||||
internal: internal,
|
||||
}, priorities, enabled);
|
||||
internal: internal
|
||||
},
|
||||
priorities,
|
||||
enabled
|
||||
);
|
||||
};
|
||||
|
||||
this.fromComparison = function(name, builds, facets, predicate, desc) {
|
||||
@@ -101,11 +102,11 @@ angular.module('app').service('Serializer', ['lodash', function (_) {
|
||||
this.enabled.push(slot.enabled ? 1 : 0);
|
||||
this.priorities.push(slot.priority);
|
||||
|
||||
return (slot.id === null)? '-' : slot.id;
|
||||
return slot.id === null ? '-' : slot.id;
|
||||
}
|
||||
|
||||
function decodeToArray(code, arr, codePos) {
|
||||
for (i = 0; i < arr.length; i++) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (code.charAt(codePos) == '-') {
|
||||
arr[i] = 0;
|
||||
codePos++;
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
angular.module('shipyard').factory('ComponentSet', ['lodash', function(_) {
|
||||
|
||||
function filter(data, maxClass, minClass, mass) {
|
||||
return _.filter(data, function(c) {
|
||||
return c.class <= maxClass && c.class >= minClass && (c.maxmass === undefined || mass <= c.maxmass);
|
||||
});
|
||||
}
|
||||
|
||||
function ComponentSet(components, mass, maxCommonArr, maxInternal, maxHardPoint) {
|
||||
this.mass = mass;
|
||||
this.common = {};
|
||||
@@ -57,12 +63,6 @@ angular.module('shipyard').factory('ComponentSet', ['lodash', function (_) {
|
||||
return this.intClass[c];
|
||||
};
|
||||
|
||||
function filter (data, maxClass, minClass, mass) {
|
||||
return _.filter(data, function (c) {
|
||||
return c.class <= maxClass && c.class >= minClass && (c.maxmass === undefined || mass <= c.maxmass);
|
||||
});
|
||||
}
|
||||
|
||||
return ComponentSet;
|
||||
|
||||
}]);
|
||||
|
||||
@@ -64,13 +64,18 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength',
|
||||
common = this.common,
|
||||
hps = this.hardpoints,
|
||||
bands = this.priorityBands,
|
||||
cl = common.length, hl = hps.length, il = internal.length,
|
||||
cl = common.length,
|
||||
i, l;
|
||||
|
||||
this.useBulkhead(comps.bulkheads || 0, true);
|
||||
this.cargoScoop.priority = priorities ? priorities[0] * 1 : 0;
|
||||
this.cargoScoop.enabled = enabled ? enabled[0] * 1 : true;
|
||||
|
||||
for (i = 0, l = this.priorityBands.length; i < l; i++) {
|
||||
this.priorityBands[i].deployed = 0;
|
||||
this.priorityBands[i].retracted = 0;
|
||||
}
|
||||
|
||||
if (this.cargoScoop.enabled) {
|
||||
bands[this.cargoScoop.priority].retracted += this.cargoScoop.c.power;
|
||||
}
|
||||
@@ -79,34 +84,35 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength',
|
||||
common[i].enabled = enabled ? enabled[i + 1] * 1 : true;
|
||||
common[i].priority = priorities ? priorities[i + 1] * 1 : 0;
|
||||
common[i].type = 'SYS';
|
||||
common[i].c = common[i].id = null; // Resetting 'old' component if there was one
|
||||
this.use(common[i], comps.common[i], Components.common(i, comps.common[i]), true);
|
||||
}
|
||||
|
||||
common[1].type = 'ENG'; // Thrusters
|
||||
common[2].type = 'ENG'; // FSD
|
||||
cl++; // Increase accounting for Cargo Scoop
|
||||
cl++; // Increase accounts for Cargo Scoop
|
||||
|
||||
for(i = 0, l = comps.hardpoints.length; i < l; i++) {
|
||||
for (i = 0, l = hps.length; i < l; i++) {
|
||||
hps[i].enabled = enabled ? enabled[cl + i] * 1 : true;
|
||||
hps[i].priority = priorities ? priorities[cl + i] * 1 : 0;
|
||||
hps[i].type = hps[i].maxClass ? 'WEP' : 'SYS';
|
||||
hps[i].c = hps[i].id = null; // Resetting 'old' component if there was one
|
||||
|
||||
if (comps.hardpoints[i] !== 0) {
|
||||
this.use(hps[i], comps.hardpoints[i], Components.hardpoints(comps.hardpoints[i]), true);
|
||||
} else {
|
||||
hps[i].c = hps[i].id = null;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0, l = comps.internal.length; i < l; i++) {
|
||||
internal[i].enabled = enabled? enabled[hl + cl + i] * 1 : true;
|
||||
internal[i].priority = priorities? priorities[hl + cl + i] * 1 : 0;
|
||||
cl += hps.length; // Increase accounts for hardpoints
|
||||
|
||||
for (i = 0, l = internal.length; i < l; i++) {
|
||||
internal[i].enabled = enabled ? enabled[cl + i] * 1 : true;
|
||||
internal[i].priority = priorities ? priorities[cl + i] * 1 : 0;
|
||||
internal[i].type = 'SYS';
|
||||
internal[i].id = internal[i].c = null; // Resetting 'old' component if there was one
|
||||
|
||||
if (comps.internal[i] !== 0) {
|
||||
this.use(internal[i], comps.internal[i], Components.internal(comps.internal[i]), true);
|
||||
} else {
|
||||
internal[i].id = internal[i].c = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,18 +185,24 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength',
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Will change the priority of the specified slot if the new priority is valid
|
||||
* @param {object} slot The slot to be updated
|
||||
* @param {number} newPriority The new priority to be set
|
||||
* @return {boolean} Returns true if the priority was changed (within range)
|
||||
*/
|
||||
Ship.prototype.changePriority = function(slot, newPriority) {
|
||||
if (newPriority >= 0 && newPriority < this.priorityBands.length) {
|
||||
var oldPriority = slot.priority;
|
||||
slot.priority = newPriority;
|
||||
|
||||
if (slot.enabled) {
|
||||
if (slot.enabled) { // Only update power if the slot is enabled
|
||||
var usage = (slot.c.passive || this.hardpoints.indexOf(slot) == -1) ? 'retracted' : 'deployed';
|
||||
this.priorityBands[oldPriority][usage] -= slot.c.power;
|
||||
this.priorityBands[newPriority][usage] += slot.c.power;
|
||||
this.updatePower();
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -214,14 +226,11 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength',
|
||||
Ship.prototype.getSlotStatus = function(slot, deployed) {
|
||||
if (!slot.c) { // Empty Slot
|
||||
return 0; // No Status (Not possible)
|
||||
}
|
||||
else if (!slot.enabled) {
|
||||
} else if (!slot.enabled) {
|
||||
return 1; // Disabled
|
||||
}
|
||||
else if (deployed) {
|
||||
} else if (deployed) {
|
||||
return this.priorityBands[slot.priority].deployedSum > this.powerAvailable ? 2 : 3; // Offline : Online
|
||||
}
|
||||
else if (this.hardpoints.indexOf(slot) != -1 && !slot.c.passive) { // Active hardpoints have no retracted status
|
||||
} else if (this.hardpoints.indexOf(slot) != -1 && !slot.c.passive) { // Active hardpoints have no retracted status
|
||||
return 0; // No Status (Not possible)
|
||||
}
|
||||
return this.priorityBands[slot.priority].retractedSum > this.powerAvailable ? 2 : 3; // Offline : Online
|
||||
@@ -254,7 +263,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength',
|
||||
this.totalCost -= old.cost;
|
||||
}
|
||||
|
||||
if(old.power) {
|
||||
if (old.power && slot.enabled) {
|
||||
this.priorityBands[slot.priority][(isHardPoint && !old.passive) ? 'deployed' : 'retracted'] -= old.power;
|
||||
powerChange = true;
|
||||
}
|
||||
@@ -284,7 +293,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength',
|
||||
this.totalCost += n.cost;
|
||||
}
|
||||
|
||||
if (n.power) {
|
||||
if (n.power && slot.enabled) {
|
||||
this.priorityBands[slot.priority][(isHardPoint && !n.passive) ? 'deployed' : 'retracted'] += n.power;
|
||||
powerChange = true;
|
||||
}
|
||||
|
||||
@@ -47,23 +47,23 @@ angular.module('shipyard', ['ngLodash'])
|
||||
cc: 'Collector Limpet Ctrl',
|
||||
|
||||
// Hard Points
|
||||
bl: "Beam Laser",
|
||||
ul: "Burst Laser",
|
||||
c: "Cannon",
|
||||
cs: "Cargo Scanner",
|
||||
cm: "Countermeasure",
|
||||
fc: "Fragment Cannon",
|
||||
ws: "Frame Shift Wake Scanner",
|
||||
kw: "Kill Warrant Scanner",
|
||||
nl: "Mine Launcher",
|
||||
ml: "Mining Laser",
|
||||
mr: "Missile Rack",
|
||||
pa: "Plasma Accelerator",
|
||||
mc: "Multi-cannon",
|
||||
pl: "Pulse Laser",
|
||||
rg: "Rail Gun",
|
||||
sb: "Shield Booster",
|
||||
tp: "Torpedo Pylon"
|
||||
bl: 'Beam Laser',
|
||||
ul: 'Burst Laser',
|
||||
c: 'Cannon',
|
||||
cs: 'Cargo Scanner',
|
||||
cm: 'Countermeasure',
|
||||
fc: 'Fragment Cannon',
|
||||
ws: 'Frame Shift Wake Scanner',
|
||||
kw: 'Kill Warrant Scanner',
|
||||
nl: 'Mine Launcher',
|
||||
ml: 'Mining Laser',
|
||||
mr: 'Missile Rack',
|
||||
pa: 'Plasma Accelerator',
|
||||
mc: 'Multi-cannon',
|
||||
pl: 'Pulse Laser',
|
||||
rg: 'Rail Gun',
|
||||
sb: 'Shield Booster',
|
||||
tp: 'Torpedo Pylon'
|
||||
})
|
||||
.value('shipPurpose', {
|
||||
mp: 'Multi Purpose',
|
||||
@@ -77,7 +77,7 @@ angular.module('shipyard', ['ngLodash'])
|
||||
'Small',
|
||||
'Medium',
|
||||
'Large',
|
||||
'Capital',
|
||||
'Capital'
|
||||
])
|
||||
.value('hardPointClass', [
|
||||
'Utility',
|
||||
@@ -163,7 +163,7 @@ angular.module('shipyard', ['ngLodash'])
|
||||
lbls: ['Unladen', 'Laden'],
|
||||
unit: 'LY',
|
||||
fmt: 'fRound'
|
||||
},
|
||||
}
|
||||
])
|
||||
/**
|
||||
* Calculate the maximum single jump range based on mass and a specific FSD
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
<td><u>SYS</u></td>
|
||||
<td>1</td>
|
||||
<td class="ri">{{fPwr(pp.c.pGen)}}</td>
|
||||
<td><u>100%</u></td>
|
||||
<td class="ri"><u>100%</u></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
80
gulpfile.js
80
gulpfile.js
@@ -1,25 +1,28 @@
|
||||
// Build / Built-in dependencies
|
||||
var gulp = require('gulp'),
|
||||
less = require('gulp-less'),
|
||||
jshint = require('gulp-jshint'),
|
||||
minifyCSS = require('gulp-minify-css'),
|
||||
concat = require('gulp-concat'),
|
||||
uglify = require('gulp-uglify'),
|
||||
sourcemaps = require('gulp-sourcemaps'),
|
||||
templateCache = require('gulp-angular-templatecache'),
|
||||
htmlmin = require('gulp-htmlmin'),
|
||||
template = require('gulp-template'),
|
||||
mainBowerFiles = require('main-bower-files'),
|
||||
del = require('del'),
|
||||
runSequence = require('run-sequence'),
|
||||
exec = require('child_process').exec,
|
||||
RevAll = require('gulp-rev-all'),
|
||||
pkg = require('./package.json');
|
||||
|
||||
// Package.json / Gulp Dependencies
|
||||
var appCache = require("gulp-manifest"),
|
||||
concat = require('gulp-concat'),
|
||||
del = require('del'),
|
||||
eslint = require('gulp-eslint');
|
||||
gutil = require('gulp-util'),
|
||||
htmlmin = require('gulp-htmlmin'),
|
||||
jsonlint = require("gulp-jsonlint"),
|
||||
karma = require('karma').server,
|
||||
less = require('gulp-less'),
|
||||
mainBowerFiles = require('main-bower-files'),
|
||||
minifyCSS = require('gulp-minify-css'),
|
||||
revAll = require('gulp-rev-all'),
|
||||
runSequence = require('run-sequence'),
|
||||
sourcemaps = require('gulp-sourcemaps'),
|
||||
svgstore = require('gulp-svgstore'),
|
||||
svgmin = require('gulp-svgmin'),
|
||||
jsonlint = require("gulp-jsonlint"),
|
||||
appCache = require("gulp-manifest"),
|
||||
jasmine = require('gulp-jasmine'),
|
||||
pkg = require('./package.json');
|
||||
template = require('gulp-template'),
|
||||
templateCache = require('gulp-angular-templatecache'),
|
||||
uglify = require('gulp-uglify');
|
||||
|
||||
var cdnHostStr = '';
|
||||
|
||||
@@ -36,20 +39,31 @@ gulp.task('less', function() {
|
||||
});
|
||||
|
||||
gulp.task('js-lint', function() {
|
||||
return gulp.src('app/js/**/*.js')
|
||||
.pipe(jshint({
|
||||
undef: true,
|
||||
unused: true,
|
||||
curly: true,
|
||||
predef: [ 'angular','DB','d3', 'ga', 'GAPI_KEY', 'document' , 'LZString' ]
|
||||
return gulp.src(['app/js/**/*.js', '!app/js/template_cache.js', '!app/js/db.js'])
|
||||
.pipe(eslint({
|
||||
globals: { angular:1, DB:1, d3:1, ga:1, GAPI_KEY:1, LZString: 1 },
|
||||
rules: {
|
||||
quotes: [2, 'single'],
|
||||
strict: 'global',
|
||||
eqeqeq: 'smart',
|
||||
'space-after-keywords': [2, 'always'],
|
||||
'no-use-before-define': 'no-func',
|
||||
'space-before-function-paren': [2, 'never'],
|
||||
'space-before-blocks': [2, 'always'],
|
||||
'object-curly-spacing': [2, "always"],
|
||||
'brace-style': [2, '1tbs', { allowSingleLine: true }]
|
||||
},
|
||||
envs: ['browser']
|
||||
}))
|
||||
.pipe(jshint.reporter('default'));
|
||||
.pipe(eslint.format())
|
||||
.pipe(eslint.failAfterError());
|
||||
});
|
||||
|
||||
gulp.task('json-lint', function() {
|
||||
return gulp.src('data/**/*.json')
|
||||
.pipe(jsonlint())
|
||||
.pipe(jsonlint.reporter());
|
||||
.pipe(jsonlint.reporter())
|
||||
.pipe(jsonlint.failAfterError());
|
||||
});
|
||||
|
||||
gulp.task('bower', function(){
|
||||
@@ -187,11 +201,11 @@ gulp.task('watch', function() {
|
||||
});
|
||||
|
||||
gulp.task('cache-bust', function(done) {
|
||||
var revAll = new RevAll({ prefix: cdnHostStr, dontRenameFile: ['.html','db.json'] });
|
||||
var rev_all = new revAll({ prefix: cdnHostStr, dontRenameFile: ['.html','db.json'] });
|
||||
var stream = gulp.src('build/**')
|
||||
.pipe(revAll.revision())
|
||||
.pipe(rev_all.revision())
|
||||
.pipe(gulp.dest('build'))
|
||||
.pipe(revAll.manifestFile())
|
||||
.pipe(rev_all.manifestFile())
|
||||
.pipe(gulp.dest('build'));
|
||||
|
||||
stream.on('end', function() {
|
||||
@@ -238,9 +252,13 @@ gulp.task('upload', function(done) {
|
||||
);
|
||||
});
|
||||
|
||||
gulp.task('test', function () {
|
||||
return gulp.src('tests/test-*.js')
|
||||
.pipe(jasmine());
|
||||
gulp.task('test', function (done) {
|
||||
karma.start({
|
||||
configFile: __dirname + '/test/karma.conf.js',
|
||||
singleRun: true
|
||||
}, function(exitStatus) {
|
||||
done(exitStatus ? new gutil.PluginError('karma', { message: 'Unit tests failed!' }) : undefined);
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('lint', ['js-lint', 'json-lint']);
|
||||
|
||||
@@ -9,14 +9,15 @@
|
||||
"engine": "node >= 0.12.2",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"angular-mocks": "^1.3.16",
|
||||
"async": "^0.9.0",
|
||||
"del": "^1.1.1",
|
||||
"gulp": "^3.8.11",
|
||||
"gulp-angular-templatecache": "^1.6.0",
|
||||
"gulp-concat": "^2.5.2",
|
||||
"gulp-eslint": "^0.13.2",
|
||||
"gulp-htmlmin": "^1.1.1",
|
||||
"gulp-jasmine": "^2.0.1",
|
||||
"gulp-jshint": "^1.10.0",
|
||||
"gulp-jsonlint": "^1.0.2",
|
||||
"gulp-less": "^3.0.2",
|
||||
"gulp-manifest": "0.0.6",
|
||||
@@ -28,7 +29,11 @@
|
||||
"gulp-template": "^3.0.0",
|
||||
"gulp-uglify": "^1.2.0",
|
||||
"gulp-util": "^3.0.4",
|
||||
"jasmine-core": "^2.3.4",
|
||||
"json-concat": "0.0.0",
|
||||
"karma": "^0.12.36",
|
||||
"karma-chrome-launcher": "^0.1.12",
|
||||
"karma-jasmine": "^0.3.5",
|
||||
"main-bower-files": "^2.6.2",
|
||||
"run-sequence": "^1.0.2",
|
||||
"uglify-js": "^2.4.19"
|
||||
|
||||
34
test/karma.conf.js
Normal file
34
test/karma.conf.js
Normal file
@@ -0,0 +1,34 @@
|
||||
// Karma configuration
|
||||
// Generated on Thu Jun 11 2015 19:39:40 GMT-0700 (PDT)
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
// frameworks to use
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: ['jasmine'],
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
'../build/lib*.js',
|
||||
'../node_modules/angular-mocks/angular-mocks.js',
|
||||
'../build/app*.js',
|
||||
'tests/**/*.js'
|
||||
],
|
||||
// list of files to exclude
|
||||
exclude: [],
|
||||
// preprocess matching files before serving them to the browser
|
||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||
preprocessors: {},
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress'
|
||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||
reporters: ['progress'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: false,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false
|
||||
});
|
||||
};
|
||||
66
test/tests/test-data.js
Normal file
66
test/tests/test-data.js
Normal file
@@ -0,0 +1,66 @@
|
||||
describe("Database", function() {
|
||||
|
||||
var shipProperties = ["grp", "name", "manufacturer", "class", "cost", "speed", "boost", "agility", "shields", "armour", "fuelcost", "mass"];
|
||||
|
||||
it("has ships and components", function() {
|
||||
expect(DB.ships).toBeDefined()
|
||||
expect(DB.components.common).toBeDefined();
|
||||
expect(DB.components.hardpoints).toBeDefined();
|
||||
expect(DB.components.internal).toBeDefined();
|
||||
expect(DB.components.bulkheads).toBeDefined();
|
||||
});
|
||||
|
||||
it("has unique IDs for every hardpoint", function() {
|
||||
var ids = {};
|
||||
var groups = DB.components.hardpoints;
|
||||
|
||||
for (var g in groups) {
|
||||
var group = groups[g];
|
||||
for (var i = 0; i < group.length; i++) {
|
||||
var id = group[i].id;
|
||||
expect(ids[id]).toBeFalsy('ID already exists: ' + id);
|
||||
expect(group[i].grp).toBeDefined('Hardpoint has no group defined, ID:' + id);
|
||||
ids[id] = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("has valid internal components", function() {
|
||||
var ids = {};
|
||||
var groups = DB.components.internal;
|
||||
|
||||
for (var g in groups) {
|
||||
var group = groups[g];
|
||||
for (var i = 0; i < group.length; i++) {
|
||||
var id = group[i].id;
|
||||
expect(ids[id]).toBeFalsy('ID already exists: ' + id);
|
||||
expect(group[i].grp).toBeDefined('Internal component has no group defined, ID:' + id);
|
||||
ids[id] = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("has data for every ship", function() {
|
||||
for (var s in DB.ships) {
|
||||
for (var p = 0; p < shipProperties.length; p++) {
|
||||
expect(DB.ships[s].properties[shipProperties[p]]).toBeDefined(shipProperties[p] + ' is missing for ' + s);
|
||||
}
|
||||
expect(DB.ships[s].slots.common.length).toEqual(7, s + ' is missing common slots');
|
||||
expect(DB.ships[s].defaults.common.length).toEqual(7, s + ' is missing common defaults');
|
||||
expect(DB.ships[s].slots.hardpoints.length).toEqual(DB.ships[s].defaults.hardpoints.length, s + ' hardpoint slots and defaults dont match');
|
||||
expect(DB.ships[s].slots.internal.length).toEqual(DB.ships[s].defaults.internal.length, s + ' hardpoint slots and defaults dont match');
|
||||
expect(DB.ships[s].retailCost).toBeGreaterThan(DB.ships[s].properties.cost, s + ' has invalid retail cost');
|
||||
expect(DB.components.bulkheads[s]).toBeDefined(s + ' is missing bulkheads');
|
||||
}
|
||||
});
|
||||
|
||||
it("has components with a group defined", function() {
|
||||
for (var i = 0; i < DB.components.common.length; i++) {
|
||||
var group = DB.components.common[i];
|
||||
for (var c in group) {
|
||||
expect(group[c].grp).toBeDefined('Common component has no group defined, Type: ' + i + ', ID: ' + c);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
34
test/tests/test-factory-ship.js
Normal file
34
test/tests/test-factory-ship.js
Normal file
@@ -0,0 +1,34 @@
|
||||
describe("Ship Factory", function() {
|
||||
|
||||
var Ship;
|
||||
|
||||
beforeEach(module('shipyard'));
|
||||
beforeEach(inject(['Ship', function (_Ship_) {
|
||||
Ship = _Ship_;
|
||||
}]));
|
||||
|
||||
it("can build all ships", function() {
|
||||
for (var s in DB.ships) {
|
||||
var shipData = DB.ships[s];
|
||||
var ship = new Ship(s, shipData.properties, shipData.slots);
|
||||
|
||||
for (p in shipData.properties) {
|
||||
expect(ship[p]).toEqual(shipData.properties[p], s + ' property [' + p + '] does not match when built');
|
||||
}
|
||||
|
||||
ship.buildWith(shipData.defaults);
|
||||
|
||||
expect(ship.totalCost).toEqual(shipData.retailCost, s + ' retail cost does not match default build cost');
|
||||
expect(ship.priorityBands[0].retracted).toBeGreaterThan(0, s + ' cargo');
|
||||
expect(ship.powerAvailable).toBeGreaterThan(0, s + ' powerAvailable');
|
||||
expect(ship.unladenRange).toBeGreaterThan(0, s + ' unladenRange');
|
||||
expect(ship.ladenRange).toBeGreaterThan(0, s + ' ladenRange');
|
||||
expect(ship.fuelCapacity).toBeGreaterThan(0, s + ' fuelCapacity');
|
||||
expect(ship.unladenTotalRange).toBeGreaterThan(0, s + ' unladenTotalRange');
|
||||
expect(ship.ladenTotalRange).toBeGreaterThan(0, s + ' ladenTotalRange');
|
||||
expect(ship.shieldStrength).toBeGreaterThan(0, s + ' shieldStrength');
|
||||
expect(ship.armourTotal).toBeGreaterThan(0, s + ' armourTotal');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,68 +0,0 @@
|
||||
var data = require('../app/db.json');
|
||||
|
||||
var shipProperties = ["grp", "name", "manufacturer", "class", "cost", "speed", "boost", "agility", "shields", "armour", "fuelcost", "mass"];
|
||||
|
||||
describe("Database", function() {
|
||||
|
||||
it("has ships and components", function() {
|
||||
expect(data.ships).toBeDefined()
|
||||
expect(data.components.common).toBeDefined();
|
||||
expect(data.components.hardpoints).toBeDefined();
|
||||
expect(data.components.internal).toBeDefined();
|
||||
expect(data.components.bulkheads).toBeDefined();
|
||||
});
|
||||
|
||||
it("has unique IDs for every hardpoint", function() {
|
||||
var ids = {};
|
||||
var groups = data.components.hardpoints;
|
||||
|
||||
for (var g in groups) {
|
||||
var group = groups[g];
|
||||
for (var i = 0; i < group.length; i++) {
|
||||
var id = group[i].id;
|
||||
expect(ids[id]).toBeFalsy('ID already exists: ' + id);
|
||||
expect(group[i].grp).toBeDefined('Hardpoint has no group defined, ID:' + id);
|
||||
ids[id] = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("has valid internal components", function() {
|
||||
var ids = {};
|
||||
var groups = data.components.internal;
|
||||
|
||||
for (var g in groups) {
|
||||
var group = groups[g];
|
||||
for (var i = 0; i < group.length; i++) {
|
||||
var id = group[i].id;
|
||||
expect(ids[id]).toBeFalsy('ID already exists: ' + id);
|
||||
expect(group[i].grp).toBeDefined('Internal component has no group defined, ID:' + id);
|
||||
ids[id] = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("has data for every ship", function() {
|
||||
for (var s in data.ships) {
|
||||
for (var p = 0; p < shipProperties.length; p++) {
|
||||
expect(data.ships[s].properties[shipProperties[p]]).toBeDefined(shipProperties[p] + ' is missing for ' + s);
|
||||
}
|
||||
expect(data.ships[s].slots.common.length).toEqual(7, s + ' is missing common slots');
|
||||
expect(data.ships[s].defaults.common.length).toEqual(7, s + ' is missing common defaults');
|
||||
expect(data.ships[s].slots.hardpoints.length).toEqual(data.ships[s].defaults.hardpoints.length, s + ' hardpoint slots and defaults dont match');
|
||||
expect(data.ships[s].slots.internal.length).toEqual(data.ships[s].defaults.internal.length, s + ' hardpoint slots and defaults dont match');
|
||||
expect(data.ships[s].retailCost).toBeGreaterThan(data.ships[s].properties.cost, s + ' has invalid retail cost');
|
||||
expect(data.components.bulkheads[s]).toBeDefined(s + ' is missing bulkheads');
|
||||
}
|
||||
});
|
||||
|
||||
it("has components with a group defined", function() {
|
||||
for (var i = 0; i < data.components.common.length; i++) {
|
||||
var group = data.components.common[i];
|
||||
for (var c in group) {
|
||||
expect(group[c].grp).toBeDefined('Common component has no group defined, Type: ' + i + ', ID: ' + c);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user