Monday, November 28, 2011

Hale Aloha Command Line Interface

Hale Aloha CLI is an interface allowing users to view information concerning energy and power consumption in the Hale Aloha residences on the University of Hawaii at Manoa campus. For this project, I worked with Jayson Gamiao and Jason Yeo in a test of Issue Driven Project Management. In addition, we experimented with a small number of technologies and tools such as Jenkins and Google Code.

IDPM unsurprisingly deals with project management, focusing on keeping project members working on issues that continue progress on the project. In theory, it might sound like micromanaging the project; in practice it seems to work much better. In IDPM, each project member receives small tasks to complete. Each project member should always have at least one task to work on. These tasks, being small, should take only a couple of days to complete. This necessitates frequent meetings so that developers have a constant supply of tasks to work on.

In practice, the group followed these guidelines fairly closely. All three group members were constantly and continuously working on the project from about 15 November, the date of our second group meeting in which we discussed how to work on the project. The exceptions to this were from 18 to 20 November, during which I was ill, 21 to 23 November, during which the WattDepot server used in the project was nonfunctional and was unable to provide us with data, and 24 November, during which we had to wait for data to accumulate after a server reset. The tasks (referred to as “issues” in the project site) could have been smaller; many of the tasks took longer than two days to complete. On the other hand, one could also argue that the tasks only seem to have taken more than two days, as some group members were reluctant to label tasks as “Done” until their code for those tasks had received extensive testing and peer review. In addition, as this is the first time any of us have worked with IDPM, there are naturally many mistakes and omissions as we forgot to refer to particular issues in our commit logs.

After my comments concerning testing for the Robocode project (essentially, that it would be better to incorporate testing early in the development process), this project allowed me to experience what such a project was like. Throughout this project, any code that I wrote was almost immediately accompanied with a JUnit test. This was never a tremendous annoyance; rather, the testing allowed me to verify my work long before any real manual testing was possible through the command-line interface.

As for the project itself, the user is provided with a few commands:

current-power [source]: Prints the current power consumption of the source.
daily-energy [source] [date]: Prints the amount of energy that the source consumed on the given date.
energy-since [source] [date]: Prints the amount of energy that the source has consumed from the given date to the present.
rank-towers [date] [date]: Prints the Hale Aloha towers in order of energy consumption between the dates given.
help: Prints a list of commands that the user may type in.
quit: Exits the interface.

Everything works as intended. There are a few features that we had hoped to implement but lacked the time to work on. In particular, we had considered the use of reflection to ease the continued expansion of this interface. This unfortunately never came about.

Much more detailed information concerning this project is available at the project site.

Tuesday, November 8, 2011

WattDepot

In keeping with the topic of energy, I have begun working with WattDepot. Though better explained on the project page for WattDepot, the basic information is that WattDepot provides the capability to retrieve energy data from sensors. Though WattDepot clients may be written in many languages, I have continued to use Java as my language of choice. (At least for programming; English is slightly better suited to entries such as this.)

As with a few previous systems, I have completed a set of simple katas to help in acquainting myself with WattDepot. These are as follows:

1: SourceListing: Connects to a WattDepot server and prints all sources on the server with their descriptions.
2: SourceLatency: Connects to a WattDepot server and prints all sources on the server with their latencies, where “latency” is defined as the time elapsed since the last measurement was taken.
3: SourceHierarchy: Connects to a WattDepot server and prints the hierarchy of the sources. This is possible through the use of virtual sources, which combine the input of multiple physical sources to produce a result that may often be more useful for real-world analysis.
4: EnergyYesterday: Connects to a WattDepot server and prints all sources on the server with the total amount of energy each source consumed on the previous date, sorted in ascending order by energy consumption.
5: HighestRecordedPowerYesterday: Connects to a WattDepot server and prints all sources on the server, sorted in ascending order based on highest recorded data for the source.
6: MondayAverageEnergy: Connects to a WattDepot server and prints all sources on the server with the average energy consumption on the past two Mondays for each source.

To start from the beginning then, SourceListing was a moderately difficult exercise. This difficulty is primarily the result of being unfamiliar with a new system. Once I knew what resources I had, actually completing the kata was not terribly difficult. This first kata took approximately an hour to complete.

Next was SourceLatency. However, SourceLatency is practically the same as SourceListing, with only the difference of printing latency instead of descriptions. As a result, the code is essentially SourceListing with a few additions to make it print the latency of all sources. This made SourceLatency perhaps one of the easiest katas, and it was completed well within forty-five minutes, even accounting for time spent going back in to remove various Checkstyle, PMD, and FindBugs errors.

