Thursday, August 29, 2013

ZKB Json parsing in Java

Json parsing in Java using gson:

   While looking into pulling kill data using zkillboard's API, I had some trouble learning how to parse Json.  This is partially because its the first time that I was using Json, and partially because I am still new to Java as a whole.  Below is an example of how to parse kill data from ZKB.

    Some notes on parsing data from ZKB:
  • You need ~15 second program pause after every call to ZKB.  This is not reflected in this code as it parses a single page of the call.
  • Please see the ZKB Api page for more information on how to make the calls you want.

package com.JEves.test;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;

import com.btr.proxy.search.ProxySearch;
import com.btr.proxy.search.ProxySearch.Strategy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;

public class SimpleKbParser   implements JsonDeserializer {

 public String m_value;
 /**
  * @param args
  */
 @SuppressWarnings("deprecation")
 public static void main(String[] args) {
  ProxySearch proxySearch = new ProxySearch();
  proxySearch.addStrategy(Strategy.OS_DEFAULT); 
  proxySearch.addStrategy(Strategy.JAVA); 
  proxySearch.addStrategy(Strategy.BROWSER); 
  ProxySelector proxySelector = proxySearch.getProxySelector(); 

  if(proxySelector != null) {
   ProxySelector.setDefault(proxySelector); 
   URI home = URI.create("http://www.google.com"); 
   //System.out.println("ProxySelector: " + proxySelector); 
   //System.out.println("URI: " + home); 
   List proxyList = proxySelector.select(home); 
   if (proxyList != null && !proxyList.isEmpty()) { 
    for (Proxy proxy : proxyList) { 
     //System.out.println(proxy); 
     SocketAddress address = proxy.address(); 
     if (address instanceof InetSocketAddress) { 
      String host = ((InetSocketAddress) address).getHostName(); 
      String port = Integer.toString(((InetSocketAddress) address).getPort()); 
      System.setProperty("http.proxyHost", host); 
      System.setProperty("http.proxyPort", port); 
     } 
    } 
   }
  }
  URLConnection.setDefaultRequestProperty("Accept-Encoding", "gzip, deflate");
  URLConnection.setDefaultRequestProperty("User-Agent", "Valkrr Dragonsworn");
  BufferedReader reader;
  String itemUrl = "http://zkillboard.com/api/kills/regionID/10000002/";
  try {
   GsonBuilder gsonBuilder = new GsonBuilder();
      gsonBuilder.registerTypeAdapter(SimpleKbParser.class, new SimpleKbParser());
      Gson gson = gsonBuilder.create();
   reader = new BufferedReader(new InputStreamReader(new URL(itemUrl).openStream()));
   SimpleKbParser[] kills = gson.fromJson(reader, SimpleKbParser[].class);
   for(int i = 0; i < kills.length; i++) {
    System.out.println("Kill: " + i);
    System.out.println(kills[i].m_value + "\n");
   }
  }
  catch(Exception e) {
   e.printStackTrace();
  }
 }

 @Override
 public SimpleKbParser deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
  SimpleKbParser ret = new SimpleKbParser();
  int killID = ((JsonObject) json).get("killID").getAsInt();
  int solarSystemID = ((JsonObject) json).get("solarSystemID").getAsInt();
  String killTime = ((JsonObject) json).get("killTime").getAsString();
  int moonID = ((JsonObject) json).get("moonID").getAsInt();
  ret.m_value += "killID: " + killID;
  ret.m_value += "\nsolarSystemID: " + solarSystemID;
  ret.m_value += "\nkillTime: " + killTime;
  ret.m_value += "\nmoonID: " + moonID;
  return ret;
 }

}

I will go through the above class section by section.  I am assuming you will be copying this into an editor so I will be referring to line numbers.

Lines 1-23:

   Your basic setup and import steps.

