Pages

Showing posts with label ics 314. Show all posts
Showing posts with label ics 314. Show all posts

Tuesday, October 11, 2011

Going In Circles And Then Some: Preparing for a Robocode Tournament

Project Overview

The robot I was attempting to design for the Robocode tournament would have avoided hitting walls altogether, and would have been able to maintain a basic lock on its target. Neither of these goals was accomplished to any useful extent.

Design

  • Movement

  • Ideally, the robot was to have moved 100 pixels each turn, turning itself perpendicular to the headings of any enemies encountered and turning back before hitting walls where possible. I attempted to do this via the avoidBounds method, which was intended to turn the robot away from walls and thus avoid collisions with the walls entirely. As far as I can tell, this instead caused freezing problems whenever the robot managed to be positioned perpendicular to a corner, and in some other cases I was unable to define.
  • Targeting

  • Ideally, the robot was to have rotated its radar 180.0 degrees per turn, turned its body to be perpendicular to an enemy robot once it was scanned, logged its opponent's name, then begun scanning in smaller 22.5-degree intervals as long as it continued to detect that same opponent. Once that opponent was destroyed or had not been seen for two scans, it would resume scanning in increments of 180.0 degrees. In reality, the robot lost targeting locks almost constantly, as its other behaviors caused it to turn too frequently to maintain a consistent heading or back-and-forth pattern of strafing.
  • Firing

  • The robot implements a basic bullet-power calculation algorithm based solely on distance, starting at the maximum of 3.0 for anything less than 100 pixels away, dropping from 2.9 to 2.0 for anything 100-300 pixels away, then to 1.9 to 1.0 for anything 300-500 pixels away, then to 0.9 to 0.5 for anything more than 500 pixels away. It fires whenever it detects the robot it is currently targeting, and targets the same robot for the duration of at least three 22.5-degree scans before giving up and looking for a new target.

Results

(Each robot was fought for 10 rounds.)


Meteor's lack of predictive targeting means that Walls has moved out of range by the time Meteor aims its cannon at where Walls used to be; Meteor has no way of accounting for drastic shifts in direction or velocity on the part of an enemy robot.
Robot NameWins AgainstLosses Against
SittingDuck10/100/10
Virtually all robots can beat SittingDuck.
Tracker1/109/10
Meteor's primary weakness against Tracker is that it takes too long to scan for changes in motion (Tracker hardly scans at all once it has a lock), and thus fires much less often than Tracker. In addition, when this robot loses track of a target, it completes a 180.0-degree radar rotation, leaving it vulnerable to attack.
Corners0/100/10
Meteor's avoidBounds method backfired here, frequently causing it to spin in circles without firing or moving while Corners swept its radar across the battlefield in increments.
Fire0/100/10
Once again, the problem was that Meteor took too long to aim and fire,getting only a fifth the bullet damage of Fire. Meteor also froze repeatedly in this match.
Crazy3/107/10
Meteor did not perform predictive movement analysis, and had no way of estimating Crazy's movement pattern, whatever it was. I am not sure why Meteor won against Crazy at all.
SpinBot0/1010/10
Meteor actually dodged several of SpinBot's projectiles, but it failed to score any hits of its own and usually got stuck against a wall after about thirty seconds, thanks to its freezing bug.
RamFire2/108/10
Once again, Meteor's need to make large turns and radar sweeps each time it lost a targeting lock did it in; this made it easy for RamFire to push Meteor into walls or otherwise obstruct its movement.
Walls0/1010/10

Testing

My tests consist of two acceptance tests, TestMeteorVersusCorners and TestMeteorVersusFire, both of which the robot fails (see the Results section); one behavioral test, TestMeteorFiring, that checks whether Meteor.calculateShotPower is functioning correctly; and three unit tests (UnitTestWhichWallOrCorner, UnitTestDistanceToWallOrCorner, UnitTestNewXAndY) for the methods Meteor.whichWallOrCorner (which returns an integer code based on whether the robot is near a wall or corner), Meteor.distanceToWallOrCorner (which calls whichWallOrCorner itself, and determines the distance to a wall or corner) and a combination unit test for the very similar Meteor.newX and Meteor.newY methods, which calculate the point that a particular motion will cause the robot to drive to. UnitTestNewXandNewY does not work, however, due to what are probably errors in how I assumed it was supposed to work.

Lessons

