Tuesday, June 29, 2010

Week Five Report

I started this week by rewriting the function that checks if the media images exist on the server. Instead of having it open a connection to the server every time it needs to see if an image exists, the client now checks the text file stored on the server called media-new, which contains a list of all the images on there. So it was simple enough to have it create an array of the list and check against that array. It's now a lot faster than it was.

After that was done, I worked on reskinning the client based on the layout I had made. There's really not much to say in terms of bugs and whatnot, since the whole process is basically exporting bits and pieces of the layout composition and coding each piece with certain css properties. What consumes the most time is getting those css properties to work the way they're supposed to.

This is what it looks like:
 

I actually moved the menu and messages dialog to the left, to uniform the whole thing a bit. They're expandable when you click their names, which is a fun effect.


I ended up redoing the css properties for all the windows in the client, such as the info panel and system panel. In fact, I combined the orders panel with the info panel and made it pop up when an icon on the map or system panel is clicked.

While getting the css to conform the way it was supposed was time consuming, the most difficult part was probably implementing a custom scroll bar to the panels, since the regular one looks out of place. However, with the current JQuery lib being used, it turned out a bit difficult to implement a custom one, so I included a plugin scrollbar class to the javascript lib.

It appears that next week I'm supposed to do the rollover object information panel. I'm not sure I want to implement this now that there's the clickable information panel, so we'll see what happens. I have to think about it. I might work on the design window instead.

Tuesday, June 22, 2010

Week Four Report

The first main thing I worked on this week was, of course, modifying TP Web. It was a bit weird this time in that I've known what exactly I need to fix because the bugs would present themselves one by one. But since this week was the start of implementing changes rather than fixing bugs, it was a bit disconcerting as to where I should start.

However, that unease was shortly lived, and I fell back into things soon after. I started with turning the static object types mentioned in the code (Ship, Planet, Galaxy) into a more dynamic list presented by the server. This began with modifying the backend python code because the function that constructs the JSON object data had a reference to this static object type list. However, the static object types were not as deeply ingrained in the backend code as they were in the frontend javascript code, so it was actually a simple modification.

I began working on the frontend code, and I believe the process, while somewhat more intensive, wasn't all that more difficult either. It was mostly just switching from reliance on a static object type array to using the object type name that gets sent in the JSON stream. However, this led to the realization that I would have to work on the dynamic media goal concurrently. Something to do with the css code needing it but I don't remember the specific reason.

Thus, I also went into the code to enable it to take the urls sent in the json stream and use those for icons and media images. What was difficult about this was that the image urls do not come with a image type attached to them, like png or gif. If it had, I could have just had the code in the frontend post the links as if they were images. Since that is not the case, I had to have the python backend go through each image link and test if it's a png. If that fails, it then tests if the image is a gif. This slows the code down a lot, and will need to be fixed later to find a more elegant solution, because it's really annoying.

When I had implemented this, I discovered that some image links that come from the server are not actually there. Llnz knows about this apparently, and I'm supposed to tell Mithro what images are not up there. But I haven't been on linux for the past couple of days, so never had them with me. Basically it's the universe/galaxy icons that are missing.

I actually managed to get those two goals done fairly quickly, so I worked on a reskin of the game. As it currently is, it looks a bit bland, not to do discredit to Tote or anything. So I spent the long weekend finalizing the redesign I've been working on since the start of GSOC. Unfortunately, any design thing I undertake tends to devour all my time and attention. I didn't think to save any in-progress shots, but here's the comparison between the current look of TP Web and the new design I plan to implement. There are still several things to address, such as the icon and the clicking menu, but I think I like the overall look.



With that, two goals are checked off. I'm a bit more ahead of schedule, but that will allow me to implement my reskin. Next week I'll work on putting the messages into a battle style format and implementing the redesign.

May 31th: Upgrade to TP04 Standard

June 7th: Upgrade to TP04 Standard
June 14th: Implement Multiple Queues
June 21st: Dynamic Object Type Support
June 28th: Dynamic Media Support


July 5th: Messages to BattleLog + Redesign
July 12th: Rollover Object Information Panel
July 19th: Display Trajectory of Objects
July 26th: Move Orders to Info Panel. Subsequent menus implement