In contrast, SourceHierarchy was the most complex of the katas, and it shows in that it took at least ten hours of programming alone, more than all the other katas combined. A fair amount of this difficulty was due to the way that Source.getSubSources was implemented: since the method returns a String rather than a list of Source instances, some String manipulation is necessary. I somewhat suspect that there is another, better way of working with the subsources, but I have yet to find it.

I also had to learn how the hierarchy worked, and I am still not entirely certain on some points about the hierarchy. For example, if B is a subsource of A and C is a subsource of B, then by transitivity we can deduce that C is a subsource of A. However, I do not know if the getSubSources method would account for that or if it would only return those sources that are immediate subsources.

My solution to printing the hierarchy involved a recursive method. This method keeps track of the “depth” that the current source is at; that is, how many levels of subsourcing lie between the current source and some root. I am not quite certain how I got the idea of using recursion, but by last Thursday I was already thinking of it even though I would barely have been working on it at that time. Although I am rather proud of the method and of thinking of it myself, I am not certain how efficient it is compared to a more linear algorithm. Then again, the recursive certainly seems a lot better than any of my other plans, which would have involved messy processes requiring multiple arrays to store sensor data and hierarchy depth.

After that intensive process for SourceHierarchy, I then moved on to EnergyYesterday. EnergyYesterday required that the list of sources be sorted based on the energy consumption of the sources, so some sorting algorithm was necessary; I chose merge sort, and thus a variant of it appears in my code. This kata was also where I began to notice the problems with having to deal with a server. If I constantly made calls to the server for sensor data, the chances of some error occurring would increase, and so my code only asks for data about the sensors once. The data is then stored in a String, actually the very same one that would be used for output. Though not as intensive as SourceHierarchy, EnergyYesterday still took about two hours to complete.

One bit of code that I am still annoyed with also started in EnergyYesterday, though I did not truly realize the problem until getting to MondayAverageEnergy. In order to calculate the energy consumed in the previous day, it is necessary to know what and when the previous day is. Since WattDepot uses the XMLGregorianCalendar class, I decided to do the same. Unfortunately, as far as I can tell the XMLGregorianCalendar class does not automatically fix its values to avoid invalid situations. That is, if “yesterday” is in a different month, then the days would have to wrap around and the month would have to be decremented. While understandable, it also results in a large portion of my code in the last three katas attempting to resolve those sorts of issues and prevent them from causing problems.

While SourceHierarchy was the most complex kata, HighestRecordedPowerYesterday was possibly the most frustrating. My original plan had been to test at intervals of fifteen minutes; however, this took up far too much time and the connection to the WattDepot server would invariably time out. Even increasing this to intervals of an hour did not help in all cases. It is at times like these that I wonder if the name is really “What Depot?” insofar as the server never seems to be working when it has to. The solution that I implemented placed a try-catch statement to handle the cases that did time out through making a new connection to the server and moving on. This is perhaps not ideal, but it works, and the user does have a message informing him or her why about half of the sources do not have a valid power level. It might have been a good idea to shift some variables around so that the list gets whatever was the highest power consumption and time for that source before losing the connection. Another issue, though less significant, was the formatting. It was necessary to print out the times at which the highest levels of power consumption were; however, the format methods were uncooperative and would refuse to accept certain conversion characters. This also led to a brute force solution where I simply took care of that formatting myself instead of using the format method. In the end, HighestRecordedPowerYesterday took about two and a half hours to finish.

Finally, MondayAverageEnergy was very similar to EnergyYesterday. The process of gathering data was almost exactly the same, the differences being that it was necessary to gather data from two separate days and that it was necessary to extend back even further than just a single day to find data. This helped find some of the problems in EnergyYesterday: while it is quite easy to miss the wraparound error described above when you only have to move back a single day, missing the same error when one must look through up to fourteen days in the past becomes quite difficult. Unfortunately, also as described above, the solution that I found is rather awkward. MondayAverageEnergy took a little over an hour to finish.

Despite all the difficulties, the programming and problem-solving processes themselves were quite enjoyable. There are certainly some issues in my solutions, and working on some of the code past midnight historically has a negative effect on the quality of my work. However, the additional experience with Java and Ant is in and of itself valuable; the fact that this work has some practical value makes it even more important.

Monday, October 31, 2011

Energy Development in Hawaii

