Through the end of November, my faction war corp QCATS and our allies in Drunk N Disorderly, had made it our goal to get into the moon mining business as a means for long term passive income. I'm not particularly savvy on the exact politics, but we were snatching up assets in Syndicate and Aridia. As the first phase of this project wound down, I got tagged for POS management because "you know how to spell POS". Being the local POS expert, I was on the short list for managers.
Unfortunately, I know EXACTLY what that workload looks like and set out to do something to make it less hair-pullingly awful. Also, it was a chance to really stretch my legs in Python, since I've been avoiding it like cleaning the garage.
So I set out to build a relatively simple POS tracker that could be hosted on Google's AppEngine and provide a light weight webpage that people can check in on POS status at-a-glance. The future hopes are to expand this to account-instanced functionality, so users can register and have their own private POS information. But that's a much later stage, and I'm not particularly interested in marketing such a tool at this time.
Data Structures - POS
The data structure is pretty simple at its face. Provide a parent-child relationship where parents are towers and children are modules. Then the individual children modules can have return values that tell us useful things about the setup. Silo capacities, POS fuel, online status, all can be assigned in this class structure.
The EVE API
This was one of the easy parts (remarkably). By first validating against the AccountInfo API, the tool can verify a correct API was loaded. Once verified, the program can move on to each of the parts of setting up each tower's classes. By querying the API in the program's MAIN section, then feeding the result webpage to Python's minidom, the DOM object can be passed into each crunch function rather than querying the API over and over.
The flow looks like:
- Query APIKeyInfo for validity check
- Query StarbaseDetail for list of towers
- Process location information and tower status (online, offline, reinforced, unanchored)
- With list of Tower() objects, load specific tower data
- Tower type
- Fuel remaining
- Unique itemID's for towers
- Iterate over list of Tower()s and use AssetList to load children objects
- Module() load, type, and relevant information about each type
Once the data structure is loaded, some simple math can be run on the snapshot. Since POS processes are an hourly occurrence, there isn't any need for live tracking.
Since the whole tool is designed around a snapshot of how assets look now, the goal is to be able to refresh (or cache until it can be refreshed) the whole structure every time the site is refreshed. It would be possible to cache the individual API calls and use them until they need to be refreshed, but again, without the need for up-to-the-minute data, that work is not justified at this time.
As for displaying data, the goal is a collapsible list of towers with their children silos and remaining fuel. To render .jpgs for each module, with some intelligence as to which resources are depleting and which are filling. Also, using the fixed rates of reactions, the goal should also be to display ETAs for full/empty for all progress bars. I have not yet spent any time on generating the output site, so any stupid-proof graph builders people might know about, I'd appreciate the help.
In this example, the red bars are depleting stocks and the green are gaining. Using the information from reactors, it should be easy to designate reactants and products rather than have to keep caches to watch which way things go. Also, though I am a fan of the minimal, getting the right python modules to hook into the output should make it as pretty or plain as required. Iterating over the intended inputs, procedurally generating the required website code, and presenting it in a pretty package as such, should be relatively simple.
I want to have an admin panel that allows the user to name the various assets as they see fit. Though my plan is to only allow control for tower names or module names, additional functionality can be added by expanding the asset classes.
Currently the plan is to only allow access to one client. I'd very much like to add instancing for as many users as you'd like. But there are some significant challenges to adding that function. Security, public sharing keys... the ability to deal with other humans... it's a to-do.
"Parallel API" functionality. I've tried to design in the ability to counteract the caching system by having multiple character APIs and have the program handle them seamlessly in the background. There's a framework for it, but I am not wholly convinced it will work well and it's not important in this first release.
What's a dev-blog without covering "what we learned"? This project is an adventure in demystifying the programming challenges. Also, the motto going forward should probably be "just do it"... most of what I learned this time around was done by just putting code down and worrying less about the issues of how to get to the finish when I know almost nothing.
I've been a fan of XML for a while now. It provides a human-readable framework to build fancy data structures. XML is also a massive pain, with its tag structure, and the amount of rope it gives you to hang yourself is quite liberal. JSON provides a much cleaner architecture to do very similar things. Unfortunately the resources for learning JSON + Python are, to be blunt, shit.
Some quick lessons:
- Once a json object is parsed (json.load()), it can be referenced like the datastructure denoted
- I used a "dictionary vector" setup: json[key1][key2][key3]=value
- Iterating over a list with for-in returns the actual contents (object, value, structure), not an integer reference to its position in the list
- No commenting in JSON. Personal pet-peeve, but add "comment" key if you're anal
I missed the boat in programming class about Object-Oriented code. There were some steps between A->B that did not click and I quickly lost taste for the practice. Many examples and some hammering on my own time has quickly evaporated the haze around this style of code. By providing classes for each component linking into eachother, and better understanding return types and how they can be passed around a program has been a godsend. Also, getting away from the more hard-core elements of C, like pointer magic, has been a breath of fresh air. Lastly, being able to generate classes with a whole range of attributes and tools makes modularizing the code much easier.
Keeping up with Progress
I hope to have most of the crunching functionality figured out this week (while work is quiet). Maybe even get a rudamentary site up. If you'd like to see what's going on, check out the repo:
I need to finish doing some clean up first. Then the data-loading cruncher. Then a basic website. We'll see if it can't start looking like the intended product by the end of next week.