August 2nd: Right-click Menu for Orders
August 9th : Build Commands Issuable through Right-Click
August 16th : Bug Hunting

Tuesday, June 15, 2010

Week Three Report - On Track + Some Extra

This blog post signifies that I am back on track with the schedule I created at the onset of working on tpweb. What I've been working on is both fixing the cache issue that was delaying my progress by days, as well as implementing multiple queue support for the program.

The way the cache is supposed to work is that its data is pickled between load and save commands, and this allows for data perpetuity. However, tp04 broke this functionality, and since it was not going to be worked on for a while, the cache had to be dealt with differently. One thing I tried was to store the cache into a global variable, but for some reason, it created thread instability when an order was submitted. The error looks like this:

File "libtpclient-py/tp/client/threadcheck.py", line 6, in thread_check_callable
    assert self._thread is threading.currentThread(), "%s can only be called by %s not %s" % (func, self._thread, threading.currentThread())

AssertionError:  can only be called by <_DummyThread(Dummy-3, started daemon -1250780304)> not <_DummyThread(Dummy-2, started daemon -1242387600)>

I tried asking people in the irc channel, but mithro's been busy and the others haven't run into this problem. The ultimate solution I arrived at, much to my disdain, was to have the cache update before each order is submitted, so that the right thread is chosen. The problem with this is, while it works over a localhost, it will create lag issues when the client is transmitting to a remote server. I'll have to go back and remedy this once I find out how to deal with this threading issue.

While I was working on this, I figured it would be best to work on the multiple queue order functionality as well. Before my acquisition of the project, tpweb only allowed one order to be maintained by an object, but the tp04 standard opened up this capability.

I attempted to have the backend submit the order id in an order queue to the frontend javascript, so that modification to both frontend and backend code sets would be minimal. However, apparently, every time the cache is updated, the order ids are changed, so that by the time a send_order command would finish, the get_orders command would already have a new order id set associated with the current orders for an object. This meant that order ids could not be passed between backend and frontend, because they would become antiquated too rapidly.

What this meant was to have both ends of code communicate these order ids based on their position in the order queue. So that if there is a Move command, followed by a Wait command, their ids would be id 0 and id 1 subsequently.

The backend accepted this structural change without much hassle, but the javascript side was less willing to accept change. For some reason, when the data gets passed between python and javascript through the json bridge, the queue order does not necessarily stay in its order. And if the javascript has a different order for the order queues, then it can't communicate with the python end. And this broke the code for a time. However, eventually I got the javascript to adhere to the order by sorting the array of orders before use, and everything become good.

The surprising thing by the end of all this was, though I should have been just caught up, according to the schedule, I'm now a week ahead. I suppose I might have overestimated the difficulty of dealing with multiple queues, but that grace was paid for by the toil of the past three weeks in dealing with just one order in queue. Since I went a bit out of order from the schedule, here's a updated terse version.

May 31th: Upgrade to TP04 Standard

June 7th: Upgrade to TP04 Standard
June 14th: Implement Multiple Queues
June 21st: Dynamic Object Type Support
June 28th: Dynamic Media Support

July 5th: Messages to BattleLog
July 12th: Rollover Object Information Panel
July 19th: Display Trajectory of Objects
July 26th: Move Orders to Info Panel. Subsequent menus implement

August 2nd: Right-click Menu for Orders
August 9th : Build Commands Issuable through Right-Click
August 16th : Bug Hunting

So yeah, on to dealing with dynamic object support and media display for objects. Essentially, I will be stripping any code that makes indication to any specific object types (such as Ship, Galaxy) and have the code construct its types based on what is sent from the server. I'll probably have to deal with the media support issues as well, so the next two weeks will be again switching between both issues.

Sunday, June 13, 2010

Week Two + Some Extra Report

Bah, so plans never go as planned. This is not the "milestone overcome" sort of post it's supposed to be, but it does tie in with what I'm supposed to do next. And it was getting absurdly overdue.

This last week plus a couple days, I've been focused on fixing the final issues with tpweb so that it could support the tp04 standard. This last "issue", which immenesified the further I attempted to eradicate it, was the order manipulation functionality. As one issue was solved, so another took its place, and the amount of code rewriting that I've done is abundant. However, here are some of the issues that have since impeded me.

