Thursday, May 31, 2007

Java: Hotline

From time to time in the call center at work we track the types of incoming calls to determine what new information we need to be providing on our website and marketing material. In the past we've used sheets of paper and placed tick marks under headings to record this information. Then the marks are tallied up at the end of the month for reporting purposes. Obviously a very manual and time intensive process, but since it is done only one month at a time not a massive issue. However now we want to track a bit more consistently so a better process is needed.

And so Hotline was born. It is designed to be very user friendly and also extremely quick to utilize, as the call representatives don't have a lot of time to be entering any notes into the system in between calls. So this is a very high level tracking system to get a general feel for what types of calls are inbound. There are two parts to the system; the call tracking side and the reporting side. The call tracking side is simply a series of buttons, one for each possible call type. When a button is pressed a pop-up message appears confirming this fact, acting as a deterrent to any accidental double-clicking as only one option should be selected per call. This will then update a text file saved on the server named according to the value in the Representative JComboBox.

The reporting side of the system was a bit more difficult to setup. The information is saved in text files as strings, so updating the information due to an incoming call relies heavily on converting part of these strings to an integer, increasing the number then converting it back to a string to insert back into the text file. For a report run on a particular representative the process is straightforward. The month selected in the JComboBoxes is located and the particular representative's file in this location is opened and its text dumped into the JTextArea.

A report run containing information for all of the representatives is a bit more involved. Each representative's file is opened individually and the values for the number of calls taken are saved into an array of strings. This string array is then converted to an integer array. The process is then repeated for each representative's file and the new call value added to the current one in the integer array. Eventually all of the information is compiled. Then the array of integers is converted back into an array of strings and these strings appended together to create the output report in the JTextArea.

Originally I was going to make the reporting call a JMenuItem instead of its own JTabbedPane, however that was becoming a bit too cumbersome. Any changes needed in the future would be more difficult with all of the reporting code in the same java file as the button panel code. So they were split apart into separate JTabbedPanes for my peace of mind. Also, some of the values are hard coded into the program, specifically the representative's names and the month/year values. Any changes that are made would require the entire program to be compiled again and a replacement executable generated. Eventually I may make these values editable by anyone, but for now the program is ready to be pushed out to the call center.

Friday, May 25, 2007

Java: CME Log Date Decoder

At work we recently, as in the past two years, updated our CD-ROM application from being a 16-bit Toolbook program to purely Java based. Along with this massive change many features were updated and revised. One such feature is the CME (Continuing Medical Education) credit tracking system. Before the update, CME was tracked in a text file on the hard drive by date. Each article viewed in the program would have it's own line in this text file and a Gregorian date would be prominently displayed for that article.

Now with the upgrade to Java things have changed. No longer is a date available to the naked eye when reviewing the logs. While each article still does have a date attached, this date is in milliseconds. And to make things slightly more complicated these are milliseconds since January 1st, 1970. Why that date was chosen I do not know.

So for our Customer Service department this poses a bit of a dilemma. They are charged with receiving these CME logs in paper format and having to determine what date to assign the CME credit. Only recently has this problem come to light, and to combat it I created a small program to automatically calculate the Gregorian date from the given millisecond variable.

The CME Log Date Decoder program is a modified version of the Password of the Day program. It will take as input the time in milliseconds, which will be a string variable as far as the program is concerned. This variable first needs to be saved into an array of strings, one bucket for each character, then converted into an array of integers. As integers each array bucket is put through an algorithm and then summed together and added to a Calendar date of 1/1/1970 in order to obtain the correct CME log date in Gregorian format. This is then displayed to the user. The program requires almost zero memory so the calculations take less than a second to perform.

Thursday, April 26, 2007

Java: En Guard Update #2

I didn't expect to be making another post about En Guard this quickly, however I ended up having some free time yesterday afternoon to work on the one remaining bug in the program. The bug in question being the fact that the word wrapping was occurring by character and not by entire words, so it was difficult to read at times. My thought process for solving this problem was simple, yet not quite as simple as the final solution. I assumed that the reason the wrapping was occurring by character was because I was saving the file's text to a StringBuffer one character at a time. So I created a new StringBuffer, nextWord, where I saved all the characters of one work and then added this variable to the final StringBuffer as a word block. The below code was written to carry out this experiment.

