# Entropyk - Story 1.3: Port and Connection System ## 🎯 Ce qui a Ă©tĂ© implĂ©mentĂ© Cette story implĂ©mente le systĂšme de ports et connexions pour les composants thermodynamiques avec le **Type-State pattern** pour la sĂ©curitĂ© Ă  la compilation. ### FonctionnalitĂ©s principales - ✅ `Port` - Structure gĂ©nĂ©rique avec Ă©tats `Disconnected` et `Connected` - ✅ `FluidId` - Identification des fluides pour validation de compatibilitĂ© - ✅ `ConnectionError` - Gestion d'erreurs avec `thiserror` - ✅ Validation des connexions (compatibilitĂ© fluide, continuitĂ© pression/enthalpie) - ✅ Extension du trait `Component` avec `get_ports()` ## 🚀 Instructions de test ### 1. PrĂ©requis ```bash # VĂ©rifier que Rust est installĂ© rustc --version cargo --version ``` ### 2. Cloner/Naviguer dans le projet ```bash cd /Users/sepehr/dev/Entropyk ``` ### 3. Compiler le projet ```bash # Compiler tout le workspace cargo build --workspace # Compiler en mode release (optimisĂ©) cargo build --workspace --release ``` ### 4. ExĂ©cuter tous les tests ```bash # Tests complets du workspace cargo test --workspace # Tests avec sortie dĂ©taillĂ©e cargo test --workspace -- --nocapture # Tests du crate components uniquement cargo test -p entropyk-components # Tests du crate core uniquement cargo test -p entropyk-core ``` ### 5. VĂ©rifier la qualitĂ© du code ```bash # Clippy (linting strict) cargo clippy --workspace -- -D warnings # Formatage du code cargo fmt --workspace # VĂ©rifier la documentation cargo doc --workspace --open ``` ## đŸ§Ș Tests manuels ### Test 1: CrĂ©ation et connexion de ports CrĂ©ez un fichier `test_ports.rs` Ă  la racine du projet : ```rust use entropyk_components::port::{Port, Disconnected, Connected, FluidId, ConnectionError}; use entropyk_core::{Pressure, Enthalpy}; fn main() -> Result<(), ConnectionError> { println!("=== Test de crĂ©ation de ports ==="); // CrĂ©er deux ports dĂ©connectĂ©s let port1 = Port::new( FluidId::new("R134a"), Pressure::from_bar(1.0), Enthalpy::from_joules_per_kg(400_000.0) ); let port2 = Port::new( FluidId::new("R134a"), Pressure::from_bar(1.0), Enthalpy::from_joules_per_kg(400_000.0) ); println!("Port 1 créé: fluid={:?}, pressure={:.2} Pa, enthalpy={:.2} J/kg", port1.fluid_id(), port1.pressure().to_pascals(), port1.enthalpy().to_joules_per_kg() ); println!("Port 2 créé: fluid={:?}, pressure={:.2} Pa, enthalpy={:.2} J/kg", port2.fluid_id(), port2.pressure().to_pascals(), port2.enthalpy().to_joules_per_kg() ); // Connecter les ports println!("\n=== Connexion des ports ==="); let (mut connected1, mut connected2) = port1.connect(port2)?; println!("✅ Ports connectĂ©s avec succĂšs!"); println!("Connected 1: pressure={:.2} Pa, enthalpy={:.2} J/kg", connected1.pressure().to_pascals(), connected1.enthalpy().to_joules_per_kg() ); // Modifier les valeurs println!("\n=== Modification des valeurs ==="); connected1.set_pressure(Pressure::from_bar(1.5)); connected1.set_enthalpy(Enthalpy::from_joules_per_kg(450_000.0)); println!("Port 1 modifiĂ©: pressure={:.2} Pa, enthalpy={:.2} J/kg", connected1.pressure().to_pascals(), connected1.enthalpy().to_joules_per_kg() ); Ok(()) } ``` Pour l'exĂ©cuter, ajoutez ce binary dans `Cargo.toml`: ```toml [[bin]] name = "test_ports" path = "test_ports.rs" ``` Puis: ```bash cargo run --bin test_ports ``` ### Test 2: Test d'erreurs ```rust use entropyk_components::port::{Port, FluidId, ConnectionError}; use entropyk_core::{Pressure, Enthalpy}; fn main() { println!("=== Test des erreurs de connexion ===\n"); // Test 1: Fluides incompatibles println!("Test 1: Fluides incompatibles"); let port1 = Port::new( FluidId::new("R134a"), Pressure::from_pascals(100_000.0), Enthalpy::from_joules_per_kg(400_000.0) ); let port2 = Port::new( FluidId::new("Water"), Pressure::from_pascals(100_000.0), Enthalpy::from_joules_per_kg(400_000.0) ); match port1.connect(port2) { Err(ConnectionError::IncompatibleFluid { from, to }) => { println!("✅ Erreur capturĂ©e: Cannot connect {} to {}", from, to); } _ => println!("❌ Erreur non capturĂ©e!"), } // Test 2: Pression diffĂ©rente println!("\nTest 2: Pression diffĂ©rente"); let port3 = Port::new( FluidId::new("R134a"), Pressure::from_pascals(100_000.0), Enthalpy::from_joules_per_kg(400_000.0) ); let port4 = Port::new( FluidId::new("R134a"), Pressure::from_pascals(200_000.0), Enthalpy::from_joules_per_kg(400_000.0) ); match port3.connect(port4) { Err(ConnectionError::PressureMismatch { from_pressure, to_pressure }) => { println!("✅ Erreur capturĂ©e: Pressure mismatch {} vs {}", from_pressure, to_pressure); } _ => println!("❌ Erreur non capturĂ©e!"), } // Test 3: Connexion rĂ©ussie println!("\nTest 3: Connexion rĂ©ussie"); let port5 = Port::new( FluidId::new("R134a"), Pressure::from_pascals(100_000.0), Enthalpy::from_joules_per_kg(400_000.0) ); let port6 = Port::new( FluidId::new("R134a"), Pressure::from_pascals(100_000.0), Enthalpy::from_joules_per_kg(400_000.0) ); match port5.connect(port6) { Ok(_) => println!("✅ Connexion rĂ©ussie!"), Err(_) => println!("❌ Connexion Ă©chouĂ©e!"), } } ``` ### Test 3: VĂ©rification Type-State (doit Ă©chouer Ă  la compilation) CrĂ©ez ce fichier pour vĂ©rifier que la sĂ©curitĂ© Ă  la compilation fonctionne: ```rust use entropyk_components::port::{Port, Disconnected}; use entropyk_core::{Pressure, Enthalpy, FluidId}; fn main() { // CrĂ©er un port dĂ©connectĂ© let port: Port = Port::new( FluidId::new("R134a"), Pressure::from_bar(1.0), Enthalpy::from_joules_per_kg(400_000.0) ); // Cette ligne doit provoquer une erreur de compilation: // error[E0599]: no method named `pressure` found for struct `Port` // let _p = port.pressure(); println!("Si vous dĂ©commentez la ligne ci-dessus, la compilation Ă©chouera!"); println!("Cela prouve que le Type-State pattern fonctionne."); } ``` ## 📊 Structure des fichiers ``` entropyk/ ├── Cargo.toml # Workspace root ├── crates/ │ ├── components/ # Crate components (modifiĂ©) │ │ ├── Cargo.toml # + DĂ©pendances ajoutĂ©es │ │ └── src/ │ │ ├── lib.rs # + Trait Component Ă©tendu │ │ └── port.rs # NOUVEAU: ImplĂ©mentation ports │ └── core/ # Crate core (existant) │ └── src/ │ └── types.rs # Pressure, Enthalpy, etc. └── _bmad-output/ └── implementation-artifacts/ └── 1-3-port-and-connection-system.md # Story document ``` ## 🔍 Points clĂ©s de l'implĂ©mentation ### Type-State Pattern ```rust // Disconnected et Connected sont des marqueurs de type vides pub struct Disconnected; pub struct Connected; // Port est gĂ©nĂ©rique sur l'Ă©tat pub struct Port { fluid_id: FluidId, pressure: Pressure, enthalpy: Enthalpy, _state: PhantomData, // Marqueur zĂ©ro-cost } // Seuls les ports Disconnected peuvent ĂȘtre connectĂ©s impl Port { pub fn connect(self, other: Port) -> Result<(Port, Port), ConnectionError> { // Validation et connexion... } } // Seuls les ports Connected exposent les mĂ©thodes de lecture/Ă©criture impl Port { pub fn pressure(&self) -> Pressure { self.pressure } pub fn set_pressure(&mut self, pressure: Pressure) { self.pressure = pressure } } ``` ### Validation des connexions ```rust pub fn connect(self, other: Port) -> Result<(Port, Port), ConnectionError> { // 1. Validation du fluide if self.fluid_id != other.fluid_id { return Err(ConnectionError::IncompatibleFluid { ... }); } // 2. Validation de la continuitĂ© de pression if pressure_diff > 1e-6 { return Err(ConnectionError::PressureMismatch { ... }); } // 3. Validation de la continuitĂ© d'enthalpie if enthalpy_diff > 1e-6 { return Err(ConnectionError::EnthalpyMismatch { ... }); } // CrĂ©ation des ports connectĂ©s avec valeurs moyennĂ©es Ok((connected1, connected2)) } ``` ## 🐛 DĂ©pannage ### Erreur: `unresolved import entropyk_core` Solution: VĂ©rifier que la dĂ©pendance est bien dans `crates/components/Cargo.toml`: ```toml [dependencies] entropyk-core = { path = "../core" } ``` ### Erreur: `approx crate not found` Solution: VĂ©rifier la dev-dependency: ```toml [dev-dependencies] approx = "0.5" ``` ### Tests qui Ă©chouent ```bash # Nettoyer et reconstruire cargo clean cargo test --workspace ``` ## 📚 Ressources - [Rust Type-State Pattern](https://rust-unofficial.github.io/patterns/patterns/behavioural/phantom-types.html) - [thiserror documentation](https://docs.rs/thiserror/) - [approx documentation](https://docs.rs/approx/) (pour les assertions flottantes) --- **Date d'implĂ©mentation**: 2026-02-14 **Story**: 1.3 - Port and Connection System **Statut**: ✅ ComplĂ©tĂ© et testĂ©