Team project page: http://code.google.com/p/hale-aloha-cli-tiger/
It was not long ago since our review of "tiger" team's code base when we were invited to join the team and add some new enhancements:
set-baseline [tower | lounge] [date]
This command defines [date] as the "baseline" day for [tower | lounge]. [date] is an optional argument in YYYY-MM-DD format and defaults to yesterday. When this command is executed, the system should obtain and save the amount of energy used during each of the 24 hours of that day for the given tower or lounge. These 24 values define the baseline power for that tower or lounge for that one hour time interval. For example, if lounge Ilima-A used 100 kWh of energy during the hour 6am-7am, then the baseline power during the interval 6am - 7am for Ilima-A is 100 kW.
monitor-power [tower | lounge] [interval]
This command prints out a timestamp and the current power for [tower | lounge] every [interval] seconds. [interval] is an optional integer greater than 0 and defaults to 10 seconds. Entering any character (such as a carriage return) stops this monitoring process and returns the user to the command loop.
monitor-goal [tower | lounge] goal [interval]
This command prints out a timestamp, the current power being consumed by the [tower | lounge], and whether or not the lounge is meeting its power conservation goal. [goal] is an integer between 1 and 99. It defines the percentage reduction from the baseline for this [tower | lounge] at this point in time. [interval] is an integer greater than 0, and defaults to 10 seconds.
For example, assume the user has previously defined the baseline power for Ilima-A as 100 kW for the time interval between 6am and 7am, and the current time is 6:30am. If the goal is set as 5, then Ilima-A's current power must be 5% less than its baseline in order to make the goal. At the current time, that means that Ilima-A should be using less than 95 kW of power in order to make its goal.
It is an error if the monitor-goal command is invoked without a prior set-baseline command for that [tower | lounge]. Entering any character (such as a carriage return) stops this monitoring process and returns the user to the command loop.
From these specifications, we identified two technical areas which needed to be implemented to support these commands:
1. Persistent storage and retrieval of baseline data for set-baseline and monitor-goal
2. Timer-based monitor loop for both monitor-power and monitor-goal
I decided to tackle #1, while Ted decided to tackle #2. Ted implemented the monitor loop with a Timer. Our design for persistent storage across command executions is to store the baseline data in XML files, each named in the pattern "[tower | lounge].xml". To support modular design, I decided to create a separate class to hold the baseline data as well as the XML file storage, parsing, and retrieval. See the file, Baseline.java, for implementation detail. The XML file handling codes were based off of this tutorial: http://totheriver.com/learn/xml/xmltutorial.html
Another technical challenge we encountered was the need to simulate user interactions in automated JUnit tests. We accomplished this by using connected pipes (PipedInputStream and PipedOutputStream) and System.setIn() to re-route the System.in stream. The test codes is then set to execute on a separate thread by wrapping it in a FutureTask object. Interactive user interactions are then simulated with timed writes to the pipe. See TestMonitorPower.java for a sample implementation. This approach was suggested in this message thread: http://www.codeguru.com/forum/showthread.php?t=453798
With these new testing methods, we were able to increase test code coverage from the initial ~30% to 70% coverage. Yet, the possibility for automated code testing that it open is now quite endless!
set-baseline [tower | lounge] [date]
This command defines [date] as the "baseline" day for [tower | lounge]. [date] is an optional argument in YYYY-MM-DD format and defaults to yesterday. When this command is executed, the system should obtain and save the amount of energy used during each of the 24 hours of that day for the given tower or lounge. These 24 values define the baseline power for that tower or lounge for that one hour time interval. For example, if lounge Ilima-A used 100 kWh of energy during the hour 6am-7am, then the baseline power during the interval 6am - 7am for Ilima-A is 100 kW.
monitor-power [tower | lounge] [interval]
This command prints out a timestamp and the current power for [tower | lounge] every [interval] seconds. [interval] is an optional integer greater than 0 and defaults to 10 seconds. Entering any character (such as a carriage return) stops this monitoring process and returns the user to the command loop.
monitor-goal [tower | lounge] goal [interval]
This command prints out a timestamp, the current power being consumed by the [tower | lounge], and whether or not the lounge is meeting its power conservation goal. [goal] is an integer between 1 and 99. It defines the percentage reduction from the baseline for this [tower | lounge] at this point in time. [interval] is an integer greater than 0, and defaults to 10 seconds.
For example, assume the user has previously defined the baseline power for Ilima-A as 100 kW for the time interval between 6am and 7am, and the current time is 6:30am. If the goal is set as 5, then Ilima-A's current power must be 5% less than its baseline in order to make the goal. At the current time, that means that Ilima-A should be using less than 95 kW of power in order to make its goal.
It is an error if the monitor-goal command is invoked without a prior set-baseline command for that [tower | lounge]. Entering any character (such as a carriage return) stops this monitoring process and returns the user to the command loop.
From these specifications, we identified two technical areas which needed to be implemented to support these commands:
1. Persistent storage and retrieval of baseline data for set-baseline and monitor-goal
2. Timer-based monitor loop for both monitor-power and monitor-goal
I decided to tackle #1, while Ted decided to tackle #2. Ted implemented the monitor loop with a Timer. Our design for persistent storage across command executions is to store the baseline data in XML files, each named in the pattern "[tower | lounge].xml". To support modular design, I decided to create a separate class to hold the baseline data as well as the XML file storage, parsing, and retrieval. See the file, Baseline.java, for implementation detail. The XML file handling codes were based off of this tutorial: http://totheriver.com/learn/xml/xmltutorial.html
Another technical challenge we encountered was the need to simulate user interactions in automated JUnit tests. We accomplished this by using connected pipes (PipedInputStream and PipedOutputStream) and System.setIn() to re-route the System.in stream. The test codes is then set to execute on a separate thread by wrapping it in a FutureTask object. Interactive user interactions are then simulated with timed writes to the pipe. See TestMonitorPower.java for a sample implementation. This approach was suggested in this message thread: http://www.codeguru.com/forum/showthread.php?t=453798
With these new testing methods, we were able to increase test code coverage from the initial ~30% to 70% coverage. Yet, the possibility for automated code testing that it open is now quite endless!