while ( (c=myFile.read()) != -1 ) {
if (c != 32)
nextWord.append((char)c);

else{
textToDisplay.append(nextWord);
nextWord.delete(0, nextWord.length());
textToDisplay.append((char)c); }

}
textToDisplay.append(nextWord);

This code block replaced the original single line piece of code, which is colored above as it did remain in the block as well. For this code C is a char variable that as long as there are characters in the associated file then the loop is performed. A space character in this example is equal to 32 before it is converted to a char value, which is where the first part of the If statement comes from.

Once this code was written it was tested and lo and behold the same problem occurs. So I looked into the java API at the setLineWrap method and found that visible at the bottom of the page was a method named setWrapStyleWord. I was intrigued and once I looked into the method found that this was what I was looking for. Applying this method to both JTextAreas so that it was set to True solved my word wrapping problems. This resolved all of the outstanding issues with the En Guard Call Tracking System. I do have it in my mind to perhaps make the Platform and Entered By drop down menus alterable by the user as right now the lists are hard coded into the program. But that is for later, for now this program is considered completed for our work environment.

Wednesday, April 25, 2007

Java: En Guard update

The En Guard Call Tracking System had a few known bugs that we were living with for the past few months until I could find time to correct them. Specifically a record could be overwritten without any prompt and the old information lost. Also when a new record was saved the default text from the top field was added to the record on occasion. Solving the second problem was the easier of the two. At the end of the constructor the New() method was called, the one used when the Reset button is pressed. This seemed to resolve the problem as it was only happening on the very first record entered after En Guard was opened. After some testing it was found that if the Reset button was pressed after opening En Guard the issue would not arise, so this is now done automatically when En Guard is initialized.

The second issue was a little more serious, but still not too difficult. There is a test when saving that checks if the file already exists so that the old information can be inserted before the new call information. Using that check I wrote a boolean If statement that would cancel the save attempt and post an error message. This would happen only if both the file already existed and the text in the Current Record JTextArea field was still the default text instead of the output from the existing file. The user would be prompted to open the old record and copy the last call's data into the Additional Information field before saving the record.

Now the next bug to fix is the word wrapping for the JTextArea fields. Currently any text will wrap, but it does so in a way that leaves part of a word on one line and continues it on the next. It wraps separate characters instead of the entire word and I think I'll need to completely rewrite that part of the program to correct this issue.

Tuesday, April 24, 2007

Java: IP Analyzer

In my current position at work I help with some of our institutional customers who access our online application. In order to verify that a customer should have access we obtain their external IPs and keep them on file. The IPs used must be unique to the institution in question and cannot be gateways for location areas larger than what is on the contract. Unfortunately what happens is that we are given IP lists that are gateways by accident and since we aren't aware of this fact those IPs become active. Eventually we come to realize what happened and obtain a correct IP list from the customer.

Our problem comes from the fact that sometimes we are given the same gateway IPs from different customers and each time we go through the same difficulty when the IPs are activated. To avoid this a Microsoft Excel spreadsheet was created that listed all of the IPs we know to be gateway IPs and before we add anything to an account they are compared to this list. Unfortunately this list is rather cumbersome so I developed a java program that would do the same thing but be easy enough for the account managers to utilize without problem.

Like all of my current programs this one is fairly basic in setup, but then again it has a simple function and therefore does not need to be more intricate anyway. The program accesses a text file on the hard drive that lists all of the IPs on the "restricted" list and this can either be added to or searched on to see if a particular IP or IP range appears on this list. When adding an IP to the list the input from the user is simply append to the end of the text document. Searching on this for a comparison is a little more difficult. The current list of "restricted" IPs are converted into an array of single IPs. Then the IP given by the user to search with is also converted into an array of IPs. Once these two steps are completed the arrays are compared and if any of the IPs are found to be present in both arrays an error message is displayed to the user with the IP in question displayed.

