tag:blogger.com,1999:blog-55418795187045086232024-02-07T17:41:40.836-08:00Zach HacksUnknownnoreply@blogger.comBlogger34125tag:blogger.com,1999:blog-5541879518704508623.post-85557065415003377232013-10-12T14:35:00.000-07:002013-10-12T14:35:31.585-07:00SourceTree: My new favorite Git GUI<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
I've started a new job, so I've been offline for a while. But I want to give a quick shout-out to Atlassian <a href="http://www.sourcetreeapp.com/">SourceTree</a>.
<p>
I like Git, and I'm not afraid of the command line, but I'd rather use faster, more informative GUI tools if they exist. I've been using <a href="http://windows.github.com/">GitHub for Windows</a> for my projects stored on GitHub. I learned about SourceTree at work and, now that I know it also integrates with GitHub, I've switched over at home as well.
<p>
GitHub for Windows is very simple, which is an advantage when you're just getting started with Git. But I find certain things can only be done through the GitHub web interface or on the command line. SourceTree, on the other hand, has a lot more power to it. As just one example, you can easily pick chunks and specific lines of a file to include as a commit.
<p>
If you like a GUI front-end to your Git, but you want a bit more power and elegance, check out SourceTree.
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-51754359439558596252013-05-09T05:00:00.002-07:002013-05-09T05:07:51.584-07:00HabitMaster: Alpha release<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
HabitMaster is now live in the wild. You can see the new <a href="http://ztomasze.github.io/habitmaster/">one-page HabitMaster project site</a> that links to everything else you might want to see, including a running Heroku instance.
<p>
Overall, this deadline has been met with limited success. I'm calling this an alpha release because the HabitMaster achievements (in other words, the actual gamification parts!) are still unimplemented. It means HabitMaster is just a basic habit tracker right now, and still a little rough around the edges at that.
<p>
This has mostly been due to just slow progress. According to my time tracker, I averaged around 8 hours a week on ICS691 projects for most the semester. I stepped that up to averaging around 12 hours a week for the past month, but I still don't appear to have much to show for it. Yet it seems all of my implementation projects go this way: I continue to underestimate just how much code is required to do things.
<p>
I spent most of my time implementing back-end details, such as streak detection given a list of activities and a particular schedule type. I was excited to use a Python generator (basically a fancy iterator) to good effect there.
<p>
I also came up with a <a href="https://github.com/ztomasze/habitmaster/blob/930c84f0d6a34da3d061dcfc33f65815c0170d1a/habitmaster/habits/models.py#L24">workable solution</a> to handling polymorphism in database objects. Specifically, my habits link to a Schedule object, but there are two subtypes of Schedule: DaysOfWeekSchedule and IntervalSchedule. Grabbing <code>habit.schedule</code> would give me a row from the Schedule table, which was fairly useless. I ended up adding a cast() method to Schedule that would resolve that instance to the proper subtype for me.
<p>
Django's unittest framework was very handy. I didn't get into the UI unit tests that actually let you test requests and responses, though. I would like to explore that more. I'm still impressed with Django and its documentation.
<p>
I picked up more HTML5 tags, which has been enjoyable. I dig all the semantic tags they have now. Twitter Bootstrap and CSS design in general was a time drain, though. There was a lot of fidgeting required to get everything laid out right. I'm still a lousy graphical designer. CSS still trips me up on things that seem like they should be easy, such as define a DIV of a given relative width and then align a couple items to the left and one or two to the right within that DIV. And then have them all play nicely as the window resizes. I will say that Bootstrap helped compared to trying to do this from scratch in CSS, though.
<p>
GitHub (and to a lesser extent Heroku) has been an increasing pleasure to use. I put GitHub Pages and GitHub's wiki, issues, and milestone features to work on this project. I code alone so often that I've developed some lazy git practices, though. The main one is that my commits are based on work-session rather than issue. It doesn't affect anyone else, but it means I often commit things half-done or in a broken state. That is going to come back to haunt me if I ever have to rollback to a previous verison. I also have a lot yet to learn about merging and pulling with git. I ran into a bit of that while I was editing on Windows, Linux, and through the GitHub web interface today.
<p>
As you can probably tell, I enjoyed all the technical learning this project has afforded me.
<p>
Regarding the gamification aspects, I have this lesson to share: It takes a lot of time. Any gamification mechanics will be in addition to implementing the underlying service you want to provide. The gamification needs to be well-thought out, too. If possible, leveraging an existing framework could help cut down on that time... though it means you'll need to spend the time learning the framework and then being bound by its limitations.
<p>
The other thing that HabitMaster has clarified for me is the difference between gamification and a serious game. I see HabitMaster as an example of the former but not of the latter. To me, gamification means being inspired in your design by the fun and rewarding engagement we find in games--even when you're designing something that is clearly not a game. Because it's not a game, you can't just paste game mechanics onto your service. You need to think about the experience you're going for... which brings us to deeper concepts like mastery, autonomy, meaning, flow, engagement, reward, and the like. A serious game, on the other hand, is when you take something that is clearly a game and try to graft non-game goals or outcomes on to it.
<p>
HabitMaster will likely be dormant for a little while as I finish up some other pressing projects, but I do hope to resume development when I get some time. I'll also be starting a new teaching job in July. I wonder if I might bring some gamification to bear on course design there.
</p>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-21174070113994922422013-04-20T03:09:00.001-07:002013-04-20T03:09:55.337-07:00HabitMaster Progress<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
This past week or so I've been implementing my <a href="http://ztomasze.blogspot.com/2013/04/habitmaster-gamified-habit-formation.html">previously-mentioned</a> Habit Master design.
<p>
So far, things are going slowly but smoothly. I decided to divide my design into three apps: habits, users, and rewards. I first defined the habit and schedule models, some unit tests for them, and got them setup for admin view access. I also defined a User model before I realized it would be a much better idea to reuse Django's existing auth system for that. I still have a users app as a good place to put the views and page templates associated with account creation, login, and logout. I learned more about how templates work, so I have a base page template I'm inheriting from. I've also sorted out how static files work for things like style sheets and html5shiv.js. I'll eventually get Twitter Bootstrap into that mix too, but I'm focusing on functionality first.
<p>
There have been no major obstacles or bugs so far (knock wood). It's just been slow due to the general learning curve. Though I feel like I had a comfortable conceptual overview thanks to earlier exercises this semester, I still had to skim through the tutorial again as I completed each step for this project. I've also been diving deeper into the Django documentation for things like the auth system, view decorators (a bit like Java annotations), and request object details. I think Django could have provided more built-in help with my login form, but I haven't dug into that yet. Overall, I still like Django and its documentation.
<p>
I've been reading the HTML 5 spec to pick up some of the many new tags and throw them into the mix too.
<p>
There have also been a few toolchain improvements along the way. For example, I learned that <code>git add .</code> doesn't remove deleted files from the repository. To handle this, I learned more about <code>git add -u</code>, which will update all modified and deleted files but not stage any new additions, and <code>git add -A</code>, which will properly stage all changes. I've also been improving my virtualbox linux environment. For example, I found that KDE's Kate editor does allow to keyboard binding customization after all: you just have to go to Settings -> Configure Shortcuts... instead of Settings -> Configure Kate... to find them.
<p>
Hopefully things continue to go well. It doesn't seem like I have much to show at this point, but it feels like I've touched all the major parts at this point--apps, settings, models, tests, views, templates, urls, static files, and deploying to Heroku--so the rest should hopefully just be fleshing out more of the same. The next two or three weeks will tell.
</p>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-44703366156537087562013-04-06T04:10:00.000-07:002013-05-16T04:44:34.385-07:00HabitMaster: Gamified Habit Formation<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
I'm starting on a new web-based gamification project. The <a href="https://github.com/ztomasze/habitmaster/wiki/Design">current design is on GitHub</a>.
<p>
This design has been evolving from its original <a href="http://www2.hawaii.edu/~ztomasze/ics691/gamifiedtm.html">broad concept</a>. Some recent design additions include:
<ul>
<li>Users can now record notes regarding each task completion, or even if they did not complete the task for a given day.
<li>Users can specify degrees of completion (green for "wholehearted" or yellow for "halfhearted"). However, to avoid discouraging those just starting out, this will be an advanced feature that is unlocked only once a habit has been firmly established.
<li>Social features have been given a bit more consideration, though they will still probably not be implemented as part of version 1.0.
<li>Fleshed out a number of specific details about the interface and flow between screens, including three new UI mockups.
</ul>
<p>
Version 1.0 will include only the core features. I could evaluate the effectiveness of these gamification features by creating a second version with them stripped out. Specifically, this would omit the mechanics of streak tracking, leveling up a habit, badges, milestones, 1UPs, and social sharing. This would leave only the ability to enter habits, check them off each day, and review their history. I could then compare user adoption of the two systems: would users use the system longer and more frequently, have more successful habit formations, and enjoy the process more with these extra gamification features?
<p>
I'm looking forward to starting the implementation next week and learning some Django from scratch.
</p>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-85575330365092740442013-04-06T03:20:00.000-07:002013-04-06T03:20:19.630-07:00 Makahiki Widget Development<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
My exploration of the Makahiki platform continued this week. I tried my hand at adding a few new widgets that could be inserted into a different pages. (Apologies to any general readers: this will be a very Makahiki-specific post.)
<p>
I started by following the
<a href="http://makahiki.readthedocs.org/en/latest/hello-world-widget-development.html">Hello World tutorial</a>.
This was fairly painless and gave a nice overview of the files and functions that comprise a widget.
<p>
Next, I built a Group Scoreboard widget. At this point I wished for a bit more of a high-level overview of how widgets should work. I wasn't sure where the best place would be to add new data-gathering code: within the template HTML page, within the related views.py, or in the corresponding manager library. I quickly learned that code within a Django template doesn't seem to handle any parentheses or parameters, so that left views.py or the manager classes. I ended up working with both of these.
<p>
Groups are closely related to teams, so there was a fair amount of existing code to review and cannibalize. But, as with any complex system, it is hard to quickly build a mental map from the bottom-up like this. I felt a bit like I was redecorating while stumbling around in a dark room.
<p>
I got my Group Scoreboard together, though. I also built two Group Resource Use widgets. This proved a little trickier since it involved "subclassing" a widget. I also initially missed the INSTALLED_COMMON_WIDGET_APPS setting in settings.py, so I couldn't figure out why my common template file couldn't be found while resource_goal's could be. Also, I made a few errors that prevented the server from starting, and so I spent a while trying to debug single-line error messages such as "Error: cannot import name Team". I learned about this command:
<pre>
./manage.py shell --traceback
</pre>
<p>
which provides a full stack trace on an error. This was invaluable for debugging.
<p>
By this point, I was running short on time. I skipped making a Group Prize widget and started on a couple group-related Status page widgets. I spent an hour or so trying to decide how best to gather the group data from the team scoring/ranking system that is spread between score_mgr and team_mgr. I started toying with a plan to filter the team data to include only those in one group. As I neared the point to start testing it, I realized I didn't know exactly how the existing score widgets were placed on the Status page.
<p>
Specifically, I found the two templates (team_point.html and team_participation.html) that I wanted to copy in the <code>widgets/status/score</code> folder. However, simply adding a new group_point.html template in the same place didn't auto-magically show up. There is also no status.score widget registered through the Makahiki interface. Instead, these templates appear to be controlled indirectly through a separate scoreboard app. Looking through scoreboard's template was a bit of a mystery, however, since it makes no explicit reference back to the status.score templates.
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgosMn5uZ35DtF6zQ7qwd400tGmbDir6Ek_W_KId5BJ-_kPENWYDJuEosk7_uZG1ptFTxKNhmAr1WYfw-wgApKuMpjKXurSysBXwjOf4WssO6bypnFwA4luX48QP0_i1-DlSeDU_kQkjXA/s1600/ztomasze-A24-widgets-files.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgosMn5uZ35DtF6zQ7qwd400tGmbDir6Ek_W_KId5BJ-_kPENWYDJuEosk7_uZG1ptFTxKNhmAr1WYfw-wgApKuMpjKXurSysBXwjOf4WssO6bypnFwA4luX48QP0_i1-DlSeDU_kQkjXA/s320/ztomasze-A24-widgets-files.png" /></a>
<p><caption><i>The listed Makahiki widgets (front right) and corresponding file structure (back left).</i></caption>
</div>
<p>
At this point, it was time to move on from this project to bigger and better things. Here is a shot of my successful widgets currently on the Profile page:
<p>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjfakaFcMd6zZTqBuRvtQCLvYp3jD9znTEEowuiwH9S8HhqF8o9DT1eu0bXgte4vaVfBsptFz6MZO8uN0dHaBOWgV4fQjNTuA4fU943zYkwq7SI1oddL2mjhovTr88vChna8714MPk7_Q/s1600/ztomasze-A24-widgets.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjfakaFcMd6zZTqBuRvtQCLvYp3jD9znTEEowuiwH9S8HhqF8o9DT1eu0bXgte4vaVfBsptFz6MZO8uN0dHaBOWgV4fQjNTuA4fU943zYkwq7SI1oddL2mjhovTr88vChna8714MPk7_Q/s320/ztomasze-A24-widgets.png" /></a>
</div>
<p>
And these are available within Makahiki to be added to any page:
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeCOAw9tEd5L9h8EMsd5gyYs2EocqL27qXJGAK36EVlphFakzmMaOCy3zxSO0kSUYgEOm5dXpyU9JldZAdWztgrKzFAA9ifYL2Ycox62ELgfVgAxWjKzqNAx1JsY5LrW3uA1t6PKI9vR4/s1600/ztomasze-A24-widgets-menu.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeCOAw9tEd5L9h8EMsd5gyYs2EocqL27qXJGAK36EVlphFakzmMaOCy3zxSO0kSUYgEOm5dXpyU9JldZAdWztgrKzFAA9ifYL2Ycox62ELgfVgAxWjKzqNAx1JsY5LrW3uA1t6PKI9vR4/s320/ztomasze-A24-widgets-menu.png" /></a>
</div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-90147395918269654002013-03-25T20:06:00.002-07:002013-03-25T20:06:25.956-07:00Makahiki Configuration<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
Building on last week's Makahiki installation, this week I played around with some common configuration tasks. Below are the steps I completed. The section numbers given in parentheses correspond to the <a href="http://makahiki.readthedocs.org/">Makahiki docs found here</a>.
<dl>
<dt>0. Update your Heroku Makahiki instance (2.1.1.2.11)
<dd>
I added the AWS credentials environment variables to the project's activate file in ~/.virtualenvs folder first.
You should also add the MAKAHIKI_ADMIN_INFO here too. Uploading took 5 minutes or so.
<p>
I noticed this line in the output:
<pre>
Environment variable MAKAHIKI_DATABASE_URL not defined. Exiting.
</pre>
<p>
It didn't seem to cause any later problems though.
<dt>1. Getting to the challenge design page (2.3.2 / 2.2.1.1)
<dd>
I couldn't get to the <code>/account/login</code> page at first. This took me 20 minutes to debug, and I reinitialized the Heroku instance during the process. It turned out I had just mistyped "account". <sigh>
<dt>2. Design the global settings (2.3.3.1)
<dd>
I changed the Name and Logo settings as a test.
<dt>3. Design the teams (2.3.4.2)
<dd>
I added a new Lehua-C team as part of the existing Lehua Group.
<dt>4. Set up users (2.3.4.3)
<dd>
I could create new users, but I could not login normally using their accounts. It was possible to login as them from the admin's account, though. It turns out this was due to having mixed-case usernames, so make your usernames all lowercase.
<dt>5. Specify the games to appear in your challenge (2.3.6.1)
<dd>
I disabled the "Drop Down" water game.
<dt>6. Learn about how to design the resource goal games (2.3.6.2.1)
<dd>
This step just involves learning about the system and the design goals behind it.
<dt>6.1. Configure the Energy Goal Game for your new team
<dd>
I switched the Lehua-C team to using manually-gathered energy data.
<dt>7. Learn about how to design Smart Grid Games (2.3.6.3)
<dd>
This is another learning-about-the-system step, but it's important for the next few sub-steps.
<dt>7.0. Design on paper
<dd>
Or at least mentally sketch out the next level your want to create in the Smart Grid Game.
<dt>7.1. Create a Level
<dd>
I create a new Level 4 that unlocks once the user has completed a couple Level 2 tasks.
<dt>7.2. Create a new Activity action
<dd>
I created an activity involving airship research.
<dt>7.3 Create a new Event action
<dd>
I created an excursion to the helium fields.
<dt>7.4 Create a new Commitment action
<dd>
I created a commitment to hold one's breath while passing a graveyard.
<dt>7.5 Finalize the grid
<dd>
I edited the existing car-pool activity and added it to my level. (I was careful to select an activity that wasn't assigned to a category or level yet.)
<p>
Although I tested each of these sub-steps as admin along the way, I ran through the tests again with a different user.
<dt>8. Design the Top Score Game (2.3.6.4)
<dd>
I created a new prize.
<dt>9. Design the Raffle Game (2.3.6.5)
<dd>
I created a teddy bear raffle prize and tested it.
<dt>10. Design the Badge Game Mechanics (2.3.6.8)
<dd>
I created a badge and earned it.
<dt>11. Manage Action submissions (2.4.2.2.1)
<dd>
I approved and rejected a few activity responses that I generated during the earlier tests.
</dl>
<p>
Overall, I found Makahiki to be a fairly polished and complete system. The most challenging parts of this proved to be my own mistakes (mistyping the URL) or undocumented requirements (such that the usernames need to be all lowercase). My general impression, though, is that Makahiki design and management is a rather long and tedious affair. I tried to create some slightly amusing activities to stay engaged with the process, but I'm still glad I'm done with this exercise.
</p>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-69791150445694765662013-03-17T02:49:00.001-07:002013-03-17T13:52:00.000-07:00Remote Makahiki Installation: A Reader's Guide<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
After <a href="http://ztomasze.blogspot.com/2013/03/local-makahiki-installation-readers.html">installing Makahiki locally</a>, it's time to try deploying it to Heroku. Once again, I'm following the user manual's <a href="http://makahiki.readthedocs.org/en/latest/installation-makahiki-heroku.html">instructions for this</a> with a report of how each step went.
<dl>
<dt>2.1.1.2.1. Install Heroku
<dd>
Already installed.
<dt>2.1.1.2.2. Add your SSH keys to Heroku
<dd>
Already done from an earlier project.
<dt>2.1.1.2.3. Verifying your Heroku account
<dd>
Grudgingly done. I didn't really want to hand out my credit card for this.
<dt>2.1.1.2.4. Setup Amazon S3
<dd>
Grudgingly done. (Later, in Step 9, I learned I should have selected US Standard as the region for my bucket.)
<dt>2.1.1.2.5. Setup environment variables
<dd>
As instructed, though I changed the admin password.
<dt>2.1.1.2.6. Download the Makahiki source
<dd>
Skipped this step, since I still have it from the local installation.
<dt>2.1.1.2.7. Initialize Makahiki
<dd>
This was probably unnecessary, but: I wasn't sure if this initialization would mess up my existing local installation. I created a new virtualenv with <code>mkvirtualenv makahiki-heroku</code>.
<p>
In the next step, I realized I also needed to run <code>pip install -r requirements.txt</code> at this point.
<p>
The upload process took about 20 minutes or so.
<dt>2.1.1.2.8. Start the server
<dd>
Everything loaded fine, but the pages lacked style and images. I checked my S3 bucket and it was empty. Trying again, I found this in the output:
<pre>
Do you wish to continue (Y/n)? Y
resetting the db...
Resetting HEROKU_POSTGRESQL_RED_URL (DATABASE_URL)... done
syncing and migrating db...
Running `python makahiki/manage.py syncdb --noinput --migrate --verbosity 0`
attached to terminal... up, run.4074
collecting static and media files...
Traceback (most recent call last):
File "/home/ztomasze/makahiki/makahiki/manage.py", line 9, in <module>
from django.core.management import execute_from_command_line
<b>ImportError: No module named django.core.management</b>
s3put -q -a AKIAJC76TME6N23PKRMA -s [...omitted...] -b ztomasze-makahiki
-g public-read -p `pwd` media
<b>sh: 1: s3put: not found</b>
s3put -q -a AKIAJC76TME6N23PKRMA -s [...omitted...] -b ztomasze-makahiki
-g public-read -p `pwd`/site_media site_media/static
<b>sh: 1: s3put: not found</b>
loading base data...
</pre>
<p>
Both django.core and the s3put commands seem to be missing. I remembered that I had created a new virtualenv, so I ran <code>pip install -r requirements.txt</code> and tried again. Problem solved.
<dt>2.1.1.2.9. Verify that Makahiki is running
<dd>
The links to images and stylesheets were still failing, even though the files were now in place on S3.
<p>
As an example, in the source code of the main page, the logo gif had this URL:
https://s3.amazonaws.com/ztomasze-makahiki/static/images/old-logo.png
<p>
Accessing this URL directly got me this error message:
<pre>
<Error>
<Code>PermanentRedirect</Code>
<Message>
The bucket you are attempting to access must be addressed using
the specified endpoint. Please send all future requests to this
endpoint.
</Message>
[...snip...]
<Endpoint>ztomasze-makahiki.s3.amazonaws.com</Endpoint>
</Error>
</pre>
<p>
And indeed, accessing https://ztomasze-makahiki.s3.amazonaws.com/static/images/old-logo.png instead worked fine.
<p>
Feedback from Yongwen, the current Makahiki admin, suggested that this URL difference is due to which region you select when creating the S3 bucket. I originally went with S3's suggestion of Oregon, but apparently US Standard gives you the URLs assumed by Makahiki. To try this, I deleted and tried to recreate my bucket. There was a temporary name conflict, so I had to choose a different bucket name. I updated the MAKAHIKI_AWS_STORAGE_BUCKET_NAME environment variable and reinitialized Makahiki (step 7).
<p>
It looks like everything now works.
</dl>
<p>
<b>Conclusion:</b> Total Time: 3 hours. This was longer than the local install, although there were fewer steps. This time difference was mainly due to waiting for downloads and uploads. Overall, this process was about as painful as any Heroku deployment, though each one gets easier with more practice.
<p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0smJuQdNXU02TROhgK4pGpNvB5gEYL3uCO2CGJ5BmDUJ5agmQTjKlvE9ZV1QxUn3zKOxjsggAI-ah1UhJOOy3ndeAOPEQgGW-OVpVfU-nsBm-RvHJInLPyK76nONBd897aRgWeYTFSbI/s1600/ztomasze-A22-remote.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0smJuQdNXU02TROhgK4pGpNvB5gEYL3uCO2CGJ5BmDUJ5agmQTjKlvE9ZV1QxUn3zKOxjsggAI-ah1UhJOOy3ndeAOPEQgGW-OVpVfU-nsBm-RvHJInLPyK76nONBd897aRgWeYTFSbI/s320/ztomasze-A22-remote.png" /></a>
<br /></div>
Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-5541879518704508623.post-83613543607539048162013-03-16T02:55:00.000-07:002013-03-25T00:49:37.021-07:00Local Makahiki Installation: A Reader's Guide<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
Today I worked through the installation of the <a href="https://github.com/csdl/makahiki/">Makahiki</a> energy competition platform, <a href="http://makahiki.readthedocs.org/">as documented here</a>. This is a record of how each step went for me. <abbrev title="Your mileage may vary.">YMMV</abbrev>.
<dl>
<dt>2.1.1.1.1.1. Hardware requirements
<dd>
Running on Debian 7 in a VirtualBox with 2GB of RAM (on Windows 7), <a href="http://ztomasze.blogspot.com/2013/02/debian-7-on-virtualbox_22.html">as described earlier</a>. Apparently I could have just <a href="http://makahiki.readthedocs.org/en/latest/installation-makahiki-windows-vm.html">grabbed a large VirtualBox image</a> and worked from there. Instead, I followed the step-by-step <a href="http://makahiki.readthedocs.org/en/latest/installation-makahiki-unix.html">Unix instructions</a> within my existing system.
<dt>2.1.1.1.1.2. Install Python
<dd>
I checked the version: already installed.
<dt>2.1.1.1.1.3. Install C Compiler
<dd>
I checked the version: already installed.
<dt>2.1.1.1.1.4. Install Git
<dd>
I checked the version: already installed.
<dt>2.1.1.1.1.5. Install Pip
<dd>
I checked the version: already installed.
<dt>2.1.1.1.1.6. Install Virtual Environment Wrapper
<dd>
Followed instructions. As root: <code>pip install virtualenvwrapper</code>
<p>
I initially moved on at this point, but I later found that workon did not work. Don't forget to setup up your shell startup file as instructed. I chose to go with lazy initialization, and I changed PROJECT_HOME to just $HOME, since that's where I've been putting my projects so far.
<dt>2.1.1.1.1.7. Install Python Imaging Library
<dd>
As instructed, I used apt-get to install python-imaging and libjpeg-dev. (I already had python-dev.) I also had to set up the symlinks as instructed.
<dt>2.1.1.1.1.8. Install PostgreSQL
<dd>
PostgreSQL was already installed, but I did need to edit pg_hba.conf as instructed. The full path to this file was: /etc/postgresql/9.1/main/pg_hba.conf
<dt>2.1.1.1.1.9. Install Memcache
<dd>
As instructed, I used apt-get to install memcached and libmemcached-dev.
<dt>2.1.1.1.1.10. Download the Makahiki source
<dd>
As instructed.
<dt>2.1.1.1.1.11. Workon makahiki
<dd>
Once I fixed the part I accidentally skipped in step 6, this worked fine.
<dt>2.1.1.1.1.12. Install required packages
<dd>
As instructed. The download and install took a while (5 minutes) with a lot of output and warnings, but no errors.
<dt>2.1.1.1.1.13. Setup environment variables
<dd>
As instructed. I added the configuration to the end of ~/.virtualenvs/makahiki/bin/postactivate. If you copy-and-paste, don't forget to remove the % signs. I also reused my existing PostgreSQL user, django. (This may or may not be a good idea, so I don't necessarily recommend it. It worked fine for me, though.) Once I wrote these to the config file, I typed <code>deactive</code> and then <code>workon makahiki</code> to refresh the settings.
<dt>2.1.1.1.1.14. Initialize Makahiki
<dd>
As instructed.
<dt>2.1.1.1.1.15. Start the server
<dd>
As instructed. Both servers worked for me.
<dt>2.1.1.1.1.16. Verify that Makahiki is running
<dd>
Yay, it runs!
</dl>
<p>
<b>Conclusion:</b> This process is fairly easy as long as you go carefully and don't miss a step.
It is less difficult than installing the Django toolchain for Heroku, though you would need to make it through much of that process first if you want to <a href="http://ztomasze.blogspot.com/2013/03/remote-makahiki-installation-readers_17.html">deploy Makahiki to Heroku</a>.
<p>
Total Time: 2.5 hours, including the time taken to document the process here. Probably only 1.5 hours or so if you were just following the directions.
<p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKxj4y7_Ax50hPnm0fybfsnAXVjlR8PFk-9oi8PRLJXv60XV1Pwox9aVFXhPpR0HxU8tVYnLFEtZCTgZ8HjQouxQngDnmXjTmemMAwdk8kY7YWUxOSnhSeathOFADtNdXJ60VrZiesUMA/s1600/ztomasze-A22-local.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKxj4y7_Ax50hPnm0fybfsnAXVjlR8PFk-9oi8PRLJXv60XV1Pwox9aVFXhPpR0HxU8tVYnLFEtZCTgZ8HjQouxQngDnmXjTmemMAwdk8kY7YWUxOSnhSeathOFADtNdXJ60VrZiesUMA/s320/ztomasze-A22-local.png" /></a>
</p>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-83920483774435795732013-03-05T21:50:00.000-08:002013-03-05T21:50:14.673-08:00 Kukui Cup: A Taste of Gamification<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
I spent this past week playing a demo run of the <a href="http://www.kukuicup.org/">Kukui Cup</a> competition. This is an online educational "game" normally run for UH undergrads living in the dorms. It intends to teach participants about current energy issues and promote new energy conservation habits.
<p>
The primary form of interaction in the Kukui Cup is completing "Get Nutz" tasks. These tasks include watching educational videos and answering a short question about each one; commiting to a daily habit such as turning off lights when you leave a room; and field-trip activites. Completing each task earns you points that you can apply to a raffle to win prizes. In the real competition, real-time energy use of the dorms would also play a role.
<p>
It was interesting to see some recent <a href="http://www2.hawaii.edu/~ztomasze/ics691/gamification.html">views on gamification</a> embodied in the mechanics of the Kukui Cup. Jane McGonigal proposes that gamification could be used to harness the energy people devote to games to affect positive change in the real-world. The Kukui Cup seems founded on that principle: that the habits and knowledge gained during the course of the game will continue to influence people afterward.
<p>
Tadhg Kelly suggests that gamification really boils down to three mechanics: social validation, completion, and prizes. The Kukui Cup uses all of these. You can see your ranking compared to others, and you are encouraged to advertise your participation through social media and on your dorm-room door. The Get Nutz layout makes it very clear what tasks are available to you and how far you've progressed through them, which gives a sense of completion. The points you earn are all given a real-world value by letting you use them to buy tickets for raffle prizes.
<p>
It is less clear to me whether the Kukui Cup contains the three ingredients that Sebastian Deterding claims are missing from most gamification efforts: meaning, mastery, and autonomy. When you strip away the game mechanics of the Kukui Cup, there is not much content left behind that is inherently meaningful to users. That is, the game needs to assume that user have an existing motivation to learn about energy and compete with their peers to conserve it; the game then provides a fun way to do so. There is no real skill that you improve by playing the Kukui Cup, although the way that Get Nutz is broken down into levels that need to be unlocked does give a sense of improvement over time. Finally, the Kukui Cup offers users a fair amount of autonomy in choosing which tasks to complete and habits to cultivate, but users are not able to propose new activities or incorporate goals of their own design into the game.
<p>
I also gathered a few practical design tips from playing the Kukui Cup. I found the steady stream of points to be almost motivation in themselves, though giving them a real value through the raffle system was also fun. It was nice to be in the running to win something even if I wasn't close to the top player's ranking. The task-unlocking system was also motivating; it felt a bit like leveling-up in an RPG. The need to check back in every day in order to claim the points for yesterday's habits was a very slick way to keep people logging in. That said, it was fairly easy to cheat on the habits, and sometimes it was unclear whether I adhered to the rule or not. For example, if I promised to do only full loads of laundry, but I didn't do laundry at all today, did I still fulfill my promise?
<p>
On the downside, the constant pressure to advertise what I had done on Facebook was a bit annoying, as were the constant requests for feedback. Because of these, it took 3 or 4 clicks to complete a task when it seemed like it should have only taken 2 or 3. Also, if the review questions for the short videos were multiple-choice or matching rather than short answer, their scoring could be automated. This would eliminate the delay in earning points and save someone a few hours "grading" time.
<p>
Overall, I found the Kukui Cup a solid example of gamification. It's always nice to explore some concrete examples of theoretical concepts.
</p>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-75130160300376602652013-02-25T17:59:00.001-08:002013-02-25T18:10:32.943-08:00Django on Heroku: Revisited<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
<a href="http://ztomasze.blogspot.com/2013/02/django-on-heroku-readers-companion.html">Last week</a>,
I spent quite a while getting a simple "Hello World" Django app in place on Heroku. This week, I wanted to see if I could repeat the process by posting a small <a href="https://github.com/cammoore/responsive-heroku">working demo project</a>. Things went much more smoothly this time around.
<p>
I used <code>git</code> to grab a local clone of the project. I used <code>virtualenv</code> to setup a virtual environment and <code>pip</code> to load that environment with the project's requirements.
<p>
I created a local PostgreSQL database so I could test things locally. I remembered to set the DATABASE_URL environmental variable and to sync Django with the new database. I debated on whether I needed to run <code>python manage.py collectstatic</code> in order to move the website's static files (such as scripts and stylesheets), but the site ran fine locally as-is without it.
<p>
Since everything seemed to work fine locally, it was time to push to Heroku. I double-checked that <code>.gitignore</code> was in place with <code>venv</code> and <code>*.pyc</code> in it. When I ran <code>git add .</code> I realized that I'd done all of this testing without touching a single project file. That's a neat design.
<p>
I created a new heroku app and used git to push the files to heroku. I initially forgot to sync the database on Heroku's end, but the resulting error message was obvious and it only took a minute to correct. To make sure everything really worked, I used Django's default admin interface to add some database contents (a poll with 4 possible answers). Everything seems to be running fine.
<p>
Given the light expected traffic, I didn't bother to switch out the default Django server for gunicorn.
<p>
All of this took me about 1 hour, compared to last week's 20 hours. Now that I've got this down, maybe Heroku isn't so bad after all!
</p>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-67871707517694416842013-02-22T02:12:00.000-08:002013-03-03T01:42:39.945-08:00Django on Heroku: A Reader's Companion<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
I recently <a href="http://ztomasze.blogspot.com/2013/02/debian-7-on-virtualbox_22.html">setup a fresh VirtualBox Debian Linux system</a>. Within that context, I then walked through the Heroku tutorial on <a href="https://devcenter.heroku.com/articles/django">Getting Started with Django on Heroku</a>. I ran into a number of errors along the way. Most of them took a few minutes (or an hour) of surfing to find a solution. If you've found this page, perhaps you hit one of those same error messages, and so my solutions will save you a little time.
<p>
I'll follow the sections of the current Django on Heroku tutorial here and just add the errors and solutions I encountered.
</p>
<h4><a href="https://devcenter.heroku.com/articles/django#prerequisites">Prerequisites</a></h4>
<p>
There are a bunch of different Python installers out there: pip, distribute, setuptools, easy_install, etc. You'll need both pip and virtualenv... but virtualenv is listed specifically as a prereq at the start of the tutorial. According to the virtualenv page, the preferred way to get virtualenv is to use pip... but the best way to get pip is to use virtualenv. To resolve this, I decided to install pip globally... but pip requires distribute. Of course, the easiest way to get distribute is to use pip to install it (<i>haha!</i>)... but there is also <a href="https://pypi.python.org/pypi/distribute#installation-instructions">this option</a> where you use curl (or wget) to download an installation script. Once you have distribute, you can do <a href="http://www.pip-installer.org/en/1.3.X/installing.html#using-get-pip">something similar</a> for pip.
</p>
<h4><a href="https://devcenter.heroku.com/articles/django#start-a-django-app-inside-a-virtualenv">Start a Django app inside a Virtualenv</a></h4>
<p>
It turns out the virtual environment needs a few things installed locally too...
<pre>
Error: pg_config executable not found.
</pre>
<p>
You need the <code>postgresql</code> package installed. (Use <code>apt-get install postgresql</code> to install it.)
<pre>
Error: You need to install postgresql-server-dev-X.Y for building a server-side
extension or libpq-dev for building a client-side application.
</pre>
<p>
Okay, so you also need the <code>postgresql-server-dev-9.1</code> package (currently).
<pre>
In file included from psycopg/psycopgmodule.c:27:0:
./psycopg/psycopg.h:30:20: fatal error: Python.h: No such file or directory
compilation terminated.
</pre>
<p>
And the <code>python-dev</code> package too.
<p>
Hooray! At this point, I could get a Python app created in the virtualenv and run it. Things seemed downhill for me from here until...
<h4><a href="https://devcenter.heroku.com/articles/python#deploy-your-application-to-heroku">Deploy to Heroku</a></h4>
<p>
Typing <code>heroku create</code> gave me:
<pre>
! Heroku client internal error.
getaddrinfo: Name or service not known (SocketError)
</pre>
This error was coming from the excon gem. <code>heroku login</code> gave me the same error. Turns out I had a DNS problem. I entered 8.8.8.8 (Google's public DNS server) into /etc/resolve.conf and tried it again. Worked.
<p>
Then <code>git push heroku master</code> lead to:
<pre>
Permission denied (publickey).
fatal: The remote end hung up unexpectedly
</pre>
<p>
I needed to generate a public key with: <code>ssh-keygen -t rsa</code> By default, this puts the key into ~/.ssh/id_rsa.pub. You then need to register it with Heroku: <code>heroku keys:add ~/.ssh/id_rsa.pub</code>
<p>
At this point, I could execute the basic Django app both locally (with <code>foreman start</code>) and on Heroku.
<p>
Although my app wasn't actually using the database, I figured I'd better try syncing with it anyway...
<h4><a href="https://devcenter.heroku.com/articles/django#syncing-the-database">Syncing the database</a></h4>
<p>
I wanted to run it locally first, so I needed to setup a local postgreSQL database. (The tips on the <a href="http://ics691s13.wordpress.com/modules/introduction-to-heroku/a18-helloheroku-project/">assignment page</a> were very helpful here.) Also, you need to be <code>postgre</code> user in order to execute the <code>psql</code> command that starts the PostgreSQL console. (It took me a while to even track that command down.) So:
<pre>
root@tinkVr:~# su postgres
postgres@tinkVr:/root$ psql
could not change directory to "/root"
psql (9.1.8)
Type "help" for help.
postgres=# CREATE USER django WITH CREATEDB PASSWORD 'djangoapp';
CREATE ROLE
postgres=# CREATE DATABASE a17 OWNER django;
CREATE DATABASE
postgres=# \q
</pre>
<p>
You'll probably want to change the lowercase details (user, password, and database names) to something else. Note that you do not need to update your Django project's settings.py with these details because dj_database_url will pull these from from the DATABASE_URL environment variable. (If you log into Heroku's web interface and check your database settings, you can see what these values will actually be in the Heroku environment.) However, to run locally, you do need to set this variable appropriately. In my case, this translates to:
<pre>
export DATABASE_URL=postgres://django:djangoapp@localhost/a17
</pre>
<p>
typed at the command prompt.
<p>
At this point, I could successfully run <code>python manage.py syncdb</code> locally. However, <code>heroku run python manage.py syncdb</code> lead to a timeout. This happened even when just trying to open a simple shell on Heroku with <code>heroku run bash</code>. Heroku does offer some <a href="https://devcenter.heroku.com/articles/one-off-dynos#troubleshooting">troubeshooting on this</a>. It turns out port 5000 was being blocked by my ISP (the wired network in the Computer Science department on campus). I switched to the public UH wireless and I was able to connect.
<p>
The rest of tutorial went smoothly for me. (pip installs gunicorn for you.) Hopefully it goes smoothly for you too!
<p>
Next up: Fleshing out the Django app to actually do something...
<br /></div>
Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-5541879518704508623.post-87194533554162091832013-02-22T00:54:00.000-08:002013-02-25T18:00:05.810-08:00Debian 7 on a VirtualBox<div dir="ltr" style="text-align: left;" trbidi="on">
I'm currently taking a <a href="http://ics691s13.wordpress.com/">class</a> on serious games. We've already <a href="http://www2.hawaii.edu/~ztomasze/ics691/django.html">covered Django</a> and the <a href="http://www2.hawaii.edu/~ztomasze/ics691/gamification.html">nature of gamification</a>. This week we are trying to deploy a simple Django project to <a href="http://heroku.com">Heroku</a>, a cloud-based app hosting service. This proved fairly difficult, requiring that we get a long toolchain in place. (Details of that process <a href="http://ztomasze.blogspot.com/2013/02/django-on-heroku-readers-companion.html">to follow</a>.)
<p>
This toolchain requires running scripts that download and install other required components. Whenever you're missing something, you get error messages that look like this:
<pre>
building 'psycopg2._psycopg' extension
error: Unable to find vcvarsall.bat
</pre>
You then have to figure out why you don't have vcvarsall.bat, or why it's not in the right place, and what you need to do to fix it.
<p>
Other students in the class reported that, since most of the required tools assume a unix-like environment, trying to get everything configured in Windows seemed to lead to even more problems. Also, project dependency managers like <a href="http://ant.apache.org/ivy/">Ivy</a> or <a href="http://www.pip-installer.org/en/1.3.X/">pip</a> always make me a little nervous. I don't really like the idea of downloading some dude's script from GitHub, running it, and having it download other arbitrary code from various points around the web and freely executing it all on my machine.
<p>
Given this context, I decided to create a Linux environment to work in. While I've dual-booted on a number of different machines before, I decided to try a virtual machine this time. There are a lot of advantages to this:
<ul>
<li>No need to mess with your current partition configuration.
<li>Your can run the virtualized OS in a window, switching back and forth between the environments, even copying clipboard and file data between them.
<li>You can pause and save a running instance. (I've already used this feature: I paused a lengthy compilation/installation process so I could shutdown the real machine and then resumed everything again in the morning.)
<li>You can take a snapshot of the whole machine as a backup, which can be especially handy before you make any significant OS changes.
<li>You can copy the entire virtual OS environment to another machine. So, once you get your OS all configured, you're not bound to the original hardware.
</ul>
<p>
For my virtual machine, I went with <a href="https://www.virtualbox.org/">VirtualBox</a> over VMware, since VirtualBox costs nothing and is open-source. Their provided <a href="https://www.virtualbox.org/manual/UserManual.html">documentation</a> is pretty good too.
<p>
I then installed Debian 7 on it. (I actually did this twice, but here's what the process looked like the second time around. I'm assuming here that you know the basics of installing a Linux system.)
<p>
Due to previous Linux endeavors, I already had an <a href="http://www.debian.org/CD/http-ftp/">ISO of the last stable Debian release</a> (6.0/"squeeze") handy on a CD. (If I was doing this from scratch, I would grab a "testing" ISO instead.) I created a VirtualBox machine with a 12.0GB hard drive. (I hear this the only parameter you can't change once you create the machine.) Although it's a little slower, I went with a dynamically-sized file to save space on my host machine. I gave the machine 2GB of RAM and 1 CPU. (I'm used to running Linux on <a href="http://www.snarkdreams.com/personal/tinker/">ancient hardware</a>, so this is more than most of my installations get.) When I first started the virtual machine, it booted off the CD and began the installation wizard.
<p>
Debian's default Graphical Install worked out fine. When asked for what subsystems to install, I unchecked everything (including Standard System Utilities), so I had the barest machine possible. The default setup reserved 500MB of my 12GB for a swap partition.
<p>
The "stable" release tends to get outdated. For example, squeeze gives you Python 2.6. The current 2.7.3 is available in the "testing" release, and that will be updated within about a week of any new Python updates. So, once the installation was done, I edited my /etc/apt/sources.list to pull from "testing" rather than "squeeze". I then ran an <code>apt-get dist-upgrade</code> to switch over.
<p>
In upgrading, I got a new kernel. On rebooting, I found that my virtualbox guest services were not longer starting up properly. I would get this error:
<pre>
AdditionsVBoxService error: VbglR3Init failed with rc=VERR_FILE_NOT_FOUND
</pre>
<p>
At this point, the only obvious problem this caused is my mouse scrollwheel stopped working, but I knew it could cause other problems later on. I eventually <a href="http://www.lornajane.net/posts/2011/missing-kernel-source-when-installing-virtualbox">learned</a> that I needed to install the appropriate linux-header package. (While I love the idea of Linux, this is an example of why I don't actually use it everyday. You upgrade something that's supposed to be routine and suddenly something else breaks with some arcane error that requires an hour to debug, some config file hacking, and some new packages to track down. <sarcasm><i>Oh, you're obviously just missing the necessary the kernel headers. Duh!</i></sarcasm>)
<p>
For my desktop environment, I used: <code>apt-get install <a href="http://lxde.org">lxde</a></code>. This is pretty minimalist desktop, but I figured it should still be snappy in the virtual machine. So far, it is responsive. It looks crude coming to it from Windows 7, but I find I don't mind so much when I have Windows 7 running in the background, a single click away! When I get some time, I'm curious to see how well the latest KDE runs under these conditions.
<p>
I also installed openjdk7 and Eclipse (which wanted openjdk6 and a bunch of other stuff).
<p>
At this point, I had a working virtual Linux machine. Time to <a href="http://ztomasze.blogspot.com/2013/02/django-on-heroku-readers-companion.html">put it to work</a>!
</p>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpOWBwsVWG8KTKluviG6B3GeBt46Mf0yrJAcrssVyFpiRfr8GEQmG2u7S2lkk-dFd4COfZK4s_k9vwEQSXdzFA8x_UD39Dwx-0u4PgVzJbsUgUInVOLLyW9HqUrFoe8U5c5yqjnIj2gmY/s1600/vboxlinux.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpOWBwsVWG8KTKluviG6B3GeBt46Mf0yrJAcrssVyFpiRfr8GEQmG2u7S2lkk-dFd4COfZK4s_k9vwEQSXdzFA8x_UD39Dwx-0u4PgVzJbsUgUInVOLLyW9HqUrFoe8U5c5yqjnIj2gmY/s320/vboxlinux.png" /></a>
<p>
<small>LXDE in maximized window with Windows taskbar readily available below.</small>
</div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-91367927254191243402013-01-28T17:23:00.001-08:002013-01-28T17:24:59.413-08:00Global Game Jam 2013: The Queen's Heart<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
I had fun hacking together a game called <i>The Queen's Heart</i> over the weekend as part of the Global Game Jam 2013. More info about the result can be found on <a href="https://sites.google.com/site/zachtomaszewski/projects/queens-heart">its new project page</a>.
</p>
<p>
In other unrelated news, I worked on picking up Clojure over the break, though that's lagged a bit now that another semester has started. I'm currently learning Git and Django (the Python-based web framework) as part of a class on serious games. All fun stuff!
</p>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-45276716584583674982012-11-11T01:15:00.000-08:002013-01-28T17:24:26.805-08:00Keyboard and Monitor Efficiency-Boosts<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
In online discussions, I've often seen two claims made about efficiency:
<ul>
<li>Two monitors are better than one
<li>Master gurus work so fast because they never take fingers off the keyboard.
</ul>
<p>
Over the past month or so, I've been exploring these for myself.
<p>
First, I bought an affordable 19" ViewSonic monitor for about $100 from Amazon. I also picked up a desk clamp, and so I was able to install it directly above my 15" laptop screen. The two are the same resolution, and, if I slide the monitor back back 3 or 4 inches, they're about the same size in my visual field. So I now have double the screen real-estate. I also installed a copy of <a href="http://www.realtimesoft.com/ultramon/">UltraMon</a>.
<p>
So far, the second monitor has been fun, but not all that useful. It's handy when I want documentation or my streaming radio up at the same time I'm working on some code. However, I find that two screenfulls of documents with white backgrounds are pretty bright at night, even though I cranked the brightness down pretty low. Also, even though the monitor is straight ahead of me, it makes my neck a little stiff if I work on it for too long. I guess I've gotten used to that slightly downward sightline of a laptop screen. Still, I don't regret the purchase and I'm fine with flipping the second monitor on whenever it's useful. I think (or at least hope) I'll gradually put it to more use over time.
<p>
The second notion I've been exploring is that keyboard-based computing is faster than mouse-based. This is often an argument for using emacs or (even more so) for vi. As <a href="http://ztomasze.blogspot.com/2012/06/efficiency-though-keyboard-shortcuts.html">mentioned previously</a>, I've been playing with <a href="http://autohotkey.com">AutoHotKey</a>. Here are a few of the interesting settings from my AutoHotKey script file:
<pre class="brush: text">
#KeyHistory 0 ; don't record keypresses
</pre>
<p>
I added this when I realized all my keystrokes--including the title of the current window--were being logged. Don't really need that info lying around.
<pre class="brush: text">
~RAlt::Shift
~RCtrl::Shift
</pre>
<p>
These turn right Alt and right Control into Shift+Alt and Shift+Ctrl. I've found this very handy with various macro and other keybindings.
<p>
This next setup was quite interesting:
<pre class="brush: text">
CoordMode ToolTip, Screen ;(at top of file)
SetCapsLockState AlwaysOff ;;CAPS button does nothing alone
CapsLock & Enter::
if GetKeyState("ScrollLock", "T") {
ToolTip ;turn it off
}else {
ToolTip NavMode, 0, 0
}
Send {ScrollLock}
return
#If GetKeyState("ScrollLock", "T")
i::Up
j::Left
k::Down
,::Down
l::Right
u::Send {PgUp}
Space::Send {PgDn}
h::Send {Home}
`;::Send {End}
a::Send {Alt Down}
a UP::Send {Alt Up}
s::Send {Shift Down}
s UP::Send {Shift Up}
d::Send {Ctrl Down}
d UP::Send {Ctrl Up}
f:: ;reserved for... mouse controls?
#If
CapsLock & i::Send {Up}
CapsLock & j::Send {Left}
CapsLock & k::Send {Down}
CapsLock & ,::Send {Down}
CapsLock & l::Send {Right}
CapsLock & u::Send {PgUp}
CapsLock & Space::Send {PgDn}
CapsLock & h::Send {Home}
CapsLock & `;::Send {End}
</pre>
<p>
The idea I had here was that the different keyboard modes (ScrollLock, NumLock, CapsLock, and InsertMode) were going largely unused, but each could allow the keyboard to be completely remapped. My laptop keyboard doesn't even have a ScrollLock or NumLock key, and lacks any keyboard indicator lights. I thought I'd start with the least used--ScrollLock. Hitting CapsLock+Enter (a double-pinky-tap) puts me into ScrollLock and, since I don't have an indicator light, pops a very small "NavMode" tooltip in the upper left-corner of the screen. The homekeys (jkli,) become arrow keys, with h and ; as Home and End and U and Space as PageUp and PageDown. a, s, and d became alt, shift, and ctrl, respectively. You could of course take this further.
<p>
The homekeys-to-arrow-keys conversion would be handy enough to use without switching modes, so the second part means I can hold down CapsLock to turn the homekeys into arrow keys.
<p>
So, there we go: no reason to ever leave the homekeys again!
<p>
I found I hardly ever used this. I'm already trained on the arrow keys and the mouse, so that's where I go. If I'm moving my cursor far, I grab the mouse. If I'm going up a line or two, just a couple arrow-key taps are good enough. Sliding my right hand over 3 inches to use either of these wasn't costing me that much time, but trying to remember to use CapsLock instead was.
<p>
I still think it's a cool idea, though, which is why I'm sharing it here. Also, an approach like this would be very handy to implement a working number pad on my laptop, since it doesn't provide one.
<p>
In the end, I reverted to:
<pre class="brush: text">
+CapsLock::CapsLock ;Shift+CapsLock toggles CapsLock mode
CapsLock::Ctrl
</pre>
<p>
which just turns CapsLock into Control.
<p>
I found I wasn't using this combo much a month ago, but this past couple days I've been exploring the fancier features of Eclipse. Ctrl+Space in particular is much handier with CapsLock as Ctrl.
<p>
Overall, my foray into keyboard efficiency has been disappointing. Supposedly the learning curve is worth it, but I doubt the extra few milliseconds are ever going to add up to the time it will take me to remap and retrain to do it. <a href="http://www.asktog.com/TOI/toi06KeyboardVMouse1.html">This old article</a> suggests that my feelings on this are perhaps not so far off after all: that the speed of keyboarding is actually illusory.
<p>
This got me thinking of the QWERTY vs DVORAK debate. Supposedly, for experts, DVORAK is 10% faster (though this claim is contested). But, even if it is, I'm not hitting the QWERTY limit. That is, other people can type way faster on QWERTY than I can. I don't think it's primarily the keyboard layout that's slowing me down there; it my physical and mental processes that are too slow.
<p>
Bringing this back to the keyboard-vs-mouse debate, I see the same thing at play. I hardly ever mouse through a menu during my normal work, which I think is the main source of the "GUIs are slow" argument. I do use common keyboard shortcuts (like Ctrl+Z/X/C/V), etc, which are very fast when combined with mouse selection. When I don't use a keyboard combo, I generally hit a toolbar button. This is about as fast as a mouse-gesture. And even heading into a well-known and shallow menu doesn't really take that long. Striving for micro-improvments in this area is not really worth it to me. (Your mileage may vary, though, which is fine.)
<p>
This brings me in turn to my recent Eclipse experience. I'm realizing that Eclipse--with its Ctrl+Space and Alt+/ completions and various Content Assists and Code Templates--can drastically improve code generation times because it writes large sections of the code for you. I suspect that this is what may really be at work with older editors like emacs and vi: not that they are keyboard-only but that they are so full of useful tools. It's the intelligent and useful tools that make you faster, not the milliseconds you saved in selecting the tool.
<p>
So I've decide to give up on this idea of converting to entirely keyboard use. Instead, I'll be embracing my mouse and toolbar use. (For example, I mapped WinKey+ScrollUp to switch screens between monitors.) I'll see what I can do about speeding those up. I'll still use the keyboard and good bindings where appropriate, of course, but writing good macros is going to save me way more time than not moving my hand 3 inches over to the arrow keys.
<p>
I have one last insight on this, which is two-fold. First, keyboard sequences (such as Alt+F, S for Save on Windows or Ctrl+X, Ctrl+S on emacs) are about as fast as a more complicated finger-spreading key-combo (such as Ctrl+Alt+S). Secondly, menus actually provide and scaffold such combos. Alt+F gets you the File menu, and then every element there has a corresponding letter. You can get to any menu option in 2 or 3 keypresses--just like an Emacs key-combo. The difference is that the menu's always there to remind you of your options, and the menu path actually informs the keybinding. For example, in Eclipse, Ctrl+F11 is Run. I find this hard to remember. Why F11 and not some other function key? But consider: Alt+R, R, Enter. Not much longer, more compact on the keyboard, and memorable because it corresponds to: Run Menu, Run, (Execute). (The Enter is required because there is more than one R-bound menu option in the Run menu.) Sequences like this also give you more keybinding options at a factorial rate. For example, if you make Alt+J the start of all your Java-based macros, you get 26 three-key bindings (or many more, given all the other non-letter keys) with that short and relevant intro mnemonic.
<p>
Anyway, I'm sure I'll continue to think on this, but I'll be putting more effort now into intelligent macro design and Eclipse tool use than trying to speed-up my keyboard use. So, if you're still a coder putting your mouse to good use, you're not alone!
</p>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-58229122318837239622012-08-16T17:52:00.000-07:002012-08-16T17:52:58.985-07:00A quick fix to improve Python3 startup time<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
My web server is very low-end. Dating from the mid-90s, it has a 200Mhz Pentium and 96MB of RAM. It was running Debian 2.2 (potato), but I recently upgraded to the most recent Debian 6.0 (squeeze). I'm impressed that it even runs.
<p>
I also upgraded to Python3 in order to handle the recent overhaul of my <a href="https://code.google.com/p/tamarin/">Tamarin</a> automated grading system. I compiled Python3 from source to do this, since Debian doesn't include it yet. They're still shipping Python 2.6.
<p>
Tamarin is little more than a bunch of CGI scripts. I expect it to run a little slowly on this machine, but, after the upgrade, any CGI request is taking about 4 seconds, which is fairly intolerable. Static webpages are still responsive enough, though. So I started up the Python3 interpreter... and waited. Yep, that's where the lag is. See for yourself:
<pre>
ztomasze@tamarin:~$ time python3 -c 'pass'
real 0m2.493s
user 0m2.336s
sys 0m0.160s
</pre>
<p>
Here, I'm just starting python3 to execute a single 'pass' statement that does nothing. This takes 2.5 seconds.
<p>
I read somewhere that not loading the local site libraries by using the -S option can give a performance boost. Since Tamarin uses only standard modules, I gave it a shot:
<pre>
ztomasze@tamarin:~$ time python3 -S -c 'pass'
real 0m0.465s
user 0m0.392s
sys 0m0.072s
</pre>
<p>
A 500% improvement! I even installed the default Python 2.6, just to compare times:
<pre>
ztomasze@tamarin:~$ time python -c 'pass'
real 0m0.448s
user 0m0.348s
sys 0m0.060s
ztomasze@tamarin:~$ time python -S -c 'pass'
real 0m0.185s
user 0m0.148s
sys 0m0.036s
</pre>
<p>
So Python3 is significantly slower for me than Python 2 was, but using the -S option at least gets me back to standard Python2 times.
<p>
This savings didn't really translate directly to improved CGI preformance though. Running two of my scripts from the command command line, I experienced the following:
<pre>
status.py upload.py
original time 4 sec 6 sec
adding -S to #! line 3 sec 5 sec
</pre>
<p>
A delay this long is still fairly intolerable. And I don't think the lag is inherent to Tamarin, since the delays weren't this long with Python2 and Debian 2.2 on the same machine.
<p>
I know I could probably shave off some more time for Tamarin by using FastCGI, SCGI, or mod_python. SCGI looks most useful to me given my existing codebase. Whenever I get some free time, I'll look into that.
</p>
<br /></div>
Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-5541879518704508623.post-85000195706424821012012-06-29T18:31:00.000-07:002012-06-29T18:31:01.615-07:00Efficiency though Keyboard Shortcuts<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
One of the things I learned from the discussion of my recent <a href="http://ztomasze.blogspot.com/2012/02/lisp-first-impressions.html">Lisp posting</a> was the value of delegating work to a good editor and the possible speed gain of good keyboard shortcuts. While I did not agree that the best path to these goals was necessarily through Emacs, I did decide to try to use my keyboard a bit more efficiently than I have been.
<p>
First, I reviewed the <a href="http://windows.microsoft.com/en-US/windows7/Keyboard-shortcuts">various keybindings</a> already used by my OS, Windows 7. Hey, that Windows Logo key actually does have a few valuable uses! I also realized that I never use my function keys very much.
<p>
I also installed <a href="http://www.autohotkey.com/">AutoHotKey</a> and tried a few simple useful bindings, including:
<ul>
<li>Capslock is now Ctrl. (Shift+Capslock acts as normal Capslock)
<li>Right Alt and Right Ctrl are now equal to Shift+Alt and Shift+Ctrl.
<li>Win+q quits a program (like Alt+F4) and Win+c opens a command prompt.
<li>The right-click menu button (AppsKey) is now a special function key. For example, I use it with various letters as shortcuts to certain directories when I'm in Windows Explorer.
</ul>
<p>
I'm still working on actually using some of these on a regular basis, though. (Old habits die hard.) I'm also trying to use my alt keys with my thumbs without taking my fingers off the home keys, and using tab (replaced appropriately with spaces) more often when coding.
<p>
Anyway, it's all rather nerdy, but the possibilities are exciting. If you work on Windows, check out AutoHotKey. You may want to customize your system across all your different applications--especially if you start thinking about all the hundreds of possible key combos currently going unused on your keyboard!
</p>
<br /></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-43364350585706667232012-06-29T18:03:00.000-07:002012-06-29T18:03:37.903-07:00Unit-testing a Python CGI script<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
This summer I'm overhauling <a href="http://code.google.com/p/tamarin/">Tamarin,</a> my automated grading system. Under the hood, Tamarin is little more than a bunch of Python CGI scripts. However, as I overhaul it and convert it from Python 2 to 3, I also wanted to build a proper unit test framework for it.
<p>
It's been a dozen years or so since I last used Perl and CGI.pm, but I recall running my scripts on the command line and manually specifying key=value pairs. So, I was somewhat surprised to find no comparable way to test my CGI scripts in Python. The official Python cgi module documentation suggests the only way to <a href="http://docs.python.org/py3k/library/cgi.html#testing-your-cgi-script">test a CGI script</a> is in a web server envirnoment. That's an unnecessarily complex environment for quick tests during development and precludes any simple separate unit tests.
<p>
In general, I'm not very impressed with the cgi module docs. In fact, browsing around <a href="http://bugs.python.org/file9507/cgitest.py">revealed</a> that there are a number of parameter options undocumented in the official docs.
<p>
Using this found information, I was able to build my own cgifactory module. Depending on the function called, it allows you to build a cgi object based on either a GET or POST query. For example:
</p>
<pre class="brush:python">
form = cgifactory.get(key1='value1', key2='v2')
</pre>
<p>
If you then write your CGI script's main function to take an optional CGI object, you can easily build a CGI query, pass it to your script, and then run string matching on the (redirected) output produced by your script. Of course, most of your unit tests will probably be of component functions used by your script, but sometimes you want to test or run your script as a whole unit. cgifactory will help you there.
<p>
The <a href="https://code.google.com/p/tamarin/source/browse/trunk/test/cgi-bin/cgifactory.py">cgifactory code is available here</a>, where you'll always find the most recent version. The code itself is actually quite short; most of the file is documentation and doctests showing how to use it. I don't guarantee it's right, but it's worked for me so far. Hopefully it might be of use to someone else too! Feel free to copy, modify, and/or redistribute.
<p>
(Oh, and if you really need a command line version, it shouldn't be too hard to write a main that parse key=values pairs into a dictionary and then calls cgifactory.get(pairs) to build the CGI object.)
</p>
<br />
</div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-18720281543917784042012-03-10T00:00:00.000-08:002012-06-29T18:31:53.045-07:00Bug: C enum variables stored as unsigned intsI read in K&R that enum values are basically int constants (like #defines in that way), and so enum variables are equivalent to ints. However, in C (not C++ though), you may assign any int value to an enum variable--even if that int value is not one of the listed values in the enum definition. You can do this without even raising a compiler warning. <br />
<p>In a program I was working on, I took advantage of that. I had an enum of values 0 through 7:<br />
<pre class="brush:cpp"> enum direction { N, NE, E, SE, S, SW, W, NW};
</pre><p>In a particular function, I was scanning a map for a target in different directions and decided to return -1 if there was nothing interesting found in any direction. However, this led to strange bug.<br />
<p>The following program shows this bug clearly:<br />
<pre class="brush:cpp">#include <stdio.h>
enum nums {zero, one, two, three};
int main(void) {
//using an enum as normal
enum nums myNum = zero;
printf("zero == %d\n", myNum);
//assigning int value to an emum
myNum = -1;
printf("-1 == %d\n", myNum);
if (myNum >= 0) {
printf("%d >= 0\n", myNum);
}else {
printf("%d < 0\n", myNum);
}
}
</pre><p>This program prints:<br />
<pre class="brush:plain gutter:false"> zero == 0
-1 == -1
-1 >= 0
</pre><p>I'm using GCC, and <a href="http://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#Enumerations">the manual itself</a> says: "By default, these values are of type signed int" and "Although such variables are considered to be of an enumeration type, you can assign them any value that you could assign to an int variable". <br />
<p>However, further research shows that gcc will store an enum variable as an <tt>unsigned int</tt> if you have no negative values in your defined enum. For example, if I add <tt>neg = -1</tt> as an extra value to my enum nums above, the output of the program changes to what I expect: -1 < 0.<br />
<p>Apparently the section 6.7.2.2 of the <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf">C99 standard</a> (draft version) clarifies that this is allowed--that the particular int format used is implementation-dependent. An official version of the C90 standard is not freely available for comparison. <tt>-std=c90</tt> doesn't change gcc's behavior on this issue.<br />
</p>Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-5541879518704508623.post-70860877498549371462012-02-13T01:18:00.000-08:002012-02-13T01:18:18.611-08:00Lisp: First Impressions<p>I learned the basics of Lisp 10 years ago when I was the TA for ICS313: Programming Language Theory. This semester, I returned to Lisp after a decade away, again in the context of TAing for ICS313. After so long away, I basically had to start over from scratch again. Though it certainly goes much faster the second time around, it's still a lot like learning it the first time. So these are my "first" impressions.<br />
<p>We are learning Common Lisp. So far, I'm not very impressed.<br />
<p>First of all, I find that Common Lisp is bloated. There are usually about 6 different ways to do something. For example, want to compare two items? Consider =, eq, eql, equal, equalp... and that's just getting started. Want to print something? Consider print, princ, prin1, pprint, format, etc. The reason that so many options exist is because each is subtly different. I'm sure that, once mastered, all these options increase your programming power, since you can pick exactly the right tool for the job. And, in many cases, some of the options seem to be now-unused holdovers that persist from earlier days in Lisp's development. So eventually you learn which ones you can ignore. But it all makes Common Lisp rather tedious to learn.<br />
<p>My next stumbling block is the formatting. As evidenced by both my students' code and my own inclinations, it seems natural as a programmer to try to format the parentheses to make matching them up much easier. The parentheses are subtle, and it's easy to get one out of place. This can produce code that compiles or loads but then fails at runtime because the meaning is subtly different to what you intended. This well-discussed <a href="http://www.gregslepak.com/on-lisps-readability">blog posting</a> sums it up fairly well. In general, I agree with the author there. Parentheses in Lisp mark the start and end of various expressions in the same way that braces mark the start and end of blocks in C-like languages. In C-like languages, we have proponents of such extremes as the <a href="http://en.wikipedia.org/wiki/Indent_style#Allman_style">Allman style</a> of indenting. These Allman proponents feel that such formatting is so essential to readability that every brace deserves its own line! Yet the Lisp community advocates the exact opposite: that no parenthesis should be clearly placed. Instead, they should all just be tucked away at the start or end of a line of code. Supposedly some day you get to the point were you can "see past the parentheses". But this seems to me like a convention that makes code unnecessarily hard to read.<br />
<p>I find most of the arguments for this "parenthesis stacking" format are weak at best. One of them that irks me is that your editor will help you. First of all, you're not always reading code in an editor. Secondly, I should have to move my cursor around or press keys or require fancy color highlighting to make quick sense of the code on the screen. It's called "readability", not "navigability". A third argument is that you can ignore the parentheses because the indenting should show you the structure. But the indenting is not what actually determines the code structure--the parenthesis do! So I need to be able to quickly spot when the parentheses are wrong even though the indenting is correct.<br />
<p>This formatting thing bugs me because it seems the problem comes from an asinine coding convention choice. And that's the one reason that has me formatting this way rather than the way that makes sense to me: because "that's how it is done in Lisp." Like the choice to drive on the right side of the road, it's hard to buck the community on such a choice as a late-comer! Yet, because it makes the code harder to work with, but with no good reasons that I can see, it feels a little like hazing: "This is the way we all had to deal with it when we learned, so you do too."<br />
<p>That brings me to the Lisp community in general. First of all, I don't care to worship at the altar of Emacs. As I mentioned above, I shouldn't have to have a special editor to write code. Don't get me wrong: an IDE is great at increasing productivity and I definitely want one. But the code should be both readable and writable without one. Then I'm free to choose the IDE that meets my own requirements. (On that note, after trying Emacs and LispWorks, I settled on <a href="http://www.sergeykolos.com/cusp/update/">Cusp</a>. It's a little tricky to get up and running, and a bit quirky at first, but it works pretty well. The highlighting of parentheses structure is very helpful.)<br />
<p>Secondly, there's just this "Lisp is so much better!" vibe in the community. Now, obviously you've got to wave the flag for your favorite language. I have no problems there. But, as others have pointed out, if Lisp is so wonderful, how come we're not all using it? Just about every computer science major has to learn a Lisp dialect at some point, so it's not just an issue of exposure. Is it because it lacks good libraries for modern tasks? Is it because, while powerfully writable, its dynamic re-writability makes it hard for someone else to read or maintain? Is it because, while a pioneer of so many cool ideas, most of those ideas have now been imported from Lisp by other languages? Is it because Lisp has built up over 50 years of cruft, but each new Lisp project to simply and overhaul it fractures the small but fanatical Lisp community, leading to inter-dialect derision and flamewars? Hard to tell. What I can tell is that the fanatical belief in Lisp's supremacy over all other programming languages is a little hard to swallow.<br />
<p>My general conclusion is that Lisp is still worth learning for the history of it. However, I don't think I'll be taking it up as my day-to-day language. I'll be looking elsewhere for more modern implementations of Lisp's contributions that are useful to me.<br />
<p>Still, the code-as-data idea is largely still unique to Lisp. That would be fun to explore more, so finding a Lisp dialect that fits me better might still be rewarding. I've considered Scheme a bit, but I think either Clojure or newLisp would be even better. (I found newLisp because I thought: "Why doesn't someone clean up and simplify Lisp back to it's glorious essence? If I did that, I'd call it 'new Lisp'." I searched... and behold! Already done 20 years ago by someone else.) Both seem to have newer, friendlier, more open communities. <a href="http://clojure.org/">Clojure</a> has the advantage of the JVM and the entire Java API behind it. <a href="http://www.newlisp.org/">newLisp</a> is targeting what I think is a great niche for Lisp: scripting. This is where powerful writability at the expense of readability and maintainability is a viable tradeoff.<br />
<p>These are my current impressions of Lisp. Perhaps they'll change with time. If so, I'll let you know!<br />
</p>Unknownnoreply@blogger.com21tag:blogger.com,1999:blog-5541879518704508623.post-32288840526970081792011-12-13T22:26:00.000-08:002011-12-13T22:26:54.683-08:00Group Programming: Some Adjustment Required<p>After last week's <a href="http://ztomasze.blogspot.com/2011/12/technical-review-hale-aloha-cli-grads.html">technical review</a>, Jeff and I swapped projects with the grads group. That is, we took over on the grads' code, and they started working on ours. Both groups added three more commands to the existing codebase that they had just inherited.<br />
<p>This was an interesting experience taking over on an existing software project. Of course, there was some initial overhead getting familiar with the layout of the new project's code. This wasn't too onerous, though, since the overall structure was fairly logical.<br />
<p>Once Jeff and I started working, the work went smoothly. We had already completed one project together. I think Jeff and I communicated well, and each of us made some significant contributions. We agreed on all of the major design issues.<br />
<p>Still, for all of the harmony, I'd say that my most interesting learning experience this week was the old "pick your battles" experience. If you've ever shared a living space with someone as an adult--whether a college roommate or a romantic partner--you probably know what I mean. There's a period of adjustment to the person's habits and quirks. For example, maybe your new roommate already put the silverware in the left drawer when you feel that it is obviously more natural to have it in the right drawer. Or maybe your new lover seems to somehow constantly drop loose change; eventually stray coins lie scattered throughout the house. <br />
<p>For each new quirk you discover, you have to decide whether it bothers you or not. If it does, then you need to figure out if you're willing to just overlook it, constantly clean up after them, or make an issue of it. If you make an issue of every little thing, you can easily become an unpleasant nag. Depending on how it's done, cleaning up behind someone can come across as a passive-aggressive show of disapproval. But, if something really does bother you and you don't speak up, you can find that your living space is not really your own. That's what I mean by picking your battles.<br />
<p>First, Jeff and I had to come to terms with the existing code. As we settled in, we found we had to "move the silverware" in a few places to meet our tastes. In particular, we overhauled the look and behavior of the user interface. We left the reflection-based loading of classes in place, though.<br />
<p>Then there were the minor differences in working style that I noticed between me and Jeff. For the most part, these were so minor as to border on petty: "If I'd done it, I wouldn't have spaced the output that way" or "I usually write one class at a time rather than mock up all the classes and then fill in the details later."<br />
<p><a href="http://ztomasze.blogspot.com/2011/11/group-programming-and-issue-based.html">A couple weeks ago</a>, I mentioned the motivating aspect of working in a group. My point this week is that, whenever you work with someone else, they are not going to do things exactly the same way you do. That is to be expected. But, even when you realize this consciously, each specific difference you discover can still cause a short pause: "Oh.. that's not how I would have done that... but that doesn't mean it's wrong... Am I going to accept how this has been done and move on, or do I want to say something and change it?" Overall, I discovered that I could just let these things go. It was just a new experience for me to adjust to someone else's presence in my coding project space, both in terms of the old code and the new.<br />
<p>Jeff and I got everything finished up before the deadline. I think our code is pretty solid, though some of our line-spacing might be a little off between different commands. <br />
<p>Testing code that connects to a server continued to be a pain. I considered making some sort of mock client object, but there proved to be too many methods that would need to be overridden to make it worthwhile. <br />
<p>I also found that, when verifying someone else's code, it's easier to run through a manual test rather than plod through all their JUnits and make sure it covers all the necessary cases. While I think it's good to get some manual testing in there occassionally--especially since that lets you spot things like typos and weird formatting that a JUnit test is not going to catch--I think this is still not quite ideal. Manual testing can find bugs that the person's JUnits missed. But, if the code is correct, manual testing won't reveal that an appropriate JUnit test is missing altogether. This means that changes to the code could cause an undetected failure later. So I guess I should work on using the person's JUnit tests as a loose guide to manual testing in order to spot missing/poor tests as well as any existing defects.<br />
<p>I'm still a fan of Issue-based Project Management. I'm also glad we kept our habit of having the other person mark completed tasks as Verified. It's an extra step, but it's a good feeling knowing that everything has been double-checked by someone else.<br />
<p>This is the last project for my software engineering course, so it may mean a blog hiatus for a while. But I should be back occasionally with news on other new software projects!<br />
</p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-65089666101666060022011-12-02T03:39:00.000-08:002011-12-02T03:40:30.979-08:00Technical Review: hale-aloha-cli-grads<p><a href="http://ztomasze.blogspot.com/2011/11/group-programming-and-issue-based.html">As I mentioned last week</a>, Jeff and I recently finished up a small command line interface program that allows a user to poll a WattDepot server for accumulated energy-use data. Since this was done as part of a software engineering course, there were a number of other groups developing their own versions of the same program. <br />
<p>This week, I'm going to perform a structured technical review of one of those other projects: <a href="http://code.google.com/p/hale-aloha-cli-grads/">hale-aloha-cli-grads</a>. This is partly for the practice of reviewing another software project in detail before contributing to it. By comparing the two, this will also hopefully shed some light on what we did well and what we could have done better on our own project. Finally, the feedback might be helpful to the grads group members.<br />
<p>A good technical review needs to be structured by a series of <a href="https://sites.google.com/site/ics314fall2011/modules/issue-driven-project-management#TOC-Assignment-A26:-Hale-Aloha-CLI-Tech">pre-determined issues to examine</a>. More generally, I'll be evaluating whether the grads project meets the <a href="https://sites.google.com/site/ics314fall2011/modules/introduction/three-prime-directives">Three Prime Directives</a> of open-source software engineering. (This is not <a href="http://ztomasze.blogspot.com/2011/08/timmon-and-three-prime-directives.html">the first time</a> I've done this sort of review.) I'll be covering the prime directives (PDs) in the order I encountered them as an interested developer.<br />
<br />
<h4>PD2: An external user can successfully install and use the system.</h4><p>The project's homepage at Google Project Hosting was sufficiently detailed, giving a basic overview of what the program does and who wrote it.<br />
It also contains a link to a wiki UserGuide. I liked that the authors included a screenshot there. The UserGuide also documented a feature not obvious from within the program itself: you can poll the physical sources (such as Ilima-04-telco) for energy data, as well as polling the towers and lounges of the dorm.<br />
<p>Since there was only one link available under the project's Downloads tab, downloading was pretty self-explanatory. The brief Installation Guide explained how to extract the necessary executable .jar from the downloaded zip file and then run the program.<br />
</p><br />
<h4>PD1: The system successfully accomplishes a useful task.</h4><p>The program starts with a paragraph-long help message describing the possible commands:<br />
<pre class="brush:text gutter:false">--Available commands are:
energy-since: [tower | lounge] [Start]
Returns the energy used since the date (yyyy-mm-dd) to now.
current-power [tower | lounge]
Returns the current power in kW for the associated tower or lounge.
daily-energy: [tower | lounge] [Date]
Returns the energy in kWh used by the tower or lounge for the specified date (yy
yy-mm-dd).
rank-towers: [start date] [end date]
Returns a list in sorted order from least to most energy consumed between the [s
tart] and [end] date (yyyy-mm-dd)
--Enter a command (type 'quit' to exit):
</pre><p>This was useful, though the help message is a little mangled when viewed in a conventional 80 character-wide console window. (Our own project's output suffered this same issue.) The last line shown here is the prompt for input, though any input entered then appears on the next blank line. This is a little unconventional for a command line prompt.<br />
<p>Although covered in the UserGuide, there was no in-program list of valid tower and lounge names that could be polled for data. I found a work-around for this: The rank-towers command gives the list of towers, and a user could probably remember how to generate lounge names from that list. But it really would be helpful to have this information explicitly available from within the program itself.<br />
<p>Although the help message was useful when first starting the program, it gets printed every turn. This means that the prompt is effectively 12 lines long every input turn, even when using the program correctly! This quickly became annoying, since it clutters the output, which is usually only a line or two for most commands. Also, this behavior did not match UserGuide screenshot mentioned earlier.<br />
<p>The program correctly supported all of the commands requested by the "client" of this software project. The error messages were generally fine, shielding user from any technical details. (One quibble: The program complains "Not enough arguments" when it is given too many arguments.) Most importantly, the program did not crash at any point. (See the <a href="#transcript">transcript</a> at this end of this review for the full details.) <br />
<p>In general, testing this program reminded me how tedious any CLI--including our own project--can be to use.<br />
</p><br />
<h4>PD3: An external developer can successfully understand and enhance the system.</h4><p>Once I knew the program itself worked, it was time to take a look at what it would take to extend or contribute to it.<br />
<p><i>Developement protocol.</i> The grads project DeveloperGuide wiki page provides a brief summary of the required development practices: the coding standards used by the project, how to follow Issue-Driven Project Management, how to ensure that new code passes verification by all of the QA tools used, and a link to the continuous integration Jenkins server used by the project. This was sufficient for me, but the DeveloperGuide may be a little too brief for someone not already familiar with these terms--such as "Elements of Java Style", "Issue-Driven Project Managements", and "CI".<br />
<p><i>QA.</i> The quality assurance (QA) script verify.build.xml failed for me after the initial check-out. The JUnit tests intermittently failed due to WattDepot server connection problems. Also, the tests printed a lot of details to the screen, which suggests that perhaps the developers were doing manual verification of all of these tests. Checkstyle initially crashed due to a problem with one of its component classes, but running <code>ant reallyclean</code> and then <code>ant -f verify.build.xml</code> again fixed the problem. So, after repeatedly running verify, it eventually passed with no code changes required. In getting through this, it helped a lot that I was already familiar with this build system, since we used the same setup for our project.<br />
<p><i>Documentation.</i> The DeveloperGuide did not explicitly mention how to generate JavaDocs. However, this is fairly obvious once one inspects the available *.build.xml files. They are generated automatically by verify.build.xml, and they can easily be generated directly from the code though Eclipse.<br />
<p>Examining the generated JavaDocs, all the packages and methods were documented. However, frequently the descriptions of the methods and parameters--particularly in the <code>processor</code> package--added very little information that wasn't already obvious from the name of the method, parameters, or return type. At least most of these names were fairly descriptive. Some classes--such as FakeCommand and ReallyFakeCommand--were not documented as to why they are needed.<br />
<p><i>Use of reflection.</i> The project uses reflection to dynamically find the implementations of the various CLI commands. While this "drop in" modularity is very sexy in theory, the execution leaves something to be desired. First of all, reflection is always verbose. This is compounded here because two different approaches are needed to cover two possible situations: the classes are normal files in a filesystem or the classes are packaged in a jar file.<br />
<p>The jar file approach is brittle and will break if the containing jar file is renamed. Also, this approach cannot (easily) be tested by a JUnit test while the project is not yet packaged in a jar.<br />
<p>A JUnit test exists for the filesystem case. However, it is poorly written in that it imports and uses the very class (FakeCommand) that it is trying to find and load through reflection. Thus, if that command class is actually missing, the JUnit test doesn't just fail, it crashes. Also, the class discovery code itself makes assumptions about the state of the filesystem that don't always hold. For example, I am using both SVN and Eclipse. When I compile the source code in the src/ directory, Eclipse also copies the corresponding .svn directories from src/ into the bin/ folder with the generated .class files. Then, when I run the JUnit tests, the command-loading code chokes on the extra .svn directories. (The JUnit tests run fine if executed through Ant because this instead executes the class files in build/classes/, which does not contain any copied .svn folders.)<br />
<p>Finally, special classes, such as FakeCommand and ReallyFakeCommand, were constructed for test purposes. Normally, this is a very good practice. However, these classes are now visible to the entire system, not only to the testing code. Therefore, they then have to be filtered out of the list of available commands at multiple points in the regular code, which is messy and error-prone. (ReallyFakeCommand is never actually used, so it's just clutter.)<br />
<p>I think the grads programmers did fairly well handling all of the technical difficulties brought on by this reflection-based approach. Kudos to them for getting it working at all! I just question whether the approach itself is worth all this clutter and overhead. In our own project, we decided it wasn't worth it.<br />
<p><i>Code Readability and Maintainability.</i> In general, the code is readable. As mentioned previously, some more descriptive/informative JavaDocs would help though.<br />
<p>Some data could be centralized to a single location. For example, every test class includes its own copy of the URL of the WattDepot server. This would make maintenance a headache if this address changes. <br />
<p>Unlike our program, the grads project does not include a list of towers or lounges. This means they cannot print a list of valid input values for the user. Also, it means any error in a source name must be sent to the server to be discovered, which puts more strain on the server. However, on the plus side, it means the CLI program would not need to be updated as source names change on the server. I think a compromise between these two approaches might be best: have the program query the server for the current list of valid sources at start up, and then use that list to inform the user and to weed out invalid queries before sending them to the server.<br />
<p><i>Testing.</i><br />
The code for the commands was somewhat verbose, but it was fairly well-tested with an amount of test code roughly equal to the amount of code being tested (100 to 200 lines per command). Jacoco test coverage results showed that most of the important code was being tested--usually 60 to 80% coverage. Untested code included such things as multiple catch blocks for the different kinds of WattDepot exceptions that might arise. This is fair, since testing all of these catch blocks would be more of a test of WattDepot's exception-throwing than of the CLI program itself.<br />
<p>As a design choice, all commands print directly to the screen when executed. This was the source of all the extra output from the JUnit tests.<br />
<p><i>Development history.</i><br />
From the @author tags in the JavaDocs and the Issue history on the project hosting page, it was easy to see who worked on which part of the system. (It's also interesting to see some different programming styles evident in the code too, even though all developers formatted their code the according to the same standards.) The work was evenly divided between the three developers.<br />
<p>The developers also followed their own development protocols. After the first handful of commits, later code commits are clearly linked to the specific issues they resolved. The team practiced continuous integration by committing code regularly (nearly every day). Except for the period during which the WattDepot server was down, there was only one commit that broke the build and this was resolved in less than an hour.<br />
</p><br />
<h4>Conclusion</h4><p>This project satisfies the three prime directives. Excusing the little minor warts and blemishes that crop up in any large project, the program 1) accomplishes the task it was designed to do, 2) is sufficiently easy to download, install, and use, and 3) is documented and structured clearly enough that a new developer could contribute code to it without too much trouble.<br />
</p><br />
<h4 id="transcript">Appendix: Testing Transcript</h4><p>The following is an transcript of some of tests I ran on this program. I cleaned up the output a bit. As mentioned above, the original output prompt included a dozen lines of help message before each prompt.<br />
<br />
<pre class="brush:text gutter:false">C:\Files\Downloads>java -jar hale-aloha-cli-grads.jar
Server: http://server.wattdepot.org:8190/wattdepot/
Welcome to hale-aloha-cli-grads
Looking for commands....
Found command: energy-since
Found command: current-power
Found command: daily-energy
Found command: rank-towers
help
--Enter a command (type 'quit' to exit):
current power lounge
'current' is not a command!
--Enter a command (type 'quit' to exit):
current-power
Invalid arguments for current-power.
current-power [tower | lounge]
Returns the current power in kW for the associated tower or lounge.
--Enter a command (type 'quit' to exit):
current-power lounge
lounge is not a valid source name.
--Enter a command (type 'quit' to exit):
current-power Lehua
Lehua's power as of 2011-11-29 11:13:44 was 22.0kW
--Enter a command (type 'quit' to exit):
current-power Lehua with extra arguments
Invalid arguments for current-power.
current-power [tower | lounge]
Returns the current power in kW for the associated tower or lounge.
--Enter a command (type 'quit' to exit):
current-power Mokihana-C
Mokihana-C's power as of 2011-11-29 11:13:44 was 4.0kW
--Enter a command (type 'quit' to exit):
current-power Ilima-04-lounge
Ilima-04-lounge's power as of 2011-11-29 11:13:44 was 2.0kW
--Enter a command (type 'quit' to exit):
current-power Ilima-04-telco
Ilima-04-telco's power as of 2011-11-29 11:18:45 was 1.9kW
--Enter a command (type 'quit' to exit):
rank-towers yesterday today
Argument "yesterday" is invalid.
--Enter a command (type 'quit' to exit):
rank-towers 2011-11-24 2011-11-26
For the interval 2011-11-24 to 2011-11-26, energy consumption by tower was:
Lehua 985 kWh
Mokihana 1029 kWh
Ilima 1098 kWh
Lokelani 1181 kWh
--Enter a command (type 'quit' to exit):
rank-towers 2011-11-19 2011-11-26
The tower ranking could not be retrieved for the dates given.
--Enter a command (type 'quit' to exit):
rank-towers 2011-11-30 2011-11-26
End date must be greater than start date.
--Enter a command (type 'quit' to exit):
rank-towers 2011-11-24 2011-11-26 and more
Invalid arguments for rank-towers.
rank-towers: [start date] [end date]
Returns a list in sorted order from least to most energy consumed between the [s
tart] and [end] date (yyyy-mm-dd)
--Enter a command (type 'quit' to exit):
energy-since Lehua-F 2011-11-27
No such source Lehua-F
--Enter a command (type 'quit' to exit):
energy-since Lehua-E 2011-Nov-27
Argument "2011-Nov-27" is invalid :2011-Nov-27
--Enter a command (type 'quit' to exit):
energy-since Lehua-E 2011-11-27
Total energy consumption by Lehua-E from 2011-11-27 00:00:00 to 2011-11-29 11:06
:30 is: 264.1 kWh
--Enter a command (type 'quit' to exit):
energy-since Lehua-E 2011-11-27 more
Not enough arguments.
--Enter a command (type 'quit' to exit):
daily-enegy Mokihana-B 2011-11-25
'daily-enegy' is not a command!
--Enter a command (type 'quit' to exit):
daily-energy Mokihana-B 2011-11-25
Mokihana-B's energy consumption for 2011-11-25 was: 92.1 kWh
--Enter a command (type 'quit' to exit):
daily-energy Mokihana-B
Not enough arguments.
--Enter a command (type 'quit' to exit):
daily-energy Mokihana-B 2011-11-25 more
Not enough arguments.
--Enter a command (type 'quit' to exit):
daily-energy Mokihana-B 25-Nov-2011
Argument "25-Nov-2011" is invalid :25-Nov-2011
--Enter a command (type 'quit' to exit):
daily-energy Mokihana-F 2011-11-25
No such source Mokihana-F
--Enter a command (type 'quit' to exit):
quit
quitting...
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-14775331594394350672011-11-26T16:18:00.000-08:002011-11-26T16:30:59.112-08:00Group Programming and Issue-based Project Management<p>I spent the last couple weeks doing some group-based programming on a <a href="http://code.google.com/p/hale-aloha-cli-jz/">small WattDepot project</a>. The project was to build a command-line interface that lets a user poll the energy data collected from one of the dorms on the University of Hawai'i--Manoa campus. Different commands allow the user to see the current power consumption of a dorm tower or lounge, to rank the different dorm towers by energy consumed over a given time period, to see the energy use of a tower or lounge for a given day, or to see the total energy consumed by a tower or lounge since a given date.<br />
<p>I haven't done any group programming in about 10 years, but I found the return to it quite enjoyable. I find it motivating to know that someone else depends upon and is eagerly awaiting my changes. I found myself prioritizing this project over my other projects to make sure I wasn't holding someone else up.<br />
<p>Our group consisted of only two programmers. We used Google Project Hosting's issue-tracking system to manage the project. We met occasionally to map out the course of the project, and we would create new issues for tasks that needed to be done. Then one of use would accept responsibility for the task and work on it. Once it was done, the other person would look over it and mark the issue as verified. Since the different issue pages allow for threaded discussion, I found this is a good way to track the progress of the project. It was also very easy to link from source code commit logs to the relevant issues and also back from an issue to those commits that solved it.<br />
<p>We happened to worked in shifts, and so we never had to deal with a code merge. I'm a little disappointed I haven't had a chance to experience this yet. <br />
<p>We also used continuous integration. That means we had a Jenkins server setup that independently verified that each commit to the Google repository still compiled successfully and passed all tests and QA checks. This was a comfort. After a commit, I'd always wait a few minutes to make sure I didn't receive an email from Jenkins. When I didn't, I felt more confident signing off for the night.<br />
<p>Our project was plagued with external problems, though. I had to make a emergency 5-day trip back to the mainland for a funeral during the middle of the project. My partner, Jeff, broke his leg around the same time. Besides being on painkillers after that, he wasn't able to drive to campus. So we only had one initial face-to-face meeting, but we compensated with a couple phone meetings and nearly-daily overview emails in addition to the issue-tracking threads. Near the end of the project, the WattDepot server went down, which halted production and then broke all of our test cases. This meant that our build appeared broken for about 3 days while we waited for the new server to generate enough data for us to work with.<br />
<p>All this planning and coordination certainly did come with an overhead. I'd say this project took 2 to 3 times longer than if we'd just done the project independently. But, like I said, I found the group atmosphere quite motivating, and it probably helped to have a couple pairs of eyes look over all the code.<br />
</p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-33434889413489986332011-11-08T03:12:00.000-08:002011-11-08T03:17:42.811-08:00WattDepot Katas<p>So I spent part of this week and all of this evening getting up to speed with <a href="http://code.google.com/p/wattdepot/">WattDepot</a> by completing a few <a href="https://sites.google.com/site/ics314fall2011/modules/introduction-to-wattdepot#TOC-Assignment-A22:-WattDepot-katas">practice katas</a>. Each kata took me about an hour, though for different reasons.<br />
<p>The first couple katas were simple requests from a WattDepot server. <br />
Given the sample code from the <a href="http://code.google.com/p/wattdepot/wiki/WritingWattDepotClients">WattDepot client tutorial</a>, this required only a big copy-and-paste and the modification of a couple lines.<br />
<p>These still took a couple hours, though, because I did the first couple katas in class on a day that we tried pair-programming. I think this might be a good practice once both programmers are comfortable with the API and understand the problem at hand. As it was, we spent most of the time setting up our Eclipse projects and then reading the assignment and the <a href="http://wattdepot.googlecode.com/svn/javadoc/index.html">WattDepot documentation</a> over each other's shoulders. I also switched groups halfway through, and we were also required to swap laptops periodically. This means the second pair I was in ended up starting over again at the beginning of one of the katas on a different machine. <br />
<p>Lulled into a false sense of security that these katas would all be as easy as the first couple, I returned to the project late this afternoon. I first took some time to install the FindBugs plugin in Eclipse. (I've been gradually installing plugins for tools that I have so far been using Ant to run. It's generally tedious and slow to run Ant compared to a plugin. But it's been a slow transition since I like to spend an hour or so reading the documentation and playing around with each plugin before I install the next one.)<br />
<p>After cleaning up what code I threw together in the last few minutes of class to see it work, I finished up kata #2. That kata and the ones after it all require sorting a list of key-value pairs by value. This stumped me a for a little while because this should be very easy... but it's not. I surfed a few 1/2 to 1-page posts of code that sort a Map by value. There were a few nice one-liners, but they required Google Collections and I didn't want to mess with an extra library.<br />
<p>In the end, this is my solution to sorting a key-value list by value. It's conceptually a "two-liner", but all the generics and the anonymous class make this look horrible:<br />
</p><pre class="brush:java"> Map<String, Long> map = ... //the map to be sorted by value
//dump map into a list of key-value pairs...
List<Map.Entry<String, Long>> entryList =
new ArrayList<Map.Entry<String, Long>>(map.entrySet());
//...and sort it with a comparator that sorts based on values
Collections.sort(entryList, new Comparator<Map.Entry<String, Long>>() {
public int compare(Map.Entry<String, Long> left,
Map.Entry<String, Long> right) {
return left.getValue().compareTo(right.getValue());
}
});
//now print the list in value order
for (Map.Entry<String, Long> entry : entryList) {
System.out.print(entry.getKey() + ": " + entry.getValue());
}
</pre><p>This solution also assumes you don't need map-like access to the sorted version, but just need to run through it for a simple task like printing.<br />
<p>The other time-consumer was learning how to use java.util.GregorianCalendar and <br />
javax.xml.datatype.XMLGregorianCalendar. (There's also org.wattdepot.util.tstamp.Tstamp,<br />
though I didn't find this to be as useful as I'd initially hoped.) This was another example<br />
of something that should be easy but isn't. For example: "Give me the date of the most recent<br />
Monday". It seems we have to start with the current time, for which I chose to use a GregorianCalendar object. Then, after a few lines spent modifying that time to the desired relative Monday date,<br />
I had to translate it to an XMLGregorianCalendar. This was fairly long and messy with the various required<br />
factory objects and exception handlers. I still like Java a lot, but I must admit that detractors<br />
have a point about how much grinding tedious boilerplate you have to wade through sometimes.<br />
<p>I also need to take a minute at some point to figure out how to control Eclipse's insertion of try/catches. The quick default just wraps the one line in a try block, which requires so much reformatting that the feature is hardly worth using in most cases.<br />
<p>In the end, I got all the katas done. This was the first time I've written an application that deals with a web connection behind the scenes. It is pretty slow and variable (read: flaky) at times due to network access delays and potential connection time-outs. For my last kata--which took a couple minutes to gather all the data it needed--I added a little "status indicator" by printing a series of dots. <br />
<p>I spot-tested my katas as I went. However, if they were production code, I think I'd like to test them a little bit more to make sure I'm really pulling the right data and that all my calendar manipulations worked correctly. But since they are mainly katas intended to practice solving the problem, I think they went quite well.<br />
</p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-9714748336799377332011-11-01T00:24:00.000-07:002011-11-01T00:24:20.566-07:00Energy Consumption in Hawaii<p>I'll soon be working with <a href="http://code.google.com/p/wattdepot/">WattDepot</a>, so this week I've been learning a bit about energy consumption in Hawaii as background.<br />
<p>First, I had to review bit of high school physics regarding the difference between energy and power. Power is rate at which work is done or energy is converted over time. Power is measured in watts. One watt is equal to one joule/second. So a 60W lightbulb burns 60 joules/second.<br />
<p>Energy is... well, energy--the stuff that makes things move, go, change, or happen. It is force applied over a distance. When related to household electricity, it is usually measured in kilowatt-hours, or kWh. One kWh is equal to 3.6 megajoules. <br />
<p>I also learned that Hawaii is in a pretty unique situation when it some to exploring alternate/green energy sources. Our energy on Oahu costs about 30 cents per kWh, which is 3x what it costs on the mainland. (And on the neighbor islands it costs 6x mainland prices!) This is because we rely predominantly (70+%) on shipped oil, whereas the mainland can also rely on nearby coal and natural gas sources. We have a number of small, discrete electrical grids here, rather than the massive interconnected grid that spans much of the mainland. This means we can't buy, sell, or shift extra energy around to neighboring states (or even neighboring islands) as demand shifts. This is fairly inefficient.<br />
<p>But, on the bright side, this expensive energy means that alternative energy sources may be more attractive here in Hawaii than they would be on the mainland. The Hawaii Clean Energy Initiative has also mandated that 70% of Hawaii's energy come from clean sources by 2030. To our benefit, we have nearly every kind of potential renewable energy source here: wind, solar, waves and tidal motion, hydrothermal, and geothermal sources. <br />
<p>Data about current energy use and how this usage will be affected by alternative sources will be essential. This information can also provide feedback to end-users to help them reduce their consumption, which is also an important goal. There is currently some interesting research going on at the University of Hawaii regarding smart sensors and tracking current use... which brings us back to WattDepot. It is currently being used to track energy use in some of the UH dorms.<br />
<p>I'll be learning more about the specifics of WattDepot this week. Check back again soon for more info!Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5541879518704508623.post-23075426675967747382011-10-20T16:15:00.000-07:002011-10-20T16:15:37.789-07:00Collaborative Review<p>The students in my software engineering class are reviewing for the midterm.<br />
To contribute to the group study session, here are 5 review questions (and answers)<br />
of my own:<br />
</p><br class="real"><br />
<h4>1) Name three features often provided by an IDE.</h4><p>The most common features include:<br />
<ul><li>Language-aware editing (syntax-highlighting)<br />
<li>Integrated compilation (and execution)<br />
<li>Integrated debugger<br />
<li>Project definition facilities<br />
</ul><p>Extra features may also include: wizards (class creation, etc), content assistance, refactoring, diagramming, project file manager, plugins (for tools such as configuration management, QA testing, JUnit, etc).
</p>
<br class="real">
<h4>2) Give an example of an annotation tag commonly used in Java.</h4><p>The Java compiler recognizes: @Override, @Deprecated, and @SuppressWarnings.
<p>JUnit uses: @Test, @Before, @After, @BeforeClass, @AfterClass, and @Ignore.
<p>Annotations can also take parameters, as in: @Test(expected=UnsupportedOperationException.class).
</p>
<br class="real">
<h4>3) Which two methods in class Object should you override if you suspect that instances of your class might some day be need to be stored in a Collection?</h4><p><code>equals</code> and <code>hashCode</code>.
</p>
<br class="real">
<h4>4) How do you use <code>@Override</code> in Java? What does it do?</h4><p>@Override is an annotation that you should add at the beginning of a method definition if that method is intended to override a method in a superclass or interface. Example:
<pre class="brush:java"> @Override
public String toSting() { ...
</pre><p>Thanks to the @Override tag, I would now get a compile-time warning that toSting() does not actually override a method. (This is because I misspelled String.)
<p>Using @Override when overriding interface methods is only supported with Java 1.6+.
</p>
<br class="real">
<h4>5) Ant is a build system. Name another one.</h4><p>Maven and Make are also build systems.
</p>Unknownnoreply@blogger.com2