Modern society depends greatly on energy. Cars need gasoline to go anywhere (aside from downhill). Cell phones need batteries to operate. Software engineers need electricity to power their computers so that they can write blog entries. While this dependency upon energy is not necessarily a bad thing—cars, cell phones, and software engineers certainly offer their conveniences—this relationship between society and energy does create the potential for problems. Hawaii, as a very unique place, has unique strengths and weaknesses in working with energy.

At first glance, Hawaii would seem to have several severe disadvantages when considering energy needs. Being an archipelago rather far away from any typical sources of energy does make certain options unviable. Oil, which is what many people automatically think of when asked about energy sources, is not naturally found in Hawaii and must be imported. The same is true of many other raw materials used in energy production. Since these materials must be imported, they are much more expensive in Hawaii than in other locations. The fact that Hawaii is comprised of a number of islands also makes them divided, unable to easily share what energy they can produce with one another. These islands are also different from one another in many respects, such that a solution that works on one island may be unworkable on another.

There also exist concerns about the usage of land on which energy development might take place. As with most land issues, there are those who own the land, those who think they own the land, and those who know that they do not own the land but want everyone to think that they do. Across all of these situations though, there is the need to carefully consider a wide range of factors when constructing facilities for energy production. The islands of Hawaii have a very limited amount of land for development, so any plans to use the land must be well thought out. Residents may not want to live near a power plant, or fertile land may be better used for agriculture.

On the other hand, the Hawaiian Islands also provide certain unique benefits and opportunities in regards to energy development. Hawaii offers a great variety of renewable resources. While Hawaii does not always fit the tourist ideal of bright sunny skies, solar energy seems to be a common choice for alternative energy, especially for residential areas. Geothermal energy is also a possibility at the State or county level, though trying to use it for individual houses would be questionable (though as with anything involving heat and particularly magma, it would certainly be interesting; a moat of lava would probably be effective at keeping trick-or-treaters away).

Even the negative characteristics of Hawaii in terms of energy development can be turned into positives given the right frame. The current cost of energy provides an incentive to find some cheaper sources of energy, and the cost of those alternatives compared to those of more conventional methods certainly seems much more appealing than it might otherwise. The limited, isolated nature of the Hawaiian Islands can also serve as a positive factor in that the energy needs are also relatively limited.

Energy production in Hawaii offers several opportunities for software engineers to participate in research. Researchers will often benefit from having tools that can analyze the data that they obtain. The data itself is just numbers; software engineers can present that data in a meaningful form not only to the researchers but to the participants and even to the general public. Software engineers can also help in providing quality assurance tools to verify the data that the researchers gather. With the amount of money invested in this sort of research, ensuring that the results are valid becomes extremely important. On a larger scale though, most of the research on energy focuses on hardware solutions: building a particular power plant, or monitoring fluctuations in energy use in different locations. Software engineers can add a software-based perspective to solving energy problems. For example, given the problem of the lights in houses being left on throughout the night, a hardware solution might involve light bulbs that are energy-efficient and circuits that automatically shut off after a certain amount of time. While this works, the hardware solution is also rather inflexible—if the user wants to keep the lights on, he or she would have to manually turn the lights back on each time the lights automatically turned off. In contrast, a software solution might involve a program allowing the user to select how long to leave the lights on before automatically turning off, with the ability to make exceptions in special cases or account for variables, perhaps giving warnings at intervals before the lights are automatically turned off.

Friday, October 21, 2011

Reflections on Software Engineering

Over the past few months, I have been learning a great deal about various tools for use in software engineering as well as the principles behind their use. Of course, the actual use of these tools tends to take precedence in most of these blog entries since that tends to be the more exciting topic. Actually doing something is more glamorous than sitting around discussing theory. However, every once in a while there is the desire to relax and look back on these general principles. This is particularly true for students, who can use the study as a means of procrastinating on other assignments while still doing something academically related.

For these reasons, I have started reflecting on what I have done over these months and have found some questions that I have learned to answer through the work I have done.

1: How does an IDE differ from a build system?

An IDE allows developers to write, compile, and test code on their own systems. Build systems provide standardized compilation, testing, packaging, and automated quality assurance that works across platforms and IDEs. IDEs are suited for individual developers; build systems allow for efficient collaboration between project members. All functions of a build system should be IDE-independent.

2: What is the difference between using == and equals to test equality?

When used with objects, == tests object identity, while the equals method tests object value. As a result, == should be used to check if objects are the same—that is, if one object literally is the other—while equals should be used to determine if two objects have the same value.

