openstudio-load-flexibility-measures 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test-measures.yml +107 -0
- data/.gitignore +5 -0
- data/.secrets.example +27 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +5 -5
- data/Jenkinsfile +1 -1
- data/LICENSE.md +1 -1
- data/README.md +7 -1
- data/docs/LOCAL_TESTING.md +119 -0
- data/lib/measures/PeakPeriodSchedulesShift/LICENSE.md +1 -1
- data/lib/measures/PeakPeriodSchedulesShift/measure.rb +16 -16
- data/lib/measures/PeakPeriodSchedulesShift/measure.xml +5 -5
- data/lib/measures/PeakPeriodSchedulesShift/tests/PeakPeriodSchedulesShift_Test.rb +10 -10
- data/lib/measures/ShiftScheduleByType/LICENSE.md +1 -1
- data/lib/measures/ShiftScheduleByType/measure.rb +30 -29
- data/lib/measures/ShiftScheduleByType/measure.xml +5 -5
- data/lib/measures/ShiftScheduleByType/tests/ShiftScheduleByType_Test.rb +5 -5
- data/lib/measures/add_central_ice_storage/LICENSE.md +1 -1
- data/lib/measures/add_central_ice_storage/measure.xml +3 -3
- data/lib/measures/add_hpwh/LICENSE.md +1 -1
- data/lib/measures/add_hpwh/measure.rb +25 -25
- data/lib/measures/add_hpwh/measure.xml +4 -4
- data/lib/measures/add_packaged_ice_storage/LICENSE.md +1 -1
- data/lib/measures/add_packaged_ice_storage/measure.xml +4 -4
- data/lib/measures/add_packaged_ice_storage/tests/add_packaged_ice_storage_test.rb +9 -9
- data/lib/openstudio/load_flexibility_measures/version.rb +1 -1
- data/openstudio-load-flexibility-measures.gemspec +9 -8
- metadata +38 -63
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f513e7a6c68031a14b3d942a44aa929b36a4b962f49ed01934726112473e5db
|
4
|
+
data.tar.gz: efbab7f50758fecf9cc7213bc7ad52eee654bdaa9d59f9de36e2d1bb982eeaac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c37eb3e9abb7eb3ce877cd8ec61cb9b996ad61b96177d73637a994e8e7f59f6e3eb0d95a5fbefffbca583037c449b1ace6953b7d52cdb33941ea83803e8b2739
|
7
|
+
data.tar.gz: 6a53c5b3f232cc484e7c24cbfd500f06d74dc59318d944df33678ca62865088a2d6a9640bef9730a13a6338a599cb7fd67b479088df42e8d31680f999e5a91f5
|
@@ -0,0 +1,107 @@
|
|
1
|
+
name: Test Measure Gems
|
2
|
+
on: push
|
3
|
+
|
4
|
+
jobs:
|
5
|
+
test-gems-latest:
|
6
|
+
runs-on: ubuntu-latest
|
7
|
+
env:
|
8
|
+
BRANCH_NAME: ${{ github.ref_name }}
|
9
|
+
BUILD_NUMBER: ${{ github.run_number }}
|
10
|
+
DEPLOY_PATH: ${{ github.repository }}/${{ github.ref_name }}/${{ github.run_number }} # Path for S3 deployment
|
11
|
+
S3_BUCKET: ext-gem-dashboard
|
12
|
+
|
13
|
+
container: # Define the Docker container for the job. All subsequent steps run inside it.
|
14
|
+
image: nrel/openstudio:3.10.0
|
15
|
+
options: -u root -e "LANG=en_US.UTF-8" # These options are passed to the 'docker run' command internally
|
16
|
+
|
17
|
+
steps:
|
18
|
+
- name: Checkout Repository
|
19
|
+
# The repository will be checked out inside the 'nrel/openstudio:3.10.0' container
|
20
|
+
uses: actions/checkout@v4 # Use v4 for better security and features
|
21
|
+
with:
|
22
|
+
submodules: true # Set to true if your repository uses Git submodules
|
23
|
+
|
24
|
+
- name: Install Node.js and AWS CLI
|
25
|
+
# Install required dependencies for AWS actions to work in the OpenStudio container
|
26
|
+
shell: bash
|
27
|
+
run: |
|
28
|
+
echo "Installing Node.js and AWS CLI..."
|
29
|
+
|
30
|
+
# Update package list
|
31
|
+
apt-get update
|
32
|
+
|
33
|
+
# Install curl and other dependencies
|
34
|
+
apt-get install -y curl unzip
|
35
|
+
|
36
|
+
# Install Node.js (using NodeSource repository for latest LTS)
|
37
|
+
curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
|
38
|
+
apt-get install -y nodejs
|
39
|
+
|
40
|
+
# Install AWS CLI v2
|
41
|
+
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
|
42
|
+
unzip awscliv2.zip
|
43
|
+
./aws/install
|
44
|
+
|
45
|
+
# Verify installations
|
46
|
+
echo "Node.js version: $(node --version)"
|
47
|
+
echo "npm version: $(npm --version)"
|
48
|
+
echo "AWS CLI version: $(aws --version)"
|
49
|
+
|
50
|
+
# Clean up
|
51
|
+
rm -rf awscliv2.zip aws/
|
52
|
+
|
53
|
+
- name: Verify Environment and Run Measures
|
54
|
+
# All 'run' commands in this job now execute inside the specified Docker container.
|
55
|
+
shell: bash # Specify the shell if needed, though bash is default for Ubuntu runners
|
56
|
+
run: |
|
57
|
+
# Fix git ownership issue in container
|
58
|
+
git config --global --add safe.directory /__w/openstudio-load-flexibility-measures-gem/openstudio-load-flexibility-measures-gem
|
59
|
+
|
60
|
+
echo "OpenStudio Version: $(openstudio --version)"
|
61
|
+
echo "Ruby Version: $(ruby -v)"
|
62
|
+
echo "Listing OpenStudio Gems: $(openstudio gem_list)"
|
63
|
+
|
64
|
+
# Install dependencies before running tests
|
65
|
+
echo "Installing gem dependencies..."
|
66
|
+
bundle install
|
67
|
+
|
68
|
+
echo "Running spec tests..."
|
69
|
+
rake spec
|
70
|
+
echo "Running measures with verbose output:"
|
71
|
+
# This command will execute within the container.
|
72
|
+
# Ensure that './lib/measures' is the correct path relative to the checkout.
|
73
|
+
openstudio --verbose measure -r ./lib/measures
|
74
|
+
|
75
|
+
# The output for 'test' should now be generated directly into the workspace
|
76
|
+
# within the container, which is mounted from the host.
|
77
|
+
# No 'docker cp' is needed as the workspace is shared.
|
78
|
+
ls -al ./test # Verify the output directory exists and contains files
|
79
|
+
|
80
|
+
- name: Configure AWS Credentials
|
81
|
+
# This step is crucial for authenticating with AWS S3
|
82
|
+
uses: aws-actions/configure-aws-credentials@v4 # Use v4 for updated features
|
83
|
+
with:
|
84
|
+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
85
|
+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # Assuming this is your secret name
|
86
|
+
aws-region: ${{ secrets.AWS_DEFAULT_REGION }} # Replace with your AWS region, e.g., us-east-1
|
87
|
+
|
88
|
+
- name: Sync files to S3 with branch and build in path
|
89
|
+
shell: bash
|
90
|
+
run: |
|
91
|
+
echo "Deploying to s3://${{ env.S3_BUCKET }}/${{ env.DEPLOY_PATH }}/"
|
92
|
+
# Ensure './test_results' is the correct source directory for the files to upload to S3.
|
93
|
+
dir_name=$(find -type d -name "test_results")
|
94
|
+
# It must match the output directory from the 'Run Measures' step.
|
95
|
+
aws s3 sync $dir_name s3://${{ env.S3_BUCKET }}/${{ env.DEPLOY_PATH }}/ \
|
96
|
+
--delete \
|
97
|
+
--acl public-read \
|
98
|
+
--cache-control "max-age=0, no-cache, no-store, must-revalidate"
|
99
|
+
echo "S3 sync complete."
|
100
|
+
echo "https://${{ env.S3_BUCKET }}.s3.amazonaws.com/${{ env.DEPLOY_PATH }}/dashboard/index.html"
|
101
|
+
echo dir_name=$dir_name >> $GITHUB_ENV # Save the directory name to an environment variable for later use
|
102
|
+
|
103
|
+
- name: Archive static site as artifact
|
104
|
+
uses: actions/upload-artifact@v4
|
105
|
+
with:
|
106
|
+
name: static-html-artifact
|
107
|
+
path: ${{ env.dir_name }} # Path should be relative to the GitHub workspace, which is shared with the container
|
data/.gitignore
CHANGED
data/.secrets.example
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Example secrets file for act (GitHub Actions runner)
|
2
|
+
# Copy this file to .secrets and replace the placeholder values with your actual AWS credentials
|
3
|
+
#
|
4
|
+
# IMPORTANT: The .secrets file is ignored by git (.gitignore) to prevent accidental commits
|
5
|
+
# DO NOT commit the .secrets file with real credentials to version control
|
6
|
+
#
|
7
|
+
# To get your AWS credentials:
|
8
|
+
# 1. Log into AWS Console
|
9
|
+
# 2. Go to IAM > Users > Your User > Security credentials
|
10
|
+
# 3. Create an access key if you don't have one
|
11
|
+
# 4. Replace the values below with your actual credentials
|
12
|
+
|
13
|
+
# Your AWS Access Key ID (starts with AKIA...)
|
14
|
+
AWS_ACCESS_KEY_ID: 'AKIAIOSFODNN7EXAMPLE'
|
15
|
+
|
16
|
+
# Your AWS Secret Access Key (long string of characters)
|
17
|
+
AWS_SECRET_ACCESS_KEY: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
|
18
|
+
|
19
|
+
# AWS Region where your S3 bucket is located (e.g., us-east-1, us-west-2, eu-west-1)
|
20
|
+
AWS_DEFAULT_REGION: 'us-east-1'
|
21
|
+
|
22
|
+
# Your S3 bucket name for uploading test results
|
23
|
+
S3_BUCKET: 'your-s3-bucket-name-here'
|
24
|
+
|
25
|
+
# Optional: If you want to test with different values
|
26
|
+
# BRANCH_NAME: 'test-branch'
|
27
|
+
# BUILD_NUMBER: '123'
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# OpenStudio Load Flexibility Measures Gem
|
2
2
|
|
3
|
+
## Version 0.11.0
|
4
|
+
* Support for OpenStudio 3.10 (upgrade to standards gem 0.8.2, extension gem 0.9.2)
|
5
|
+
* Improved CI/CD workflows:
|
6
|
+
* Added GitHub Actions for measure testing
|
7
|
+
* Improved Docker container permissions and test workflow reliability
|
8
|
+
* Added local testing support and AWS integration
|
9
|
+
* Enhanced S3 deployment configuration for test artifacts
|
10
|
+
* Added rake spec test execution to CI workflow
|
11
|
+
* Added example secrets file and local testing documentation
|
12
|
+
|
13
|
+
## Version 0.10.1
|
14
|
+
* Update dependencies for 3.9
|
15
|
+
|
3
16
|
## Version 0.10.0
|
4
17
|
- Support for OpenStudio 3.9 (upgrade to standards gem 0.7.0, extension gem 0.8.1)
|
5
18
|
|
data/Gemfile
CHANGED
@@ -12,8 +12,8 @@ gemspec
|
|
12
12
|
allow_local = ENV['FAVOR_LOCAL_GEMS']
|
13
13
|
|
14
14
|
# Only uncomment if you need to test a different version of the extension gem
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
if allow_local && File.exist?('../OpenStudio-extension-gem')
|
16
|
+
gem 'openstudio-extension', path: '../OpenStudio-extension-gem'
|
17
|
+
elsif allow_local
|
18
|
+
gem 'openstudio-extension', github: 'NREL/OpenStudio-extension-gem', branch: 'develop'
|
19
|
+
end
|
data/Jenkinsfile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
//Jenkins pipelines are stored in shared libaries. Please see: https://github.com/NREL/cbci_jenkins_libs
|
2
2
|
|
3
|
-
@Library('cbci_shared_libs
|
3
|
+
@Library('cbci_shared_libs') _
|
4
4
|
|
5
5
|
// Build for PR to develop branch only.
|
6
6
|
if ((env.CHANGE_ID) && (env.CHANGE_TARGET) ) { // check if set
|
data/LICENSE.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
OpenStudio(R), Copyright (c) 2008,
|
1
|
+
OpenStudio(R), Copyright (c) 2008, 2023 Alliance for Sustainable Energy, LLC.
|
2
2
|
|
3
3
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
4
4
|
|
data/README.md
CHANGED
@@ -31,6 +31,8 @@ Detailed instructions for usage are included in each measure's respective README
|
|
31
31
|
|
32
32
|
|OpenStudio Load Flexibility Measures Gem|OpenStudio|Ruby|
|
33
33
|
|:--------------:|:----------:|:--------:|
|
34
|
+
| 0.11.0| 3.10 | 3.2.2 |
|
35
|
+
| 0.10.1| 3.9 | 3.2.2 |
|
34
36
|
| 0.10.0| 3.9 | 3.2.2 |
|
35
37
|
| 0.9.0| 3.8 | 3.2.2 |
|
36
38
|
| 0.8.0| 3.7 | 2.7 |
|
@@ -43,10 +45,14 @@ Detailed instructions for usage are included in each measure's respective README
|
|
43
45
|
| 0.1.1 - 0.1.3 | 3.0 | 2.5 |
|
44
46
|
|
45
47
|
|
46
|
-
# Contributing
|
48
|
+
# Contributing
|
47
49
|
|
48
50
|
Please review the [OpenStudio Contribution Policy](https://openstudio.net/openstudio-contribution-policy) if you would like to contribute code to this gem.
|
49
51
|
|
52
|
+
## Local Testing
|
53
|
+
|
54
|
+
To test the GitHub Actions workflow locally using `act`, see the [Local Testing Guide](docs/LOCAL_TESTING.md).
|
55
|
+
|
50
56
|
# Releasing
|
51
57
|
|
52
58
|
* Update `CHANGELOG.md`
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# Local Testing with Act
|
2
|
+
|
3
|
+
This document explains how to run the GitHub Actions workflow locally using [act](https://github.com/nektos/act) with proper AWS credentials.
|
4
|
+
|
5
|
+
## Prerequisites
|
6
|
+
|
7
|
+
1. **Install act**: Follow the [installation instructions](https://github.com/nektos/act#installation)
|
8
|
+
2. **Install Docker**: act requires Docker to run containers
|
9
|
+
3. **AWS Credentials**: You'll need valid AWS credentials with S3 access
|
10
|
+
|
11
|
+
## Quick Setup
|
12
|
+
|
13
|
+
### 1. Create Local Secrets File
|
14
|
+
|
15
|
+
Copy the example secrets file and fill in your credentials:
|
16
|
+
|
17
|
+
```bash
|
18
|
+
cp .secrets.example .secrets
|
19
|
+
```
|
20
|
+
|
21
|
+
Then edit `.secrets` with your actual AWS credentials:
|
22
|
+
|
23
|
+
```bash
|
24
|
+
# Your actual AWS credentials
|
25
|
+
AWS_ACCESS_KEY_ID=AKIA...your_actual_key
|
26
|
+
AWS_SECRET_ACCESS_KEY=your_actual_secret_key
|
27
|
+
AWS_DEFAULT_REGION=us-east-1
|
28
|
+
S3_BUCKET=your-actual-bucket-name
|
29
|
+
```
|
30
|
+
|
31
|
+
### 2. Run the Workflow
|
32
|
+
|
33
|
+
```bash
|
34
|
+
act
|
35
|
+
```
|
36
|
+
|
37
|
+
That's it! The workflow will:
|
38
|
+
- Use the OpenStudio 3.10.0 container
|
39
|
+
- Install Node.js and AWS CLI automatically
|
40
|
+
- Run the measures
|
41
|
+
- Upload results to S3 (if credentials are provided)
|
42
|
+
- Create local artifacts
|
43
|
+
|
44
|
+
## Alternative Methods
|
45
|
+
|
46
|
+
### Method 2: Command Line Secrets
|
47
|
+
|
48
|
+
```bash
|
49
|
+
act --secret AWS_ACCESS_KEY_ID=your_key \
|
50
|
+
--secret AWS_SECRET_ACCESS_KEY=your_secret \
|
51
|
+
--secret AWS_DEFAULT_REGION=us-east-1 \
|
52
|
+
--secret S3_BUCKET=your-bucket
|
53
|
+
```
|
54
|
+
|
55
|
+
### Method 3: Environment Variables
|
56
|
+
|
57
|
+
```bash
|
58
|
+
act -e AWS_ACCESS_KEY_ID=your_key \
|
59
|
+
-e AWS_SECRET_ACCESS_KEY=your_secret \
|
60
|
+
-e AWS_DEFAULT_REGION=us-east-1 \
|
61
|
+
-e S3_BUCKET=your-bucket
|
62
|
+
```
|
63
|
+
|
64
|
+
### Method 4: Custom Secrets File
|
65
|
+
|
66
|
+
```bash
|
67
|
+
act --secret-file /path/to/custom/secrets.env
|
68
|
+
```
|
69
|
+
|
70
|
+
## Security Best Practices
|
71
|
+
|
72
|
+
1. **Never commit `.secrets`**: This file is already in `.gitignore`
|
73
|
+
2. **Use IAM roles with minimal permissions**: Only grant S3 access needed
|
74
|
+
3. **Rotate credentials regularly**: Especially if they might be compromised
|
75
|
+
4. **Use temporary credentials**: Consider AWS STS for temporary access
|
76
|
+
|
77
|
+
## Troubleshooting
|
78
|
+
|
79
|
+
### Common Issues
|
80
|
+
|
81
|
+
**Error: "Input required and not supplied: aws-region"**
|
82
|
+
- Solution: Make sure all required secrets are in your `.secrets` file
|
83
|
+
|
84
|
+
**Error: "docker: command not found"**
|
85
|
+
- Solution: Install Docker and ensure it's running
|
86
|
+
|
87
|
+
**Error: "act: command not found"**
|
88
|
+
- Solution: Install act following the official installation guide
|
89
|
+
|
90
|
+
### Debugging
|
91
|
+
|
92
|
+
Run with verbose output:
|
93
|
+
```bash
|
94
|
+
act --verbose
|
95
|
+
```
|
96
|
+
|
97
|
+
Run specific job:
|
98
|
+
```bash
|
99
|
+
act -j test-gems-latest
|
100
|
+
```
|
101
|
+
|
102
|
+
## What Gets Tested
|
103
|
+
|
104
|
+
The local workflow tests:
|
105
|
+
1. ✅ OpenStudio environment setup
|
106
|
+
2. ✅ Measure execution with verbose output
|
107
|
+
3. ✅ AWS credentials configuration (if provided)
|
108
|
+
4. ✅ S3 file upload (if credentials provided)
|
109
|
+
5. ✅ Artifact creation
|
110
|
+
|
111
|
+
## Expected Output
|
112
|
+
|
113
|
+
When successful, you should see:
|
114
|
+
- OpenStudio version information
|
115
|
+
- Ruby version information
|
116
|
+
- Measure execution logs
|
117
|
+
- Test results in `./test` directory
|
118
|
+
- S3 upload confirmation (if configured)
|
119
|
+
- Artifact creation confirmation
|
@@ -1,4 +1,4 @@
|
|
1
|
-
OpenStudio(R), Copyright (c) 2008,
|
1
|
+
OpenStudio(R), Copyright (c) 2008, 2023 Alliance for Sustainable Energy, LLC.
|
2
2
|
|
3
3
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
4
4
|
|
@@ -134,12 +134,12 @@ class PeakPeriodSchedulesShift < OpenStudio::Measure::ModelMeasure
|
|
134
134
|
end
|
135
135
|
|
136
136
|
peak_period_length = end_hour - begin_hour
|
137
|
-
if
|
137
|
+
if peak_period_length + schedules_peak_period_delay > 12
|
138
138
|
runner.registerError("Specified peak period (#{begin_hour} - #{end_hour}), plus the delay (#{schedules_peak_period_delay}), must be no longer than 12 hours.")
|
139
139
|
return false
|
140
140
|
end
|
141
141
|
|
142
|
-
if
|
142
|
+
if peak_period_length + end_hour + schedules_peak_period_delay > 24
|
143
143
|
runner.registerError('Cannot shift day schedules into the next day.')
|
144
144
|
return false
|
145
145
|
end
|
@@ -166,9 +166,9 @@ class PeakPeriodSchedulesShift < OpenStudio::Measure::ModelMeasure
|
|
166
166
|
|
167
167
|
shifted_schedule = false
|
168
168
|
schedule_ruleset = schedule_rulesets.find { |schedule_ruleset| schedule_ruleset.name.to_s == schedule_ruleset_name }
|
169
|
-
schedule_ruleset.scheduleRules.
|
170
|
-
if schedules_peak_period_weekdays_only
|
171
|
-
next
|
169
|
+
schedule_ruleset.scheduleRules.reverse_each do |schedule_rule|
|
170
|
+
if schedules_peak_period_weekdays_only && !(schedule_rule.applyMonday || schedule_rule.applyTuesday || schedule_rule.applyWednesday || schedule_rule.applyThursday || schedule_rule.applyFriday)
|
171
|
+
next # at least one weekday applies
|
172
172
|
end
|
173
173
|
|
174
174
|
new_schedule_rule = schedule_rule.clone.to_ScheduleRule.get
|
@@ -249,7 +249,7 @@ class PeakPeriodSchedulesShift < OpenStudio::Measure::ModelMeasure
|
|
249
249
|
|
250
250
|
schedules = Schedules.new(file_path: external_file_path)
|
251
251
|
schedules.shift_schedules(model, runner, schedule_file_column_names_enabled, begin_hour, end_hour, schedules_peak_period_delay, schedules_peak_period_allow_stacking, total_days_in_year, sim_start_day, steps_in_day, schedules_peak_period_weekdays_only)
|
252
|
-
schedules.export
|
252
|
+
schedules.export
|
253
253
|
end
|
254
254
|
|
255
255
|
return true
|
@@ -309,21 +309,21 @@ class Schedules
|
|
309
309
|
def initialize(file_path:)
|
310
310
|
@file_path = file_path
|
311
311
|
|
312
|
-
import
|
312
|
+
import
|
313
313
|
end
|
314
314
|
|
315
|
-
def import
|
315
|
+
def import
|
316
316
|
@schedules = {}
|
317
317
|
columns = CSV.read(@file_path).transpose
|
318
318
|
columns.each do |col|
|
319
319
|
col_name = col[0]
|
320
320
|
|
321
|
-
values = col[1
|
321
|
+
values = col[1..].reject(&:nil?)
|
322
322
|
|
323
323
|
begin
|
324
324
|
values = values.map { |v| Float(v) }
|
325
325
|
rescue ArgumentError
|
326
|
-
|
326
|
+
raise "Schedule value must be numeric for column '#{col_name}'. [context: #{schedules_path}]"
|
327
327
|
end
|
328
328
|
|
329
329
|
@schedules[col_name] = values
|
@@ -336,7 +336,7 @@ class Schedules
|
|
336
336
|
schedule_file = model.getScheduleFiles.find { |schedule_file| schedule_file.name.to_s == schedule_file_column_name }
|
337
337
|
|
338
338
|
next if schedule_file.nil?
|
339
|
-
next if !@schedules.
|
339
|
+
next if !@schedules.key?(schedule_file_column_name)
|
340
340
|
next if !peak_period_shift_enabled
|
341
341
|
|
342
342
|
schedule = @schedules[schedule_file_column_name]
|
@@ -387,8 +387,8 @@ class Schedules
|
|
387
387
|
new_end_ix = new_begin_ix + period
|
388
388
|
|
389
389
|
shifted = false
|
390
|
-
if !allow_stacking
|
391
|
-
return shifted
|
390
|
+
if !allow_stacking && schedule[new_begin_ix...new_end_ix].any? { |x| x > 0 }
|
391
|
+
return shifted # prevent stacking
|
392
392
|
end
|
393
393
|
|
394
394
|
shifted = true if schedule[peak_begin_ix...peak_end_ix].any? { |x| x > 0 } # schedule was actually moved
|
@@ -398,7 +398,7 @@ class Schedules
|
|
398
398
|
return shifted
|
399
399
|
end
|
400
400
|
|
401
|
-
def export
|
401
|
+
def export
|
402
402
|
CSV.open(@file_path, 'wb') do |csv|
|
403
403
|
csv << @schedules.keys
|
404
404
|
rows = @schedules.values.transpose
|
@@ -413,9 +413,9 @@ class Schedules
|
|
413
413
|
end
|
414
414
|
|
415
415
|
def self.parse_time_range(time_range)
|
416
|
-
begin_end_times = time_range.split('-').map
|
416
|
+
begin_end_times = time_range.split('-').map(&:strip)
|
417
417
|
if begin_end_times.size != 2
|
418
|
-
|
418
|
+
raise "Invalid time format specified for '#{time_range}'."
|
419
419
|
end
|
420
420
|
|
421
421
|
begin_hour = begin_end_times[0].strip.to_i
|
@@ -3,8 +3,8 @@
|
|
3
3
|
<schema_version>3.1</schema_version>
|
4
4
|
<name>peak_period_schedules_shift</name>
|
5
5
|
<uid>4954275f-9caf-422c-9e1f-061244ade152</uid>
|
6
|
-
<version_id>
|
7
|
-
<version_modified>
|
6
|
+
<version_id>380db2d7-6b81-4cd8-83d6-6a8e68585f7d</version_id>
|
7
|
+
<version_modified>2025-08-01T16:03:34Z</version_modified>
|
8
8
|
<xml_checksum>A8988589</xml_checksum>
|
9
9
|
<class_name>PeakPeriodSchedulesShift</class_name>
|
10
10
|
<display_name>PeakPeriodSchedulesShift</display_name>
|
@@ -105,7 +105,7 @@
|
|
105
105
|
<filename>LICENSE.md</filename>
|
106
106
|
<filetype>md</filetype>
|
107
107
|
<usage_type>license</usage_type>
|
108
|
-
<checksum>
|
108
|
+
<checksum>BFFB1AA6</checksum>
|
109
109
|
</file>
|
110
110
|
<file>
|
111
111
|
<filename>README.md</filename>
|
@@ -176,13 +176,13 @@
|
|
176
176
|
<filename>measure.rb</filename>
|
177
177
|
<filetype>rb</filetype>
|
178
178
|
<usage_type>script</usage_type>
|
179
|
-
<checksum>
|
179
|
+
<checksum>A557EE11</checksum>
|
180
180
|
</file>
|
181
181
|
<file>
|
182
182
|
<filename>PeakPeriodSchedulesShift_Test.rb</filename>
|
183
183
|
<filetype>rb</filetype>
|
184
184
|
<usage_type>test</usage_type>
|
185
|
-
<checksum>
|
185
|
+
<checksum>AA5A7B2A</checksum>
|
186
186
|
</file>
|
187
187
|
<file>
|
188
188
|
<filename>base-schedules-detailed-occupancy-stochastic.osm</filename>
|
@@ -8,7 +8,7 @@
|
|
8
8
|
require 'openstudio'
|
9
9
|
require 'openstudio/measure/ShowRunnerOutput'
|
10
10
|
require 'minitest/autorun'
|
11
|
-
require_relative '../measure
|
11
|
+
require_relative '../measure'
|
12
12
|
require 'fileutils'
|
13
13
|
|
14
14
|
class PeakPeriodSchedulesShiftTest < Minitest::Test
|
@@ -30,7 +30,7 @@ class PeakPeriodSchedulesShiftTest < Minitest::Test
|
|
30
30
|
|
31
31
|
# load the test model
|
32
32
|
translator = OpenStudio::OSVersion::VersionTranslator.new
|
33
|
-
path = OpenStudio::Path.new(File.dirname(__FILE__)
|
33
|
+
path = OpenStudio::Path.new("#{File.dirname(__FILE__)}/base.osm")
|
34
34
|
model = translator.loadModel(path)
|
35
35
|
assert(!model.empty?)
|
36
36
|
model = model.get
|
@@ -98,7 +98,7 @@ class PeakPeriodSchedulesShiftTest < Minitest::Test
|
|
98
98
|
|
99
99
|
# load the test model
|
100
100
|
translator = OpenStudio::OSVersion::VersionTranslator.new
|
101
|
-
path = OpenStudio::Path.new(File.dirname(__FILE__)
|
101
|
+
path = OpenStudio::Path.new("#{File.dirname(__FILE__)}/base.osm")
|
102
102
|
model = translator.loadModel(path)
|
103
103
|
assert(!model.empty?)
|
104
104
|
model = model.get
|
@@ -166,7 +166,7 @@ class PeakPeriodSchedulesShiftTest < Minitest::Test
|
|
166
166
|
|
167
167
|
# load the test model
|
168
168
|
translator = OpenStudio::OSVersion::VersionTranslator.new
|
169
|
-
path = OpenStudio::Path.new(File.dirname(__FILE__)
|
169
|
+
path = OpenStudio::Path.new("#{File.dirname(__FILE__)}/base.osm")
|
170
170
|
model = translator.loadModel(path)
|
171
171
|
assert(!model.empty?)
|
172
172
|
model = model.get
|
@@ -234,7 +234,7 @@ class PeakPeriodSchedulesShiftTest < Minitest::Test
|
|
234
234
|
|
235
235
|
# load the test model
|
236
236
|
translator = OpenStudio::OSVersion::VersionTranslator.new
|
237
|
-
path = OpenStudio::Path.new(File.dirname(__FILE__)
|
237
|
+
path = OpenStudio::Path.new("#{File.dirname(__FILE__)}/base.osm")
|
238
238
|
model = translator.loadModel(path)
|
239
239
|
assert(!model.empty?)
|
240
240
|
model = model.get
|
@@ -309,7 +309,7 @@ class PeakPeriodSchedulesShiftTest < Minitest::Test
|
|
309
309
|
assert_equal(result.info.size, 9)
|
310
310
|
|
311
311
|
# save the model
|
312
|
-
output_file_path = OpenStudio::Path.new(File.dirname(__FILE__)
|
312
|
+
output_file_path = OpenStudio::Path.new("#{File.dirname(__FILE__)}/test_smooth_schedules.osm")
|
313
313
|
model.save(output_file_path, true)
|
314
314
|
|
315
315
|
# after
|
@@ -349,7 +349,7 @@ class PeakPeriodSchedulesShiftTest < Minitest::Test
|
|
349
349
|
|
350
350
|
# load the test model
|
351
351
|
translator = OpenStudio::OSVersion::VersionTranslator.new
|
352
|
-
path = OpenStudio::Path.new(File.dirname(__FILE__)
|
352
|
+
path = OpenStudio::Path.new("#{File.dirname(__FILE__)}/base-schedules-detailed-occupancy-stochastic.osm")
|
353
353
|
model = translator.loadModel(path)
|
354
354
|
assert(!model.empty?)
|
355
355
|
model = model.get
|
@@ -424,7 +424,7 @@ class PeakPeriodSchedulesShiftTest < Minitest::Test
|
|
424
424
|
assert_equal(result.info.size, 5)
|
425
425
|
|
426
426
|
# save the model
|
427
|
-
output_file_path = OpenStudio::Path.new(File.dirname(__FILE__)
|
427
|
+
output_file_path = OpenStudio::Path.new("#{File.dirname(__FILE__)}/test_stochastic_schedules.osm")
|
428
428
|
model.save(output_file_path, true)
|
429
429
|
|
430
430
|
# after
|
@@ -484,7 +484,7 @@ class PeakPeriodSchedulesShiftTest < Minitest::Test
|
|
484
484
|
|
485
485
|
# load the test model
|
486
486
|
translator = OpenStudio::OSVersion::VersionTranslator.new
|
487
|
-
path = OpenStudio::Path.new(File.dirname(__FILE__)
|
487
|
+
path = OpenStudio::Path.new("#{File.dirname(__FILE__)}/base-schedules-detailed-occupancy-stochastic.osm")
|
488
488
|
model = translator.loadModel(path)
|
489
489
|
assert(!model.empty?)
|
490
490
|
model = model.get
|
@@ -557,7 +557,7 @@ class PeakPeriodSchedulesShiftTest < Minitest::Test
|
|
557
557
|
assert_equal(result.info.size, 5)
|
558
558
|
|
559
559
|
# save the model
|
560
|
-
output_file_path = OpenStudio::Path.new(File.dirname(__FILE__)
|
560
|
+
output_file_path = OpenStudio::Path.new("#{File.dirname(__FILE__)}/test_stochastic_schedules_no_stacking.osm")
|
561
561
|
model.save(output_file_path, true)
|
562
562
|
|
563
563
|
# after
|
@@ -1,4 +1,4 @@
|
|
1
|
-
OpenStudio(R), Copyright (c) 2008,
|
1
|
+
OpenStudio(R), Copyright (c) 2008, 2023 Alliance for Sustainable Energy, LLC.
|
2
2
|
|
3
3
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
4
4
|
|