• Welcome to the new COTI server. We've moved the Citizens to a new server. Please let us know in the COTI Website issue forum if you find any problems.

Starship Data Formats

robject

SOC-14 10K
Admin Award
Marquis
Structure
First off, a starship record has two main parts, a header and a component list. The header has roll-up summary information about the ship. Most of them are:

  • hull volume
  • hull config
  • overall TL
  • tons free
  • name
  • mission
  • disposition
  • owner's name
  • architect's name
  • builder's name
  • keel laid down date
  • first flight date
  • total cost
  • total crew
  • total passengers
  • high passengers
  • medium passengers
  • low passengers
  • the number of troop squads
  • the jump fuel percentage per parsec
  • the power plant fuel percentage per month
  • the number of crew shifts
  • control stations for: pilots, astrogators, engineers, stewards, gunners, medics, etc.


Each component contains at least the following data:
  • a short label
  • a descriptive notes field
  • a cost
  • a volume
  • a 'type' (a grouping type, i.e. 'Weapons')

A component may also contain:
  • an efficiency rating
  • a control rating
  • a 'category' (a potentially unique string for searches, i.e. 'bridge')
  • various quality ratings
  • TL
  • a base TL (if the actual is altered)
  • a task modifier
  • a target number for use in tasks
  • a mount type and range, for defenses and sensors
  • the "original record" in case the component has been modified


Formats
I permit loading and saving ships in three formats: XML, JSON, and YAML.

Since the header is essentially a hashmap, I use attributes heavily for XML. As a result, the XML header looks more or less like a wrapped JSON element:

XML said:
<header numShifts="1" gunner="1" jumpFuelPercentage="0.11111111111111112" totalMcr="14" format="1.0" troop="0" totalCrew="5" tons="200" medic="0" disposition="In Service" tonsFree="0.5" totalMCr="48" passengers="10" config="S" steward="1" builder="Clan Severn" shifts="1" tl="11" pilot="1" staff="0" owner="A. L. Jamison" low="10" mult="1" crew="5" sensop="0" astrogator="1" powerFuelPercentage="0.011111111111111112" medium="2" mission="A" jf="1" shipname="Beowulf" pf="1" qsp="acs-A-211-Beowulf" high="8" demand="-1" crewComfort="-2" troops="0" driver="0" crewLocked="yes" engineer="1" spaciousness="2" freightmaster="0" ></header>

...while components look like this:
XML said:
<components name="bridge" mcr="0" type="Ops" eff="1" tons="10" label="Spacious Bridge" category="bridge" ></components>


Compare the above with the JSON snippets:

JSON said:
"header":{"numShifts":1,"gunner":1,"jumpFuelPercentage":0.11111111111111112,"totalMcr":14,"format":"1.0","troop":0,"totalCrew":5,"tons":200,"medic":0,"disposition":"In Service","tonsFree":0.5,"totalMCr":48,"name":"","passengers":10,"config":"S","steward":1,"url":"","builder":"Clan Severn","shifts":1,"tl":11,"pilot":1,"staff":0,"owner":"A. L. Jamison","low":10,"mult":1,"keel":"","flight":"","architect":"","crew":5,"sensop":0,"astrogator":1,"powerFuelPercentage":0.011111111111111112,"medium":2,"mission":"A","jf":1,"id":"","shipname":"Beowulf","pf":1,"qsp":"acs-A-211-Beowulf","high":8,"demand":-1,"crewComfort":-2,"troops":0,"driver":0,"crewLocked":"yes","engineer":1,"spaciousness":2,"freightmaster":0}

and

JSON said:
{"name":"bridge","mcr":0,"notes":"","type":"Ops","eff":1,"tons":10,"label":"Spacious Bridge","category":"bridge"}


Finally, the YAML. No surprises here either.

Code:
header: 
   numShifts: 1
   gunner: 1
   jumpFuelPercentage: 0.11111111111111112
   totalMcr: 14
   format: '1.0'
   totalCrew: 5
   tons: 200
   medic: 0
   disposition: 'In Service'
   tonsFree: 0.5
   totalMCr: 48
   passengers: 10
   config: 'S'
   steward: 1
   builder: 'Clan Severn'
   shifts: 1
   tl: 11
   pilot: 1
   staff: 0
   owner: 'A. L. Jamison'
   low: 10
   mult: 1
   keel: ''
   flight: ''
   architect: ''
   crew: 5
   sensop: 0
   astrogator: 1
   powerFuelPercentage: 0.011111111111111112
   medium: 2
   mission: 'A'
   id: ''
   shipname: 'Beowulf'
   qsp: 'acs-A-211-Beowulf'
   high: 8
   demand: -1
   crewComfort: -2
   troops: 0
   driver: 0
   crewLocked: 'yes'
   engineer: 1
   spaciousness: 2
   freightmaster: 0

and