3: In what order will Ant resolve dependencies?

Ant will not run a target until all dependencies for that target have been resolved. As a result, the target order will be like a stack in which the first targets are the last to be executed.

4: Does 100% coverage from a white-box test mean that the code is free of bugs?

No; 100% coverage only indicates that the test or tests went through every line of code. This result does not mean that there were no errors in the operation of the application.

5: If the trunk of an SVN project is always supposed to be a working version of the project, why is it necessary to run the “verify” target upon checkout of an updated version?

Running the “verify” target ensures that the updated version does in fact work. The fact that the trunk should always be a working version does not necessarily mean that it will always be a working version. If this initial use of “verify” does not produce any errors, then any errors that are produced after edits to the code must be due to those edits, making resolving those problems easier. However, if the trunk does not pass the “verify” target, then the trunk should be fixed before development can progress further.

Wednesday, October 19, 2011

Configuration Management

Configuration management was relatively easy after the work done on the competitive Robocode robot. I was greatly aided in this in that I had previously used Google Project Hosting for another project, though my experiences with the service were somewhat mixed. Because I had no experience with SVN at that time, I was limited to editing the files that were already on the project page, which meant updating files one at a time. Obviously, this was a terribly inefficient method of working on the project. There were ultimately never any problems with the project not working—unless someone attempted to checkout the project while I was between updating files, no one would notice that the files were out of sync—but still, there was that risk, and there was also the danger that I might forget to update one or more files, resulting in a final product that did not work. On the positive side, having to update files one by one meant that I was recorded as making a lot of updates to the code, so someone taking a casual glance at the list of updates would assume that I was doing my fair share of the work.

I was successful in making updates to a sample project page and creating a project site for my own DeaconBlues Robocode robot. In doing this, I learned how to use Google Project Hosting and TortoiseSVN. There was a mild issue with TortoiseSVN in that the latest version does not support Windows XP with Service Pack 2, which is what my current system uses, so I am using version 1.6.16. However, at least for these early stages where I only have to checkout, update, and commit files, any loss in functionality is not noticeable.

Obviously, using SVN to commit changes to a project all at once is much easier than going through all of the files one by one. TortoiseSVN is a very convenient, clever system that allows me to easily commit changes. I remain more ambivalent about Google Project Hosting; though it certainly does what it is supposed to, I still think that being able to upload and especially to delete files through Google Project Hosting itself should be much easier than it is now. Although I can work around this with SVN (and doing so is in fact better since it allows me to run a verification check before committing the change), I think that since the files are on the project site, it should be possible to add to or delete from that set of files through the project site.

Overall though, this first experience with SVN and configuration management was positive. I can see how Google Project Hosting will be very useful for collaboration with others in the future.

Tuesday, October 11, 2011

Competitive Robocode Robot

Overview

In continuation of my work on the Robocode and Ant katas, I have produced a competitive robot called “DeaconBlues” (though represented as “deaconblues” in Robocode itself) for use in the Robocode system. I use “competitive” in the loosest possible sense, of course; this particular robot has difficulty even in defeating some of the sample robots. However, this robot does have the potential to succeed so long as circumstances are not too adverse.

My objective in this project was to create a robot that could reliably defeat the sample Walls robot; my understanding from my initial observations of Robocode was that Walls would be the most difficult to fight against. However, I spent most of the time from when I finished the Robocode katas until the present on developing a targeting system that would have been extremely valuable in any competitive robot. Of course, being able to track an enemy is useful for any target, not just against Walls. I actually did manage to implement my system a few days before this writing. It was fast, reasonably efficient, and only required knowledge of basic trigonometry to understand. It also did not work, which was a significant problem.

Fortunately, I also had a backup plan for a robot that focused primarily on defeating Walls. This robot is described below.

Design

Movement
DeaconBlues moves in a pattern very similar to that of Walls in that it circles around the outer edge of the field. When fighting against robots that are not Walls, DeaconBlues and Walls are virtually identical in their movement. However, when DeaconBlues detects an enemy that appears to be using a Walls strategy, it determines whether the enemy is moving clockwise or counterclockwise around the field and then goes in the opposite direction. The hope is that doing so will result in a situation such as that in the picture below.


The sample Walls robot always tries to face toward the center of the field. This leaves its flanks vulnerable as it moves along the edges. As the picture shows, DeaconBlues is able to fire at Walls without fear of counterattack, even though Walls has nearly seventy more energy than DeaconBlues does. In fact, a few seconds later DeaconBlues was able to destroy Walls through a combination of ramming and shooting.


