Files
Entropyk/_bmad-output/implementation-artifacts/11-15-bitzer-parser.md

7.8 KiB
Raw Blame History

Story 11.15: Bitzer Parser

Status: done

Story

As a refrigeration engineer, I want Bitzer compressor data integration, so that I can use Bitzer coefficients in simulations.

Acceptance Criteria

  1. Given a BitzerBackend struct When constructed via BitzerBackend::new() Then it discovers compressor models from CSV files in data/bitzer/compressors/ (e.g. by scanning *.csv or loading an index) And eagerly pre-caches all discovered models into memory

  2. Given a valid Bitzer CSV file (Bitzer polynomial format) When parsed by BitzerBackend Then it yields a CompressorCoefficients struct with 10 capacity and 10 power coefficients compatible with AHRI 540 And Bitzer polynomial format is mapped to the standard polynomial form (Ts, Td, Ts², Ts·Td, Td², …)

  3. Given BitzerBackend 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 (e.g. file stem of a CSV) When I call get_compressor_coefficients("4NFC-20Y") 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 BitzerBackend When Bitzer only provides compressor data here Then it returns Ok(vec![]) (empty list, not an error)

  7. Given get_bphx_parameters("anything") called on BitzerBackend When Bitzer only provides compressor data here Then it returns VendorError::InvalidFormat with a descriptive message

  8. Given unit tests When cargo test -p entropyk-vendors is run Then all existing tests still pass And new Bitzer-specific tests pass (CSV loading, format mapping, error cases)

Tasks / Subtasks

  • Task 1: Define Bitzer CSV format and sample data (AC: 2)
    • Subtask 1.1: Document or adopt Bitzer polynomial CSV layout (columns for capacity/power coefficients, validity range)
    • Subtask 1.2: Create data/bitzer/compressors/ and at least one sample CSV (e.g. 4NFC-20Y.csv or equivalent)
    • Subtask 1.3: If using an index, add index.json or index.csv listing model names
  • Task 2: Implement BitzerBackend (AC: 1, 3, 4, 5, 6, 7)
    • Subtask 2.1: Create src/compressors/bitzer.rs with BitzerBackend struct
    • Subtask 2.2: Implement BitzerBackend::new() resolving data path via ENTROPYK_DATA with fallback to CARGO_MANIFEST_DIR/data
    • Subtask 2.3: Implement CSV discovery (glob *.csv in data/bitzer/compressors/ and use file stem as model id, or load from index) and pre-cache
    • Subtask 2.4: Implement CSV parsing: Bitzer polynomial format → CompressorCoefficients (and CompressorValidityRange)
    • Subtask 2.5: Implement VendorBackend for BitzerBackend (list_compressor_models sorted, get_compressor_coefficients, list_bphx_models empty, get_bphx_parameters InvalidFormat)
  • Task 3: Wire up module exports
    • Subtask 3.1: Add pub mod bitzer; in src/compressors/mod.rs (uncomment or add)
    • Subtask 3.2: Re-export BitzerBackend in src/lib.rs
  • Task 4: Write unit tests (AC: 8)
    • Subtask 4.1: Test BitzerBackend::new() (or from_path) successfully constructs
    • Subtask 4.2: Test list_compressor_models() returns sorted models
    • Subtask 4.3: Test get_compressor_coefficients() returns valid data for a known CSV
    • Subtask 4.4: Test ModelNotFound for unknown model
    • Subtask 4.5: Test list_bphx_models() returns empty
    • Subtask 4.6: Test get_bphx_parameters() returns InvalidFormat
  • Task 5: Verify build and tests (AC: 8)
    • Subtask 5.1: Run cargo test -p entropyk-vendors
    • Subtask 5.2: Run cargo clippy -p entropyk-vendors -- -D warnings

Dev Notes

  • Bitzer supplies compressor data in CSV format with a proprietary polynomial layout; the implementation must map this to the existing CompressorCoefficients and CompressorValidityRange types in vendor_api.rs.
  • Reuse the same data-path resolution and error-handling patterns as DanfossBackend and CopelandBackend: ENTROPYK_DATA, path sanitization (reject model names containing /, \, or ..), log::warn! for skipped files, and structured VendorError (e.g. IoError { path, source }, InvalidFormat(message)).
  • Keep list_compressor_models() deterministic by maintaining a sorted list of model names (e.g. sorted_models: Vec<String> populated and sorted after loading).

Project Structure Notes

  • Alignment with existing vendors layout:
    • crates/vendors/data/bitzer/compressors/ for CSV files (and optional index).
    • crates/vendors/src/compressors/bitzer.rs for BitzerBackend; export in compressors/mod.rs and lib.rs.

References

Dev Agent Record

Agent Model Used

Cursor / Auto (dev-story workflow)

Debug Log References

Completion Notes List

  • Task 1: Defined Bitzer CSV format with header row (model, manufacturer, refrigerant, c0..c9, p0..p9, t_suction_min/max, t_discharge_min/max). Created data/bitzer/compressors/4NFC-20Y.csv and 4HES-5Y.csv. Discovery by glob *.csv (no index file).
  • Task 2: Implemented BitzerBackend in src/compressors/bitzer.rs with new(), from_path(), load_compressors() (dir scan), load_model() and parse_bitzer_csv(). Path resolution via ENTROPYK_DATA / CARGO_MANIFEST_DIR/data. Path sanitization and log::warn! for skipped files. VendorBackend impl: list_compressor_models (sorted), get_compressor_coefficients, list_bphx_models empty, get_bphx_parameters / compute_ua return InvalidFormat.
  • Task 3: Added pub mod bitzer in compressors/mod.rs and re-exported BitzerBackend in lib.rs.
  • Task 4: Added 11 unit tests in bitzer.rs (new, from_path, vendor_name, list_compressor_models, get_compressor 4NFC-20Y/4HES-5Y, validity_range, model_not_found, list_bphx_empty, get_bphx_error, object_safety).
  • Task 5: cargo test -p entropyk-vendors (65 tests passed), cargo clippy -p entropyk-vendors -- -D warnings (fixed unnecessary_map_or → is_some_and). Added csv = "1.3" to Cargo.toml.
  • Code review (AI): Addressed MEDIUM/LOW findings: documented AHRI 540 column order (c0..c9, p0..p9 = Ts, Td, Ts², Ts·Td, Td², Ts³, Td·Ts², Ts·Td², Td³) in bitzer.rs module and parse_bitzer_csv doc; documented single-data-row behaviour (first row used, extra rows ignored) and added test test_bitzer_csv_multiple_rows_first_used; updated compressors/mod.rs comment (Danfoss 11.14, Bitzer 11.15).

File List

  • crates/vendors/Cargo.toml (modified added csv dependency)
  • crates/vendors/data/bitzer/compressors/4NFC-20Y.csv (created)
  • crates/vendors/data/bitzer/compressors/4HES-5Y.csv (created)
  • crates/vendors/src/compressors/bitzer.rs (created, then modified code review: AHRI 540 doc, single-row doc, test)
  • crates/vendors/src/compressors/mod.rs (modified pub mod bitzer; then code review: comment update)
  • crates/vendors/src/lib.rs (modified re-export BitzerBackend)