From 3436a66149bbac71f64b06654193d17efe58c912 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 28 Feb 2022 16:10:56 -0700 Subject: [PATCH 1/5] Account for broken older gcc/constexpr support --- include/json2cpp/json2cpp.hpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/include/json2cpp/json2cpp.hpp b/include/json2cpp/json2cpp.hpp index 67ea136..d37fa46 100644 --- a/include/json2cpp/json2cpp.hpp +++ b/include/json2cpp/json2cpp.hpp @@ -287,10 +287,7 @@ template struct basic_json [[nodiscard]] constexpr iterator cend() const noexcept { return end(); } - [[nodiscard]] constexpr std::size_t size() const noexcept - { - return size_; - } + [[nodiscard]] constexpr std::size_t size() const noexcept { return size_; } [[nodiscard]] static constexpr std::size_t size(const basic_json &obj) noexcept { @@ -367,7 +364,7 @@ template struct basic_json constexpr static basic_json object() { return basic_json{ data_t{ basic_object_t{} } }; } constexpr static basic_json array() { return basic_json{ data_t{ basic_array_t{} } }; } - template [[nodiscard]] constexpr Type get() const + template[[nodiscard]] constexpr Type get() const { if constexpr (std::is_same_v || std::is_same_v) { if (const auto *uint_value = data.get_if_uinteger(); uint_value != nullptr) { @@ -375,18 +372,20 @@ template struct basic_json } else if (const auto *value = data.get_if_integer(); value != nullptr) { return Type(*value); } + throw std::runtime_error("Incorrect type for get(), integer requested"); } else if constexpr (std::is_same_v) { if (const auto *value = data.get_if_floating_point(); value != nullptr) { return *value; } + throw std::runtime_error("Incorrect type for get(), double requested"); } else if constexpr (std::is_same_v> || std::is_same_v>) { if (const auto *value = data.get_if_string(); value != nullptr) { return *value; } + throw std::runtime_error("Incorrect type for get(), string requested"); } else if constexpr (std::is_same_v) { if (const auto *value = data.get_if_boolean(); value != nullptr) { return *value; } + throw std::runtime_error("Incorrect type for get(), boolean requested"); } else { throw std::runtime_error("Unexpected type for get()"); } - - throw std::runtime_error("Incorrect type for get()"); } [[nodiscard]] constexpr bool is_object() const noexcept { return data.selected == data_t::selected_type::object; } @@ -421,13 +420,13 @@ template struct basic_json data_t data; - std::size_t size_{size(*this)}; + std::size_t size_{ size(*this) }; }; using json = basic_json; using object_t = basic_object_t; using value_pair_t = basic_value_pair_t; using array_t = basic_array_t; -}// namespace constexpr_json +}// namespace json2cpp #endif From f3c52a9133c5a7e7de91874b0f1b4eac54413e4d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 28 Feb 2022 16:11:21 -0700 Subject: [PATCH 2/5] Update EPJson schema file --- examples/Energy+.schema.epJSON | 611 +++++++++++++++++++++++++++++++-- 1 file changed, 591 insertions(+), 20 deletions(-) diff --git a/examples/Energy+.schema.epJSON b/examples/Energy+.schema.epJSON index fd84c97..c9fd429 100644 --- a/examples/Energy+.schema.epJSON +++ b/examples/Energy+.schema.epJSON @@ -6547,7 +6547,18 @@ "type": "number", "note": "Must be evenly divisible into 60", "minimum": 1.0, - "maximum": 60.0 + "maximum": 60.0, + "default": 60.0 + }, + "adjust_schedule_for_daylight_savings": { + "type": "string", + "note": "\"No\" means do not include Daylight Savings Time in the schedule, instead, use the schedule directly from the Schedule:File csv (default) \"Yes\" means include Daylight Savings Time to the schedule", + "enum": [ + "", + "No", + "Yes" + ], + "default": "Yes" } }, "required": [ @@ -6603,6 +6614,10 @@ "minutes_per_item": { "field_name": "Minutes per Item", "field_type": "n" + }, + "adjust_schedule_for_daylight_savings": { + "field_name": "Adjust Schedule for Daylight Savings", + "field_type": "a" } }, "fields": [ @@ -6614,7 +6629,8 @@ "number_of_hours_of_data", "column_separator", "interpolate_to_timestep", - "minutes_per_item" + "minutes_per_item", + "adjust_schedule_for_daylight_savings" ], "alphas": { "fields": [ @@ -6622,7 +6638,8 @@ "schedule_type_limits_name", "file_name", "column_separator", - "interpolate_to_timestep" + "interpolate_to_timestep", + "adjust_schedule_for_daylight_savings" ] }, "numerics": { @@ -6636,7 +6653,7 @@ }, "type": "object", "memo": "A Schedule:File points to a text computer file that has 8760-8784 hours of data.", - "min_fields": 5.0 + "min_fields": 10.0 }, "Material": { "patternProperties": { @@ -17619,7 +17636,7 @@ "extension": "tags" }, "type": "object", - "memo": "Defines a space (room) in the building. All Spaces are part of a Zone. Every Zone contains one or more spaces. Space is an optional input. If a Zone has no Space(s) specified in input then a default Space named will be created. If some surfaces in a Zone are assigned to a space and some are not, then a default Space named -Remainder will be created. Input references to Space Names must have a matching Space object (default space names may not be referenced except in output variable keys).", + "memo": "Defines a space (room) in the building. All Spaces are part of a Zone. Every Zone contains one or more spaces. Space is an optional input. If a Zone has no Space(s) specified in input then a default Space named will be created. If some surfaces in a Zone are assigned to a space and some are not, then a default Space named -Remainder will be created. Input references to Space Names must have a matching Space object (default space names may not be referenced except in output variable keys).", "min_fields": 3.0, "extensible_size": 1.0 }, @@ -17927,7 +17944,7 @@ } }, "type": "object", - "memo": "Defines a thermal zone of the building. Every zone contains one or more Spaces. Space is an optional input. If a Zone has no Space(s) specified in input then a default Space named will be created. If some surfaces in a Zone are assigned to a space and some are not, then a default Space named -Remainder will be created. Input references to Space Names must have a matching Space object (default space names may not be referenced except in output variable keys).", + "memo": "Defines a thermal zone of the building. Every zone contains one or more Spaces. Space is an optional input. If a Zone has no Space(s) specified in input then a default Space named will be created. If some surfaces in a Zone are assigned to a space and some are not, then a default Space named -Remainder will be created. Input references to Space Names must have a matching Space object (default space names may not be referenced except in output variable keys).", "format": "vertices" }, "ZoneList": { @@ -22547,6 +22564,36 @@ "minimum": 0.0, "maximum": 1.0, "default": 0.0 + }, + "nfrc_product_type_for_assembly_calculations": { + "type": "string", + "enum": [ + "", + "CasementDouble", + "CasementSingle", + "CurtainWall", + "DoorSidelite", + "DoorTransom", + "DualAction", + "Fixed", + "Garage", + "Greenhouse", + "HingedEscape", + "HorizontalSlider", + "Jal", + "Pivoted", + "ProjectingDual", + "ProjectingSingle", + "SideHingedDoor", + "Skylight", + "SlidingPatioDoor", + "SpandrelPanel", + "TropicalAwning", + "TubularDaylightingDevice", + "VerticalSlider" + ], + "default": "CurtainWall", + "note": "Used when computing the assembly u-factor, SHGC and visible transmittance for reporting only" } } } @@ -22662,6 +22709,10 @@ "inside_reveal_solar_absorptance": { "field_name": "Inside Reveal Solar Absorptance", "field_type": "n" + }, + "nfrc_product_type_for_assembly_calculations": { + "field_name": "NFRC Product Type for Assembly Calculations", + "field_type": "a" } }, "fields": [ @@ -22689,12 +22740,14 @@ "inside_sill_depth", "inside_sill_solar_absorptance", "inside_reveal_depth", - "inside_reveal_solar_absorptance" + "inside_reveal_solar_absorptance", + "nfrc_product_type_for_assembly_calculations" ], "alphas": { "fields": [ "name", - "divider_type" + "divider_type", + "nfrc_product_type_for_assembly_calculations" ] }, "numerics": { @@ -22727,7 +22780,7 @@ }, "type": "object", "memo": "Specifies the dimensions of a window frame, dividers, and inside reveal surfaces. Referenced by the surface objects for exterior windows and glass doors (ref: FenestrationSurface:Detailed, Window, and GlazedDoor).", - "min_fields": 20.0 + "min_fields": 26.0 }, "WindowProperty:AirflowControl": { "patternProperties": { @@ -44643,7 +44696,7 @@ "reference_temperature": { "type": "number", "units": "C", - "note": "Enter the reference temperature under which the surface crack data were obtained. Suggested value 20C." + "note": "Enter the reference temperature under which the surface crack data were obtained. Suggested value 20C." }, "reference_barometric_pressure": { "type": "number", @@ -66244,7 +66297,7 @@ "extension": "space_specs" }, "type": "object", - "memo": "Defines a list of DesignSpecification:OutdoorAir names which can be referenced as a group. The DesignSpecification:OutdoorAir:SpaceList name may be used in Sizing:Zone and Controller:MechanicalVentilation to specify space-by-space OA requirements and anywhere else that accepts a DesignSpecification:OutdoorAir object name.", + "memo": "Defines a list of DesignSpecification:OutdoorAir names which can be referenced as a group. The DesignSpecification:OutdoorAir:SpaceList name may be used in Sizing:Zone and Controller:MechanicalVentilation to specify space-by-space OA requirements and anywhere else that accepts a DesignSpecification:OutdoorAir object name.", "min_fields": 3.0, "extensible_size": 2.0 }, @@ -66474,7 +66527,7 @@ }, "design_specification_outdoor_air_object_name": { "type": "string", - "note": "Specify the name of a DesignSpecification:OutdoorAir object to specify one set of requirements for the Zone. Use a DesignSpecification:OutdoorAir:SpaceList object name to specify different requirements for Spaces within the Zone.", + "note": "Specify the name of a DesignSpecification:OutdoorAir object to specify one set of requirements for the Zone. Use a DesignSpecification:OutdoorAir:SpaceList object name to specify different requirements for Spaces within the Zone.", "data_type": "object_list", "object_list": [ "DSOASpaceListNames", @@ -67623,7 +67676,7 @@ }, "occupant_diversity": { "default": "Autosize", - "note": "The Occupant Diversity is used to determine a multi-zone system's outdoor air intake when the System Outdoor Air Method is Standard62.1VentilationRateProcedure or the Standard62.1SimplifiedProcedure. If set to be autosized, it will be calculated using the information in the People objects assigned to each zone attached to this system/airloop.", + "note": "The Occupant Diversity is used to determine a multi-zone system's outdoor air intake when the System Outdoor Air Method is Standard62.1VentilationRateProcedure or the Standard62.1SimplifiedProcedure. If set to be autosized, it will be calculated using the information in the People objects assigned to each zone attached to this system/airloop.", "anyOf": [ { "type": "number", @@ -83772,6 +83825,201 @@ "memo": "Central air system air distribution unit, serves as a wrapper for a specific type of air terminal unit. This object is referenced in a ZoneHVAC:EquipmentList.", "min_fields": 4.0 }, + "ZoneHVAC:ExhaustControl": { + "patternProperties": { + "^.*\\S.*$": { + "type": "object", + "properties": { + "availability_schedule_name": { + "type": "string", + "note": "Availability schedule name for this exhaust system. Schedule value > 0 means it is available. If this field is blank, the exhaust system is always available. If the attached AirLoopHVAC:ExhaustSystem is off, then the flow will be zero.", + "data_type": "object_list", + "object_list": [ + "ScheduleNames" + ] + }, + "zone_name": { + "type": "string", + "note": "Zone the exhaust inlet node is part of", + "data_type": "object_list", + "object_list": [ + "ZoneNames" + ] + }, + "inlet_node_name": { + "type": "string", + "note": "Inlet node name for the exhaust. Must be a zone exhaust node." + }, + "outlet_node_name": { + "type": "string", + "note": "Outlet node name for the exhaust" + }, + "design_exhaust_flow_rate": { + "units": "m3/s", + "default": "Autosize", + "anyOf": [ + { + "type": "number", + "exclusiveMinimum": 0.0 + }, + { + "type": "string", + "enum": [ + "", + "Autosize" + ] + } + ] + }, + "flow_control_type": { + "type": "string", + "note": "Control type of the zone exhaust flow", + "enum": [ + "", + "FollowSupply", + "Scheduled" + ], + "default": "Scheduled" + }, + "exhaust_flow_fraction_schedule_name": { + "type": "string", + "note": "Schedule name of the exhaust flow fraction. Used only with Scheduled control type. If this field is blank, the flow fraction is always 1.0.", + "data_type": "object_list", + "object_list": [ + "ScheduleNames" + ] + }, + "supply_node_or_nodelist_name": { + "type": "string", + "note": "Used only with FollowSupply control type." + }, + "minimum_zone_temperature_limit_schedule_name": { + "type": "string", + "note": "Schedule name of the Minimum Zone Temperature Limit in degree Celsius If this field is blank, there is no limit.", + "data_type": "object_list", + "object_list": [ + "ScheduleNames" + ] + }, + "minimum_exhaust_flow_fraction_schedule_name": { + "type": "string", + "note": "Schedule name of the minimum exhaust flow fraction. Applied when the zone temperature falls below the Minimum Zone Temperature Limit.", + "data_type": "object_list", + "object_list": [ + "ScheduleNames" + ] + }, + "balanced_exhaust_fraction_schedule_name": { + "type": "string", + "note": "Schedule name of the Balanced Exhaust Fraction.", + "data_type": "object_list", + "object_list": [ + "ScheduleNames" + ] + } + }, + "required": [ + "zone_name", + "inlet_node_name", + "outlet_node_name" + ] + } + }, + "group": "Zone HVAC Air Loop Terminal Units", + "name": { + "type": "string", + "is_required": true + }, + "additionalProperties": false, + "legacy_idd": { + "field_info": { + "name": { + "field_name": "Name", + "field_type": "a" + }, + "availability_schedule_name": { + "field_name": "Availability Schedule Name", + "field_type": "a" + }, + "zone_name": { + "field_name": "Zone Name", + "field_type": "a" + }, + "inlet_node_name": { + "field_name": "Inlet Node Name", + "field_type": "a" + }, + "outlet_node_name": { + "field_name": "Outlet Node Name", + "field_type": "a" + }, + "design_exhaust_flow_rate": { + "field_name": "Design Exhaust Flow Rate", + "field_type": "n" + }, + "flow_control_type": { + "field_name": "Flow Control Type", + "field_type": "a" + }, + "exhaust_flow_fraction_schedule_name": { + "field_name": "Exhaust Flow Fraction Schedule Name", + "field_type": "a" + }, + "supply_node_or_nodelist_name": { + "field_name": "Supply Node or NodeList Name", + "field_type": "a" + }, + "minimum_zone_temperature_limit_schedule_name": { + "field_name": "Minimum Zone Temperature Limit Schedule Name", + "field_type": "a" + }, + "minimum_exhaust_flow_fraction_schedule_name": { + "field_name": "Minimum Exhaust Flow Fraction Schedule Name", + "field_type": "a" + }, + "balanced_exhaust_fraction_schedule_name": { + "field_name": "Balanced Exhaust Fraction Schedule Name", + "field_type": "a" + } + }, + "fields": [ + "name", + "availability_schedule_name", + "zone_name", + "inlet_node_name", + "outlet_node_name", + "design_exhaust_flow_rate", + "flow_control_type", + "exhaust_flow_fraction_schedule_name", + "supply_node_or_nodelist_name", + "minimum_zone_temperature_limit_schedule_name", + "minimum_exhaust_flow_fraction_schedule_name", + "balanced_exhaust_fraction_schedule_name" + ], + "alphas": { + "fields": [ + "name", + "availability_schedule_name", + "zone_name", + "inlet_node_name", + "outlet_node_name", + "flow_control_type", + "exhaust_flow_fraction_schedule_name", + "supply_node_or_nodelist_name", + "minimum_zone_temperature_limit_schedule_name", + "minimum_exhaust_flow_fraction_schedule_name", + "balanced_exhaust_fraction_schedule_name" + ] + }, + "numerics": { + "fields": [ + "design_exhaust_flow_rate" + ] + } + }, + "type": "object", + "memo": "Defines a controlled exhaust flow from a zone which finally feeds into one of AirLoopHVAC:ZoneMixer's inlets, which are part of an AirLoopHVAC:ExhaustSystem." + }, "ZoneHVAC:EquipmentList": { "patternProperties": { "^.*\\S.*$": { @@ -86490,7 +86738,7 @@ "design_inlet_water_temperature": { "units": "C", "default": "Autosize", - "note": "This input field is optional. If specified, it is used for sizing the coil Design Geomtery Parameters. If autosized, the Design Loop Exit Temperature value specified in Sizing:Plant object is used for sizing the coil Design Geomtery Parameters. If the autosized value is higher than the coil design outlet air temperature, then the design inlet water temperature value is reset to coil design outlet air temperature minus 5.0 DeltaC.", + "note": "This input field is optional. If specified, it is used for sizing the coil Design Geomtery Parameters. If autosized, the Design Loop Exit Temperature value specified in Sizing:Plant object is used for sizing the coil Design Geomtery Parameters. If the autosized value is higher than the coil design outlet air temperature, then the design inlet water temperature value is reset to coil design outlet air temperature minus 5.0 DeltaC.", "anyOf": [ { "type": "number", @@ -86742,7 +86990,7 @@ "None" ], "default": "None", - "note": "None = meet sensible load only. Valid with all cooling coil types. When a heat exchanger assisted cooling coil is used, the heat exchanger is locked on at all times. Multimode = activate water coil and meet sensible load. If no sensible load exists, and Run on Latent Load = Yes, and a latent load exists, the coil will operate to meet the latent load. If the latent load cannot be met the heat exchanger will be activated. Valid only with cooling coil type CoilSystem:Cooling:Water:HeatExchangerAssisted. CoolReheat = cool beyond the dry-bulb setpoint as required to meet the humidity setpoint. Valid with all cooling coil types. When a heat exchanger assisted cooling coil is used, the heat exchanger is locked on at all times. For all dehumidification controls, the max humidity setpoint on the Sensor Node is used. SetpointManager:SingleZone:Humidity:Maximum, SetpointManager:MultiZone:Humidity:Maximum, or SetpointManager:MultiZone:MaximumHumidity:Average, and SetpointManager:OutdoorAirPretreat (optional) objects." + "note": "None = meet sensible load only. Valid with all cooling coil types. When a heat exchanger assisted cooling coil is used, the heat exchanger is locked on at all times. Multimode = activate water coil and meet sensible load. If no sensible load exists, and Run on Latent Load = Yes, and a latent load exists, the coil will operate to meet the latent load. If the latent load cannot be met the heat exchanger will be activated. Valid only with cooling coil type CoilSystem:Cooling:Water:HeatExchangerAssisted. CoolReheat = cool beyond the dry-bulb setpoint as required to meet the humidity setpoint. Valid with all cooling coil types. When a heat exchanger assisted cooling coil is used, the heat exchanger is locked on at all times. For all dehumidification controls, the max humidity setpoint on the Sensor Node is used. SetpointManager:SingleZone:Humidity:Maximum, SetpointManager:MultiZone:Humidity:Maximum, or SetpointManager:MultiZone:MaximumHumidity:Average, and SetpointManager:OutdoorAirPretreat (optional) objects." }, "run_on_sensible_load": { "type": "string", @@ -86789,7 +87037,7 @@ }, "companion_coil_used_for_heat_recovery": { "type": "string", - "note": "Only used for heat recovery loops. Entering a coil name indicates a heat recovery loop is specified. Coil listed is connected in series with this objects coil on demand side branch of a plant loop. A dedicated plant loop with no supply side equipment, other than a pump, is currently required. Only Coil:Cooling:Water coil type is currently allowed for heat recovery loops.", + "note": "Only used for heat recovery loops. Entering a coil name indicates a heat recovery loop is specified. Coil listed is connected in series with this objects coil on demand side branch of a plant loop. A dedicated plant loop with no supply side equipment, other than a pump, is currently required. Only Coil:Cooling:Water coil type is currently allowed for heat recovery loops.", "data_type": "object_list", "object_list": [ "CoolingCoilsWater" @@ -119010,7 +119258,7 @@ }, "design_specification_outdoor_air_object_name": { "type": "string", - "note": "Specify the name of a DesignSpecification:OutdoorAir object to specify one set of requirements for the Zone. Use a DesignSpecification:OutdoorAir:SpaceList object name to specify different requirements for Spaces within the Zone. If left blank, the name will be taken from the Sizing:Zone object for this zone. If no specification is found for this zone, then the default of 0.00944 m3/s-person will be used.", + "note": "Specify the name of a DesignSpecification:OutdoorAir object to specify one set of requirements for the Zone. Use a DesignSpecification:OutdoorAir:SpaceList object name to specify different requirements for Spaces within the Zone. If left blank, the name will be taken from the Sizing:Zone object for this zone. If no specification is found for this zone, then the default of 0.00944 m3/s-person will be used.", "data_type": "object_list", "object_list": [ "DSOASpaceListNames", @@ -120535,6 +120783,90 @@ "memo": "A return air path can only contain one AirLoopHVAC:ZoneMixer and one or more AirLoopHVAC:ReturnPlenum objects.", "extensible_size": 2.0 }, + "AirLoopHVAC:ExhaustSystem": { + "patternProperties": { + "^.*\\S.*$": { + "type": "object", + "properties": { + "zone_mixer_name": { + "type": "string", + "data_type": "object_list", + "note": "The name of the exhaust system AirLoopHVAC:ZoneMixer", + "object_list": [ + "ZoneMixers" + ] + }, + "fan_object_type": { + "type": "string", + "enum": [ + "Fan:ComponentModel", + "Fan:SystemModel" + ] + }, + "fan_name": { + "type": "string", + "data_type": "object_list", + "object_list": [ + "FansComponentModel", + "FansSystemModel" + ] + } + }, + "required": [ + "zone_mixer_name", + "fan_object_type", + "fan_name" + ] + } + }, + "group": "Air Distribution", + "name": { + "type": "string", + "is_required": true, + "note": "Name of the exhaust system" + }, + "additionalProperties": false, + "legacy_idd": { + "field_info": { + "name": { + "field_name": "Name", + "field_type": "a" + }, + "zone_mixer_name": { + "field_name": "Zone Mixer Name", + "field_type": "a" + }, + "fan_object_type": { + "field_name": "Fan Object Type", + "field_type": "a" + }, + "fan_name": { + "field_name": "Fan Name", + "field_type": "a" + } + }, + "fields": [ + "name", + "zone_mixer_name", + "fan_object_type", + "fan_name" + ], + "alphas": { + "fields": [ + "name", + "zone_mixer_name", + "fan_object_type", + "fan_name" + ] + }, + "numerics": { + "fields": [] + } + }, + "type": "object", + "memo": "Defines a general exhaust system with a central exhaust fan drawing from one or more ZoneHVAC:ExhaustControl outlet nodes via an AirLoopHVAC:ZoneMixer.", + "min_fields": 4.0 + }, "AirLoopHVAC:DedicatedOutdoorAirSystem": { "patternProperties": { "^.*\\S.*$": { @@ -161251,6 +161583,246 @@ "memo": "This setpoint manager is used to place a temperature setpoint on a plant supply outlet node based on a target return water setpoint. The setpoint manager attempts to achieve the desired return water temperature by adjusting the supply temperature setpoint based on the plant conditions at each system time step.", "min_fields": 7.0 }, + "SetpointManager:SystemNodeReset:Temperature": { + "patternProperties": { + "^.*\\S.*$": { + "type": "object", + "properties": { + "control_variable": { + "type": "string", + "enum": [ + "MaximumTemperature", + "MinimumTemperature", + "Temperature" + ] + }, + "setpoint_at_low_reference_temperature": { + "type": "number", + "units": "C" + }, + "setpoint_at_high_reference_temperature": { + "type": "number", + "units": "C" + }, + "low_reference_temperature": { + "type": "number", + "units": "C" + }, + "high_reference_temperature": { + "type": "number", + "units": "C" + }, + "reference_node_name": { + "type": "string", + "note": "The name of an HVAC system node that gets referenced." + }, + "setpoint_node_or_nodelist_name": { + "type": "string", + "note": "Node(s) at which temperature will be set" + } + }, + "required": [ + "control_variable", + "setpoint_at_low_reference_temperature", + "setpoint_at_high_reference_temperature", + "low_reference_temperature", + "high_reference_temperature", + "reference_node_name", + "setpoint_node_or_nodelist_name" + ] + } + }, + "group": "Setpoint Managers", + "name": { + "type": "string", + "is_required": true + }, + "additionalProperties": false, + "legacy_idd": { + "field_info": { + "name": { + "field_name": "Name", + "field_type": "a" + }, + "control_variable": { + "field_name": "Control Variable", + "field_type": "a" + }, + "setpoint_at_low_reference_temperature": { + "field_name": "Setpoint at Low Reference Temperature", + "field_type": "n" + }, + "setpoint_at_high_reference_temperature": { + "field_name": "Setpoint at High Reference Temperature", + "field_type": "n" + }, + "low_reference_temperature": { + "field_name": "Low Reference Temperature", + "field_type": "n" + }, + "high_reference_temperature": { + "field_name": "High Reference Temperature", + "field_type": "n" + }, + "reference_node_name": { + "field_name": "Reference Node Name", + "field_type": "a" + }, + "setpoint_node_or_nodelist_name": { + "field_name": "Setpoint Node or NodeList Name", + "field_type": "a" + } + }, + "fields": [ + "name", + "control_variable", + "setpoint_at_low_reference_temperature", + "setpoint_at_high_reference_temperature", + "low_reference_temperature", + "high_reference_temperature", + "reference_node_name", + "setpoint_node_or_nodelist_name" + ], + "alphas": { + "fields": [ + "name", + "control_variable", + "reference_node_name", + "setpoint_node_or_nodelist_name" + ] + }, + "numerics": { + "fields": [ + "setpoint_at_low_reference_temperature", + "setpoint_at_high_reference_temperature", + "low_reference_temperature", + "high_reference_temperature" + ] + } + }, + "type": "object", + "memo": "This Setpoint Manager is used to place a temperature setpoint on a system node according to the reference (e.g., return) temperature using a reset rule. The temperature setpoint is obtained by retrieving the temperature of the user specified reference system node." + }, + "SetpointManager:SystemNodeReset:Humidity": { + "patternProperties": { + "^.*\\S.*$": { + "type": "object", + "properties": { + "control_variable": { + "type": "string", + "enum": [ + "HumidityRatio", + "MaximumHumidityRatio", + "MinimumHumidityRatio" + ] + }, + "setpoint_at_low_reference_humidity_ratio": { + "type": "number", + "units": "kgWater/kgDryAir" + }, + "setpoint_at_high_reference_humidity_ratio": { + "type": "number", + "units": "kgWater/kgDryAir" + }, + "low_reference_humidity_ratio": { + "type": "number", + "units": "kgWater/kgDryAir" + }, + "high_reference_humidity_ratio": { + "type": "number", + "units": "kgWater/kgDryAir" + }, + "reference_node_name": { + "type": "string", + "note": "The name of an HVAC system node that gets referenced." + }, + "setpoint_node_or_nodelist_name": { + "type": "string", + "note": "Node(s) at which humidity ratio will be set" + } + }, + "required": [ + "control_variable", + "setpoint_at_low_reference_humidity_ratio", + "setpoint_at_high_reference_humidity_ratio", + "low_reference_humidity_ratio", + "high_reference_humidity_ratio", + "reference_node_name", + "setpoint_node_or_nodelist_name" + ] + } + }, + "group": "Setpoint Managers", + "name": { + "type": "string", + "is_required": true + }, + "additionalProperties": false, + "legacy_idd": { + "field_info": { + "name": { + "field_name": "Name", + "field_type": "a" + }, + "control_variable": { + "field_name": "Control Variable", + "field_type": "a" + }, + "setpoint_at_low_reference_humidity_ratio": { + "field_name": "Setpoint at Low Reference Humidity Ratio", + "field_type": "n" + }, + "setpoint_at_high_reference_humidity_ratio": { + "field_name": "Setpoint at High Reference Humidity Ratio", + "field_type": "n" + }, + "low_reference_humidity_ratio": { + "field_name": "Low Reference Humidity Ratio", + "field_type": "n" + }, + "high_reference_humidity_ratio": { + "field_name": "High Reference Humidity Ratio", + "field_type": "n" + }, + "reference_node_name": { + "field_name": "Reference Node Name", + "field_type": "a" + }, + "setpoint_node_or_nodelist_name": { + "field_name": "Setpoint Node or NodeList Name", + "field_type": "a" + } + }, + "fields": [ + "name", + "control_variable", + "setpoint_at_low_reference_humidity_ratio", + "setpoint_at_high_reference_humidity_ratio", + "low_reference_humidity_ratio", + "high_reference_humidity_ratio", + "reference_node_name", + "setpoint_node_or_nodelist_name" + ], + "alphas": { + "fields": [ + "name", + "control_variable", + "reference_node_name", + "setpoint_node_or_nodelist_name" + ] + }, + "numerics": { + "fields": [ + "setpoint_at_low_reference_humidity_ratio", + "setpoint_at_high_reference_humidity_ratio", + "low_reference_humidity_ratio", + "high_reference_humidity_ratio" + ] + } + }, + "type": "object", + "memo": "This Setpoint Manager is used to place a humidity ratio setpoint on a system node according to the reference (e.g., return) humidity ratio using a reset rule. The humidity ratio setpoint is obtained by retrieving the humidity ratio of the user specified reference system node." + }, "Refrigeration:Case": { "patternProperties": { "^.*\\S.*$": { @@ -175015,7 +175587,7 @@ "extension": "surfaces" }, "type": "object", - "memo": "Used for harvesting rainwater falling on building surfaces. The rainwater is sent to a WaterUse:Storage object. In order to use this object it is necessary to also include a Site:Precipitation object to describe the rates of rainfall.", + "memo": "Used for harvesting rainwater falling on building surfaces. The rainwater is sent to a WaterUse:Storage object. In versions up till Version 9.6, it is necessary to also include a Site:Precipitation object to describe the rates of rainfall, in order to use this object. In later versions, if the Site:Precipitation is not present, precipitation depth in the weather input .epw will be used instead. When this is the case, please make sure the precipitation in the .epw is accurate.", "extensible_size": 1.0 }, "FaultModel:TemperatureSensorOffset:OutdoorAir": { @@ -199542,7 +200114,6 @@ "extension": "global_py_vars" }, "type": "object", - "maxProperties": 1, "memo": "This object defines name identifiers for custom Python Plugin variable data that should be shared among all running Python Plugins.", "min_fields": 2.0, "extensible_size": 1.0 @@ -199799,5 +200370,5 @@ "GlobalGeometryRules" ], "epJSON_schema_version": "22.1.0", - "epJSON_schema_build": "2f3618a629" + "epJSON_schema_build": "7b4360192f" } From bfe2f47defa25227abeff8f1520b1584ef58f230 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 28 Feb 2022 16:21:51 -0700 Subject: [PATCH 3/5] Further workarounds for buggy gcc --- include/json2cpp/json2cpp.hpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/include/json2cpp/json2cpp.hpp b/include/json2cpp/json2cpp.hpp index d37fa46..9ae391b 100644 --- a/include/json2cpp/json2cpp.hpp +++ b/include/json2cpp/json2cpp.hpp @@ -366,26 +366,36 @@ template struct basic_json template[[nodiscard]] constexpr Type get() const { + bool error = false; if constexpr (std::is_same_v || std::is_same_v) { if (const auto *uint_value = data.get_if_uinteger(); uint_value != nullptr) { return Type(*uint_value); } else if (const auto *value = data.get_if_integer(); value != nullptr) { return Type(*value); } - throw std::runtime_error("Incorrect type for get(), integer requested"); + error = true; } else if constexpr (std::is_same_v) { if (const auto *value = data.get_if_floating_point(); value != nullptr) { return *value; } - throw std::runtime_error("Incorrect type for get(), double requested"); + error = true; } else if constexpr (std::is_same_v> || std::is_same_v>) { if (const auto *value = data.get_if_string(); value != nullptr) { return *value; } - throw std::runtime_error("Incorrect type for get(), string requested"); + error = true; } else if constexpr (std::is_same_v) { if (const auto *value = data.get_if_boolean(); value != nullptr) { return *value; } - throw std::runtime_error("Incorrect type for get(), boolean requested"); + error = true; } else { throw std::runtime_error("Unexpected type for get()"); } + + if (error) { + // we have this boolean only because of a broken gcc implementation + // that incorrect says this is not a constexpr function + throw std::runtime_error("Type mismatch in get()"); + } else { + // this code is terrible and it makes me sad + return Type{}; + } } [[nodiscard]] constexpr bool is_object() const noexcept { return data.selected == data_t::selected_type::object; } From 64adc861e6da3778b2e212b14a15422dc9bd97ab Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 1 Mar 2022 15:59:09 -0700 Subject: [PATCH 4/5] Fix compat with nlohmann::json --- include/json2cpp/json2cpp.hpp | 75 +++++++++++++++++---------- include/json2cpp/json2cpp_adapter.hpp | 2 +- 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/include/json2cpp/json2cpp.hpp b/include/json2cpp/json2cpp.hpp index 9ae391b..894f3ce 100644 --- a/include/json2cpp/json2cpp.hpp +++ b/include/json2cpp/json2cpp.hpp @@ -191,6 +191,8 @@ template struct basic_json struct iterator { + constexpr iterator() noexcept = default; + constexpr explicit iterator(const basic_json &value, std::size_t index = 0) noexcept : parent_value_(&value), index_{ index } {} @@ -289,6 +291,8 @@ template struct basic_json [[nodiscard]] constexpr std::size_t size() const noexcept { return size_; } + [[nodiscard]] constexpr bool empty() const noexcept { return size_ == 0; } + [[nodiscard]] static constexpr std::size_t size(const basic_json &obj) noexcept { if (obj.is_null()) { return 0; } @@ -308,16 +312,7 @@ template struct basic_json } } - [[nodiscard]] constexpr iterator find(const std::basic_string_view key) const noexcept - { - for (auto itr = begin(); itr != end(); ++itr) { - if (itr.key() == key) { return itr; } - } - - return end(); - } - - [[nodiscard]] constexpr const basic_json &operator[](const std::basic_string_view key) const + [[nodiscard]] constexpr const basic_json &at(const std::basic_string_view key) const { const auto &children = object_data(); @@ -343,6 +338,33 @@ template struct basic_json } } + template[[nodiscard]] constexpr std::size_t count(const Key &key) const noexcept + { + if (is_object()) { + const auto found = find(key); + if (found == end()) { + return 0; + } else { + return 1; + } + } + return 0; + } + + [[nodiscard]] constexpr iterator find(const std::basic_string_view key) const noexcept + { + for (auto itr = begin(); itr != end(); ++itr) { + if (itr.key() == key) { return itr; } + } + + return end(); + } + + [[nodiscard]] constexpr const basic_json &operator[](const std::basic_string_view key) const + { + return at(key); + } + constexpr const auto &array_data() const { if (const auto *result = data.get_if_array(); result != nullptr) { @@ -364,38 +386,35 @@ template struct basic_json constexpr static basic_json object() { return basic_json{ data_t{ basic_object_t{} } }; } constexpr static basic_json array() { return basic_json{ data_t{ basic_array_t{} } }; } - template[[nodiscard]] constexpr Type get() const + template[[nodiscard]] constexpr auto get() const { - bool error = false; - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) { if (const auto *uint_value = data.get_if_uinteger(); uint_value != nullptr) { return Type(*uint_value); } else if (const auto *value = data.get_if_integer(); value != nullptr) { return Type(*value); + } else if (const auto *fpvalue = data.get_if_floating_point(); fpvalue != nullptr) { + return Type(*fpvalue); + } else { +// std::stringstream ss; + // ss << is_string() << is_object() << is_array() << is_string() << is_boolean() << is_structured() << is_number() << is_null() << is_binary() << is_primitive(); + throw std::runtime_error("Unexpected type: number requested");// + ss.str() ); } - error = true; - } else if constexpr (std::is_same_v) { - if (const auto *value = data.get_if_floating_point(); value != nullptr) { return *value; } - error = true; } else if constexpr (std::is_same_v> || std::is_same_v>) { if (const auto *value = data.get_if_string(); value != nullptr) { return *value; } - error = true; + else { + throw std::runtime_error("Unexpected type: string-like requested"); + } } else if constexpr (std::is_same_v) { if (const auto *value = data.get_if_boolean(); value != nullptr) { return *value; } - error = true; + else { + throw std::runtime_error("Unexpected type: bool requested"); + } } else { throw std::runtime_error("Unexpected type for get()"); } - if (error) { - // we have this boolean only because of a broken gcc implementation - // that incorrect says this is not a constexpr function - throw std::runtime_error("Type mismatch in get()"); - } else { - // this code is terrible and it makes me sad - return Type{}; - } } [[nodiscard]] constexpr bool is_object() const noexcept { return data.selected == data_t::selected_type::object; } @@ -430,7 +449,7 @@ template struct basic_json data_t data; - std::size_t size_{ size(*this) }; + std::size_t size_{ basic_json::size(*this) }; }; using json = basic_json; diff --git a/include/json2cpp/json2cpp_adapter.hpp b/include/json2cpp/json2cpp_adapter.hpp index 07bc907..eb68a3c 100644 --- a/include/json2cpp/json2cpp_adapter.hpp +++ b/include/json2cpp/json2cpp_adapter.hpp @@ -49,7 +49,7 @@ SOFTWARE. #pragma once -#include +#include "json2cpp.hpp" #include #include From 6c94abf0ca7116eeea4525a53ddac8009ae0a9ab Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 1 Mar 2022 16:09:47 -0700 Subject: [PATCH 5/5] Add some comments --- include/json2cpp/json2cpp.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/json2cpp/json2cpp.hpp b/include/json2cpp/json2cpp.hpp index 894f3ce..180a84d 100644 --- a/include/json2cpp/json2cpp.hpp +++ b/include/json2cpp/json2cpp.hpp @@ -23,7 +23,7 @@ SOFTWARE. */ // Important note: the types in this file are only intended for compile-time construction -// but consteval doesn't exist in C++17 +// but consteval doesn't exist in C++17, and we're targeting C++17 #ifndef CONSTEXPR_JSON_HPP_INCLUDED #define CONSTEXPR_JSON_HPP_INCLUDED @@ -34,6 +34,7 @@ SOFTWARE. #include #include +// simple pair to speed up compilation a bit compared to std::pair namespace json2cpp { template struct pair { @@ -41,6 +42,7 @@ template struct pair Second second; }; +// simple span because std::span is not in C++17 template struct span { template @@ -388,6 +390,8 @@ template struct basic_json template[[nodiscard]] constexpr auto get() const { + // I don't like this level of implicit conversions in the `get()` function, + // but it's necessary for API compatibility with nlohmann::json if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) { if (const auto *uint_value = data.get_if_uinteger(); uint_value != nullptr) { return Type(*uint_value); @@ -396,8 +400,6 @@ template struct basic_json } else if (const auto *fpvalue = data.get_if_floating_point(); fpvalue != nullptr) { return Type(*fpvalue); } else { -// std::stringstream ss; - // ss << is_string() << is_object() << is_array() << is_string() << is_boolean() << is_structured() << is_number() << is_null() << is_binary() << is_primitive(); throw std::runtime_error("Unexpected type: number requested");// + ss.str() ); } } else if constexpr (std::is_same_v