# EVEShip.fit's Dogma Engine
[](https://crates.io/crates/esf-dogma-engine)
[](https://www.npmjs.com/package/@eveshipfit/dogma-engine)
[](https://github.com/EVEShipFit/dogma-engine/actions/workflows/testing.yml)
[](https://docs.rs/esf-dogma-engine)
[](https://discord.gg/S5V5BkvNf7)
This library calculates accurately statistics of an EVE Online ship fit.
The input are several data-files provided by EVE Online, together with a ship fit.
The output are all the Dogma attributes of the ship, its items and the character.
## Implementation
This Dogma engine implements a multi-pass approach.
- [pass 1](./crates/esf-dogma-engine/src/calculate/pass_1.rs): collect all the Dogma attributes of the hull and modules.
- [pass 2](./crates/esf-dogma-engine/src/calculate/pass_2.rs): collect all the Dogma effects of the hull and modules.
- [pass 3](./crates/esf-dogma-engine/src/calculate/pass_3.rs): apply all the Dogma effects to the hull/modules, calculating the actual Dogma attribute values.
- [pass 4](./crates/esf-dogma-engine/src/calculate/pass_4.rs): augment the Dogma attributes with EVEShip.fit specific attributes, that are too complex for the Dogma itself to handle.
## Input and output
`calculate` takes a fit and options, and returns a calculation.
All identifiers are those from the SDE.
### Fit
- `name` (optional): name of the fit.
- `ship`: the ship being fitted.
- `type_id`: its type.
- `items`: everything fitted or carried. Each item has:
- `type_id`: its type.
- `slot`: where the item is.
- `type`: `high`, `medium`, `low`, `rig`, `subsystem`, `service`, `drone_bay` or `cargo`.
_`cargo` is carried, but not calculated._
- `index`: position within that slot type, starting at 0. Absent for `drone_bay` and `cargo`.
- `quantity` (optional, default 1): stack size for drones and cargo.
- `state`: requested state; `offline`, `online`, `active` or `overload`.
- `charge` (optional): the loaded charge, as `type_id`.
- `character` (optional):
- `skills`: level (0 to 5) per skill type ID. A missing skill gives no bonuses.
### Options
- `sources` (optional, default false): report per attribute what its value was calculated from.
Leave it off unless you show it; it makes the calculation several times bigger.
### Calculation
- `ship`: result for the ship.
- `items`: one result per item of the fit, in the same order.
- `character`: result for the character.
Each result has:
- `attributes`: per attribute ID, its `base` value before effects and its final `value`.
With the `sources` option, also `sources`: every modifier on it, in the order they were applied. Each has:
- `from`: where it comes from; `type` is `ship`, `character`, `item` or `charge` (with the `index` into `items`), or `skill` (with its `type_id`).
- `effect_id`: the effect that modifies.
- `source_attribute_id`: the attribute on the source that holds `value`.
- `operator`: `pre_assign`, `pre_mul`, `pre_div`, `mod_add`, `mod_sub`, `post_mul`, `post_div`, `post_percent` or `post_assign`.
- `value`: the value of the modifying attribute.
- `quantity`: how many times it counts. A stacking penalised stack is listed once per item instead.
- `penalty`: the stacking penalty factor it got, or `null` if not penalised.
- `applied`: false when the source's state is too low for the effect.
How much each source added is not reported: multiplications compound and stacking penalties depend on order, so there is no single answer.
- `state`: the state the item reached, which can be lower than requested.
- `max_state`: the highest state the item can reach.
- `charge`: result for its charge, if it has one.
### Things to know
- A stack, like five drones, has the attributes of a single item; its bonuses count once per item in the stack.
## EVEShip.fit's specific attributes
`Pass 4` create Dogma attributes that do not exist in-game, but are rather complicated to calculate.
To make rendering a fit easier, these are calculated by this library, and presented as new Dogma attributes.
Their identifier is always a negative value, to visually separate them.
What additional attributes exist are defined in [EVEShipFit/sde-patched](https://github.com/EVEShipFit/sde-patched) repository.
## Development
Make sure you have [Rust installed](https://www.rust-lang.org/tools/install).
Next, we need the data-files.
They are Flatbuffers, built by [sde-patched](https://github.com/EVEShipFit/sde-patched) and published on npm as [`@eveshipfit/sde`](https://www.npmjs.com/package/@eveshipfit/sde):
```bash
npm ci
```
- `sde.dat` holds everything needed to calculate a fit.
- `names.dat` holds the type names in the other seven languages EVE supports.
It is optional.
English names live in `sde.dat`, so an EFT-fit written in English imports without it; `names.dat` is only consulted when a name does not match.
After that, we can run the application.
```bash
flatc --rust --gen-onefile -o crates/esf-data/src/sde/ node_modules/@eveshipfit/sde/specs/eve.fbs node_modules/@eveshipfit/sde/specs/names.fbs
cargo run --release -p esf-cli
```
The regression suite reads the same paths; set `ESF_SDE` and `ESF_NAMES` to point it elsewhere.
## Regression
The engine is locked down by snapshot tests.
A case calculates one fit with one set of skills, and compares the result against a stored snapshot in [tests/snapshots](./tests/snapshots).
```bash
cargo test
```
If failures are expected differences, use `insta` to resolve them:
```bash
cargo install cargo-insta
cargo insta review
```
## Integration
### Javascript (WebAssembly)
The primary goal of this library is to build a WebAssembly variant that can easily be used in the browser.
This means that there is no need for a server-component, and everything can be calculated in the browser.
This is done with [wasm-pack](https://rustwasm.github.io/wasm-pack/):
```bash
cargo install wasm-pack
wasm-pack build crates/esf-wasm --release --out-dir ../../pkg
```
In the `pkg` folder is now a NPM module to use.
Javascript hands over `sde.dat` once, and every lookup after that happens inside WebAssembly.
The file is a Flatbuffer, so nothing is parsed: the bytes are used where they land.
```js
import init, { init as initPanicHook, load_sde, calculate } from "@eveshipfit/dogma-engine";
await init();
initPanicHook();
const sde = await fetch("/sde.dat").then((response) => response.arrayBuffer());
const buildNumber = load_sde(new Uint8Array(sde));
const fit = {
ship: { type_id: 587 },
items: [{ type_id: 2873, slot: { type: "high", index: 0 }, state: "active", charge: { type_id: 185 } }],
character: { skills: { 3300: 5 } },
};
const calculation = calculate(fit);
/* Or if you want to know the source of the effects: */
const withSources = calculate(fit, { sources: true });
```