Obviously this is a brute strength approach to comparing the IPs and as a result has its problems. First, any IP ranges of Class B or A cannot be used as they crash the program due to the memory requirements. Thankfully this does not come up often and therefore hasn't been encountered yet. However I'd like to add internal IP ranges to this program as part of the "restricted" list but I can't do this as 10.*.*.* is internal and would crash the program every time. Secondly, IPs must be entered in an exact format or they will not be recognized by the program and the comparison will not function correctly. IPs must be entered in the four octet format with no spaces and a dash between the start and end of the IP range, such as 52.52.52.52-52.52.52.178.

Overall the program works quite well for the purpose intended. If the document containing the "restricted" list was something other than a text file, such as a database or spreadsheet, then the searching algorithm may not be quite as memory intensive. However for the purpose intended such a change is not worth the effort.

Tuesday, April 17, 2007

Java: En Guard Call Tracker

I haven’t been able to create any personal projects for java programming recently but thankfully the workplace creates them for me. One thing our technical support department has always lacked is the ability to keep track of what each call was about so that if that customer calls back we don’t have to recreate the wheel. I do know that my company is working on purchasing just such a program but that will be at least a year in the future. So recently I created a poor man’s call tracking system for only our technical support group and not the entire call center in general.

I named the program En Guard as I was playing with the GoldIcon program to create icons and one of the ones I liked best was a shield with swords on it, rather medieval looking. It sounds much better than the original name of “Technical Support Call Tracking System”. This program will save all call information into a text document, Microsoft Word, with the documents organized by subscriber number and saved into a central location on our network. The call information itself that is asked for is very basic: name, subscriber number, contact information, representative and product version. Beyond that the topic of the call is recorded and entered before the record itself is created and saved.

This program went through several versions before a working one was produced. The most difficulty part was getting the program to read a file already on the network and save any updates accordingly back into the same file. Thankfully something similar was done with the AMAS program so as in that program a FileWriter/Reader was created. The entire program consists of two files; one for the main window with the buttons at the bottom and the other for the panel containing the variable information. Each document is setup the same way with the variable information at top followed by the contents of the call. So the FileReader reads and erases the customer information one piece at a time to fill in those fields then takes the rest and places it into the “Current Record” field. In order for this to work the spacing of the information had to be hard coded into the system, which wasn’t the most elegant way but is effective. The Platform and Entered By fields are also hard coded into the program, so if this were to be altered for someone else’s use the basic code would need to be altered.

With this program, unlike the other ones, I was able to obtain some feedback from my colleagues to make it more user friendly. The suggestions taken were setting the JTextArea fields to accept word wrapping, automatically adding the current date to the record, adding a separator between record entries rather than a simple newline character and last but not least a skin chooser. The skin chooser was more of a joke one of my colleagues threw out at me as he didn’t like the color I had picked, light goldenrod. But I took it as a challenge and it turned out to not be as hard as originally expected. Making sure I caught all of the setBackground calls in the skin chooser method was a bit tough, but perhaps that was more because I was trying to do it manually since the entire program is about six hundred lines of code. In order to change the program’s skin I did have to ask for the RGB values, which of course no one knows off the top of their heads.

Overall not the most difficult program I’ve created however it has been very useful in the workplace, being used several times a day. Some updates do need to be made, specifically that a skin can be used that obscures the JLabels as they are defaulted to black, a record can be overwritten without prompting the user if that is really what they want to do and the Platform and Entered By fields don’t need to be hard coded. I’ll get to all of these in the future, but for not the program is working quite well for our limited needs.

Monday, April 16, 2007

PC Games: Civilization: Call To Power

Civilization: Call To Power (CCTP) is one of those games I’ve had for quite a while but never played until now. I’ve have both the original version and Civilization II and played both quite a bit. CCTP is supposed to be an upgrade to Civ II but also an independent game, not an expansion pack or add-on.

