diff --git a/app/js/controllers/controller-outfit.js b/app/js/controllers/controller-outfit.js index 147fca76..fc123275 100755 --- a/app/js/controllers/controller-outfit.js +++ b/app/js/controllers/controller-outfit.js @@ -211,6 +211,24 @@ angular.module('app').controller('OutfitController', ['$window', '$rootScope', ' } }; + /** + * Export the build to detailed JSON + */ + $scope.exportBuild = function(e) { + e.stopPropagation(); + + if ($scope.buildName) { + $state.go('modal.export', { + data: Serializer.toJsonBuild( + $scope.buildName, + ship, + $state.href($state.current.name, $state.params, { absolute: true }), + $scope.code || Serializer.fromShip(ship) + ) + }); + } + }; + /** * Permanently delete the current build and redirect/reload this controller * with the 'factory' build of the current ship. diff --git a/app/js/service-serializer.js b/app/js/service-serializer.js index a17ffc4d..3b84ad9a 100755 --- a/app/js/service-serializer.js +++ b/app/js/service-serializer.js @@ -1,7 +1,7 @@ /** * Service managing seralization and deserialization of models for use in URLs and persistene. */ -angular.module('app').service('Serializer', ['lodash', function(_) { +angular.module('app').service('Serializer', ['lodash', 'GroupMap', 'MountMap', function(_, GroupMap, MountMap) { /** * Serializes the ships selected components for all slots to a URL friendly string. @@ -32,8 +32,8 @@ angular.module('app').service('Serializer', ['lodash', function(_) { * Updates an existing ship instance's slots with components determined by the * code. * - * @param {Ship} ship The ship instance to be updated - * @param {string} code The string to deserialize + * @param {Ship} ship The ship instance to be updated + * @param {string} dataString The string to deserialize */ this.toShip = function(ship, dataString) { var common = new Array(ship.common.length), @@ -54,10 +54,6 @@ angular.module('app').service('Serializer', ['lodash', function(_) { decodeToArray(code, internal, decodeToArray(code, hardpoints, decodeToArray(code, common, 1))); - // get the remaining substring / split into parts for - // - priorities - // - enabled/disabled - ship.buildWith( { bulkheads: code.charAt(0) * 1, @@ -70,6 +66,48 @@ angular.module('app').service('Serializer', ['lodash', function(_) { ); }; + this.toJsonBuild = function(buildName, ship, url, code) { + var standard = ship.common, + hardpoints = ship.hardpoints, + internal = ship.internal; + + var data = { + $schema: 'http://cdn.coriolis.io/schemas/ship-loadout/1-draft.json#', + name: buildName, + ship: ship.name, + references: [{ + name: 'Coriolis.io', + url: url, + code: code, + shipId: ship.id + }], + components: { + standard: { + bulkheads: ship.bulkheads.c.name, + powerPlant: { class: standard[0].c.class, rating: standard[0].c.rating }, + thrusters: { class: standard[1].c.class, rating: standard[1].c.rating }, + frameShiftDrive: { class: standard[2].c.class, rating: standard[2].c.rating }, + lifeSupport: { class: standard[3].c.class, rating: standard[3].c.rating }, + powerDistributor: { class: standard[4].c.class, rating: standard[4].c.rating }, + sensors: { class: standard[5].c.class, rating: standard[5].c.rating }, + fuelTank: { class: standard[6].c.class, rating: standard[6].c.rating } + }, + hardpoints: _.map(_.filter(hardpoints, function(slot) { return slot.maxClass > 0; }), slotToSchema), + utility: _.map(_.filter(hardpoints, function(slot) { return slot.maxClass === 0; }), slotToSchema), + internal: _.map(internal, slotToSchema) + }, + stats: {} + }; + + for (var stat in ship) { + if (!isNaN(ship[stat])) { + data.stats[stat] = Math.round(ship[stat] * 100) / 100; + } + } + + return data; + }; + this.fromComparison = function(name, builds, facets, predicate, desc) { var shipBuilds = []; @@ -118,4 +156,19 @@ angular.module('app').service('Serializer', ['lodash', function(_) { return codePos; } + function slotToSchema(slot) { + if (slot.c) { + var o = { class: slot.c.class, rating: slot.c.rating, group: GroupMap[slot.c.grp] }; + if (slot.c.name) { + o.name = slot.c.name; + } + if (slot.c.mode) { + o.mount = MountMap[slot.c.mode]; + } + return o; + } + return null; + } + + }]); diff --git a/app/js/shipyard/factory-component-set.js b/app/js/shipyard/factory-component-set.js index 15aeca64..59009639 100755 --- a/app/js/shipyard/factory-component-set.js +++ b/app/js/shipyard/factory-component-set.js @@ -14,26 +14,27 @@ angular.module('shipyard').factory('ComponentSet', ['lodash', function(_) { this.hpClass = {}; this.intClass = {}; - for (var i = 0; i < components.common.length; i++) { - var max = maxCommonArr[i]; - switch (i) { - // Slots where component class must be equal to slot class - case 3: // Life Support - case 5: // Sensors - this.common[i] = filter(components.common[i], max, max, this.mass); - break; - // Other slots can have a component of class lower than the slot class - default: - this.common[i] = filter(components.common[i], max, 0, this.mass); - } - } + this.common[0] = filter(components.common[0], maxCommonArr[0], 0, mass); // Power Plant + this.common[2] = filter(components.common[2], maxCommonArr[2], 0, mass); // FSD + this.common[4] = filter(components.common[4], maxCommonArr[4], 0, mass); // Power Distributor + this.common[6] = filter(components.common[6], maxCommonArr[6], 0, mass); // Fuel Tank + + // Thrusters, filter components by class only (to show full list of ratings for that class) + var minThrusterClass = _.reduce(components.common[1], function(minClass, thruster) { + return (thruster.maxmass >= mass && thruster.class < minClass) ? thruster.class : minClass; + }, maxCommonArr[1]); + this.common[1] = filter(components.common[1], maxCommonArr[1], minThrusterClass, 0); // Thrusters + + // Slots where component class must be equal to slot class + this.common[3] = filter(components.common[3], maxCommonArr[3], maxCommonArr[3], 0); // Life Supprt + this.common[5] = filter(components.common[5], maxCommonArr[5], maxCommonArr[5], mass); // Sensors for (var h in components.hardpoints) { - this.hardpoints[h] = filter(components.hardpoints[h], maxHardPoint, 0, this.mass); + this.hardpoints[h] = filter(components.hardpoints[h], maxHardPoint, 0, mass); } for (var g in components.internal) { - this.internal[g] = filter(components.internal[g], maxInternal, 0, this.mass); + this.internal[g] = filter(components.internal[g], maxInternal, 0, mass); } } diff --git a/app/js/shipyard/factory-ship.js b/app/js/shipyard/factory-ship.js index fc8401f9..d3be8a14 100755 --- a/app/js/shipyard/factory-ship.js +++ b/app/js/shipyard/factory-ship.js @@ -40,7 +40,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', } } // Make a Ship 'slot'/item similar to other slots - this.c = { incCost: true, type: 'SHIP', discountedCost: this.cost, c: { name: this.name, cost: this.cost } }; + this.c = { incCost: true, type: 'SHIP', discountedCost: this.hullCost, c: { name: this.name, cost: this.hullCost } }; this.costList = _.union(this.internal, this.common, this.hardpoints); this.costList.push(this.bulkheads); // Add The bulkheads @@ -55,8 +55,8 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', this.powerList.unshift(this.common[2]); // Add FSD this.powerList.unshift(this.common[0]); // Add Power Plant - this.shipDiscount = 1; - this.componentDiscount = 1; + this.shipCostMultiplier = 1; + this.componentCostMultiplier = 1; this.priorityBands = [ { deployed: 0, retracted: 0, retOnly: 0 }, @@ -86,8 +86,8 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', this.armourAdded = 0; this.shieldMultiplier = 1; this.totalCost = this.c.incCost ? this.c.discountedCost : 0; - this.unladenMass = this.mass; - this.armourTotal = this.armour; + this.unladenMass = this.hullMass; + this.armour = this.baseArmour; this.totalDps = 0; this.bulkheads.c = null; @@ -157,7 +157,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', var oldBulkhead = this.bulkheads.c; this.bulkheads.id = index; this.bulkheads.c = Components.bulkheads(this.id, index); - this.bulkheads.discountedCost = this.bulkheads.c.cost * this.componentDiscount; + this.bulkheads.discountedCost = this.bulkheads.c.cost * this.componentCostMultiplier; this.updateStats(this.bulkheads, this.bulkheads.c, oldBulkhead, preventUpdate); }; @@ -186,7 +186,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', var oldComponent = slot.c; slot.id = id; slot.c = component; - slot.discountedCost = (component && component.cost) ? component.cost * this.componentDiscount : 0; + slot.discountedCost = (component && component.cost) ? component.cost * this.componentCostMultiplier : 0; this.updateStats(slot, component, oldComponent, preventUpdate); } }; @@ -313,7 +313,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', } if (slot.incCost && old.cost) { - this.totalCost -= old.cost * this.componentDiscount; + this.totalCost -= old.cost * this.componentCostMultiplier; } if (old.power && slot.enabled) { @@ -335,9 +335,6 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', case 'cr': this.cargoCapacity += n.capacity; break; - case 't': - this.maxMass = n.maxmass; - break; case 'hr': this.armourAdded += n.armouradd; break; @@ -347,7 +344,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', } if (slot.incCost && n.cost) { - this.totalCost += n.cost * this.componentDiscount; + this.totalCost += n.cost * this.componentCostMultiplier; } if (n.power && slot.enabled) { @@ -362,7 +359,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', } this.ladenMass = this.unladenMass + this.cargoCapacity + this.fuelCapacity; - this.armourTotal = this.armourAdded + this.armour; + this.armour = this.armourAdded + this.baseArmour; if (!preventUpdate) { if (powerChange) { @@ -390,7 +387,7 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', Ship.prototype.updateShieldStrength = function() { var sgSlot = this.findInternalByGroup('sg'); // Find Shield Generator slot Index if any - this.shieldStrength = sgSlot && sgSlot.enabled ? calcShieldStrength(this.mass, this.shields, sgSlot.c, this.shieldMultiplier) : 0; + this.shieldStrength = sgSlot && sgSlot.enabled ? calcShieldStrength(this.hullMass, this.baseShieldStrength, sgSlot.c, this.shieldMultiplier) : 0; }; /** @@ -408,24 +405,24 @@ angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', /** * Recalculate all item costs and total based on discounts. - * @param {number} shipDiscount Ship cost multiplier discount (e.g. 0.9 === 10% discount) - * @param {number} componentDiscount Component cost multiplier discount (e.g. 0.75 === 25% discount) + * @param {number} shipCostMultiplier Ship cost multiplier discount (e.g. 0.9 === 10% discount) + * @param {number} componentCostMultiplier Component cost multiplier discount (e.g. 0.75 === 25% discount) */ - Ship.prototype.applyDiscounts = function(shipDiscount, componentDiscount) { + Ship.prototype.applyDiscounts = function(shipCostMultiplier, componentCostMultiplier) { var total = 0; var costList = this.costList; for (var i = 0, l = costList.length; i < l; i++) { var item = costList[i]; if (item.c && item.c.cost) { - item.discountedCost = item.c.cost * (item.type == 'SHIP' ? shipDiscount : componentDiscount); + item.discountedCost = item.c.cost * (item.type == 'SHIP' ? shipCostMultiplier : componentCostMultiplier); if (item.incCost) { total += item.discountedCost; } } } - this.shipDiscount = shipDiscount; - this.componentDiscount = componentDiscount; + this.shipCostMultiplier = shipCostMultiplier; + this.componentCostMultiplier = componentCostMultiplier; this.totalCost = total; }; diff --git a/app/js/shipyard/module-shipyard.js b/app/js/shipyard/module-shipyard.js index 368e5f78..30585261 100755 --- a/app/js/shipyard/module-shipyard.js +++ b/app/js/shipyard/module-shipyard.js @@ -66,6 +66,11 @@ angular.module('shipyard', ['ngLodash']) sb: 'Shield Booster', tp: 'Torpedo Pylon' }) + .value('MountMap', { + 'F': 'Fixed', + 'G': 'Gimballed', + 'T': 'Turret' + }) .value('shipSize', [ 'N/A', 'Small', @@ -102,7 +107,7 @@ angular.module('shipyard', ['ngLodash']) }, { // 2 title: 'Armour', - props: ['armourTotal'], + props: ['armour'], unit: '', fmt: 'fCrd' }, diff --git a/app/js/shipyard/service-components.js b/app/js/shipyard/service-components.js index 05a8f202..de59dc2a 100755 --- a/app/js/shipyard/service-components.js +++ b/app/js/shipyard/service-components.js @@ -51,7 +51,7 @@ angular.module('shipyard').service('Components', ['lodash', 'ComponentsDB', 'Shi */ this.forShip = function(shipId) { var ship = Ships[shipId]; - return new ComponentSet(C, ship.properties.mass + 5, ship.slots.common, ship.slots.internal[0], ship.slots.hardpoints[0]); + return new ComponentSet(C, ship.minMassFilter || ship.properties.hullMass + 5, ship.slots.common, ship.slots.internal[0], ship.slots.hardpoints[0]); }; }]); diff --git a/app/schemas/ship-loadout/1-draft.json b/app/schemas/ship-loadout/1-draft.json new file mode 100644 index 00000000..c5dd2a00 --- /dev/null +++ b/app/schemas/ship-loadout/1-draft.json @@ -0,0 +1,287 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "id": "http://cdn.coriolis.io/schemas/ship-loadout/1-draft.json#", + "title": "Ship Loadout", + "type": "object", + "description": "The details for a specific ship build/loadout", + "required": ["name", "ship", "components"], + "properties": { + "name": { + "description": "The name of the build/loadout", + "type": "string", + "minLength": 2 + }, + "ship": { + "description": "The full display name of the ship", + "type": "string", + "minimum": 3 + }, + "manufacturer": { + "description": "The ship manufacturer", + "type": "string" + }, + "references" : { + "description": "3rd Party references and/or links to this build/loadout", + "type": "array", + "items": { + "type": "object", + "required": ["name","url"], + "properties": { + "name": { + "description": "The name of the 3rd party, .e.g 'Coriolis.io' or 'E:D Shipyard'", + "type": "string" + }, + "url": { + "description": "The link/url to the 3rd party referencing this build/loadout", + "type": "string" + }, + "shipId": { + "type": "string" + }, + "code": { + "description": "The serialized code or string for the build/loadout", + "type": "string" + } + } + } + }, + "components": { + "description": "The components used by this build", + "type": "object", + "additionalProperties": false, + "required": ["standard", "internal", "hardpoints", "utility"], + "properties": { + "standard": { + "description": "The set of standard components across all ships", + "type": "object", + "additionalProperties": false, + "required": ["bulkheads", "powerPlant", "thrusters", "frameShiftDrive", "lifeSupport", "powerDistributor", "sensors", "fuelTank"], + "properties": { + "bulkheads": { + "enum": ["Lightweight Alloy", "Reinforced Alloy", "Military Grade Composite", "Mirrored Surface Composite", "Reactive Surface Composite"] + }, + "powerPlant": { + "required": ["class", "rating"], + "properties": { + "class": { "type": "integer", "minimum": 2, "maximum": 8 }, + "rating": { "$ref": "#/definitions/standardRatings" } + } + }, + "thrusters": { + "required": ["class", "rating"], + "properties": { + "class": { "type": "integer", "minimum": 2, "maximum": 8 }, + "rating": { "$ref": "#/definitions/standardRatings" } + } + }, + "frameShiftDrive": { + "required": ["class", "rating"], + "properties": { + "class": { "type": "integer", "minimum": 2, "maximum": 8 }, + "rating": { "$ref": "#/definitions/standardRatings" } + } + }, + "lifeSupport": { + "required": ["class", "rating"], + "properties": { + "class": { "type": "integer", "minimum": 1, "maximum": 6 }, + "rating": { "$ref": "#/definitions/standardRatings" } + } + }, + "powerDistributor": { + "required": ["class", "rating"], + "properties": { + "class": { "type": "integer", "minimum": 1, "maximum": 8 }, + "rating": { "$ref": "#/definitions/standardRatings" } + } + }, + "sensors": { + "required": ["class", "rating"], + "properties": { + "class": { "type": "integer", "minimum": 1, "maximum": 8 }, + "rating": { "$ref": "#/definitions/standardRatings" } + } + }, + "fuelTank": { + "required": ["class", "rating"], + "properties": { + "class": { "type": "integer", "minimum": 1, "maximum": 6 }, + "rating": { "$ref": "#/definitions/standardRatings" } + } + } + } + }, + "internal": { + "type": "array", + "items": { + "type": ["object", "null"], + "required": ["class", "rating", "group"], + "properties" : { + "class": { "type": "integer", "minimum": 1, "maximum": 8 }, + "rating": { "$ref": "#/definitions/standardRatings" }, + "group": { + "description": "The group of the component, e.g. 'Shield Generator', or 'Cargo Rack'", + "type": "string" + }, + "name": { + "description": "The name identifying the component (if applicable), e.g. 'Advance Discovery Scanner', or 'Detailed Surface Scanner'", + "type": "string" + } + } + }, + "minItems": 3 + }, + "hardpoints": { + "type": "array", + "items": { + "type": ["object", "null"], + "required": ["class", "rating", "group", "mount"], + "properties" : { + "class": { "type": "integer", "minimum": 1, "maximum": 4 }, + "rating": { "$ref": "#/definitions/allRatings" }, + "mount": { "type": "string", "enum": ["Fixed", "Gimballed", "Turret"] }, + "group": { + "description": "The group of the component, e.g. 'Beam Laser', or 'Missile Rack'", + "type": "string" + }, + "name": { + "description": "The name identifing the component (if applicable), e.g. 'Retributor', or 'Mining Lance'", + "type": "string" + } + } + }, + "minItems": 1 + }, + "utility": { + "type": "array", + "items": { + "type": ["object", "null"], + "required": ["class", "rating", "group"], + "properties" : { + "class": { "type": "integer", "minimum": 0, "maximum": 0 }, + "rating": { "$ref": "#/definitions/allRatings" }, + "group": { + "description": "The group of the component, e.g. 'Shield Booster', or 'Kill Warrant Scanner'", + "type": "string" + }, + "name": { + "description": "The name identifing the component (if applicable), e.g. 'Point Defence', or 'Electronic Countermeasure'", + "type": "string" + } + } + }, + "minItems": 1 + } + } + }, + "stats": { + "description": "Optional statistics from the build", + "type": "object", + "additionalProperties": true, + "properties": { + "agility": { + "type": "integer", + "minimum": 0 + }, + "armour": { + "description": "Sum of base armour + any hull reinforcements", + "type": "integer", + "minimum": 1 + }, + "armourAdded":{ + "description": "Armour added through Hull reinforcement", + "type": "integer", + "minimum": 1 + }, + "baseShieldStrength": { + "type": "integer", + "minimum": 1 + }, + "baseArmour": { + "type": "integer", + "minimum": 1 + }, + "boost": { + "description": "Maximum boost speed of the ships (4 pips, straight-line)", + "type": "number", + "minimum": 1 + }, + "cargoCapacity": { + "type": "integer", + "minimum": 0 + }, + "class": { + "description": "Ship Class/Size [Small, Medium, Large]", + "enum": [1,2,3] + }, + "dps": { + "description": "Cumulative DPS based on the in-game 1-10 statistic", + "type": "integer", + "minimum": 0 + }, + "hullCost": { + "description": "Cost of the ship's hull", + "type": "integer", + "minimum": 1 + }, + "hullMass": { + "description": "Mass of the Ship hull only", + "type": "number", + "minimum": 1 + }, + "fuelCapacity": { + "type": "integer", + "minimum": 1 + }, + "fullTankRange": { + "description": "Single Jump range with a full tank (unladenMass + fuel)", + "type": "number", + "minimum": 0 + }, + "ladenMass": { + "description": "Mass of the Ship + fuel + cargo (hull + all components + fuel tank + cargo capacity)", + "type": "number", + "minimum": 1 + }, + "ladenRange": { + "description": "Single Jump range with full cargo load, see ladenMass", + "type": "number", + "minimum": 0 + }, + "masslock": { + "description": "Mass Lock Factor of the Ship", + "type": "integer", + "minimum": 1 + }, + "shieldStrength": { + "description": "Shield strengh in Mega Joules (Mj)", + "type": "number", + "minimum": 0 + }, + "speed": { + "description": "Maximum speed of the ships (4 pips, straight-line)", + "type": "number", + "minimum": 1 + }, + "totalCost": { + "type": "integer", + "minimum": 1 + }, + "unladenRange": { + "description": "Single Jump range when unladen, see unladenMass", + "type": "number", + "minimum": 0 + }, + "unladenMass": { + "description": "Mass of the Ship (hull + all components)", + "type": "number", + "minimum": 1 + } + } + } + }, + "definitions": { + "standardRatings": { "enum": ["A", "B", "C", "D", "E"] }, + "allRatings": { "enum": ["A", "B", "C", "D", "E", "F", "I" ] } + } +} \ No newline at end of file diff --git a/app/views/page-outfit.html b/app/views/page-outfit.html index 27b862e2..bea2cd15 100644 --- a/app/views/page-outfit.html +++ b/app/views/page-outfit.html @@ -19,6 +19,9 @@ + @@ -59,9 +62,9 @@ {{fRound(ship.speed)}} m/s {{fRound(ship.boost)}} m/s {{fRound(ship.totalDps)}} - {{ship.armourTotal}} ({{ship.armour}} + {{ship.armourAdded}}) + {{ship.armour}} ({{ship.baseArmour}} + {{ship.armourAdded}}) {{fRound(ship.shieldStrength)}} MJ ({{fRPct(ship.shieldMultiplier)}}) - {{ship.mass}} T + {{ship.hullMass}} T {{fRound(ship.unladenMass)}} T {{fRound(ship.ladenMass)}} T {{fRound(ship.cargoCapacity)}} T @@ -117,7 +120,7 @@
Optimal Mass: {{th.c.optmass}} T
Max Mass: {{th.c.maxmass}} T
-
+
diff --git a/data/ships/adder.json b/data/ships/adder.json index b2bb7094..b5644323 100755 --- a/data/ships/adder.json +++ b/data/ships/adder.json @@ -1,18 +1,16 @@ { "adder": { "properties": { - "grp": "ex", "name": "Adder", "manufacturer": "Zorgon Peterson", "class": 1, - "cost": 39993, + "hullCost": 39993, "speed": 220, "boost": 320, "agility": 8, - "shields": 60, - "armour": 162, - "fuelcost": 50, - "mass": 35, + "baseShieldStrength": 60, + "baseArmour": 162, + "hullMass": 35, "masslock": 7 }, "retailCost": 87808, diff --git a/data/ships/anaconda.json b/data/ships/anaconda.json index 30d3afb2..ab165938 100755 --- a/data/ships/anaconda.json +++ b/data/ships/anaconda.json @@ -1,18 +1,16 @@ { "anaconda": { "properties": { - "grp": "mp", "name": "Anaconda", "manufacturer": "Faulcon DeLacy", "class": 3, - "cost": 141889932, + "hullCost": 141889932, "speed": 180, "boost": 240, "agility": 2, - "shields": 350, - "armour": 945, - "fuelcost": 50, - "mass": 400, + "baseShieldStrength": 350, + "baseArmour": 945, + "hullMass": 400, "masslock": 23 }, "retailCost": 146969451, diff --git a/data/ships/asp.json b/data/ships/asp.json index 91ee4cb5..7d0dca34 100755 --- a/data/ships/asp.json +++ b/data/ships/asp.json @@ -1,18 +1,16 @@ { "asp": { "properties": { - "grp": "ex", "name": "Asp Explorer", "manufacturer": "Lakon", "class": 2, - "cost": 6135658, + "hullCost": 6135658, "speed": 250, "boost": 340, "agility": 6, - "shields": 140, - "armour": 378, - "fuelcost": 50, - "mass": 280, + "baseShieldStrength": 140, + "baseArmour": 378, + "hullMass": 280, "masslock": 11 }, "retailCost": 6661153, diff --git a/data/ships/cobra_mk_iii.json b/data/ships/cobra_mk_iii.json index 8b0734b8..aef584be 100755 --- a/data/ships/cobra_mk_iii.json +++ b/data/ships/cobra_mk_iii.json @@ -1,18 +1,16 @@ { "cobra_mk_iii": { "properties": { - "grp": "mp", "name": "Cobra Mk III", "manufacturer": "Faulcon DeLacy", "class": 1, - "cost": 235787, + "hullCost": 235787, "speed": 280, "boost": 400, "agility": 6, - "shields": 80, - "armour": 216, - "fuelcost": 50, - "mass": 180, + "baseShieldStrength": 80, + "baseArmour": 216, + "hullMass": 180, "masslock": 8 }, "retailCost": 379718, diff --git a/data/ships/diamondback.json b/data/ships/diamondback.json index 8090ca24..d012d9b9 100644 --- a/data/ships/diamondback.json +++ b/data/ships/diamondback.json @@ -1,21 +1,20 @@ { "diamondback": { "properties": { - "grp": "ex", "name": "Diamondback Scout", "manufacturer": "Lakon", "class": 1, - "cost": 461341, + "hullCost": 461341, "speed": 283, "boost": 384, "agility": 8, - "shields": 118, - "armour": 216, - "fuelcost": 50, - "mass": 170, + "baseShieldStrength": 118, + "baseArmour": 216, + "hullMass": 170, "masslock": 8 }, "retailCost": 564329, + "minMassFilter": 180.5, "slots": { "common": [ 4, diff --git a/data/ships/diamondback_explorer.json b/data/ships/diamondback_explorer.json index 0ccd4277..84f3254b 100644 --- a/data/ships/diamondback_explorer.json +++ b/data/ships/diamondback_explorer.json @@ -1,18 +1,16 @@ { "diamondback_explorer": { "properties": { - "grp": "ex", "name": "Diamondback Explorer", "manufacturer": "Lakon", "class": 1, - "cost": 1635691, + "hullCost": 1635691, "speed": 242, "boost": 316, "agility": 5, - "shields": 146, - "armour": 270, - "fuelcost": 50, - "mass": 298, + "baseShieldStrength": 146, + "baseArmour": 270, + "hullMass": 298, "masslock": 7 }, "retailCost": 1894760, diff --git a/data/ships/eagle.json b/data/ships/eagle.json index 85483ab3..89074741 100755 --- a/data/ships/eagle.json +++ b/data/ships/eagle.json @@ -1,18 +1,16 @@ { "eagle": { "properties": { - "grp": "co", "name": "Eagle", "manufacturer": "Core Dynamics", "class": 1, - "cost": 10446, + "hullCost": 10446, "speed": 240, "boost": 350, "agility": 10, - "shields": 60, - "armour": 72, - "fuelcost": 50, - "mass": 50, + "baseShieldStrength": 60, + "baseArmour": 72, + "hullMass": 50, "masslock": 6 }, "retailCost": 44800, diff --git a/data/ships/federal_dropship.json b/data/ships/federal_dropship.json index 48d85ff7..85e4b239 100755 --- a/data/ships/federal_dropship.json +++ b/data/ships/federal_dropship.json @@ -1,18 +1,16 @@ { "federal_dropship": { "properties": { - "grp": "mp", "name": "Federal Dropship", "manufacturer": "Core Dynamics", "class": 2, - "cost": 18969990, + "hullCost": 18969990, "speed": 180, "boost": 300, "agility": 2, - "shields": 200, - "armour": 540, - "fuelcost": 50, - "mass": 580, + "baseShieldStrength": 200, + "baseArmour": 540, + "hullMass": 580, "masslock": 14 }, "retailCost": 19814205, diff --git a/data/ships/fer_de_lance.json b/data/ships/fer_de_lance.json index 7d150f70..3b49683b 100755 --- a/data/ships/fer_de_lance.json +++ b/data/ships/fer_de_lance.json @@ -1,18 +1,16 @@ { "fer_de_lance": { "properties": { - "grp": "co", "name": "Fer-de-Lance", "manufacturer": "Zorgon Peterson", "class": 2, - "cost": 51232230, + "hullCost": 51232230, "speed": 260, "boost": 350, "agility": 6, - "shields": 300, - "armour": 405, - "fuelcost": 50, - "mass": 250, + "baseShieldStrength": 300, + "baseArmour": 405, + "hullMass": 250, "masslock": 12 }, "retailCost": 51567040, diff --git a/data/ships/hauler.json b/data/ships/hauler.json index a67a7436..1b506f41 100755 --- a/data/ships/hauler.json +++ b/data/ships/hauler.json @@ -1,18 +1,16 @@ { "hauler": { "properties": { - "grp": "fr", "name": "Hauler", "manufacturer": "Zorgon Peterson", "class": 1, - "cost": 29807, + "hullCost": 29807, "speed": 200, "boost": 300, "agility": 6, - "shields": 50, - "armour": 90, - "fuelcost": 50, - "mass": 14, + "baseShieldStrength": 50, + "baseArmour": 90, + "hullMass": 14, "masslock": 6 }, "retailCost": 52720, diff --git a/data/ships/imperial_clipper.json b/data/ships/imperial_clipper.json index 9460be30..7a8a6f70 100755 --- a/data/ships/imperial_clipper.json +++ b/data/ships/imperial_clipper.json @@ -1,18 +1,16 @@ { "imperial_clipper": { "properties": { - "grp": "mp", "name": "Imperial Clipper", "manufacturer": "Gutamaya", "class": 3, - "cost": 21077784, + "hullCost": 21077784, "speed": 300, "boost": 380, "agility": 2, - "shields": 180, - "armour": 486, - "fuelcost": 50, - "mass": 400, + "baseShieldStrength": 180, + "baseArmour": 486, + "hullMass": 400, "masslock": 12 }, "retailCost": 22296860, diff --git a/data/ships/imperial_courier.json b/data/ships/imperial_courier.json index ae365ab3..0c77ed38 100644 --- a/data/ships/imperial_courier.json +++ b/data/ships/imperial_courier.json @@ -1,18 +1,16 @@ { "imperial_courier": { "properties": { - "grp": "mp", "name": "Imperial Courier", "manufacturer": "Gutamaya", "class": 1, - "cost": 2481552, + "hullCost": 2481552, "speed": 277, "boost": 380, "agility": 6, - "shields": 197, - "armour": 144, - "fuelcost": 50, - "mass": 35, + "baseShieldStrength": 197, + "baseArmour": 144, + "hullMass": 35, "masslock": 7 }, "retailCost": 2542931, diff --git a/data/ships/orca.json b/data/ships/orca.json index ebc06fd5..8297e868 100755 --- a/data/ships/orca.json +++ b/data/ships/orca.json @@ -1,18 +1,16 @@ { "orca": { "properties": { - "grp": "pa", "name": "Orca", "manufacturer": "Saud Kruger", "class": 3, - "cost": 47798079, + "hullCost": 47798079, "speed": 300, "boost": 380, "agility": 2, - "shields": 220, - "armour": 396, - "fuelcost": 50, - "mass": 580, + "baseShieldStrength": 220, + "baseArmour": 396, + "hullMass": 580, "masslock": 13 }, "retailCost": 48539887, diff --git a/data/ships/python.json b/data/ships/python.json index 9e386881..0deae2f0 100755 --- a/data/ships/python.json +++ b/data/ships/python.json @@ -1,18 +1,16 @@ { "python": { "properties": { - "grp": "mp", "name": "Python", "manufacturer": "Faulcon DeLacy", "class": 2, - "cost": 55171395, + "hullCost": 55171395, "speed": 230, "boost": 280, "agility": 6, - "shields": 260, - "armour": 468, - "fuelcost": 50, - "mass": 350, + "baseShieldStrength": 260, + "baseArmour": 468, + "hullMass": 350, "masslock": 17 }, "retailCost": 56978179, diff --git a/data/ships/sidewinder.json b/data/ships/sidewinder.json index 6afd883d..3dd2edf9 100755 --- a/data/ships/sidewinder.json +++ b/data/ships/sidewinder.json @@ -1,18 +1,16 @@ { "sidewinder": { "properties": { - "grp": "mp", "name": "Sidewinder", "manufacturer": "Faulcon DeLacy", "class": 1, - "cost": 12887, + "hullCost": 12887, "speed": 220, "boost": 320, "agility": 8, - "shields": 40, - "armour": 108, - "fuelcost": 50, - "mass": 25, + "baseShieldStrength": 40, + "baseArmour": 108, + "hullMass": 25, "masslock": 6 }, "retailCost": 32000, diff --git a/data/ships/type_6_transporter.json b/data/ships/type_6_transporter.json index ad767f6f..3e14b986 100755 --- a/data/ships/type_6_transporter.json +++ b/data/ships/type_6_transporter.json @@ -1,18 +1,16 @@ { "type_6_transporter": { "properties": { - "grp": "fr", "name": "Type-6 Transporter", "manufacturer": "Lakon", "class": 2, - "cost": 865782, + "hullCost": 865782, "speed": 220, "boost": 350, "agility": 3, - "shields": 90, - "armour": 162, - "fuelcost": 50, - "mass": 155, + "baseShieldStrength": 90, + "baseArmour": 162, + "hullMass": 155, "masslock": 8 }, "retailCost": 1045945, diff --git a/data/ships/type_7_transport.json b/data/ships/type_7_transport.json index 0f124623..c1592522 100755 --- a/data/ships/type_7_transport.json +++ b/data/ships/type_7_transport.json @@ -1,18 +1,16 @@ { "type_7_transport": { "properties": { - "grp": "fr", "name": "Type-7 Transporter", "manufacturer": "Lakon", "class": 3, - "cost": 16881511, + "hullCost": 16881511, "speed": 180, "boost": 300, "agility": 2, - "shields": 120, - "armour": 216, - "fuelcost": 50, - "mass": 420, + "baseShieldStrength": 120, + "baseArmour": 216, + "hullMass": 420, "masslock": 10 }, "retailCost": 17472252, diff --git a/data/ships/type_9_heavy.json b/data/ships/type_9_heavy.json index a9f8f18b..818b2310 100755 --- a/data/ships/type_9_heavy.json +++ b/data/ships/type_9_heavy.json @@ -1,18 +1,16 @@ { "type_9_heavy": { "properties": { - "grp": "fr", "name": "Type-9 Heavy", "manufacturer": "Lakon", "class": 3, - "cost": 73255168, + "hullCost": 73255168, "speed": 130, "boost": 200, "agility": 0, - "shields": 240, - "armour": 432, - "fuelcost": 50, - "mass": 1000, + "baseShieldStrength": 240, + "baseArmour": 432, + "hullMass": 1000, "masslock": 16 }, "retailCost": 76555842, diff --git a/data/ships/viper.json b/data/ships/viper.json index 381553fe..f5689f22 100755 --- a/data/ships/viper.json +++ b/data/ships/viper.json @@ -1,18 +1,16 @@ { "viper": { "properties": { - "grp": "co", "name": "Viper", "manufacturer": "Faulcon DeLacy", "class": 1, - "cost": 95893, + "hullCost": 95893, "speed": 320, "boost": 400, "agility": 6, - "shields": 105, - "armour": 126, - "fuelcost": 50, - "mass": 60, + "baseShieldStrength": 105, + "baseArmour": 126, + "hullMass": 60, "masslock": 7 }, "retailCost": 142931, diff --git a/data/ships/vulture.json b/data/ships/vulture.json index 6f9b607a..57f05e3b 100755 --- a/data/ships/vulture.json +++ b/data/ships/vulture.json @@ -1,18 +1,16 @@ { "vulture": { "properties": { - "grp": "co", "name": "Vulture", "manufacturer": "Core Dynamics", "class": 1, - "cost": 4689629, + "hullCost": 4689629, "speed": 210, "boost": 340, "agility": 9, - "shields": 240, - "armour": 288, - "fuelcost": 50, - "mass": 230, + "baseShieldStrength": 240, + "baseArmour": 288, + "hullMass": 230, "masslock": 10 }, "retailCost": 4925615, diff --git a/gulpfile.js b/gulpfile.js index 58f5bb9a..daa795c5 100755 --- a/gulpfile.js +++ b/gulpfile.js @@ -60,7 +60,7 @@ gulp.task('js-lint', function() { }); gulp.task('json-lint', function() { - return gulp.src('data/**/*.json') + return gulp.src(['data/**/*.json' , 'app/schemas/**/*.json']) .pipe(jsonlint()) .pipe(jsonlint.reporter()) .pipe(jsonlint.failAfterError()); @@ -126,7 +126,7 @@ gulp.task('js', function() { }); gulp.task('copy', function() { - return gulp.src(['app/images/**','app/fonts/**','app/db.json'], {base: 'app/'}) + return gulp.src(['app/images/**','app/fonts/**','app/db.json', 'app/schemas/**'], {base: 'app/'}) .pipe(gulp.dest('build')); }); @@ -192,7 +192,7 @@ gulp.task('serve-stop', function(cb) { gulp.task('watch', function() { gulp.watch(['app/index.html','app/icons/*.svg'], ['generateIndexHTML']); - gulp.watch(['app/images/**','app/fonts/**', 'app/db.json'], ['copy']); + gulp.watch(['app/images/**','app/fonts/**', 'app/db.json', 'app/schemas/**'], ['copy']); gulp.watch('app/less/*.less', ['less']); gulp.watch('app/views/**/*', ['html2js']); gulp.watch('app/js/**/*.js', ['js']); diff --git a/package.json b/package.json index b80d9613..b3d5782e 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,6 @@ }, "private": true, "engine": "node >= 0.12.2", - "dependencies": {}, "devDependencies": { "angular-mocks": "1.3.x", "async": "0.9.x", @@ -30,9 +29,12 @@ "gulp-uglify": "1.2.x", "gulp-util": "3.0.x", "jasmine-core": "2.3.x", + "jsen": "^0.6.0", "json-concat": "0.0.x", "karma": "0.12.x", + "karma-fixture": "^0.2.5", "karma-jasmine": "0.3.x", + "karma-json-fixtures-preprocessor": "0.0.4", "karma-mocha-reporter": "1.0.x", "karma-phantomjs-launcher": "0.2.x", "main-bower-files": "2.8.x", diff --git a/test/karma.conf.js b/test/karma.conf.js index c1db9aee..df35c777 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -1,23 +1,25 @@ -// 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 + frameworks: ['jasmine', 'fixture'], + preprocessors: { + '../build/schemas/**/*.json': ['json_fixtures'] + }, files: [ '../build/lib*.js', '../node_modules/angular-mocks/angular-mocks.js', + '../node_modules/jsen/dist/jsen.js', '../build/app*.js', - 'tests/**/*.js' + '../build/schemas/**/*.json', + 'tests/**/*.js', ], + jsonFixturesPreprocessor: { + stripPrefix: '.*build', + variableName: '__json__' + }, reporters: ['mocha'], 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: ['PhantomJS'], diff --git a/test/tests/test-data.js b/test/tests/test-data.js index 3523e70f..c5305345 100644 --- a/test/tests/test-data.js +++ b/test/tests/test-data.js @@ -1,8 +1,8 @@ -describe("Database", function() { +describe('Database', function() { - var shipProperties = ["grp", "name", "manufacturer", "class", "cost", "speed", "boost", "agility", "shields", "armour", "fuelcost", "mass"]; + var shipProperties = ['name', 'manufacturer', 'class', 'hullCost', 'speed', 'boost', 'agility', 'baseShieldStrength', 'baseArmour', 'hullMass', 'masslock']; - it("has ships and components", function() { + it('has ships and components', function() { expect(DB.ships).toBeDefined() expect(DB.components.common).toBeDefined(); expect(DB.components.hardpoints).toBeDefined(); @@ -10,7 +10,7 @@ describe("Database", function() { expect(DB.components.bulkheads).toBeDefined(); }); - it("has unique IDs for every hardpoint", function() { + it('has unique IDs for every hardpoint', function() { var ids = {}; var groups = DB.components.hardpoints; @@ -25,7 +25,7 @@ describe("Database", function() { } }); - it("has valid internal components", function() { + it('has valid internal components', function() { var ids = {}; var groups = DB.components.internal; @@ -40,7 +40,7 @@ describe("Database", function() { } }); - it("has data for every ship", function() { + 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); @@ -49,12 +49,12 @@ describe("Database", function() { 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.ships[s].retailCost).toBeGreaterThan(DB.ships[s].properties.hullCost, s + ' has invalid retail cost'); expect(DB.components.bulkheads[s]).toBeDefined(s + ' is missing bulkheads'); } }); - it("has components with a group defined", function() { + 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) { diff --git a/test/tests/test-factory-ship.js b/test/tests/test-factory-ship.js index 708c589f..fa3200d3 100644 --- a/test/tests/test-factory-ship.js +++ b/test/tests/test-factory-ship.js @@ -29,7 +29,7 @@ describe("Ship Factory", function() { 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'); + expect(ship.armour).toBeGreaterThan(0, s + ' armour'); } }); @@ -74,7 +74,7 @@ describe("Ship Factory", function() { var testShip = new Ship(id, cobra.properties, cobra.slots); testShip.buildWith(cobra.defaults); - var originalHullCost = testShip.cost; + var originalHullCost = testShip.hullCost; var originalTotalCost = testShip.totalCost; var discount = 0.9; diff --git a/test/tests/test-service-serializer.js b/test/tests/test-service-serializer.js new file mode 100644 index 00000000..c4a9ee36 --- /dev/null +++ b/test/tests/test-service-serializer.js @@ -0,0 +1,41 @@ +describe("Serializer Service", function() { + beforeEach(module('app')); + + var Ship, Serializer; + + beforeEach(inject(function (_Ship_, _Serializer_) { + Ship = _Ship_; + Serializer = _Serializer_; + })); + + describe("Detailed Export", function() { + var code = '48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4yo5dig=.MwBhEYy6duwEziA', + url = 'http://a.test.url.com', + anaconda = DB.ships['anaconda'], + testBuild, + exportData; + + beforeEach(function() { + testBuild = new Ship('anaconda', anaconda.properties, anaconda.slots); + Serializer.toShip(testBuild, code); + exportData = Serializer.toJsonBuild('Test Build', testBuild, url, code); + }); + + it("conforms to the ship-loadout schema", function() { + var shipLoadoutSchema = __json__['/schemas/ship-loadout/1-draft']; + var validate = jsen(shipLoadoutSchema); + var valid = validate(exportData); + expect(valid).toBeTruthy(); + }); + + xit("contains the correct components", function() { + // TODO: implement + }); + + xit("contains the correct stats", function() { + // TODO: implement + }); + + }); + +});