bool WaterToAirComponent_Impl::removeFromAirLoopHVAC() { if( auto t_oaSystem = airLoopHVACOutdoorAirSystem() ) { if( t_oaSystem->oaComponent(handle()) ) { return HVACComponent_Impl::removeFromLoop(t_oaSystem->outboardOANode().get(), t_oaSystem.get(), airInletPort(), airOutletPort()); } else if( t_oaSystem->reliefComponent(handle()) ) { return HVACComponent_Impl::removeFromLoop(t_oaSystem.get(), t_oaSystem->outboardReliefNode().get(), airInletPort(), airOutletPort()); } } else if( auto t_airLoop = airLoopHVAC() ) { if( t_airLoop->supplyComponent(handle()) ) { return HVACComponent_Impl::removeFromLoop(t_airLoop->supplyInletNode(), t_airLoop->supplyOutletNode(), airInletPort(), airOutletPort()); } } return false; }
void ZoneHVACComponent_Impl::removeFromAirLoopHVAC() { if( boost::optional<AirLoopHVAC> t_airLoopHVAC = airLoopHVAC() ) { boost::optional<Node> t_inletNode = inletNode(); OS_ASSERT(t_inletNode); boost::optional<Node> t_outletNode = outletNode(); OS_ASSERT(t_outletNode); unsigned targetPort = t_outletNode->connectedObjectPort(t_outletNode->outletPort()).get(); ModelObject targetModelObject = t_outletNode->connectedObject(t_outletNode->outletPort()).get(); t_outletNode->disconnect(); t_outletNode->remove(); Model t_model = model(); t_model.connect( t_inletNode.get(), t_inletNode->outletPort(), targetModelObject, targetPort ); std::vector<AirTerminalSingleDuctInletSideMixer> terminalMixers = subsetCastVector<AirTerminalSingleDuctInletSideMixer>(t_airLoopHVAC->demandComponents(t_airLoopHVAC->demandInletNode(),t_inletNode.get())); if( ! terminalMixers.empty() ) { if( boost::optional<Node> secondaryNode = terminalMixers.front().secondaryAirInletNode() ) { secondaryNode->disconnect(); secondaryNode->remove(); } } } }
bool Mixer_Impl::isRemovable() const { if( airLoopHVAC() || plantLoop() ) { return false; } else { return true; } }
std::vector<ThermalZone> AirLoopHVACZoneSplitter_Impl::thermalZones() { std::vector<ThermalZone> zones; std::vector<ModelObject> modelObjects; std::vector<ModelObject> _outletModelObjects = outletModelObjects(); OptionalAirLoopHVAC _airLoopHVAC = airLoopHVAC(); OptionalNode demandOutletNode; OptionalNode demandInletNode; if( _airLoopHVAC ) { demandOutletNode = _airLoopHVAC->demandOutletNode(); demandInletNode = _airLoopHVAC->demandInletNode(); } else { return zones; } modelObjects = _airLoopHVAC->demandComponents( demandInletNode.get(), demandOutletNode.get(), ThermalZone::iddObjectType() ); for( std::vector<ModelObject>::iterator it = modelObjects.begin(); it < modelObjects.end(); it++ ) { OptionalThermalZone zone; zone = it->optionalCast<ThermalZone>(); if( zone ) { zones.push_back(*zone); } } return zones; }
bool WaterToAirComponent_Impl::removeFromAirLoopHVAC() { Model _model = model(); ModelObject thisObject = getObject<ModelObject>(); if( boost::optional<AirLoopHVAC> airLoop = airLoopHVAC() ) { if( airOutletModelObject().get() == airLoop->supplyOutletNodes().front() && airInletModelObject().get() == airLoop->supplyInletNode() ) { ModelObject sourceModelObject = airInletModelObject().get(); unsigned sourcePort = connectedObjectPort( airInletPort() ).get(); ModelObject targetModelObject = airOutletModelObject().get(); unsigned targetPort = connectedObjectPort( airOutletPort() ).get(); model().disconnect(thisObject,airOutletPort()); model().disconnect(thisObject,airInletPort()); _model.connect( sourceModelObject, sourcePort, targetModelObject, targetPort ); return true; } else if( airOutletModelObject().get() == airLoop->supplyOutletNodes().front() ) { Node sourceModelObject = airInletModelObject()->optionalCast<Node>().get(); ModelObject targetModelObject = airOutletModelObject().get(); unsigned targetPort = connectedObjectPort( airOutletPort() ).get(); ModelObject source2ModelObject = sourceModelObject.inletModelObject().get(); unsigned source2Port = sourceModelObject.connectedObjectPort( sourceModelObject.inletPort() ).get(); model().disconnect(thisObject,airOutletPort()); model().disconnect(thisObject,airInletPort()); _model.connect( source2ModelObject, source2Port, targetModelObject, targetPort ); sourceModelObject.remove(); return true; } else { ModelObject sourceModelObject = airInletModelObject().get(); unsigned sourcePort = connectedObjectPort( airInletPort() ).get(); Node targetModelObject = airOutletModelObject()->optionalCast<Node>().get(); ModelObject target2ModelObject = targetModelObject.outletModelObject().get(); unsigned target2Port = targetModelObject.connectedObjectPort( targetModelObject.outletPort() ).get(); model().disconnect(thisObject,airOutletPort()); model().disconnect(thisObject,airInletPort()); _model.connect( sourceModelObject, sourcePort, target2ModelObject, target2Port ); targetModelObject.remove(); return true; } } return false; }
bool WaterToAirComponent_Impl::addToNode(Node & node) { Model _model = node.model(); ModelObject thisModelObject = getObject<ModelObject>(); boost::optional<AirLoopHVACOutdoorAirSystem> oaSystem = node.airLoopHVACOutdoorAirSystem(); if( node.airLoopHVAC() && ! oaSystem ) { AirLoopHVAC airLoop = node.airLoopHVAC().get(); if( airLoop.demandComponent( node.handle() ) ) { return false; } else { if( airLoopHVAC() ) { removeFromAirLoopHVAC(); } if( node == airLoop.supplyOutletNode() && node.inletModelObject().get() == airLoop.supplyInletNode() ) { unsigned oldOutletPort = node.connectedObjectPort( node.inletPort() ).get(); unsigned oldInletPort = node.inletPort(); ModelObject oldSourceModelObject = node.connectedObject( node.inletPort() ).get(); ModelObject oldTargetModelObject = node; _model.connect( oldSourceModelObject, oldOutletPort, thisModelObject, airInletPort() ); _model.connect( thisModelObject, airOutletPort(), oldTargetModelObject, oldInletPort ); return true; } if( node == airLoop.supplyInletNode() && node.outletModelObject().get() == airLoop.supplyOutletNode() ) { unsigned oldOutletPort = node.outletPort(); unsigned oldInletPort = node.connectedObjectPort( node.outletPort() ).get(); ModelObject oldSourceModelObject = node; ModelObject oldTargetModelObject = node.outletModelObject().get(); _model.connect( oldSourceModelObject, oldOutletPort, thisModelObject, airInletPort() ); _model.connect( thisModelObject, airOutletPort(), oldTargetModelObject, oldInletPort ); return true; } else if( node == airLoop.supplyOutletNode() ) { unsigned oldOutletPort = node.connectedObjectPort( node.inletPort() ).get(); unsigned oldInletPort = node.inletPort(); ModelObject oldSourceModelObject = node.connectedObject( node.inletPort() ).get(); ModelObject oldTargetModelObject = node; Node newNode( _model ); _model.connect( oldSourceModelObject, oldOutletPort, newNode, newNode.inletPort() ); _model.connect( newNode, newNode.outletPort(), thisModelObject, airInletPort() ); _model.connect( thisModelObject, airOutletPort(), oldTargetModelObject, oldInletPort ); return true; } else { unsigned oldOutletPort = node.outletPort(); unsigned oldInletPort = node.connectedObjectPort( node.outletPort() ).get(); ModelObject oldSourceModelObject = node; ModelObject oldTargetModelObject = node.connectedObject( node.outletPort() ).get(); Node newNode( _model ); _model.connect( oldSourceModelObject, oldOutletPort, thisModelObject, airInletPort() ); _model.connect( thisModelObject, airOutletPort(), newNode, newNode.inletPort() ); _model.connect( newNode, newNode.outletPort(), oldTargetModelObject, oldInletPort ); return true; } } } else if( node.plantLoop() ) { PlantLoop _plantLoop = node.plantLoop().get(); if( ! _plantLoop.demandComponent( node.handle() ) ) { return false; } else { if( plantLoop() ) { removeFromPlantLoop(); } if( node == _plantLoop.demandOutletNode() && node.inletModelObject().get() == _plantLoop.demandInletNode() ) { unsigned oldOutletPort = node.connectedObjectPort( node.inletPort() ).get(); unsigned oldInletPort = node.inletPort(); ModelObject oldSourceModelObject = node.connectedObject( node.inletPort() ).get(); ModelObject oldTargetModelObject = node; _model.connect( oldSourceModelObject, oldOutletPort, thisModelObject, waterInletPort() ); _model.connect( thisModelObject, waterOutletPort(), oldTargetModelObject, oldInletPort ); return true; } else if( node == _plantLoop.demandOutletNode() ) { unsigned oldOutletPort = node.connectedObjectPort( node.inletPort() ).get(); unsigned oldInletPort = node.inletPort(); ModelObject oldSourceModelObject = node.connectedObject( node.inletPort() ).get(); ModelObject oldTargetModelObject = node; Node newNode( _model ); _model.connect( oldSourceModelObject, oldOutletPort, newNode, newNode.inletPort() ); _model.connect( newNode, newNode.outletPort(), thisModelObject, waterInletPort() ); _model.connect( thisModelObject, waterOutletPort(), oldTargetModelObject, oldInletPort ); return true; } else { unsigned oldOutletPort = node.outletPort(); unsigned oldInletPort = node.connectedObjectPort( node.outletPort() ).get(); ModelObject oldSourceModelObject = node; ModelObject oldTargetModelObject = node.connectedObject( node.outletPort() ).get(); Node newNode( _model ); _model.connect( oldSourceModelObject, oldOutletPort, thisModelObject, waterInletPort() ); _model.connect( thisModelObject, waterOutletPort(), newNode, newNode.inletPort() ); _model.connect( newNode, newNode.outletPort(), oldTargetModelObject, oldInletPort ); return true; } } } else { return false; } }
std::vector<IdfObject> AirTerminalSingleDuctInletSideMixer_Impl::remove() { Model _model = this->model(); AirTerminalSingleDuctInletSideMixer thisObject = this->getObject<AirTerminalSingleDuctInletSideMixer>(); boost::optional<ThermalZone> t_thermalZone; boost::optional<ZoneHVACComponent> t_zoneComp; if( boost::optional<AirLoopHVAC> t_airLoopHVAC = airLoopHVAC() ) { std::vector<ZoneHVACComponent> zoneComps = subsetCastVector<ZoneHVACComponent>(t_airLoopHVAC->demandComponents(thisObject,t_airLoopHVAC->demandOutletNode())); if( ! zoneComps.empty() ) { t_zoneComp = zoneComps.front(); t_thermalZone = t_zoneComp->thermalZone(); t_zoneComp->removeFromThermalZone(); } } boost::optional<ModelObject> sourceModelObject = this->inletModelObject(); boost::optional<unsigned> sourcePort = this->connectedObjectPort(this->inletPort()); boost::optional<ModelObject> targetModelObject = this->outletModelObject(); boost::optional<unsigned> targetPort = this->connectedObjectPort(this->outletPort()); std::vector<ThermalZone> thermalZones = _model.getConcreteModelObjects<ThermalZone>(); for( auto & thermalZone : thermalZones ) { std::vector<ModelObject> equipment = thermalZone.equipment(); if( std::find(equipment.begin(),equipment.end(),thisObject) != equipment.end() ) { thermalZone.removeEquipment(thisObject); break; } } if( sourcePort && sourceModelObject && targetPort && targetModelObject ) { if( boost::optional<Node> inletNode = sourceModelObject->optionalCast<Node>() ) { if( boost::optional<ModelObject> source2ModelObject = inletNode->inletModelObject() ) { if( boost::optional<unsigned> source2Port = inletNode->connectedObjectPort(inletNode->inletPort()) ) { _model.connect( source2ModelObject.get(), source2Port.get(), targetModelObject.get(), targetPort.get() ); inletNode->disconnect(); inletNode->remove(); std::vector<IdfObject> result = StraightComponent_Impl::remove(); if( t_thermalZone ) { t_zoneComp->addToThermalZone(t_thermalZone.get()); } return result; } } } } model().disconnect(getObject<ModelObject>(),inletPort()); model().disconnect(getObject<ModelObject>(),outletPort()); return StraightComponent_Impl::remove(); }
boost::optional<ModelObject> HVACComponent_Impl::airLoopHVACAsModelObject() const { if (OptionalAirLoopHVAC intermediate = airLoopHVAC()) { return *intermediate; } return boost::none; }
OptionalModelObject ReverseTranslator::translateAirLoopHVAC( const WorkspaceObject & workspaceObject ) { if( workspaceObject.iddObject().type() != IddObjectType::AirLoopHVAC ) { LOG(Error, "WorkspaceObject is not IddObjectType: AirLoopHVAC"); return boost::none; } OptionalModelObject result; boost::optional<double> val; boost::optional<std::string> optionalString; Workspace _workspace = workspaceObject.workspace(); openstudio::model::AirLoopHVAC airLoopHVAC( m_model ); boost::optional<std::string> supplyInletNodeName = workspaceObject.getString(AirLoopHVACFields::SupplySideInletNodeName); boost::optional<std::string> supplyOutletNodeName = workspaceObject.getString(AirLoopHVACFields::SupplySideOutletNodeNames); boost::optional<std::string> demandInletNodeName = workspaceObject.getString(AirLoopHVACFields::DemandSideInletNodeNames); boost::optional<std::string> demandOutletNodeName = workspaceObject.getString(AirLoopHVACFields::DemandSideOutletNodeName); Node supplyInletNode = airLoopHVAC.supplyInletNode(); Node supplyOutletNode = airLoopHVAC.supplyOutletNode(); Node demandInletNode = airLoopHVAC.demandInletNode(); Node demandOutletNode = airLoopHVAC.demandOutletNode(); if( supplyInletNodeName ) { supplyInletNode.setName(supplyInletNodeName.get()); } if( supplyOutletNodeName ) { supplyOutletNode.setName(supplyOutletNodeName.get()); } if( demandInletNodeName ) { demandInletNode.setName(demandInletNodeName.get()); } if( demandOutletNodeName ) { demandOutletNode.setName(demandOutletNodeName.get()); } optionalString = workspaceObject.getString(AirLoopHVACFields::Name); if( optionalString ) { airLoopHVAC.setName(optionalString.get()); } optionalString = workspaceObject.getString(AirLoopHVACFields::DesignSupplyAirFlowRate); if( optionalString && istringEqual(optionalString.get(),"AutoSize") ) { airLoopHVAC.autosizeDesignSupplyAirFlowRate(); } else if( (val = workspaceObject.getDouble(AirLoopHVACFields::DesignSupplyAirFlowRate)) ) { airLoopHVAC.setDesignSupplyAirFlowRate(val.get()); } // Go find the supply branch. // Currently only supporting one supply branch. // Dual ducts are not supported. OptionalWorkspaceObject _supplyBranchList; OptionalWorkspaceObject _supplyBranch; _supplyBranchList = workspaceObject.getTarget(AirLoopHVACFields::BranchListName); if( _supplyBranchList ) { _supplyBranch = _supplyBranchList->getExtensibleGroup(0).cast<WorkspaceExtensibleGroup>().getTarget(BranchListExtensibleFields::BranchName); if( ! _supplyBranch ) { LOG(Error, _supplyBranchList->briefDescription() << ": Missing supply branch"); } else { // March through the equipment on the supply branch and convert them. for( unsigned i = 0; ! _supplyBranch->getExtensibleGroup(i).empty(); i++ ) { WorkspaceExtensibleGroup eg = _supplyBranch->getExtensibleGroup(i).cast<WorkspaceExtensibleGroup>(); boost::optional<std::string> componentName = eg.getString(BranchExtensibleFields::ComponentName); boost::optional<std::string> componentType = eg.getString(BranchExtensibleFields::ComponentObjectType); boost::optional<std::string> componentInletNodeName = eg.getString(BranchExtensibleFields::ComponentInletNodeName); boost::optional<std::string> componentOutletNodeName = eg.getString(BranchExtensibleFields::ComponentOutletNodeName); boost::optional<WorkspaceObject> wo; OptionalNode node; OptionalModelObject targetModelObject; if( componentName && (componentName.get() != "") && componentType && (componentType.get() != "") ) { IddObjectType iddType(componentType.get()); wo = _workspace.getObjectByTypeAndName(iddType,componentName.get()); } if( wo ) { targetModelObject = translateAndMapWorkspaceObject( wo.get() ); if( !targetModelObject) { LOG(Error, "Error importing object: " << wo->briefDescription() ); continue; } if( OptionalHVACComponent hvacComponent = targetModelObject->optionalCast<HVACComponent>() ) { Node node = airLoopHVAC.supplyOutletNode(); if( hvacComponent->addToNode(node) ) { if( boost::optional<StraightComponent> straightComponent = hvacComponent->optionalCast<StraightComponent>() ) { Node outletNode = straightComponent->outletModelObject()->cast<Node>(); Node inletNode = straightComponent->inletModelObject()->cast<Node>(); if( componentOutletNodeName ) { outletNode.setName(componentOutletNodeName.get()); } if( componentInletNodeName ) { inletNode.setName(componentInletNodeName.get()); } } else if( boost::optional<AirLoopHVACOutdoorAirSystem> oaSystem = hvacComponent->optionalCast<AirLoopHVACOutdoorAirSystem>() ) { Node outletNode = oaSystem->mixedAirModelObject()->cast<Node>(); Node inletNode = oaSystem->returnAirModelObject()->cast<Node>(); if( componentOutletNodeName ) { outletNode.setName(componentOutletNodeName.get()); } if( componentInletNodeName ) { inletNode.setName(componentInletNodeName.get()); } } } } } else { LOG(Error, _supplyBranch->briefDescription() << ": Missing object listed at ComponentName " << i); } } } } else { LOG( Error, workspaceObject.briefDescription() << ": Missing supply branch list, " << "Supply equipment will be incomplete"); } // March through the zone on the demand side and add branches for them. if( demandOutletNodeName ) { // Find the zone mixer for this air loop std::vector<WorkspaceObject> _airLoopHVACZoneMixers; _airLoopHVACZoneMixers = workspaceObject.workspace().getObjectsByType(IddObjectType::AirLoopHVAC_ZoneMixer); boost::optional<WorkspaceObject> _airLoopHVACZoneMixer; for( const auto & elem : _airLoopHVACZoneMixers ) { boost::optional<std::string> mixerOutletNodeName; mixerOutletNodeName = elem.getString(AirLoopHVAC_ZoneMixerFields::OutletNodeName); if( mixerOutletNodeName && mixerOutletNodeName.get() == demandOutletNodeName.get() ) { _airLoopHVACZoneMixer = elem; break; } } if( _airLoopHVACZoneMixer ) { for( int i = 2; _airLoopHVACZoneMixer->getString(i); i++ ) { std::vector<WorkspaceObject> _zoneHVACEquipmentConnections; std::string mixerInletNodeName = _airLoopHVACZoneMixer->getString(i).get(); _zoneHVACEquipmentConnections = _workspace.getObjectsByType(IddObjectType::ZoneHVAC_EquipmentConnections); for( const auto & _zoneHVACEquipmentConnection : _zoneHVACEquipmentConnections ) { OptionalString returnAirNodeName = _zoneHVACEquipmentConnection.getString(ZoneHVAC_EquipmentConnectionsFields::ZoneReturnAirNodeName); OptionalString inletAirNodeName = _zoneHVACEquipmentConnection.getString(ZoneHVAC_EquipmentConnectionsFields::ZoneAirInletNodeorNodeListName); OptionalString zoneName = _zoneHVACEquipmentConnection.getString(ZoneHVAC_EquipmentConnectionsFields::ZoneName); OptionalString zoneEquipListName = _zoneHVACEquipmentConnection.getString(ZoneHVAC_EquipmentConnectionsFields::ZoneConditioningEquipmentListName); OptionalWorkspaceObject _zone; OptionalWorkspaceObject _zoneEquipmentList; OptionalWorkspaceObject _zoneEquipment; OptionalWorkspaceObject _airTerminal; if( returnAirNodeName && returnAirNodeName.get() == mixerInletNodeName && zoneName && zoneEquipListName ) { _zone = _workspace.getObjectByTypeAndName(IddObjectType::Zone,*zoneName); _zoneEquipmentList = _workspace.getObjectByTypeAndName(IddObjectType::ZoneHVAC_EquipmentList,zoneEquipListName.get()); if( ! _zone ) { LOG( Error, airLoopHVAC.briefDescription() << " is connected to a zone that does not exist." ); break; } if( ! _zoneEquipmentList ) { LOG( Error, _zone->briefDescription() << " does not have a zone equipment list, but it is attached to a loop." ); break; } for( int j = 1; (optionalString = _zoneEquipmentList->getString(j)); j = j + 4 ) { boost::optional<std::string> zoneEquipmentName = _zoneEquipmentList->getString(j+1) ; // Possible Zone Equipment // // ZoneHVAC:AirDistributionUnit // AirTerminal:SingleDuct:Uncontrolled // ZoneHVAC:EnergyRecoveryVentilator // ZoneHVAC:FourPipeFanCoil // ZoneHVAC:OutdoorAirUnit // ZoneHVAC:PackagedTerminalAirConditioner // ZoneHVAC:PackagedTerminalHeatPump // ZoneHVAC:UnitHeater // ZoneHVAC:UnitVentilator // ZoneHVAC:VentilatedSlab // ZoneHVAC:WaterToAirHeatPump // ZoneHVAC:WindowAirConditioner // ZoneHVAC:Baseboard:RadiantConvective:Electric // ZoneHVAC:Baseboard:RadiantConvective:Water // ZoneHVAC:Baseboard:RadiantConvective:Steam // ZoneHVAC:Baseboard:Convective:Electric // ZoneHVAC:Baseboard:Convective:Water // ZoneHVAC:HighTemperatureRadiant // ZoneHVAC:LowTemperatureRadiant:VariableFlow // ZoneHVAC:LowTemperatureRadiant:ConstantFlow // ZoneHVAC:LowTemperatureRadiant:Electric // ZoneHVAC:Dehumidifier:DX // ZoneHVAC:IdealLoadsAirSystem // Fan:ZoneExhaust // WaterHeater:HeatPump // if( zoneEquipmentName ) { if( istringEqual(optionalString.get(),"AirTerminal:SingleDuct:Uncontrolled") ) { _airTerminal = _workspace.getObjectByTypeAndName(IddObjectType::AirTerminal_SingleDuct_Uncontrolled,zoneEquipmentName.get()); break; } else if( istringEqual(optionalString.get(),"ZoneHVAC:AirDistributionUnit") ) { boost::optional<WorkspaceObject> _airDistributionUnit = _workspace.getObjectByTypeAndName(IddObjectType::ZoneHVAC_AirDistributionUnit,zoneEquipmentName.get()); if( _airDistributionUnit ) { boost::optional<std::string> airUnitName; boost::optional<std::string> airUnitType; airUnitType = _airDistributionUnit->getString(ZoneHVAC_AirDistributionUnitFields::AirTerminalObjectType); airUnitName = _airDistributionUnit->getString(ZoneHVAC_AirDistributionUnitFields::AirTerminalName); if( airUnitName && airUnitType ) { _airTerminal = _workspace.getObjectByTypeAndName(IddObjectType(airUnitType.get()),airUnitName.get()); } } break; } } } OptionalModelObject airTerminalModelObject; OptionalSpace space; OptionalStraightComponent straightComponent; OptionalThermalZone thermalZone; if( _airTerminal ) { airTerminalModelObject = translateAndMapWorkspaceObject( _airTerminal.get() ); } if( _zone ) { if( OptionalModelObject mo = translateAndMapWorkspaceObject( _zone.get() ) ) { space = mo->optionalCast<Space>(); } } if( space ) { thermalZone = space->thermalZone(); } if( airTerminalModelObject ) { straightComponent = airTerminalModelObject->optionalCast<StraightComponent>(); } bool success = false; if( straightComponent && thermalZone ) { success = airLoopHVAC.addBranchForZone(thermalZone.get(),straightComponent.get()); } else if( thermalZone ) { Model m; success = airLoopHVAC.addBranchForZone(thermalZone.get(),boost::none); } if( success ) { if( inletAirNodeName ) { thermalZone->inletPortList().airLoopHVACModelObject()->cast<Node>().setName(inletAirNodeName.get()); } if( returnAirNodeName ) { thermalZone->returnAirModelObject()->cast<Node>().setName(returnAirNodeName.get()); } } } } } } } return airLoopHVAC; }