Code:
   - 
      name: 'bridge'
      mcr: 0
      notes: ''
      type: 'Ops'
      eff: 1
      tons: 10
      label: 'Spacious Bridge'
      category: 'bridge'
 

NEW STRUCTURE


The 'new' structure is a shorthand form of the current structure. The idea is that most of the data is known, and therefore can be represented in a more compact way, though without resorting to binary files.

This new structure is more nearly just text, and therefore does not need a YAML or JSON parser.

Each Component is a single line matching one of the following formats:

<TYPE>: <STRING>
<TYPE>: <TONS> [<STAGE>] [<MOUNT>] <CODE>[-<TL>] [Label or Name]
<TYPE>: (<COUNT>) <TONS> [<STAGE>] [<MOUNT>] <CODE>[-<TL>] [Label or Name]

...where 'Type' is one of Armor, Drive, Sensor, Weapon, Defense, Ops, Vehicle, and so on.


Example. Here's the tentative file contents for the 200t Droyne Miymosa-class trader:

Code:
---
- format: ACS1.0
- qsp: A-BL11-13
- name: Miymosa
- armor: 0t Kinetic Shell
- bridge: Spacious
- bridge: 1t CC
- bridge: (3) 1t OC
- ops: 2t Std Landing Legs with Pads
- ops: 1t Std Life Support Adaptable
- ops: 1t Std Life Support Luxury
- ops: 2t Std Life Support Long Term
- ops: 1t Std Computer Model/1
- powerFuel: 2t
- jumpFuel: 20t
- drive: 4t Std PowerPlant A
- drive: 10t Std Jump A
- drive: 2t Std Maneuver A
- drive: 2t Std SP
- drive: 2t Std BP
- drive: 2t Std NP
- weapon: (2) 1t Std AR T1 M-13
- weapon: 1t Std Magazine
- passenger: (6) 4t Std Passenger Lounge
- passenger: (8) 2t Std Stateroom
- passenger: (2) 0.5t Std Shared Fresher
- crew: 1t Std Common Fresher
- crew: 0.5 Std Shared Fresher
- crew: (4) 3t Triple Stateroom
- payload: (2) 44t Std Cargo Hold


CURRENT STRUCTURE


I use YAML as the primary or preferred storage format, but the structure has no shared referenced data, so JSON works as well.

The current structure's root is a hashtable. My software only looks for two elements in this hash table:

'components'

and

'header'

Commentary. One might be tempted to say that that's a ridiculous use of a hashtable. It sort of is. There is some flexibility at least: other elements can be in this hashtable, and my program won't die because of it.


HEADER
'header' is a hashtable with roll-up and common data:

'format' - currently 'T5-ACS-1'
'tl'
'shipname'
'tons'
'qsp'
'config' - e.g. 'S' for streamlined, and so on.
'mission' - mission code, a one or two letter code
'comments'
'staff'
'totalCargoSpace'
'passengers'
'low'
'demand'
'tonsFree'
'undertons' - an alias for 'tonsFree'
'overtons'
'jumpFuelPercentage'
'shifts'
'powerFuelPercentage'
'jf' - number of parsecs' jump fuel
'pf' - number of months of powerplant fuel
'controlConsoles'
'operatingConsoles'
'workstations'
'spaciousness'
'crew'
'totalMCr'
'crewComfort'
'troops'


COMPONENT
'components' is an array of every component in the starship.

Each Array Element

Each array element is a hashtable, with mandatory data, and optional data. Again, a hashtable was chosen for flexibility. Some components have more mandatory data than others, but all of them require this as a minimum:

'tl'
'tons'
'category'
'type'
'label'
'tons'
'sq'
'mcr'
'code' - this is mandatory for the hull, weapons, defenses, drives.
'rating' - this is mandatory for drives.
'mount' - this is mandatory for sensors, weapons, defenses.

Several of these, such as code, mount, category and type, have a valid range of values.

Optional elements include QREBS ('q', 'r', 'e', 'b', 's'), efficiency ('eff'), notes, and stage.

Calculated elements include:

'howMany'
'totalTons'
'totalMCr'

Totals are calculated and stored when the "howMany" count changes in the program.
 
Last edited:
I'll add my 2Cr in and explain the structure I have used. Not to suggest its better, it is still just a flat array of data.

My goals include;

  1. making a CT ship designer as an independent module, Software as a Service to use an industry phrase. Other software I create, can then build on an accessible and reliable ship builder with a stable API.
  2. the export data format needs to be short/minimal and focus on ship design only. Details relating to ship ownership, construction, current location, etc., are left to other apps. Calculations from this minimal set of data can be serviced by the ship designer app, which helps keep the export data minimal. (Note the lack of crew details in the example below. Retrieving the crew count or jump drive tonnage for this design is simply a http request)
I chose JSON because of its wide acceptance. Of the other main contenders, IMHO XML is overkill for this type of project and while YAML brings the significant benefit of being easily human readable, I don't expect users to read the data file. JSON can easily be parsed into XML or YAML, but I will leave that to others.