In terms of general game play, not much has changed for CCTP. You are still expected to build cities, explore the planet, perform research and war with your neighbors in the pursuit of a final objective. That said many of the details did change significantly. The research was reorganized with new names and more options. As a result it takes longer to finish research, but not to worry as the final date for game play is 3000 AD, instead of 2100 AD. Hand in hand with more research is more buildings and items being available, which is my first issue with the game.

There are an absolutely ridiculous number of units available overall. They range from the traditional Settlers and Legions to the new Slavers and War Walkers. As time progresses the player must replace old units with new and as this happens quite a few times the player finds themselves constantly replacing units. Not only that but some units are stealthy and therefore traditional units can’t see them. So to combat these units and their attacks the defender must also build these same units. A player will find themselves with at least one unit, if not more, per city with the sole purpose of thwarting a specific non-military attack. Since all units now require upkeep in terms of gold this can get expensive.

Along with more units there are also more buildings. All of the traditional buildings are still in place and performing the same function, such as factories and granaries, with the additional buildings mostly giving the same effects as traditional ones. For example the Temple provides happiness to the population, and now there is a Theatre that does the same thing. This allows each city, which can get far larger than in Civ II, to exponentially increase their productivity, scientific output, gold or happiness. This leads us to a feature that makes life far easier. The larger the empire becomes the harder it is for the player to manage what each city should build. Enter the Build Queue, a very helpful feature. Instead of setting building orders one at a time, several units and/or buildings can be placed in a queue at once. Then the player need only manage a city if something happens, such as a riot or military attack, until everything is built. This saves a great deal of time and confusion for the player and was sorely missed in Civ II.

The military side of the game was also altered significantly. Before in Civ II units could stack in one space but only attack one at a time. So when attacking a city it was traditional to hold 40+ items, for example Howitzers, in place before assaulting a few enemy cities. When completed units would be scattered all over the map, some stacked and some not. This left them open to retaliation as when attacked only one item would defend for the entire stack, if it loses the battle then all units on the tile are lost. Now the battle system allows units to attack as a full stack of up to nine units. With this setup the ranged units are in back and the melee units up front. Each side takes turns until one or the other is eliminated.

As a result tactics comes into play quite a bit as the more powerful units may not win if they don’t attack in the correct combination. However this same battle system has a downside in that one side could be completely outclassing their opponent and still lose. For example in this picture I had Musketeers and Cannons and was attacking a group of Samurai and Phalanxes. I had ranged units as well as superior defensive units and should have massacred my opponent. That didn’t happen; in fact I lost badly in several reruns. Obviously the battle system is not true to real life in any sense, so care must be taken when engaging in combat. I’ve taken to bombarding my opponent for several rounds before attacking a city, this basically eliminates any resistance. As a side effect it does reduce the population and eliminate some buildings but it’s a price I’m willing to pay to avoid losing stacks of units.

A few other small changes are that after a battle the winner, if offense, moves to claim the tile where the defender had stood. Before in Civ II the attacker remained where they were once a battle was completed. This helps when attacking cities as now a second stack of units isn’t necessary to claim each city. Partisans were also removed from the game. This I definitely like as it was extremely annoying to conquer a city, then find yourself surrounded by a dozen partisan units. They weren’t strong enough to save the city, only extend the time it took to move on to the next city. Also there was an introduction of sea and space colonies so the entire map can be covered with cities leading to enormous empire populations, such as the nine billion I had in my first game.

Overall the game is quite enjoyable; however a few issues do remain which is why I see it wasn’t quite as popular as the other Civilization games, such as Civilization III that came out later. It almost appears as if the developers had all these great ideas and tried to cram all of them into one game, even though doing so took away from some of these same ideas. Space and sea colonies are excellent, but together with the huge amount of units and buildings takes away a bit from the general game play. The player feels more like an accountant than a gamer at times, especially near the end when the empires can be vast in size. The building queue and other such features help manage the empire and they do a decent job, and while the game is quite good, it could have been even better.