The Robocode design process has revealed a harsh truth about my coding style: specifically, that it tends to produce a lot of code, most of which performs as expected, but most of which goes towards performing some extremely complex task (avoiding walls) which in the long run is not very important. In addition, the sheer length of my code virtually guarantees problems like Meteor's mysterious freezing episodes, which could come from any number of points in the code which control movement and which do not seem to share any common factors. Thus, I have a robot with about 400 lines of code (excluding comments) that cannot beat any of the sample robots with any sort of reliability, is still incapable of detecting when it is near a wall and stopping, and shoots straight but on average takes longer than most of its opponents to do so. The major problem is the freezing bug, which I have repeatedly failed to fix over the course of the last two days. If I had tried to do this over again, I would have spent less time trying to reinvent the wheel and more time modifying example code, as my attempt to implement a wall-avoiding function took so much time there was little left to actually test anything else.

Wednesday, September 28, 2011

Apache Ant Code Katas: Learning A Build System In One Week

Introduction

Build systems are software packages which help software developers by automating project tasks that need to be done repeatedly, such as compiling source code, running compiled code, generating documentation, and packaging a system for distribution. All of these tasks do not take much time to do by hand for small projects, but for large academic or enterprise projects with hundreds or thousands of files, doing anything manually is virtually impossible. Apache Ant, a free build system commonly used in enterprise, carries out all of these tasks and more by using Java libraries to process instructions in user-created XML files. Users can extend Ant's functionality by writing their own libraries or by combining it with dependency-management tools like Ivy, which download whatever third-party libraries are needed to run a given piece of code, then save them locally. For this exercise, I completed several code katas designed to teach me some of the basic functionality of Ant 1.8.2. Each kata required me to create a specific filename.build.xml file, which would contain processing instructions for Ant.

Kata 1: "Hello World"

In the time-honored tradition of everything in computer science, I started here. The objective here was to teach use of the <echo> element to print informative text to the console. This did not take very long.

Kata 2: Properties Are Immutable

This kata was intended to teach procedures for defining properties, and to demonstrate that properties cannot be changed once defined within a build file. I defined a property, then attempted to define another property with the same name. As intended, this had no effect whatsoever, and the <target> which printed the property value printed the first value which was defined.

Kata 3: Dependencies

In Ant, the "depends" attribute of a <target> element specifies which targets must be completed before a target's instructions will be executed. This is used to make sure that any prerequisites for a target to run correctly (e.g., compiling code before trying to run it) can be carried out. This kata required us to print the name of the target as it was being executed, and I spent a few hours fruitlessly trying to print each target's "name" attribute before discovering that it might not be possible without Javascript workarounds. In the end, I defined properties with the same names and values as the targets they were defined within, and settled for <echo>ing those.

Kata 4: Calling the Java Compiler on HelloAnt

This exercise used a simple Java program which printed "Hello Ant" to the console. Here, within a "compile" target, I defined two properties: paths to a source directory (where the .java file was) and a build directory (where the .class files would be output to). I then used the <javac> element, which would tell Ant to run the javac compiler given the specified directories as parameters. This kata was still fairly easy. More importantly, running this script repeatedly was faster than having to specify the directories each time I ran javac from the command line.

Kata 5: Running HelloAnt

This exercise called for importing the .xml file from Kata 4 and using its "compile" target to compile the system before running it. As it turned out, defining the directory paths in Kata 4 meant I could easily reuse them here, as importing a file also imports all of its defined properties. Using the same principles outlined by the Dependencies kata, I made the "run" target dependent on "compile". The hardest part of this was guessing at how to write the <java> element's "classname" attribute for java files in a package, which I couldn't find an example of in the Apache documentation. At first, I tried to treat the class name as a series of nested folders (/edu/hawaii/ics314/filename.extension), which is how it appears in the file system. After several variations on this, I learned that ant requires that the classname be written using its Java format (edu.hawaii.ics314.filename, no file extension).

Kata 6: Making Documentation for HelloAnt

This kata demonstrated the use of the <javadoc> element, within a target that was dependent on the <compile> target, which was imported. This ensured that the Javadoc files would only be generated if the source code actually compiled. The <javadoc> element also allows you to control what information is included in the javadoc by setting attributes such as "author" or "overview" to "true". Generating documentation manually is always tedious, and the attribute options are less tedious to use than typing each option individually (every time you needed to revise the documentation) and running Javadoc from the command line.