Below is an example of the Free Trader class. While this is from my download file, I have edited it to better conform with where I am headed (by removing data with values of; empty string; false or int 0, plus two elements that appear superfluous). My TODO list is long and other features are taking priority.

For non-coders, the data is a list of key:value pairs. For example "date" is a key understood by the app, "1100-55" is the value associated with that key. The way the data is arranged is JSON. XML offers richer information for each "key", while YAML arranges the data vertically (line breaks instead of commas) and uses indentation (instead of curly braces).

{"date":"1100-55", "empire":"Ubiquitous", "techLevel":7, "shipName":"Free Trader (type A)", "shipSize":"200", "civilianDesign":true, "primaryType":"Merchant-A", "secondaryType":"Provincial", "hullStandard":"200tn hull", "configuration":"streamlined", "bridge":"Bridge", "computer":"model 1", "driveJump":"A drive, usp 1", "driveManeouver":"A drive, usp 1", "powerPlant":"A drive, usp 1", "fuelScoops":true, "sandCaster":"sand caster x1", "laser":"pulse laser x1", "xsandCaster":1, "xlaser":1, "fuelJump":"1", "fuelPower":"4", "cargo":"82", "payload_1":"Turret fire control", "xpayload_1":1, "payload_2":"Hardpoint", "xpayload_2":1, "passengersHigh":6, "passengersLow":20, "created_at":"2015-02-20T16:05:02.171Z", "updated_at":"2015-02-20T16:05:02.171Z"}

Just in tidying this up I have seen more opportunities for improvement. Clearly my API is far from stable yet :)
 
Last edited:
Matt, that's pretty much where I'm headed. JSON is an excellent choice due to its ubiquity.

I'm heading towards a tiny subset of YAML, but it's not really different from JSON.

I do prefer one component per line, because (1a) it speeds up debugging, (1b) it's easier for me to read other people's designs at a glance, since it closely approximates a printed ship "design sheet", and (2) it makes it even simpler for programs to parse -- they don't even need library support.

Regarding your keys: I worry, perhaps needlessly, over repeated components, and especially components which are ALMOST but not quite the same. This is a T5 phenomenon, not a CT one.
 
NOTE: I might be wrong.

For example, when there are eight turrets, we might group them by exact type ("triple turret L-L-M") and note the quantity. You could uniquely define them by crafting a unique key for each, but then you've multiplied your keys, and that can get out of hand. Could get out of hand. In CT, maybe you could define them solely by battery factor; while this minimizes the keys, it creates backend work as you translate from factors to number of guns and back.

Currently, I use a hashmap for the rollup data, and a list for the components.

But the list is never really very long for a computer (suppose you had a separate entry for every battery in a Tigress -- which you wouldn't do, but still -- you get what, maybe a thousand items? Big shmeal for a computer), so I'm moving towards just having a list, and letting the program roll things up on the fly (it has to anyway).

Your data looks prettier to me this way:

Code:
{
  'civilianDesign': 'true',
  'empire': 'Ubiquitous',
  'cargo': '82',
  'shipSize': '200',
  'xlaser': 1,
  'secondaryType': 'Provincial',
  'date': '1100-55',
  'passengersLow': 20,
  'xsandCaster': 1,
  'fuelJump': '1',
  'driveManeouver': 'A drive, usp 1',
  'driveJump': 'A drive, usp 1',
  'created_at': '2015-02-20T16:05:02.171Z',
  'fuelScoops': 'true',
  'fuelPower': '4',
  'powerPlant': 'A drive, usp 1',
  'configuration': 'streamlined',
  'payload_2': 'Hardpoint',
  'sandCaster': 'sand caster x1',
  'xpayload_2': 1,
  'techLevel': 7,
  'primaryType': 'Merchant-A',
  'bridge': 'Bridge',
  'xpayload_1': 1,
  'payload_1': 'Turret fire control',
  'passengersHigh': 6,
  'shipName': 'Free Trader (type A)',
  'updated_at': '2015-02-20T16:05:02.171Z',
  'laser': 'pulse laser x1',
  'computer': 'model 1',
  'hullStandard': '200tn hull'
}
 
NOTE: I might be wrong.
All good, so might I :). I think my confusion is from not really examining the T5 system, I haven't had time to do more than lightly skim it when it first turned up.

The way you describe defining the CT system by batteries, is the approach I have taken. It may not be apparent from the JSON file, given its only a Free Trader but the text for Sandcasters "sandcaster x1" is only a token representing a battery (with one sandcaster). The backend, as you suggest, does the heavy lifting.

Your data looks prettier to me this way:
I can't argue with that!

On the subject of export stuff, the text description I provide is based on the original CT version. HGS does an alternative human readable text format which is quite good, have you seen any improvement on that?
 
Back
Top