Targeting
Unfortunately, targeting is one of the weak points in DeaconBlues. Without the working targeting system that I was hoping to develop, DeaconBlues must simply fire upon seeing an enemy and hope that it is still there when the bullet arrives. DeaconBlues also falls a bit short in selecting targets, though this is not as great a problem if DeaconBlues only has to deal with a single opponent at a time. The one aspect of targeting that DeaconBlues is reasonably competent in is remembering the characteristics of its targets; the downside is that DeaconBlues must thus focus wholly on a single target or else invalidate all that information.

Firing
DeaconBlues is somewhat weak in terms of firing, for the same reasons as its weakness in targeting. However, DeaconBlues does have a formula to determine the strength of its shots, accounting for factors such as enemy velocity, heading, bearing, and distance. As mentioned in the Targeting section, DeaconBlues fires as soon as it sees its target. Aside from quite possibly missing a moving target, this makes it difficult to hit even stationary targets at times. This is because DeaconBlues fires as soon as its radar detects the target, which is in the moment when the radar touches the edge of the enemy. As a result, DeaconBlues is aiming for the edge, not the center of the enemy, and thus from difficult angles misses are much more common for DeaconBlues.

Results
DeaconBlues can reliably beat any of the sample robots provided with Robocode. The results provided here may be slightly optimistic about the performance of DeaconBlues, as usually the scores are much closer. Nonetheless, DeaconBlues has an excellent record against the sample robots, with single defeats only to SpinBot, Tracker, and Walls.

SpinBot is difficult to fight against largely because of the circular motion, which makes aiming difficult. The same problem exists for Crazy, but SpinBot has a more regular pattern. Since DeaconBlues moves along the walls, if SpinBot is also near a wall that DeaconBlues must pass by there will inevitably be some shots exchanged.

Losing to Tracker was a bit of a surprise. My best guess as to what happened is that DeaconBlues was stuck in a corner at some point where Tracker should shoot at DeaconBlues while DeaconBlues was too focused on escaping to fight back.
I had anticipated that Walls would be a difficult opponent. I believe that this is so because Walls stays on the outside, away from danger, where enemies only have 180 degrees of space in which to aim at Walls. Walls also benefits from constantly moving around, making it difficult for opponents to aim shots. Since it is a very effective strategy, I integrated it into DeaconBlues as its course of action when not hunting down Walls.

Improvements to DeaconBlues would naturally be in the area where it is currently weakest: targeting. A good targeting system should make DeaconBlues a much more effective combatant.


Testing
Testing DeaconBlues provided another level of challenges to overcome. This was really my first time working with JUnit, and as such there were a few early struggles to deal with. After the initial learning curve though, JUnit was not too difficult to get used to.

I created six separate tests for DeaconBlues. The first two tests were fairly simple initially, as I only had to set up SpinBot and Walls to fight against DeaconBlues. As is usual for me though, I managed to make both more complicated than necessary. DeaconBlues only has to beat SpinBot seventy-five percent of the time to pass the test, and to pass Walls DeaconBlues must obtain more points than Walls during their fights. Despite these tests being objectively rather easy, DeaconBlues has some difficulty with them. DeaconBlues is not a very consistent competitor: on one test it might win all of its matches against Walls while on the next it must struggle to win half of the battles.

Three of the other tests focused on the behavior of DeaconBlues. One tested the ability of DeaconBlues to move to the corners. Since the decision of which corner to move to is somewhat random, this test looks more at how truly random the randomizing method is, keeping track of how often DeaconBlues moves to each corner and examining whether the time spent at these different corners is equally distributed amongst the corners. Another test examines the ability of DeaconBlues to evade enemy fire. That test is slightly inaccurate: it does notice when DeaconBlues takes damage, but it does not adequately discern between the different potential causes for the change in energy. DeaconBlues could have fired its cannon or run into an enemy, both of which could also cause a decrease in energy. The final behavioral test is on the accuracy of fire that DeaconBlues has. As noted above, DeaconBlues is horribly inaccurate.

The last test is a fairly simple unit test that runs through some of the utility methods in DeaconBlues. The calculations are nothing too intensive, and one could probably go through them even without a calculator to prove that DeaconBlues is performing as expected in that regard.

Lessons Learned
I have learned that software engineering is certainly a very intensive process. As I write this, I have spent three of the last four nights without sleep in order to work on DeaconBlues. At the same time, the work is amongst the most rewarding that I have ever done. I enjoy the work, and perhaps the fact that it is an enjoyable project helps as well.