Line 25:

   public class SimpleKbParser   implements JsonDeserializer<SimpleKbParser> {

  JsonDeserializer is what makes the magic easy an quick.  This basically allows you to have your storage class get 1 element at a time from the series of elements and have to worry about parsing just that one element.  

Lines 33-57:

   I do part of my programming behind a firewall and the other part outside of a firewall.  This piece of code allows the script to auto detect the correct proxy type and use that by default. This requires proxy-vole to be linked to the project, so if you are not worried about firewalls, remove these lines along with lines 15 and 16.

Lines 58-75:

   An extremely basic program for grabbing and printing kill data.

   The key line here is line 67:
      SimpleKbParser[] kills = gson.fromJson(reader, SimpleKbParser[].class);
    This line tells gson that you want to parse the BufferedReader with your json in it into an array of SimpleKbParser objects.

Lines 79-90:

   Here is the function overloaded from JsonDeserializer.  For this example I just pulled some of the simple information out of the json and added it to a member string to be later printed.  Depending on what you are trying to do with this information, you will have to decide what information you want.

int killID = ((JsonObject) json).get("killID").getAsInt();

   You have to cast the JsonElement json to JsonObject, then run the get(Element Tag) which returns a JsonElement.  You run the getAs<Type>() function on the resulting JsonElement to get the value in a usable format.

JsonArray attackers = ((JsonObject) json).get("attackers").getAsJsonArray();
for(int i = 0; i < attackers.size(); i++) {
   JsonObject attacker = attackers.get(i).getAsJsonObject();
}

   For array data inside a json element, you cast as above, but you get it as a JsonArray type.  You can then iterate over that array, getting each object as a JsonObject to make getting values easier.


Summary:

   So, we learned how to get ZKB data into our programs in just a few dozen lines of actual code, less that 100 total lines.  There are some things not covered here to keep it simple, line how to effectively iterate over pages in a query and pretty much any error checking.  All of the coding is done in Eclipse build v21.1.0 using the ADT install package.  Other compilers might have compiler specific requirements that could prevent the above code from compiling.

   My source code can be found at Rapid Assembly.  This include git source repository and an occasional executable of my tool.  I have not made much use of the zkillboard parser yet, but I have plans to do so as part of a product selection GUI.

The Increasingly poor decisions of an Eve Industrialist

The Increasingly poor decisions of an Eve Industrialist:

Product Selection:


   I recently moved my main into faction warfare.  This has been widely regarded as a bad idea.  So I become a war target, and in my noobish innocence I figured I would be safe in my miltias high-sec space... and I was forcefully corrected on this misconception by a war target Machariel sitting outside the dead end  system that I used to do invention out of... to the tune of 500 M isk.

https://zkillboard.com/detail/32099354/

   So Red Frog Freight and I have become very good friends.  For 4.5M I can have 800K m3 of freight moved 11 jumps.  I am sold.  Try to combine as much as possible into a single contract to make the most of it.

   So, my main is now in Black Rise doing Caldari faction warfare with several million skill points in industry just wasting away, so I decide to try some T1 industry.  I buy a Thrasher BPO (ME 10, PE 10) and a Moa BPO (ME 22, PE 15).  Both are doctrine ships in my alliance.  I build 30 Moas and 100 Thrashers and put them up for sale in Black Rise, and ~25 days later, 6 Moas and 5 Thrashers have sold.  FML.  There is 380M tied up for a month for no good reason.



  In this time I spent about a billion isk on PvP ships stocking up doctrine ships I have yet to really use.  I have lost a couple to frigate hot drops in plexes, but have yet to manage to kill anything.  A carebear in PvP is like a seal trying to play fight club in the shark tank, its going to have a bad time.

  I have been working on product selection programs for a while now, both for T1, which is much easier, and T2, which is complicated by meta items and decryptors in the invention process.  My tool told me to look a Covert Ops Cloaking Devices.  So I loaded them up in my tool, and they were showing 6 day build times and 400-500K isk/hour/manufacturing line and 50% profit.  That comes out to something in the neighborhood of 2.6B in profit/month.


   I bought a researched BPO (100,15) for 250M and a copy blank from NPC for 100M.  Then I spent over 500M to buy enough materials to invent 10 T2 BPCs and build an additional 100 units of Prototype Cloaking Device.  Then I went to install my blank to make invention copies, when I noticed the real problem.  Not only does it take 277.78 days to make 20 100 run copies needed for normal invention, but there are additional materials required to make those copies.  The above image shows the copy time, but includes the cost of copy materials.  So this caused me to add copy time to the display of my tool, and also to take the greater of the copy or build time to determine ISK / hour.


   Looking at it with copy time determining isk/hr, it now looks like a much worse product.  You still have > 50% profit, but now with only 100K isk/hr, which comes out to somewhere around 672M isk/month.  There are so many easier ways to make that kind of isk, this is only 200M isk above Scorch M, which has a negligible effort.  So what about using decoders?

  Just reducing the number of runs on the T1 copy to minimum almost doubles your isk/hr.


  Inventing on Augmentation decryptors brings your isk/hr sky rocketing back into an area that I am willing to work with.  You are still making 50% profit, or 100% Return on investment(ROI).  5 day copy time, ~70 copies to make 20 T2 BPCs assuming level 4 invention skills.  As it sits right now, I am sitting on this material, after making 200 units of Prototype Cloaking Device, trying to decide how far down the rabbit hole I want to go.


And then you add another inventor into the mix...

   So, after all of that fun, I have another inventor coming up on completing the invention training plan in less than 3 weeks.  With an 12-16 day lead time on high sec copy slots, its time to select the products for her.  So I spent some time in the last week working on my invention profiteer, see my previous post for more info.  I came up with 3 products, each with ~50% profit and a 1.5-2 day adjusted build time.  Those products I will keep to my self, as I do not want to encourage more competition.

   Below is a chart of the 90 day history of build cost (red) verses sell price (blue) for my 3 inventors.  It will probably take a couple of months to get this into full swing and find a good balance.  My main will have 6-7 day build times, my new inventor will have 1.5 -2 day build times, and my old inventor has 1-2 day build times.  I spent an additional 30 million on BPO blanks for copying for my main and new inventor.



Plans:

    I know in the early posts of this blog, I talked about doing a high-sec T2 inventor in only NPC stations, but that is quickly becoming impractical.  The problem is not invention or manufacturing slots, if you move around and are flexible enough you can find a sweet spot to do that in that will allow you to have near 100% efficiency. The problem is that you need ~105% or more of the T1 BPCs to make T2 BPCs.  You will find that in most high sec areas, you are looking at 8-30 days lead time until your copy starts.  Another trap you run into is that some of the copy slots have costs an order of magnitude higher than the rest.  Normally, my copy costs are in the 140K-280K isk range for full runs and 20 copies, and I'm fine with that.  But you sometimes find a line that will cost you 2.5M isk for the same thing, which I am not ok with.

   So, I need to look into dropping a couple of POSs.  2 Medium POSs will allow me to run up to 8 inventors, doing copying, inventing, and manufacturing at the POS.  This will also run me ~440M isk/month, or almost a PLEX.  I can't afford to do that until I have my other 2 invention lines established.  Not only that, but I don't have any characters with faction standing above 5, so I will have to hire a standings service to be able to drop the POSs.  POS cost is also another problem, to drop 2 medium towers will cost nearly a billion ISK, with only 4 equipment arrays and 1 each of mobile and advanced mobile labs.  This is the minimum needed for 2 characters.  The second tower is so that I don't have to worry about a standings service when I outgrow the first.  I also need to start doing missions on one of my invention characters so that I can boost my corp faction standings myself.

  This is all not mentioning the fact that I have been neglecting my faction warfare duties.  I need to have time to be bad at PvP and run plexes.  Oh well, it keeps Eve interesting :)

