145 lines
7.2 KiB
Markdown
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)
|