Figuring out how the order structure changed was very difficult as I don't know anywhere that listed specifically the new structures, such as submitting a position change order. The nesting seems to have changed, and I'm not sure what the reasoning behind it was. For example, a move order looks like this: [[[0,0,0]]]. Another weird thing is that the code submits dummy orders and then updates those orders once the player has decided on the specifics. The apparent problem with this is if they submit a dummy order and their turn ends before specifying those details, the order is a waste. Another change to the data structure, which took a lot of time and figuring to get correct was the build order, which changed the inner most container to a tuple. It looks like this:
[0, 10, -1, 2, 0, [], [[(1, u'Scout', 100), (2, u'Frigate', 100), (3, u'Battleship', 100)], [[1, 1]]], [0,"A Fleet"]] Null_000 was very helpful in helping me out, and now that I have internet at home, maybe my time can be spent on actual programming and not research.

The cache has been giving me problems again as well since it was converted to a variable that remains in memory as opposed to storing it in a pickled file. There's some sort of issue that's arising between calls to the python backend.

Since the orders have been separated from the objects in cache, it uses a separate id to point to an object's order queue. Both the javascript and python sides had to be thus changed in order to handle this, and it took some effort to harmonize the two coding sets.

In terms of progress, the basic functionality for dealing with orders has been fixed. Again, I'm still having an issue with the cache (something to do with the incompatibility between threads), but it appears that orders can now be sent, updated, and removed. In order to continue working on this cache issue, as well as make some progress on my milestone goals, I'm going to change the schedule a bit. I was slotted to work on implementing the dynamic media capabilities (have the objects retrieve their icons from a repository rather than having their locations hard-coded into the javascript) but I think I'll work on modifying the code to handle multiple order queues that the tp04 standard supports. Since I've been working with queue manipulation for the past week, it should make it somewhat easier to accomplish this within a small time frame. I shall make another blog post in a few days to reflect the progress I've made and get back on schedule, now that I can hole myself in my room for however long I need.

Tuesday, June 1, 2010

Week One Report

Since the week has been a flurry of being pulled hither and thither by coding and school, I haven't really kept a detailed list of bugs I ran into, since there were a lot of issues which were mostly due to my misunderstanding of the structure of the Thousand Parsec code. What has arisen from my coding binges over the past week is that Tpweb launches under tp04 libraries without any impedance and displays most of the information it must. The object panel, which displays object information when selected, does need to parse several pieces of data differently because the array of data it receives has changed, however, this can be dealt with later since I'll be moving that information to another dialog.

The issue that still impedes tpweb from running fully under the tp04 standard is the orders functionality. As of this moment, I've hit a wall that I need to talk to mithro about, as it appears to me that one of the functions involved in sending orders to the server might be outdated. Otherwise, I'm simply misunderstanding the code yet again.

Mentionable Issues:
The first major issue I faced in getting tpweb running under the tp04 standard was the issue with the cache. Apparently the cache used to be pickled, but with the inclusion of dynamic objects in the tp04 standard, this makes pickling throw errors. It took a lot of time to actually track down that issue, and five minutes talking with Mithro to confirm it, but it enabled me more understanding of the code and how the cache is created. From there, I simply had the backend python code store the cache in a global variable which will suffice for now. In doing this, there are two new functions added to the backend middleman method that deal with this local version of the cache.

Another issue with fixing up tpweb was understanding and taking command of the modified structures of an object's properties. A lot of information has been moved into nests of general parent headers, such as position and velocity within a parent header of Positional. Initially, I thought I could just use Greywhind's getPositionList function in the objectutils file, however, that would be ill-equipped to parse the rest of the nested data. After several rewrites, I managed to produce a recursive function (posted at end of this post) which converts all the properties of an object into a nested dictionary so that the javascript portion of tpweb can handle the data. I also ended up creating a recursive search function for it as well, since the order's functionality requires the queueid nestled within the objects property.

In dealing with these troublesome data structures, I discovered where the turn counter was stored. In tp03, it was apparently stored in a shallow dictionary within object[0] (the universe), however it is now stored in the object[0].__Informational.Year.value position of the universe object.

