Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ default-members = [
]

[workspace.package]
version = "0.1.2"
version = "0.1.3"
edition = "2021"
license = "LGPL-3.0-or-later"
repository = "https://github.com/EX-CT/EXFA-Engine"
Expand Down
2 changes: 1 addition & 1 deletion ci/round1-base.sha256
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0a5a98a58365583019c389dc641b7bb41c89975db2e49457234515187e7be353
15a7de5171113377fadf902d16fd6470f73431a4a03c7ab7943cc08f87eb7fe2
2 changes: 1 addition & 1 deletion ci/round1.sha256
Original file line number Diff line number Diff line change
@@ -1 +1 @@
d5bd8a282b17ed6a7e3afbe052d6c62752a7242750264f22b42f62689b12be33
2142f097d8c37d25ff094c1e436c687fd20d6ce797b37bdfabd4916b8e3a6b9c
7 changes: 6 additions & 1 deletion contract/CONTRACT.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# eve-dogma request/response contract (v1, revision 1.4.5)
# eve-dogma request/response contract (v1, revision 1.4.7)

Stateless: **one JSON `FitRequest` in → one JSON `FitStats` out.** No hidden state, no clocks, no network.
The same request with the same dataset must give byte-identical output. Unknown request fields are ignored.
Expand Down Expand Up @@ -273,6 +273,9 @@ Existing FitStats fields, now scored against Pyfa (oracle `ORACLE_EXTRA=profile,
capacity / chargeSize / chargeGroup1–4 → CHARGE_CAPACITY / CHARGE_SIZE / CHARGE_GROUP (each checked on its own);
`checkRequirements` → MISSING_SKILL. A fit with violations is still computed in full ("Disable Fitting
Restrictions", ENG-VAL-005): the `val_*` cases also score every bench metric. Cases `val_*`.
Engine-side additions (Pyfa shows these only as red resource bars, not fit problems): drone bay / fighter bay /
cargo volume over capacity → DRONE_BAY / FIGHTER_BAY / CARGO_OVERLOAD; fighter squads over the ship's tubes
(total and per light/support/heavy class) → FIGHTER_TUBES. These fire in addition to the mapped set.
- Draft (reported, not part of pass): per-module codes carry the `module_index` of **every** module that breaks
the rule (Pyfa flags all modules of an over-limit group, not just the ones past the limit); SLOTS_EXCEEDED may
carry `slot`; MISSING_SKILL is one entry per missing skill with `skill_type_id` and `level`, following Pyfa
Expand Down Expand Up @@ -369,3 +372,5 @@ case's `_fields` param lists the fields it scores).
previously warning-side-channel corrections now silent. `type` RPC gains `allowed_states` (additive) for edit-time
constraints. `warnings[]` remains for genuine gaps (missing skills, unsupported projected kinds, unknown warfare
buff ids, `nothing to optimize`).
- v1.4.7 (2026-10-06, applies on top of 1.4.6): `violations[]` gains DRONE_BAY, FIGHTER_BAY, CARGO_OVERLOAD and
FIGHTER_TUBES for resource-bar overloads (Pyfa shows these as red bars, not fit problems).
27 changes: 25 additions & 2 deletions crates/exfa-core/src/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1131,7 +1131,10 @@ impl Fit {
out.push_kv("bombing".into(), bombing);
out.push_kv("modules".into(), J::A(module_rows));
if req.options.validate {
out.push_kv("violations".into(), J::A(self.validate(cpu_used, pg_used, calib_used, bw_used)));
out.push_kv("violations".into(), J::A(self.validate(
cpu_used, pg_used, calib_used, bw_used, bay_used, fbay_used, cargo_used,
[tubes_used as f64, class_used("light"), class_used("support"), class_used("heavy")],
)));
}
if !self.warnings.is_empty() {
out.push_kv("warnings".into(), jv!(self.warnings.clone()));
Expand Down Expand Up @@ -1184,7 +1187,7 @@ impl Fit {
J::O(m)
}

fn validate(&self, cpu: f64, pg: f64, calib: f64, bw: f64) -> Vec<J> {
fn validate(&self, cpu: f64, pg: f64, calib: f64, bw: f64, bay: f64, fbay: f64, cargo: f64, tubes: [f64; 4]) -> Vec<J> {
let ship = self.ship;
let g = |i: usize, x: u16| self.get(i, x);
let mut v = Vec::new();
Expand All @@ -1201,6 +1204,26 @@ impl Fit {
if bw > g(ship, a::droneBandwidth) + 1e-9 {
push("DRONE_BANDWIDTH", format!("Drone bandwidth used {bw} > {}", g(ship, a::droneBandwidth)), None);
}
if bay > g(ship, a::droneCapacity) + 1e-9 {
push("DRONE_BAY", format!("Drone bay used {bay:.1} m3 > capacity {:.1}", g(ship, a::droneCapacity)), None);
}
if fbay > g(ship, a::fighterCapacity) + 1e-9 {
push("FIGHTER_BAY", format!("Fighter bay used {fbay:.1} m3 > capacity {:.1}", g(ship, a::fighterCapacity)), None);
}
if cargo > g(ship, a::capacity) + 1e-9 {
push("CARGO_OVERLOAD", format!("Cargo used {cargo:.1} m3 > capacity {:.1}", g(ship, a::capacity)), None);
}
for (u, attr, label) in [
(tubes[0], a::fighterTubes, "fighter"),
(tubes[1], a::fighterLightSlots, "light fighter"),
(tubes[2], a::fighterSupportSlots, "support fighter"),
(tubes[3], a::fighterHeavySlots, "heavy fighter"),
] {
let lim = g(ship, attr);
if u > lim + 1e-9 {
push("FIGHTER_TUBES", format!("{label} squads {u} > tubes {lim}"), None);
}
}
let modules: Vec<usize> = (0..self.items.len()).filter(|&i| self.items[i].kind == Kind::Module).collect();
for (slot, attr) in [
(Slot::High, a::hiSlots),
Expand Down
Loading