From the perspective of software development, in the future I would prefer to incorporate testing into my project much earlier than I did this time. Checkstyle in particular caused a brief moment of panic when it informed me that I had twenty-seven errors to fix this past evening. Most of those errors were in regards to not simplifying expressions (ex. writing “if (isWalls == true)” instead of just “if (isWalls).”) My instinctive reaction to this was to remove the Boolean value and the comparison from all of the lines that Checkstyle warned about, grumbling that this would make the code more difficult to understand. This had an immediate effect on the code, as “if (isWalls == false)” is somewhat different in meaning from “if (isWalls).” Fortunately, I was able to find and fix these errors (at least the ones that I could find). In any event, this sort of testing would be better done earlier in the development process so that these problems could be discovered and resolved with less difficulty.

Wednesday, September 28, 2011

Ant Code Katas

Build systems allow multiple developers on different platforms to coordinate work on a project with relative ease. Though I am by myself a single developer, I anticipate that I will have to work with others on projects in the future, and in any event becoming familiar with build systems should serve as a useful experience. For the moment, I am working in Ant (discussed in more detail at http://ant.apache.org ), which as I understand is the standard build system for Java applications. To familiarize myself with Ant, I have worked on eight Ant katas, similar in purpose to the Robocode Code Katas that I completed a little over a week ago.

1: Ant Hello World: Prints “Hello World.”
2: Ant Immutable Properties: Demonstrates the immutability of build properties; once defined, the value of a property cannot change.
3: Ant Dependencies: Shows how targets depend on one another.
4: Hello Ant Compilation: Compiles a file HelloAnt.java from a src directory and creates a build/classes directory for the class file to be placed into.
5: Hello Ant Execution: Runs the compiled HelloAnt program.
6: Hello Ant Documentation: Generates the JavaDocs for the HelloAnt program.
7: Cleaning Hello Ant: Adds a “clean” target to the compilation kata that removes the build directory.
8: Packaging Hello Ant: Creates a zip file containing the Ant katas and the source code for HelloAnt.

All eight of these katas were completed successfully, though as with the Robocode katas some difficulties became apparent only as I worked on the programming. Ant uses XML files, and though I have a passing familiarity with XML structure I have never actually written anything in XML for at least a few years. Fortunately these katas are relatively simple, and since Ant has its own keywords I did not have to learn XML and Ant simultaneously.

The main difficulty that I had in completing these katas was with Kata 5, in which I had to execute the HelloAnt program. The java task in Ant can take either a .jar or a class file as the file to run. Given that the kata preceding this compiled HelloAnt.java into a class file, I felt that using the class file was the more logical choice. However, the vast majority of the examples available on the Internet use .jar files with java.

This lack of examples led to the next problem. Kata 5 originally worked as intended, running the Java program without errors. However, when working on Kata 6, I realized that I had forgotten to specify the package that HelloAnt.java should be in. Fixing this was simple enough, and soon Kata 6 was working. Unfortunately, when I got to Kata 8, which required that everything in HelloAnt work perfectly, the code from Kata 5 began to produce errors. Specifically, Java could not find the HelloAnt.class file. After some investigation, I understood that the error had something to do with the package but could not find a solution; even specifying the exact folder that the file was in for the class path did not work. None of the resources online offered any substantive advice. It was not until much later, when I asked a classmate about the matter, that I learned that the class name for the java task had to be fully qualified. This resolved the problem immediately.

I understand why Ant would do this. After all, there could be classes in different packages with the same name, in which case the best and possibly only way to tell them apart might well be the package. At the same time, I cannot help but think that a system should be able to recognize that a file with the same name and in a series of folders that matches the package structure of the file that it is searching for could actually be the file that it is searching for.

Overall, the katas were not terribly difficult. The problem with the class name was the only significant delay in completing the katas, even if that one problem was severely stressful. Aside from that issue, there were only the usual problems with trying to learn what is essentially a new language for me. I do not consider myself fluent in Ant yet, but I can at least use Ant and write files that Ant can use, if with the occasional need to look through some reference source.

I learned a great deal about Ant from completing these katas. However, perhaps more importantly, I was reminded of the value of human sources of information. Most of the times when I want to learn something, I look on the Internet or in a book. Humans though serve as a source that can account for context and focus on relevant details. Although I still prefer written sources of information, I will have to remember that humans such as my classmates are still valid sources as well.