Kata 7: Cleaning the Software Package

This exercise required me to modify the .xml file from Kata 4 to add a target which deleted the "build" directory generated by the "compile" target. This was intended to teach the use of the <delete> element, which instructs Ant to delete the directory specified in the "dir" attribute.

Kata 8: Package HelloAnt for Distribution

I had a recurring problem when I first tried to implement this kata: as required, it would delete the build directory, but it would mysteriously include the build directory in the .zip file it created for distribution. Eventually, I realized that because I had to create the build directory again to store the .zip file in build/dist, it was always saving the empty build directory into the .zip file. I fixed this problem by modifying some code from a class example to first save the .zip file to a temporary directory, copy it over to the desired directory, then delete the temporary directory. The main lesson here was to use the "excludes" attribute to exclude the build directory from the distribution. Regardless, manually excluding unnecessary files before creating the distribution directory would have been an annoyance for a small project like HelloAnt, but impossible for any enterprise project of moderate size.

The second requirement was to make sure that unzipping the directory from the command line would preserve the original directory structure. This was simpler and involved creating a directory with the same name as the current directory within the distribution directory. Removing the build files from the distribution not only reduces its file size, but makes sense in light of Prime Directive 2: forcing other developers or users to build the system using the build files you've provided is a good way to verify that others can install and use your system.

Ant / Ivy and the Three Prime Directives

As free software packages which work together, Ant and Ivy are fairly easy to install as long as one follows the site instructions (Prime Directive 2), and automating otherwise tedious tasks easily fulfills a useful task (Prime Directive 1). While I can't say that I have personally tried to extend the system, I was able to complete most of the katas without going outside Apache's documentation, which does go some of the way towards fulfilling the third prime directive as well. It is also worth noting that despite my initial problems on some of the later katas, all of the tasks I was trying to instruct Ant to perform would have taken just as long, if not longer, if they had to be performed by hand and/or directly from the command line over and over again. Build systems may take time to learn, but a little time invested up front here will always save more time in the end.

Final Thoughts

Though I wouldn't claim to understand everything about Ant at this point, the code katas did force me to learn enough to understand its basic capabilities and encourage me to look further into its other features. The extensive use of custom XML markup for interpretation by Ant and Ivy's Java libraries demonstrates to me that XML, as a user-defined markup language, is as useful as a developer wants it to be. Learning new software tools or APIs quickly is always a little like jumping into a pool; code katas won't get you into the deep end right away, but they can teach you enough to slowly move into deeper water and not drown.

Saturday, August 27, 2011

The Three Prime Directives of Open Source Software: PDF Split and Merge

Introduction

In the world of open-source software, the "Three Prime Directives" define the characteristics of a true open-source project. To fulfill the first directive, "the system must successfully accomplish a useful task." To fulfill the second prime directive, it must be true that "an external user can successfully install and use the system." The third directive is fulfilled when "an external developer can successfully understand and enhance the system." Fulfilling the three prime directives is important for an open-source project because it ensures that users and other developers can contribute bug reports, feature requests, and their own add-ons to the project, thus enabling the developers to better understand the needs of their customers and improve their system.

Sourceforge

Sourceforge is a well-known source code repository for open-source software, offering hosting and version-control services and providing a means for end users to directly contact development teams with bug reports and other feedback. ICS 314 is a Java-oriented class, so we were asked to find and review a Java-based project.

PDF Split and Merge

PDF Split and Merge's homepage describes itself as "... an open source tool (GPL license) designed to handle pdf files." Its GUI is written in Java Swing, and the command line interface is also based on Java.

The Windows installer for PDF Split and Merge can be found at http://sourceforge.net/projects/pdfsam/, and the other installers can be found at http://www.pdfsam.org/?page_id=32.

Prime Directive 1

PDF Split and Merge (referred to as PDFSam from here on) provides a wide suite of tasks related to the manipulation of PDF files. These include splitting and merging the pages of existing PDF files, rotating PDF pages, and combining multiple sections extracted from PDFs into a single new document. Most other programs which provide these functions are proprietary (e.g., Adobe Acrobat or Adolix Split Merge PDF), so consumer demand does exist for the useful task which PDFSam accomplishes.

Prime Directive 2

Ease of Installation