Monday, August 26, 2013

Top Invention Products: Modules

Top Invention Products: Modules

   I have another inventor coming up on fully trained and I need to decide what products to invent on her.  So I have been working on a script to give me insight into the best products, in both ISK/hr and volume.  What I came up with was an industrial index, expressed by the following formula:

   Industrial Index = ((Sell Price - (Build cost + Invent Cost + Copy Cost(materials))) / (Greater of Build or copy Time rounded up to the next 12 hour increment)) * (lesser of 1 or (20 % daily sales volume / Volume Produced/day by 1 mfg line);

   What this means is that its estimating the isk/hr based on the actual time it will take most people to flip jobs.  Most people cannot keep a 16 hour line going at 16 hours, so we round up to 24 hours to calculate isk/hr.  The sales volume component makes sure that you are not thoroughly out producing the market.  What I am sharing with you today are the top 50 modules (no decoders or meta items considered) to produce based on numbers on 8/25/13.  There are some products, like 125mm Gatling AutoCannon II that when investigated clearly show they are in a bubble.  There are also a lot of products which had no volume on that day.  But given the amount of time it takes to run this, ~20 seconds / day / product configuration, I don't see me running a 90 day comparison of all products any time soon.

   I will be doing a series of posts that give the same kind of information for different market groups.

   And without further ado, here is the top 50 modules per Industrial Index, sorted ASCII-betically.

100MN Afterburner II
125mm Gatling AutoCannon II
1MN Afterburner II
1MN Microwarpdrive II
200mm AutoCannon II
200mm Reinforced Steel Plates II
800mm Reinforced Steel Plates II
Adaptive Nano Plating II
Cap Recharger II
Capacitor Flux Coil II
Capacitor Power Relay II
Co-Processor II
Cruise Missile Launcher II
Damage Control II
Drone Damage Amplifier II
Drone Link Augmentor II
Dual 180mm AutoCannon II
Energized Adaptive Nano Membrane II
Expanded Cargohold II
Explosive Plating II
Heavy Capacitor Booster II
Heavy Ion Blaster II
Heavy Neutron Blaster II
Inertia Stabilizers II
Large Remote Armor Repair System II
Light Electron Blaster II
Light Ion Blaster II
Light Missile Launcher II
Light Neutron Blaster II
Magnetic Field Stabilizer II
Medium Armor Repairer II
Medium Capacitor Booster II
Medium Shield Booster II
Medium Shield Extender II
Mining Laser Upgrade II
Nanofiber Internal Structure II
Overdrive Injector System II
Power Diagnostic System II
Rapid Light Missile Launcher II
Relic Analyzer II
Remote Sensor Booster II
Rocket Launcher II
Scan Pinpointing Array II
Sensor Booster II
Shield Power Relay II
Small Armor Repairer II
Small Energy Neutralizer II
Survey Scanner II
Warp Core Stabilizer II
Warp Scrambler II