I really like XML. It is really amazing what you can do with it. All you have to do is define a structure and then create a document that follows that structure. You can mix and match attributes and elements in individual tags or in lists of tags. The real power of XML is not in the static documents, but in having it be interpreted in running applications.
While I use a lot of programming languages on a regular basis, one of my favorites is C#. One of the reasons C# is so easy to use is because of the built in ability to serialize and deserialize objects directly to XML. This ability is made possible by the XmlSerializer class. With simple annotations you can directly map the objects into the XML structure. The power of this approach is that you can build individual objects that represent each part of the XML and then load the entire document into memory with a single operation.
Java does not provide this functionality out of the box, but Simple XML provides a very small library that allows for an almost identical approach to be used in Java.
With the appropriate calls, the above code could easily read in and produce the following XML document:
While there are some differences between the C# approach and the Simple XML implementation, they are minor. Other than the minor syntax differences, they two handle arrays of objects slightly different. The biggest difference is the default behavior related to unexpected XML attributes and elements. C# is very forgiving and will be able to handle missing and extra elements and attributes without throwing an exception. However, it will throw an exception if there is a type mismatch such as trying to load a string into an integer. The Simple XML framework uses a strict parsing by default and the application will throw an exception if unexpected elements or attributes are encountered. Luckily there is a parameter that can override this behavior. The main reason I have encountered this requirement is to maintain backward compatibility as an XML schema changes over time.
My real complaint is the way the iPhone (Objective-C) deals with XML parsing. While there is no lack of parsing libraries on the iPhone, none of them use the object annotation approaches that I described above. This boils down to the different approach Objective-C uses with regard to syntax and the way objects are defined.
One of the projects I am currently working on requires that I port over several application libraries that has already been written in both C# and Java to Objective-C so it can run on the iPhone. While I have managed to avoid writing complex XML parsers up till now, it seems unavoidable at this point.
With respect to the iPhone, there is a built in plist parsers. Alternatively, JSON provides another means for document communication that would be somewhat easier. In the end I will have to live with my previous decision related to application architecture and choose an XML parsing engine and write the necessary code.
Saturday, August 20, 2011
Programming for XML: The Easy Way
Monday, June 6, 2011
Building an Android Application in One Week
As you can see from the chart below, I began coding on Monday May 30,2011. The majority of the code was written in the first three days of the project. This work mostly consisted of building the model that was use to represent the field events and participants. This code would have likely taken longer to create if I did not include the Simple XML third party library. Unlike the XML serialization capabilities built into .NET and C#, Java has no built in way to quickly and easily serialize objects into XML. While I could have used binary serialization, that had the possibility of causing problems in the future.
Using the Simple library was so quick and easy, I will likely use it in some other Java based applications that require some trivial XML parsing capabilities. The most attractive feature of Simple is the fact that it is very small. The APK for Track and Field Clipboard is only 156k, which has the library bundled with it. Other libraries were in the multiple megabyte range by themselves.
Android provides a variety of ways to store data persistently. I settled on using files and not an SQLite database to dramatically simplify the process. The process involves writing and reading the serialized object's XML to and from a file. Initial testing on this approach was very promising. The file was read using an AsyncTask and then the appropriate Activity was launched. Since all of the manipulations to the object were being performed in a single activity, this approach worked perfectly. When the activity was paused, another AsyncTask was dispatched to save the object back to the file so nothing would be lost. While I did have some performance issues, it turned out those were primarily cause by having the debugger attached to my device.
The weekly activity graph for this project is very interesting since the project is only a week old. The number of commits peaked and then fell indicating that the application was starting to stabilize. Since the project was a straight forward application there were very few stumbling blocks that I encountered during the process.
At the moment, I am currently between the end of my college career and the start of my first full time job. This means I have had several weeks (and still have several weeks more) where I can decided how to spend my time. Unlike many geeks, I am not a night person. I tend to wake up fairly early and do not stay up late into the morning hours. I have code commits as early as 9 AM and they only go as late as 2 PM. The drop in the number of commits in the later hours is likely when I was hungry and tended to take a break from coding. My lunch breaks were obviously much shorter. The graph reveals my peek productivity times: after lunch and before I go to bed.
This is obviously a very new project and I am confident that there are still a number of bugs in the code. There are also some simple features that did not make it into the initial release. Spending the past week creating this application has been my form of relaxing. Learning how to write an application that targets Honeycomb was definitely worth my time and effort.
Sunday, June 5, 2011
Introducing Track and Field Clipboard
It is a fairly simple idea and I had even talked about it before, but this past week I decided to actually build it. As someone who has been around Track and Field meets since I was very young, it was a perfect opportunity for me to build an application for an Android Honeycomb tablet. The basic idea is to replace the clipboard, paper, and pencil used to record scores for field events with a tablet.
When Google gave a Samsung Galaxy Tab 10.1 to everyone attending Google IO (including myself) there was a less than subtle nudge to "go forth and create apps." Not wanting to spend all of my time playing Angry Birds and now Plants vs Zombies, I decided to actually build a fully functional and useful application.
While I have one other application on the market and another long term project that has an Android component, I wanted to specifically focus on Honeycomb. While the application I build could have targeted phones, that was not my goal. The use case for a small screen is far less attractive, but the biggest motivation for only focusing on Honeycomb was simply to learn some of the new APIs and methodologies. I have spent some time working with the compatibility API for fragments and developing a pure Honeycomb application seemed like a more enjoyable activity.
Now a little bit about the application itself. I finally settled on the name Track and Field Clipboard for the application. Breaking with my long tradition of open sourcing my side projects, I have decided to keep this application close source. However, it is available for free on the Android Market. There is the possibility of me adding some advanced features in a paid version of the application if it gains some adoption.
The application is designed to be very easy to use. You create an event, add participants, and then record marks. The field events that are supported include Discus, Shot Put, Javelin, Long Jump, and Triple Jump. High Jump and Pole Vault are not supported since the rules for those competitions are significantly different and more complex.
The main benefit of using this application as opposed to an analog piece of paper is the automation that it provides. If the competition has flights, the athletes that qualify for the finals along with the order is automatically determined. Each participants best mark is highlighted to provide an accurate summary of the results at the current moment. Additionally, each participants current place is also available along with a view that summarizes the results. After you have finished with the event, the results can be emailed.
My goal here is to have this application just be slightly ahead of its time. There is not a large adoption of Android Tablet users at track meets yet, but with some luck that may change in the next year.
I need to thank Cassie for her help with the graphics (as always). I also need to thank my father for helping me work out some of the details to make sure they matched what would be expected by the user. He also served as my first actual user at the Bluegrass State Games yesterday.
In the end, my goal is to help bring technology into a new area and provide a good user experience. Hopefully I can find some users. More likely, I hope some users can find my app.
Sunday, March 20, 2011
DPX-Tools Version 0.3.5.0 Released
I typically would not announce a release of a new version of my DPX-Tools software, but this version is somewhat special. This update really only includes changes to the DPX Answers application. This application is what I used for my masters thesis. While I have not quite finished my thesis yet, I'm definitely in the home stretch, I have finished all of the coding. This latest release of my set of tools that are able to open and interpret files created by DyKnow Vision includes a new ability. The application can now automatically analyze and cluster student answers.
After the application launches, if it is able to identify a clustering library this it loads into memory. When a file is opened, after the contents of the Answer Boxes have been interpreted using handwriting recognition, the clustering algorithm will merge together what it thinks are identical or near identical answers. The goal here is to reduce the overall amount of effort required by the person grading the student responses.
From a technical standpoint I am very proud of the design of DPX Answers. The application is highly multi-threaded, since processing the the Answer Boxes is a CPU intensive activity. Worker queues are used to perform handwriting recognition and the Dispatcher is used to maintain the GUI interface. This application is the most complicated desktop application I have written to date. While I was having problems with major memory leaks for a time because of some GUI elements, I believe I ended up with a simple, but functional application that focuses on a very specific problem.
Overall I am very pleased with where I landed with my thesis. I will be spending the next few weeks putting the final touches on my thesis and preparing for my defense. It is almost impossible for me to calculate how much time I have spent working on the code that makes up DPX-Tools. The DPXReader library, which is able to open a DyKnow file and render the ink content, took me hundreds of hours to develop along with the various applications that utilize its functionality. As I finish my degree at UofL, I will no longer be using DyKnow Vision. I have worked very hard developing this software and hope that someone else will find this code base and the applications useful.
Wednesday, August 4, 2010
Automated Generation of Javadocs for Open Source Android Applications
While Java is not my favorite language, it has its benefits. With one Android application already posted on the market and another application in development, I decided to start using Javadocs a little more seriously. The process of generating Javadocs is not that complicated using Eclipse, but that is not the solution I wanted. My goal was to automate the generation and posting of the docs as the source code changed.
- Clean up any files from the previous run of the script
- Download the latest source code from the svn repository using svn export. It is notable that you can use svn export with Github since they support accessing repositories using the SVN protocol. Awesome!
- Generate the javadocs based off of the freshly downloaded code using the desired parameters.
- Copy the newly generated javadocs to the desired server. For my purposes, secure copy was the best solution. With my server's public key installed on the shared host, I was able to log into the remote box without prompting for a user name and password.
#!/bin/bash
cd /path/to/files/docs/
rm -rf ampted.svn
rm -rf ampted
svn export http://ampted.googlecode.com/svn/trunk/
mv trunk ampted.svn
JAVADOCHEADER='<a target="_top" href="http://www.amptedapp.com/">Android Mobile Physical Therapy Exercise Documenter</a>'
JAVADOCFOOTER="Generated on `date`"
javadoc -private -header "$JAVADOCHEADER" -footer "$JAVADOCFOOTER" -d /path/to/files/docs/ampted/ -sourcepath /path/to/files/docs/ampted.svn/android/src/ -subpackages com.AMPTedApp -classpath /path/to/files/lib/android.jar
scp -r /path/to/files/docs/ampted remoteuser@example.com:/path/to/remote/files/docs/
Thursday, July 1, 2010
My First Android Application: OpenNoteSecure
Yesterday I published my first Android application, OpenNoteSecure (which is open source), to the Android market. It is a simple application that stores encrypted text files on your phone using AES or DES. It was built for my Cryptology project this semester as a demonstration for securely storing information on your phone.
Wednesday, June 2, 2010
The State of Development
I have been doing quite a bit of development lately, and since most of what I do is open source I thought I would provide some type of update. I have managed to keep up development on some of my projects, but others have not received any attention.
Monday, April 26, 2010
Capstone Project: CardSurface
After four months and 15,031 lines of C# code my capstone project is finally complete!
CardSurface is a card game engine designed to work on a a multitouch screen and allow players to play a card game in a somewhat natural way. The engine itself is client-server based and allows multiple table clients to access the same server. Face down cards are viewable on mobile devices trough a web based interface.
Our project took an entire semester worth of work, but it ended up being a huge success! We implemented not only a GUI based table client using the Microsoft Surface SDK, we created a command line client that is also able to connect to the server and play a game.
Our engine is designed to implement any turn based card game. For our demonstration of the engine we implemented Blackjack, however Poker would be a better demonstration of our engine's features.
The biggest accomplishment of our engine is that the client itself has no knowledge about the game that it is playing. It requires the server to provide an updated game state after each move or action that is performed in the game. Additionally we support multiple clients and multiple games running on the same server!
There is a lot of room for improvement with this project and we probably only finished half of what we would have liked to have accomplished. However, it is definitely a project that I am proud of. The entire code base is available open source on card-surface on Google Code.
I also want to thank Aaron and Kyle one last time for being amazing partners on this capstone project. We definitely went above and beyond what was required and created something that will live on past this project.
Friday, March 26, 2010
Organization Budget and Finance
It was about a year ago when I started working on my Student Council Attendance tool for Speed School Student Council. This tool was designed to solve the problem of accurately tracking member attendance and make my job as DoA easier. After successfully putting this tool into use, I was ready for my next challenge. The next item on my list was creating a way to transparently track our council's budget including how we spend our money. I ended up spending the majority of my spring break this year working on my newest open source PHP tool, Organization Budget and Finance.
This is my first web based application that I designed in such a way that it could very easily be used by other groups or individuals. The design takes into account no special considerations from SSSC and simply attempts to fill a very specific need. This application is not designed to be a complete financial tool or even be used to balance a budget or an account. I am hopeful that someone will come across this tool and find a use for it.
This tool is used for allocating funds and tracking receipts for specific line items. I have implemented almost all of the major features and hope to have our new DoF put this tool into use very soon. The tool is based around the concept of a line item. This is a budgetary item that can have any number of sub line items. This can go as many levels deep as desired or necessary. This essentially creates a tree structure which represents the budget itself. The top level is designed to be used for each years budget. The next level will be used for all of the major events or funded items. The successive levels provide additional details to how funds are allocated. Multiple funding sources can be allocated to each line item. Any number of receipts can also associated with line items and represent money spent. There is not direct connection between the funds and the receipts meaning the allocated funds are treated as essentially one pile of money that receipts deduct from.
The design approach for this tool was to keep it as simple as possible, specifically with respect to the database. However, some interesting features have been built on top of this core set of information. Receipts, sources, and line item's can be made private. The reason for this is that not all information should be made publicly available, at least initially. The obvious use of this feature would be hiding items that are not yet finalized, such as next year's budget, or hiding receipts that have not cleared the account yet or the amount has not been confirmed.
Other features include the ability search the database for specific receipts or line items. This will especially be useful when trying to find out how much was spent on something from a previous year. The budget pages use custom CSS formating which allows for easy printing and avoids all of the fancy styling that is part of the web site. Lastly, the entire database can be easily downloaded in a single click as an XML file for easy backup and data portability.
Why put in all of this work for this tool? In the end it boils down to transparency. I strongly believe that SSSC will benefit from more transparency. It starts with having this tool being open source and ends with our budget being available for anyone to look at. In the end, not many people will care how much we spent on pizza at Fall Festival or how much the E-Expo name tags cost for all of the council members. However, certain council members will care about this information and having an accurate record is priceless.
Our historical records with respect to finances have mostly been lost to time. The real judge of my success will be time. What will the state of these records be 10 years from now? Hopefully I remember to look back and see if I was successful.
Thursday, March 18, 2010
Becoming an Open Source Developer
I have been writing computer programs for a very long time. My first experience was writing Logo programs when I was in elementary school. I have come a long way since then. In high school I began programming in PHP and was able to make functional applications. In college, as a Computer Engineering & Computer science student, I have completed a wide variety of programming projects, but only recently have I started releasing my code open source.
Friday, September 11, 2009
An Open Source Semester
This semester I have already expressed that I am swamped with school/work, but so far have been having fun. As a small distraction I have a few interesting facts to share. I have determined that on a weekly basis I will be coding in five programming languages. They are:
- PHP for Student Council's Website and any other web code I decide I "need" to write
- C# for my CECS 550 project and the DPX software I am developing
- Java for my CES 220 class
- Assembly language for my ECE 412 class
- Objective C for my work on the iPhone
At this moment, I have three projects that I am working on that are hosted on Google Code. They are:
There are a few other large pieces of software that I have written that I am thinking about releasing open source. The one that it at the top of my list is my Alien Defense game that I wrote for my object oriented class last fall. While it isn't a very fun game, it is almost complete. At the very least it is playable, just not fun. With a lot of re-factoring and some time dedicated to balancing the game difficulty is needed, it would be a fun game if it was finished.
As for SCM, I have a dedicated computer that I have off site and always running that I have set up CVSNT on. However, I do not know if that is the SCM software I will end up using. SVN is probably a better choice. I have tried using GIT, but the lack of integration into some IDEs have kept me away from it. Since my biggest projects are already in an SVN hosted by Google, I will not be rushing to find a solution for myself.
Even though I have a lot of work to do, I am excited to be contributing to open source projects. While these projects are ones that I have started, in the future I will probably try to find some other projects to contribute to.
Saturday, August 22, 2009
YubiKey, Authenticate Me Please
I enjoy really geeky gadgets and potentially one of the geekiest things I have purchased lately was a YubiKey from Yubico.
For someone not very technical it might be a little hard to understand what a YubiKey actually does. From a security standpoint it is quite simple, it authenticates you. It looks like a very thin flash drive with a button on top. When plugged into any computer it acts like a USB keyboard. This means it works on anything with a USB port that supports a keyboard.
The point of having a YubiKey is to have a one time password. Just like the name implies, a one time password is a password that only works once. Evey time you click the button on the YubiKey generates a unique password that will only be valid once.
How a YubiKey Works
Stored inside of the YubiKey and on the server that authenticates the YubiKey is a secret key that uses strong AES 128 encryption to encrypt the message, OTP, that is sent to the server. The encrypted message is encoded in mod-hex (32 characters long) using an alphabet that is common to all keyboards. It actually doesn't use the letters, rather it works at the lowest level using scan codes that are common across all keyboard.
The actual message that is encrypted is broken down as follows:
- Private identity (6 bytes) - Uniquely identifies the YubiKey
- Usage counter - Increments every time the YubiKey is used. Insures every OTP is unique
- Timer field - (24 bits) - Initialized with random number which then counts up using an 8 Hz timer
- Random number (16 bits) - Initizlized with a random number
- Checksum - CRC16 Checksum of all of the fields
All of this information is encrypted to authenticate that you have the encryption key that was used to encrypt the message. The security of the entire system is based on the ability to keep the encryption key private and the inherent security of AES encryption.
What I've Done with my YubiKey
I have left my YubiKey authentication in the hands of Yubico so I am able to log into the Yubico wiki and forums in one click. I have also played with authenticating my own PHP web applications. It is a fairly simple process to run a client authentication on a web server.
Yubico is very open source with their product and provides authentication server and authentication client for many different languages and platforms. This includes my favorite language on the web, PHP. The authentication process is rather simple using the Standalone Yubico PHP class linked to from the Yubico web services clients page on their site.
The amazing part of the system is that you do not need a user name or password to log in if you want to use single factor authentication. It is for sake or argument, impossible for anyone to generate a valid OTP without having my Yubikey or the private encryption key which is kept secret. This means all I have to do to log into my own site is plug my YubiKey into my computer and press the button.
I have only played around with this authentication so far, but will hopefully be adding MediWiki YubiKey authentication to https://www.jaredhatfield.com/ soon.
Another Cool Feature
While the entire point of a YubiKey is to have a one time password, it has another functionality where you can store a static password in the device that it will simply type in on demand. With the added feature of having each YubiKey have two modes that it can operate in depending on how long you press the button (OTP + OTP, OTP + Static, Static + Static) I will be playing with this feature very soon.
This means you do not have to remember a very long password and can simply have a YubiKey type it in for you. This is very useful when you look at having long wireless encryption passwords or passwords used on encrypted drives or file containers.
I will continue to play and post on this topic when I have made more progress.
Thursday, October 23, 2008
My Adventures with Ink
I don't know how I've gone this long without attempting to program applications specifically for Tablet PC's before. It was a strange string of events that resulted in my new obsession.
Last Wednesday I went to WIPTE where I presented my poster on STUG and attended several informational sessions. As a result I missed collecting the DyKnow in class problem for the calculus classes. As a result I was given the files on a standard jump drive. This was nothing too crazy and may not seem related to programming, but everything comes together very quickly.
My job in the calculus class can be divided into two main tasks. First, I provide technical support during class to help the students quickly resolve their problems. The other part of my job is managing the in class problem. This job goes even farther than just collecting and managing in that I am designing a system to make easier for future semesters. Next semester when I'm not there they will likely not have a student willing to write a computer program to solve technical problems as they arise.
The accident that started my new obsession was an unintended right click. I simply right clicked one of these DyKnow files and realized that Al Zip could unzip it. I've looked into parsing DyKnow's file format earlier and ran into, what I assumed was, compression. This confirmed my assumption. After unzipping the file it was revealed that DyKnow simply uses XML to store all of the information. A fairly standard approach for storing files that contain digital ink.
As a result I was able to read the file in using a simple C# program and read in the information that I care about. So far I have not done anything too complicated. One of the biggest problem I was having with DyKnow was not having any ability to export the user names of the students whose panels were collected for the in class problem. I spent almost 20 minutes manually transcribing these names. Now I have a simple program that can extract the tames and I can copy and paste them from my simple GUI.
Here is just a short C# code sample that I use to actually open the DyKnow file:
//Open the file
FileStream input = new FileStream(dyKnowFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
//Uncompress the file
GZipStream gzip = new GZipStream(input, CompressionMode.Decompress, true);
//Read the uncompressed file as XML
XmlTextReader textReader = new XmlTextReader(gzip);
This simply opens the file as a stream, uncompresses the stream, then reads the stream as XML. However, this is only the first half of the story.
I ended up having to do some very simple reverse engineering to understand how DyKnow's file format works. I won't post any of that information in this post, but if I post some more code I will explain the tags that I had to use. After I got past the standard compression it was trivial to understand the data that is being stored.
The part that now has me busy is understanding the ink data that is stored as part of the file. I have learned that ink strokes are stored as base64 strings. This appears to be standard for Microsoft inking applications and I simply need to pass it to the correct methods to display it. I have found some example code but I haven't made much progress yet. It seems that ink applications are still slightly complicated to make.
Wednesday, October 22, 2008
Programming with Ink
I've only recently started programming applications that have a GUI. I've spent most of my time working on the web. However, I have had a recent obsession with programing with Ink on Tablet PC's. It is only logical, I'm already a Tablet PC nut.
At first I found it difficult to get started. I am running Vista Ultimate with Visual Studio 2008 so I expected it to work without any problems. Well, apparently I should have read the fine print when I stumbled across some Digital Ink Sample Programs on Microsoft's website. I have been able to compile these are make some small modifications to them to start to learn about the ink support. Baby steps... compiling examples is a good start.
I have also run across Stefan Wick's Weblog - Development with Silverlight, WPF and Tablet PC. There are a number of very useful code samples posted on his blog that I will definitely be playing with soon. This also raised my interested in programming for the Ink on a Tablet with Silverlight.
While I haven't made much progress making any programs of my own, I have learned that I will be needing to study up on XAML. I realized it was used in making the interface for many Windows applications, but I didn't realize how extensively it was used when dealing with Ink. Basically, you can have an inking application with only XAML code and no actual C# written.
I'm not sure what direction I'm going to take with this new obsession, but the rate at which I've been making progress is exciting. However, I should probably get back to the homework I've been ignoring.
Thursday, August 16, 2007
Egyptian Ratscrew
A while back I programmed the game of War. It was a simple problem to solve. My goal was mainly to see the distribution for number of rounds it took to win a game.
Having mastered that problem (but never really published my results, I'll do that sometime) I moved on to a new challenge. The name of the game is Egyptian Ratscrew. While there are many different variants of this game, I'm focusing on the one I'm familiar with.
The problem with ERS as opposed to war is the choice involved. While War involves no decisions by the player, ERS adds the component of "slapping" the deck. I'll attempt to overcome these difficulties by applying different approaches to the game.
Although I currently have a working prototype of the game, it is not worth publishing anything yet as it is still in the early stages of development.
Sunday, May 13, 2007
Why I Like Facebook
I am in college, and I will admit to obsessing over Facebook just a little too much. I use Firefox (most of the time) to browse the internet, and one of my favorite ad-ons is PermaTabs. PermaTabs basically makes it so a tab will launch when Firefox starts and it is not possible to close the tab. I have three tabs that I always have open: Yahoo! Mail, Digg, and Facebook
All of that is really beside the point. Basically, Facebook is really high on my list of websites that I frequent. I even have wall posts, messages, pokes, and Cassie's status updates sent as text messages to my cell phone.
Personally, I am not a fan of MySpace. This mainly stems form the fact it does not qualify as a Web 2.0 site by my definition. Facebook on the other hand is constantly adding innovative features that keep pushing the social networking envelope. Sadly, these new features anger many members (probably those that like MySpace). Facebook's News Feed was probably the mosts famous of these features (as it made national news) but I now consider (and did when it was released) one of the more useful features the site has ever offered. The second place Facebook riot would probably be when they went public allowing anyone to register, but that was just a step in the sites evolution. Facebook still provides powerful tools to help guard ones privacy.
Finally, the actual reason I like Facebook is because I will one day become a software developer and Facebook seems to have many good practices going for them. Personally, I already have used PHP many times to program simple websites (although none are published). Facebook in their recent post on their blog talked PHP and Facebook. Basically, Facebook is one of the largest users of PHP and they are constantly developing to meet the demands of their large user base. Facebook users are probably some of the most loyal users with many of them visiting every day. (Citation Needed ;) Facebook constantly is contributing to these projects which they actually use in day to day operations.
Personally, I am very happy that companies such as Facebook are contributing back to the open source community that helped them get started. I predict that this cycle will only continue and the free software projects such as PHP will continue to thrive even in the face of competition from monetized alternatives.
Friday, May 11, 2007
Programing: Card Game War (Part 5 of 5)
This is the last post in my first series about the card game of war. I used C++ to implement this game and it is a computer playing itself. The basic concept here is to not determine who the winner is, rather, how many rounds it took to complete the game. My first post was about the RandomGenerator class I used to shuffle the deck of cards. The next class I made was a card class. This class simply represented a single playing card. Obviously, the deck class followed which was used to make an entire deck, shuffle it, then deal it. Lastly, was the war class which actually played the game and could return the number of rounds.
The concept here is to find, if any, mathematical anomalies that appear while playing the game War. These are the minimum and maximum number of tricks along with any trends that involve the frequency of a game ending after a specific number of tricks.
The remaining code calls on all of the previous classes. In my implementation I used header files which each post gives examples of what they should be named. Here is the final portion of code that will play 50,000 games of war.
#include <cstdlib>
#include <iostream>
#include <cstdlib> //Used for rand() & srand()
#include <string>
#include <fstream>
//Used to just make all kinds of crazy random numbers
#include "randomNumbers.h"
//Used to make an individual card object
#include "card.h"
//Used to hold an entire deck of cards
#include "deck.h"
//A game of War
#include "war.h"
using namespace std;
int main()
{
//An array containing the number of hits for each number
int winNumber[10001];
for(int i = 0; i < 10001; i++)
{
winNumber[i] = 0;
}
int max = 0;
int min = 10000;
long total = 0;
int successfulRuns = 0;
int trys = 50000;
int ties = 0;
for(int i = 0; i < trys; i++)
{
//srand(rand());
war myWar;
int rounds = myWar.returnRounds();
winNumber[rounds]++;
if(rounds < 10000)
{
//outFile << rounds <<"\n";
total += rounds;
successfulRuns++;
if(rounds > max)
max = rounds;
if(rounds < min)
min = rounds;
}
else
{
ties++;
}
cout << double(i)/double(trys)*100 << "\r";
}
cout << "100.0" << endl;
//outFile.close();
//Save the distribution of the number of rounds
ofstream outFile1;
outFile1.open("myfile1.txt");
for(int i = 1; i < 10001; i++)
{
outFile1 << winNumber[i] << endl;
}
outFile1.close();
//Save the results of the game
ofstream outFile2;
outFile2.open("myfile2.txt");
outFile2 << "The Number of Games Calculated Is: " << trys << endl;
outFile2 << "The Number of Ties is: " << ties << endl;
outFile2 << "The Maximum Number of Rounds Is: "<< max << endl;
outFile2 << "The Minimum Number of Rounds Is: " << min << endl;
outFile2 << "The # of Total Rounds Is: " << total << endl;
outFile2 << "The Average Number of Rounds Is: " << total/double(successfulRuns) << endl;
//Display the results of the game
cout << "The Number of Games Calculated Is: " << trys << endl;
cout << "The Number of Ties is: " << ties << endl;
cout << "The Maximum Number of Rounds Is: "<< max << endl;
cout << "The Minimum Number of Rounds Is: " << min << endl;
cout << "The # of Total Rounds Is: " << total << endl;
cout << "The Average Number of Rounds Is: " << total/double(successfulRuns) << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
Finally, time for some results. First, to preface all of these results, I do not believe them to be accurate. I am confident that they are in no way comprehensive as I have earlier talked about the number of possible games to be in the order of 52!, a number many magnitudes larger than 50,000. I've already started work on a more accurate and simpler way of playing war, although less like the actual game, more useful for statistical purposes.
My first discovery when I ran the code is that I would run into infinite loops. Basically, I came to the conclusion that a game of war could be a tie based on the fact the players eventually run into a cycle where they end up playing the same hands over and over again.
Here are the results that were returned by my program:
The Number of Games Calculated Is: 50000
The Number of Ties is: 382
The Maximum Number of Rounds Is: 9798
The Minimum Number of Rounds Is: 9
The # of Total Rounds Is: 19431676
The Average Number of Rounds Is: 391.626
I simply put the cap on the game at 10,000 because I was not able to find a game which lasted longer than 9798 rounds. However, this is not to say that a game could last longer than this. I was not able to identify a game which lasted longer than this in my testing.
The horizontal axis is the number of rounds the game took to complete. The vertical axis is the number of times out of 50,000 that the game was competed in that number of rounds.
The above graph is generated form the raw data on the number on the amount of times each game went a certain number of rounds. Notice the dot at 10,000 this is the games that tied or whose number of rounds is greater than 10,000. It is obvious that there is a very sharp spike to the left of the graph. The number of rounds that occurred the most (ignoring the 10,000 maximum) in the data was 61 rounds. A game of War ended after 61 rounds 314 times out of the 50000 games total. That is equal to 0.628% of the time.
The above graph begins to indicate some broader trends but is not percice enough to actually identify them. Lets focus in on only games that took less than 1000 rounds to complete.
The horizontal axis is the number of rounds the game took to complete. The vertical axis is the number of times out of 50,000 that the game was competed in that number of rounds.
The above graph clearly indicates that there are two distinct curves: the first is a lower curve which has more frequency of happening but a wider range, the second is a higher curve which has less frequency, but a much steeper slope.
Another interesting point to note is the fact the shortest game lasted only 9 rounds. This is interesting to point out because it is definitely possible to have even fewer rounds. This only further emphasizes the fact that my data set is not comprehensive.
I would also like to note that in my program the game is played perfectly. That is, no cards are mixed up and a player puts the cards back into his deck in a very predictable manner.
I would like to do further analysis on this data, but it will have to wait. Due to me fears that this algorithm is not accurate, I will post a much more through analysis of the game of War after I rewrite my code from scratch. I expect to publish my new (more through) findings after I complete the code and get some free time to actually think about some of the intricacies of the problem.
Programing: Card Game War (Part 4 of 5)
In my last post in this series I talked about the deck class. This class represented the deck of cards that will be used in the game. It simply served to make all 52 cards, shuffle them, then deal them to each player. This part of the code is the most complex, and before I even post it I would like to state my question about the accuracy of this code.
First off, this is an old piece of code that I mainly just wanted to publish so I putting it out that, basically as is.
This segment of the code implements the actual logic involved in the game of war. Sadly, i think it does not do it accurately. I do know it is not efficient. I am going to post this code in its current state even though I think there is a major logical error somewhere in the game.
Again, here are the header files that were used up to this point.
#include <cstdlib>
#include <iostream>
#include <cstdlib> //Used for rand() & srand()
#include <string>
#include <fstream>
//Used to just make all kinds of crazy random numbers
#include "randomNumbers.h"
//Used to make an individual card object
#include "card.h"
//Used to hold an entire deck of cards
#include "deck.h"
So, here is the code which is stored in the header file war.h
class war
{
private:
card player1[52];
card player2[52];
card buffer1[52];
card buffer2[52];
card playingArea[52];
int indexPlayer1;
int indexPlayer2;
int indexBuffer1;
int indexBuffer2;
int indexPlayingArea;
int rounds;
card getPlayer1Card();
card getPlayer2Card();
void player1WinTrick();
void player2WinTrick();
int playTrick();
public:
war();
int returnRounds();
};
war::war()
{
//Make The Deck Shuffle The Cards
deck myDeck;
myDeck.shuffleCards();
//Set Some Default Values
indexPlayer1 = 52/2 - 1;
indexPlayer2 = 52/2 - 1;
indexBuffer1 = 0;
indexBuffer2 = 0;
indexPlayingArea = 0;
//Deal out a deck
for(int i = 0; i < 52/2; i++)
{
player1[i] = myDeck.dealCard();
player2[i] = myDeck.dealCard();
}
int winner;
int i = 0;
bool loop = true;
while(loop)
{
winner = playTrick();
if(winner == 1)
{
player1WinTrick();
}
else if(winner == 2)
{
player2WinTrick();
}
if(indexPlayer1 <= 0 && indexBuffer1 <= 0)
{
loop = false;
}
if(indexPlayer2 <= 0 && indexBuffer2 <= 0)
{
loop = false;
}
i++;
//Give up on round 10,000 - declare tie!
if(i == 10000)
{
loop = false;
}
}
rounds = i;
}
int war::returnRounds()
{
return rounds;
}
void war::player1WinTrick()
{
card nullCard;
for(int i = 0; i < indexPlayingArea; i++)
{
buffer1[indexBuffer1] = playingArea[i];
indexBuffer1++;
playingArea[i] = nullCard;
}
indexPlayingArea = 0;
}
void war::player2WinTrick()
{
card nullCard;
for(int i = 0; i < indexPlayingArea; i++)
{
buffer2[indexBuffer2] = playingArea[i];
indexBuffer2++;
playingArea[i] = nullCard;
}
indexPlayingArea = 0;
}
int war::playTrick()
{
card nullCard;
//Get Player 1's Card
card player1Card = getPlayer1Card();
//Get Player 2's Card
card player2Card = getPlayer2Card();
//Player 1 Wins The Trick
if( player1Card.getCardValue() > player2Card.getCardValue() )
{
//Put the two cards in the hand
playingArea[indexPlayingArea++] = player1Card;
playingArea[indexPlayingArea++] = player2Card;
return 1;
}
//Player 2 Wins The Trick
else if( player1Card.getCardValue() < player2Card.getCardValue() )
{
//Put the two cards in the hand
playingArea[indexPlayingArea++] = player2Card;
playingArea[indexPlayingArea++] = player1Card;
return 2;
}
//Tie Game and add 3 to the pile and play another trick
else
{
//Put the two cards in the hand
playingArea[indexPlayingArea++] = player1Card;
playingArea[indexPlayingArea++] = player2Card;
// W
player1Card = getPlayer1Card();
player2Card = getPlayer2Card();
playingArea[indexPlayingArea++] = player1Card;
playingArea[indexPlayingArea++] = player2Card;
// A
player1Card = getPlayer1Card();
player2Card = getPlayer2Card();
playingArea[indexPlayingArea++] = player1Card;
playingArea[indexPlayingArea++] = player2Card;
// R
player1Card = getPlayer1Card();
player2Card = getPlayer2Card();
playingArea[indexPlayingArea++] = player1Card;
playingArea[indexPlayingArea++] = player2Card;
// WAR
return playTrick();
}
}
card war::getPlayer1Card()
{
card nullCard;
//There are cards left in the deck and then deal a card
if(indexPlayer1 >= 0)
{
card player1Card = player1[indexPlayer1];
player1[indexPlayer1] = nullCard;
indexPlayer1--;
return player1Card;
}
//Player 1 Has No Cards Left In hand therefore needs to move buffer to hand
else
{
//If Cards Are In The Buffer
if(indexBuffer1 > 0)
{
for(int i = 0; i < indexBuffer1; i++)
{
player1[++indexPlayer1] = buffer1[i];
buffer1[i] = nullCard;
}
indexBuffer1 = 0;
return getPlayer1Card();
}
else
{
return nullCard;
}
}
}
card war::getPlayer2Card()
{
card nullCard;
//There are cards left in the deck and then deal a card
if(indexPlayer2 >= 0)
{
card player2Card = player2[indexPlayer2];
player2[indexPlayer2] = nullCard;
indexPlayer2--;
return player2Card;
}
//Player 1 Has No Cards Left In hand therefore needs to move buffer to hand
else
{
//If Cards Are In The Buffer
if(indexBuffer2 > 0)
{
for(int i = 0; i < indexBuffer2; i++)
{
player2[++indexPlayer2] = buffer2[i];
buffer2[i] = nullCard;
}
indexBuffer2 = 0;
return getPlayer2Card();
}
else
{
return nullCard;
}
}
}
First off, the actual implementation of the game is awful, primarily because of the coding practices. It is difficult to follow the code, I will admit. However, I'll explain some of the basics so at least it is a little understandable.
First off, when the constructor is called, it is passed no parameters. The constructor actually plays through all of the rounds of the game and the results can then be accessed. There is only one public method named returnRounds() which if you haven't already guessed returns the number of rounds that it took to complete the game. That is the main focus of this entire project.
The actual logic of the code involves several complex (and inefficient) interactions of arrays which very accurately mimic how the game would be played in real life. Again, program efficiency was sacrificed for realism to how the game is played.
My last post in this series will be the actual main class that creates an instance of the war class and gets some results out of this program. I'll be looking for any pattern that arise from this implementation of the game.
Sunday, May 6, 2007
Programing: Card Game War (Part 3 of 5)
In my last post in the series I published the card class. This class will now be used in the deck class. Additionally, this class also uses the random class which was part of my first post of this series.
As before, I am going to post the header files used used in all of the classes. However, this time I will include the header files that include the randomNumber.h and card.h files.
#include <cstdlib>
#include <iostream>
#include <cstdlib> //Used for rand() & srand()
#include <string>
#include <fstream>
//Used to just make all kinds of crazy random numbers
#include "randomNumbers.h"
//Used to make an individual card object
#include "card.h"
The deck class is actually a very simple class. It serves two purposes. First, it creates an entire deck of cards using the card class. The other main purpose is to actually shuffle the cards. I would like to emphasize the real lack of thoroughness by using this shuffle method. More about the later. Here is the code, but remember this code requires the RandomGenerator and card class.
class deck
{
private:
card myCard[52];
int cardPosition;
RandomGenerator number;
public:
deck();
void resetDeck();
void printCard(int);
void printDeck();
void shuffleCards();
card dealCard();
};
deck::deck()
{
resetDeck();
}
void deck::resetDeck()
{
cardPosition = 0;
for(int i = 0; i < 52; i++)
{
card newCard(i);
myCard[i] = newCard;
}
}
void deck::printCard(int myIndex)
{
(myCard[myIndex]).printCard();
cout << " ";
}
void deck::printDeck()
{
for(int i = 0; i < 52; i++)
printCard(i);
}
void deck::shuffleCards()
{
//Cycles through entire deck
for (int i = cardPosition; i < 52; i++)
{
//Picks a random card
int r = number.cardIndex();
card temp = (myCard[i]);
//Swaps the cards
myCard[i] = myCard[r];
myCard[r] = temp;
}
}
card deck::dealCard()
{
//Deck is dealt from 0 to 51
if(cardPosition < 52)
{
return myCard[cardPosition++];
}
else
{
//return NULL;
}
}
Looking at this code, it becomes obvious that there are quite a few ways to arrange a deck of playing cards. I believe it is equal to 52! which is a huge number. I had to look it up on a table and found it to be equal to 8065817517094387857166063685640376
6975289505440883277824000000000000 (that is all one number, I just split it in half so it would mess with my blog's formatting.) Not to be totally obvious, but I'm not going to run this many test to see what the results to every possible game of war is (not yet at least, or with this type of implementation).
For my purposes, I'm just going to run a very small sample of games. The code I currently have is not able to predetermine a deck of cards. A future version might, but that would require indexing all the possible combinations and 52! is a ton of possible combinations and indexes. I'll leave that headache for another day. If I experiment with having all possible combinations of War played out, it would most likely be with a smaller deck before I moved up to such large numbers. I can only imagine how long these computations would take.
To above code is very simple. It simply serves to make a deck of cards. Then the cards will be shuffled. Then the cards will be dealt out. This is all the above deck is used for, nothing else. Once the deck is dealt out, it will no longer be used. The cards will be tracked using the code that will be part of my next post.
Programing: Card Game War (Part 2 of 5)

In my last post about this subject I talked about some of the basic concepts and posted the code for the random number generating class. Programing: Card Game War (Part 1 of 5)
This program was implemented using C++ and was designed around a very object oriented design. So much so, that many of the methods available in the classes are never used. In this section of the series I am going to post the class that implements a single card in a deck of cards. Obviously, this is the most basic element needed in having a deck of cards that will be used for a game.
A card has several features that need to be stored in order for it to have all the features of a normal playing card. These include its suit and its face value. Not to be over obvious, but there are four suits and thirteen different cards for each suit. Also, for the purposes of War each card needs a numerical value. The numerical value will be the number for the numbered cards and then for the face cards it will be 11 for J, 12 for Q, 13 for K, and 14 for A. This way the winner of each trick can be determined by comparing these numerical values. In my implementation suit does not matter (although it can be played this way to break ties, but the winner would always be the person with the ace of spades). Additionally, each card has an index between 0 and 51 used to create the card.
The features of this class should become evident upon looking at the source code. In my later construction of the game of war, many of these methods go unused, but could be used to display the games progress. In my implementation, I am mostly concerned about the number of rounds the game was completed in and if the game was a tie, but more on this later.
As stated in my earlier post I implemented this code using multiple files. Here are the headers which I used for all of my code.
#include <cstdlib>
#include <iostream>
#include <cstdlib> //Used for rand() & srand()
#include <string>
#include <fstream>
This class is stored in the header file card.h
using namespace std;
class card
{
private:
string suit;
char shortSuit;
string face;
char shortFace;
int index;
int cardValue;
string color;
void setSuit();
void setFace();
public:
card();
card(int);
int getIndex();
int getCardValue();
string getSuit();
string getFace();
char getShortSuit();
char getShortFace();
void printCardName();
void printCard();
};
card::card()
{
//VOID CONSTRUCTOR
index = -1;
}
card::card(int myIndex)
{
index = myIndex;
setSuit();
setFace();
}
int card::getIndex()
{
return index;
}
int card::getCardValue()
{
return cardValue;
}
void card::setSuit()
{
if(index >= 0 && index <= 12)
{
suit = "Spades";
shortSuit = 6;
color = "Black";
}
else if(index >= 13 && index <= 25)
{
suit = "Diamonds";
shortSuit = 4;
color = "Red";
}
else if(index >= 26 && index <= 38)
{
suit = "Clubs";
shortSuit = 5;
color = "Black";
}
else if(index >= 39 && index <= 51)
{
suit = "Hearts";
shortSuit = 3;
color = "Red";
}
}
void card::setFace()
{
int tempCard = (index+1)%13;
switch(tempCard)
{
case 1:
face = "Ace";
shortFace = 'A';
cardValue = 14;
break;
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
face = (tempCard + int('0'));
shortFace = face[0];
cardValue = tempCard;
break;
case 10:
face = "10";
shortFace = 'T';
cardValue = 10;
break;
case 11:
face = "Jack";
shortFace = 'J';
cardValue = 11;
break;
case 12:
face = "Queen";
shortFace = 'Q';
cardValue = 12;
break;
case 0:
//This is case 0 & not 13 because 13%13 = 0
face = "King";
shortFace = 'K';
cardValue = 13;
break;
default:
face = "Invalid";
shortFace = 'I';
cardValue = -1;
break;
}
}
string card::getSuit()
{
return suit;
}
string card::getFace()
{
return face;
}
char card::getShortSuit()
{
return shortSuit;
}
char card::getShortFace()
{
return shortFace;
}
void card::printCardName()
{
cout << "The " << getFace() << " of " << getSuit() << endl;
}
void card::printCard()
{
cout << shortFace << shortSuit;
}
Now, I'll explain some basics about the code. The constructor of this class requires a number between 0 and 51 to actually construct a playing card. This is the card's index. If the default constructor is used then the card's index will be -1 or the card will be the equivalent to a blank card or an empty spot.
This card class simply serves as the basis of a form of realism. This class could easily be replaced with an array of numbers containing the numbers 1 through 13 four times. This would be a more efficient implementation, but the realism of having a deck of cards would not be there. I may eventually use a more efficient method of playing war, but for this first series of posts, I am publishing the code I already have.