PDFSam was easy to install, and though there were problems with the installation, they were quickly fixed. The Downloads page features "basic" versions for Windows, Mac OS X, and a .zip file, which contains all the files that the .exe installer creates. The program requires Java SE 2 version 1.6 or higher to run. The site also offers an "enhanced" version that is free (if you compile the code yourself) or available as a regular installer for "a single donation of any amount." I installed the basic version.

Installing From A .zip File

Once the files are extracted, the program is easily run from the pdfsam-2.2.1.jar file. For some reason, the folder still contains a useless "pdfsam-starter.exe" file, exactly like the folder created by the .exe installer. The .exe installer had its own set of problems, which are covered in the next section.

Using the Windows Installer

The .exe installer ran with no problems on my Windows 7 machine, but the application failed to launch from the startup menu. I ran a compatibility check, which recommended running it using Windows XP SP2 settings. This caused the program to open and crash, saying it had failed to find "pdfsam-2.2.1.jar." The installer had created pdfsam-2.2.1.jar in the installation directory, but for whatever reason pdfsam-starter.exe couldn't detect it.

The readme.txt file included with the installation stated the following:

"Installation: Unzip the archive into a directory. Double click pdfsam-2.2.1.jar or open a console a type the command "java -jar /pathwhereyouunzipped/pdfsam-2.2.1.jar"".

Following this instruction successfully launched the program. Though the program runs from the .jar file, and readme.txt does tell the user to run the .jar file and not the nonfunctioning launcher "pdfsam-starter.exe," there are problems with this approach. Any user who used the .exe installer would not be able to easily access the program from the start menu, which only provides a link to the broken "pdfsam-starter.exe" file and no link to the .jar file that actually runs the program.
The program isn't unusable by any means, but the need to read documentation to get around a broken launcher implies that the problem is known but still not addressed, and doesn't satisfy the first prime directive's requirement for ease of installation.

Ease of Use

I was able to use most of PDFSam's PDF manipulation features without consulting the included instruction manual. It has five basic functions: "Alternate mix" (which can reverse the order of a document's pages or mix pages from documents at specified intervals), "Merge/Extract" (which lets you merge specific parts of PDFs), "Rotate" (which rotates all pages in a document in increments of 90 degrees), "Split" (which divides a document into pieces), "Visual document composer" (which lets you take individual pages of multiple documents and merge them into a single document) and Visual reorder (which lets you change the order of pages in one document). I tested PDFSam's basic functions with multi-page PDFs of lorem ipsum text and found the features easy to use.


The PDFSam GUI.

The command-line features are less easy to use, but still usable by following the instructions in the tutorial PDF or its wiki (command line instructions shown):

The mistake to avoid making here is to assume that "options" and "required" mean the "options" and "required" arguments that apply to "command." Actually, "required" covers all the arguments exclusive to "command," whether the arguments are specified as optional or not. After an hour or so of working through my confusion, I successfully did this:


The command line output produced by merging two PDFs.

To be fair, my mistake was a careless one, and command-line tools aren't usually intended for casual users (who will mostly use the GUI), so any difficulty on the part of the command-line tools doesn't detract much from the program's overall usability. PDFSam still mostly fulfills the second Prime Directive as it relates to ease of use.

PDFSam does a mixed job of fulfilling the second Prime Directive, and is easier to use than it is to fix it after it installs.

Prime Directive 3

PDFSam does a good job of fulfilling the third Prime Directive. Source code and developer-level documentation is easy to find on the project's official (non-Sourceforge) site. The source code is available on the Downloads page. Each Java source code file begins by making developers aware of their modification rights under the GPL, and each file includes cross-references to other Java files. This is demonstrated by the code excerpt below:

Developer-level documentation is provided on the Resources page. Java documentation is provided for both the basic and enhanced version's APIs, and changelogs and software requirements are also available. The Resources page also provides links to request features and access its SVN repository. Bugs are reported in the forums. Developer documentation is easy to find, the source code is readily available, and changes are publicly proposed and discussed, fulfilling the Third Prime Directive.

Conclusion

Despite my problems with PDFSam's Windows installer, its GUI is easy to understand and provides many useful ways of manipulating PDFs. Developer documentation, source code, and forums for communicating with developers are easily accessed. Overall, PDFSam fulfills many of the requirements of the Three Prime Directives.

Tuesday, August 23, 2011

Hello World.

This blog is part of my Information and Computer Science 314 class, and covers my experiences in learning about software development and carrying out programming projects. With any luck, this will be the first post of many.