Another sub issue I had was dealing with positional data of the objects, since that is necessary element in an object's visual quality. The structure of the Position property is:
'__Positional': [Position: [vector: [x(q): 0, y(q): 0, z(q): 0], relative(I): 0]
A bit elaborate for my tastes, and it required some condensing for easier insertion into the javascript framework. I spent some time on the best way to condense it, but this was still while I was thinking I could use the getPositionList function. It became obvious that I would need a more robust function and so my attention and time was directed at that.

An aside: I found an error in the getPositionList when it deals with relative positioning of objects. When it would get to this section of the code, it would call get_position_list, which was the old name for this function, and thus cause it to fail. I submitted the corrected file to github, but since I fail utterly with git, it may not be up there or may have been deleted.

I believe I had some issue with the Universe size as well, but this may have been what finally forced me to write the recursive function to parse an object's property data.

Before the client would even display, the get orders function would also have to be addressed as well. When I would output what was stored in the cache, it showed a collection of only four order queues which I thought was strange considering the collection of objects had a total of ten or so queues in their properties. Thus, I went on a maddening chase to insure that the function which constructs an object's order's queue was not somehow malfunctioning.

It was not however, which led to the next maddening quandary as to why the order's queueid's listed 0, 11, 12, 13, 14 when my planet and ships were ids 20, 21, 22, 23. Id 11 was an uninhabited planet, so there was no way it could or should have an order's queue. Upon looking at the massive data log I had in front of me for an hour or two and trying many different things to figure out the cause of this mismatch, I realized that the queueid was actually distinct from the object's id and that the object had stored in it a reference to its queue id. With that settled, the client magically displayed.

I had up to this point commented out the types of orders that would get sent to the browser, since the constraints it initially relied on had been changed into another confounding data structure in parameters. Once tpweb did finally display in the browser, reimplementing these were not as difficult since Greywhind had listed on his blog how to deal with them. In theory, by fixing that, the client should now be able to display orders, but since I have yet to get the submit orders functionality working, that theory is likely only half-baked.

Submit orders, remove orders, and update orders still need to be addressed before tpweb can return to normal functionality. So those are the things I'll be focusing on this week, because they need to be finished by next weekend if I am to stay on schedule. But, I am also done with school next Monday, so I can do more coding binges if it becomes trickier than I'm thinking it will be. Just have to figure out why the orders are not sending to the server.

As an aside: queue is most evil a word.


def getPropertyList(obj):
"""
Examines an objects properties structure and outputs a nested dict of the entire thing for use
by the javascript portion of tpweb

Referenced from Greywhind's getPositionList function in objectutils
"""
propertieslist = {}
variable_list = {}
for propertygroup in obj.properties:
if type(propertygroup) != Structures.GroupStructure:
continue
for property in propertygroup.structures: #Position
property_list = getattr(obj, propertygroup.name) #Gets Positional List
def propertyparselist(property, property_list):
"""Todo: Relative Position/Vector needs to be accounted for"""
vardict = {}
subvardict = {}
if property.__dict__.has_key('structures'): #Is group sturcture
subproperty_list = getattr(property_list, property.name) #Gets Position list
for subproperty in property.structures:
subvardict.update(propertyparselist(subproperty, subproperty_list))

if(len(subvardict) > 0):
vardict[safestr(property.name)] = subvardict
else:
if type(property_list) == Structures.ListStructure.ListProxy:
for key, value in enumerate(property_list):
vardict[key] = value
elif type(property_list) == Structures.GroupStructure.GroupProxy:
vardict[safestr(property.name)] = safestr(getattr(property_list, property.name))
else:
print property
print type(property)
print property_list
print type(property_list)
print "===================="

return vardict

propertieslist.update(propertyparselist(property, property_list))

return propertieslist



def searchPropertyList(propertylist, attribute, found=False):
# print "Find this attribute: ", attribute
# print "Propertylist incoming: ", propertylist
# print type(propertylist)
if type(propertylist) == type(dict()) and len(propertylist) > 0:
for keys in propertylist.keys():
if keys == attribute:
return propertylist[keys], True
else:
propertyl, found = searchPropertyList(propertylist[keys], attribute)
if found:
return propertyl, True
return None, False