145 lines
7.2 KiB
Markdown

# Story 11.14: Danfoss Parser
Status: done
<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
## Story
As a refrigeration engineer,
I want Danfoss compressor data integration,
so that I can use Danfoss coefficients in simulations.
## Acceptance Criteria
1. **Given** a `DanfossBackend` struct
**When** constructed via `DanfossBackend::new()`
**Then** it loads the compressor index from `data/danfoss/compressors/index.json`
**And** eagerly pre-caches all referenced model JSON files into memory
2. **Given** a valid Danfoss JSON file
**When** parsed by `DanfossBackend`
**Then** it yields a `CompressorCoefficients` struct with all 10 capacity and 10 power coefficients
**And** it supports AHRI 540 format extraction
3. **Given** `DanfossBackend` implements `VendorBackend`
**When** I call `list_compressor_models()`
**Then** it returns all model names from the pre-loaded cache in sorted order
4. **Given** a valid model name
**When** I call `get_compressor_coefficients("some_model")`
**Then** it returns the full `CompressorCoefficients` struct
5. **Given** a model name not in the catalog
**When** I call `get_compressor_coefficients("NONEXISTENT")`
**Then** it returns `VendorError::ModelNotFound("NONEXISTENT")`
6. **Given** `list_bphx_models()` called on `DanfossBackend`
**When** Danfoss only provides compressor data here
**Then** it returns `Ok(vec![])` (empty list, not an error)
7. **Given** `get_bphx_parameters("anything")` called on `DanfossBackend`
**When** Danfoss only provides compressor data here
**Then** it returns `VendorError::InvalidFormat` with descriptive message
8. **Given** unit tests
**When** `cargo test -p entropyk-vendors` is run
**Then** all existing tests still pass
**And** new Danfoss-specific tests pass (model loading, error cases)
## Tasks / Subtasks
- [x] Task 1: Create sample Danfoss JSON data files (AC: 2)
- [x] Subtask 1.1: Create `data/danfoss/compressors/index.json` with sample models
- [x] Subtask 1.2: Create `data/danfoss/compressors/model1.json` with realistic coefficients
- [x] Subtask 1.3: Create `data/danfoss/compressors/model2.json` as second model
- [x] Task 2: Implement `DanfossBackend` (AC: 1, 3, 4, 5, 6, 7)
- [x] Subtask 2.1: Create `src/compressors/danfoss.rs` with `DanfossBackend` struct
- [x] Subtask 2.2: Implement `DanfossBackend::new()` resolving to `ENTROPYK_DATA` with fallback to `CARGO_MANIFEST_DIR`/data
- [x] Subtask 2.3: Implement `load_index()` and `load_model()` pre-caching logic (incorporating fixes from Swep)
- [x] Subtask 2.4: Implement `VendorBackend` trait for `DanfossBackend`
- [x] Task 3: Wire up module exports
- [x] Subtask 3.1: Add `pub mod danfoss;` in `src/compressors/mod.rs`
- [x] Subtask 3.2: Re-export `DanfossBackend` in `src/lib.rs`
- [x] Task 4: Write unit tests (AC: 8)
- [x] Subtask 4.1: Test `DanfossBackend::new()` successfully constructs
- [x] Subtask 4.2: Test `list_compressor_models()` returns sorted models
- [x] Subtask 4.3: Test `get_compressor_coefficients()` returns valid data
- [x] Subtask 4.4: Test `ModelNotFound` error for unknown model
- [x] Subtask 4.5: Test `list_bphx_models()` returns empty
- [x] Subtask 4.6: Test `get_bphx_parameters()` returns `InvalidFormat`
- [x] Task 5: Verify all tests pass (AC: 8)
- [x] Subtask 5.1: Run `cargo test -p entropyk-vendors`
- [x] Subtask 5.2: Run `cargo clippy -p entropyk-vendors -- -D warnings`
- [x] Task 6: Review Follow-ups (AI)
- [x] Fix Error Swallowing during JSON deserialization to provide contextual file paths
- [x] Fix Path Traversal vulnerability by sanitizing model parameter
- [x] Improve Test Quality by asserting multiple coefficients per array
- [x] Improve Test Coverage by adding test directly validating `DanfossBackend::from_path()`
- [ ] Address Code Duplication with `CopelandBackend` (deferred to future technical debt story)
## Dev Notes
### Architecture
**This builds entirely on the `VendorBackend` trait pattern** established in epic 11. Similar to `CopelandBackend` and `SwepBackend`, `DanfossBackend` pre-caches JSON files containing coefficients mapping to `CompressorCoefficients`.
### Project Structure Notes
```text
crates/vendors/
├── data/danfoss/compressors/
│ ├── index.json # NEW: ["model1", "model2"]
│ ├── model1.json # NEW: Ahri 540 coefficients
│ └── model2.json # NEW: Ahri 540 coefficients
└── src/
├── compressors/
│ ├── danfoss.rs # NEW: main implementation
│ └── mod.rs # MODIFY: add `pub mod danfoss;`
├── lib.rs # MODIFY: export DanfossBackend
```
### Critical Git/Dev Context
- Keep error logging idiomatic: use `log::warn!` instead of `eprintln!` (from recent `SwepBackend` fix `c5a51d8`).
- Maintain an internal sorted `Vec` for models in the struct to guarantee deterministic output from `list_compressor_models()` without resorting every time (Issue M1 from Swep).
- Make sure `data` directory resolution uses standard pattern `ENTROPYK_DATA` with fallback to `CARGO_MANIFEST_DIR` in debug mode.
### Testing Standards
- 100% test coverage for success paths, missing files, invalid formats, and `vendor_name()`.
- Place tests in `src/compressors/danfoss.rs` in `mod tests` block.
### References
- [Source: epics.md#Story-11.14](file:///Users/sepehr/dev/Entropyk/_bmad-output/planning-artifacts/epics.md)
- [Source: copeland.rs](file:///Users/sepehr/dev/Entropyk/crates/vendors/src/compressors/copeland.rs) - Primary implementation reference for compressors
- [Source: swep.rs](file:///Users/sepehr/dev/Entropyk/crates/vendors/src/heat_exchangers/swep.rs) - Reference for the latest architectural best-practices applied
## Dev Agent Record
### Agent Model Used
Antigravity (Gemini)
### Debug Log References
### Completion Notes List
- Comprehensive story details extracted from Epic 11 analysis and previously corrected Swep implementation.
- Status set to ready-for-dev with BMad-compliant Acceptance Criteria list.
- Implemented `DanfossBackend` mimicking the robust pattern of `CopelandBackend`, and applied architectural fixes from `SwepBackend` (idomatic error logging, sorting `list_compressor_models`).
- Created Danfoss JSON data files: `index.json`, `SH090-4.json`, `SH140-4.json`.
- Integrated `danfoss` module into the vendors crate and re-exported `DanfossBackend` inside `lib.rs`.
- Added unit tests mimicking Copeland coverage. Ran `cargo test` and `cargo clippy` to achieve zero warnings with all tests passing.
- Advanced story status to `review`.
- Code review findings addressed: fixed error swallowing during deserialization, sanitized input to prevent path traversal, added `from_path()` test coverage, and tightened test assertions. Deferred code duplication cleanup.
- Advanced story status from `review` to `done`.
### File List
- `crates/vendors/data/danfoss/compressors/index.json` (created)
- `crates/vendors/data/danfoss/compressors/SH090-4.json` (created)
- `crates/vendors/data/danfoss/compressors/SH140-4.json` (created)
- `crates/vendors/src/compressors/danfoss.rs` (created)
- `crates/vendors/src/compressors/mod.rs` (modified)
- `crates/vendors/src/lib.rs` (modified)