# HG changeset patch # User Vladimir Vukicevic # Date 1198629234 28800 # Node ID 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 # Parent 0000000000000000000000000000000000000000 initial diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 .classpath --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.classpath Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,6 @@ + + + + + + diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,3 @@ +bin/.* +build/.* +.*~ diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 .project --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.project Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,17 @@ + + + EveBerry + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 LogFile.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LogFile.txt Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,2 @@ +SecureRandomThread-start +SecureRandomThread-end diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 build.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build.xml Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 images/EveBerry.alx --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/EveBerry.alx Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,27 @@ + + + + EveBerry + + + Blackberry EVE Monitor + + + 0.1 + + + Mr. Rupert's Quality Software Group + + + Copyright (c) 2007 MRQSG + + + + + + + EveBerry.cod + + + + diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 images/eve_icon_book.png Binary file images/eve_icon_book.png has changed diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 images/eve_icon_persona.png Binary file images/eve_icon_persona.png has changed diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 src/org/mrrupert/eveberry/DocHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/mrrupert/eveberry/DocHandler.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,25 @@ +package org.mrrupert.eveberry; + +import java.util.*; + +public interface DocHandler { + public void startElement(String tag,Hashtable h) throws Exception; + public void endElement(String tag) throws Exception; + public void startDocument() throws Exception; + public void endDocument() throws Exception; + public void text(String str) throws Exception; +} + +class DefaultDocHandler implements DocHandler { + public void startElement(String tag,Hashtable h) throws Exception + { } + public void endElement(String tag) throws Exception + { } + public void startDocument() throws Exception + { } + public void endDocument() throws Exception + { } + public void text(String str) throws Exception + { } +} + diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 src/org/mrrupert/eveberry/EveAPI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/mrrupert/eveberry/EveAPI.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,607 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is EveBerry. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +package org.mrrupert.eveberry; + +import javax.microedition.io.*; + +import java.util.*; +import java.io.*; + +import net.rim.device.api.util.*; +import net.rim.device.api.compress.*; + +//import java.text.*; + +public class EveAPI { + //static String kAPIPrefix = "http://api.eve-online.com"; + static String kAPIPrefix = "http://vlad.off.net/misc/eproxy.php"; + + static String kCharactersXMLURL = kAPIPrefix + "/account/Characters.xml.aspx"; + static String kSkillInTrainingXMLURL = kAPIPrefix + "/char/SkillInTraining.xml.aspx"; + static String kCharacterSheetXMLURL = kAPIPrefix + "/char/CharacterSheet.xml.aspx"; + + static String kCharacterImageURL = "http://img.eve.is/serv.asp?s=64&c="; + + static String kURLSuffix = ";deviceside=true"; + + public static EveCharacterList GetCharacters(String userid, String key) { + HttpConnection http = null; + OutputStream os = null; + + EveCharacterList retval = null; + + try { + http = (HttpConnection) Connector.open(kCharactersXMLURL + kURLSuffix); + http.setRequestMethod(HttpConnection.POST); + http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + http.setRequestProperty("Accept-Encoding", "gzip"); + + EveBerry.debug("GetCharacters: '" + userid + "' key: '" + key + "'"); + + os = http.openOutputStream(); + os.write(("userID=" + userid + "&apiKey=" + key).getBytes()); + + int rc = http.getResponseCode(); + if (rc != HttpConnection.HTTP_OK) { + // er, what now? + return null; + } + + InputStream is; + if (http.getHeaderField("Content-Encoding").indexOf("gzip") != -1) { + is = new GZIPInputStream(http.openInputStream()); + } else { + is = http.openInputStream(); + } + + retval = new EveCharacterList(); + + QDParser sax = new QDParser(); + DocHandler handler = new CharactersXMLHandler(retval); + sax.parse(handler, new InputStreamReader(is)); + + http.close(); + } catch (Exception ex) { + EveBerry.debug("Exception caught! " + ex); + retval = null; + } + + return retval; + } + + public static EveCharacterSheet GetCharacterSheet(String userid, String key, long charid) { + HttpConnection http = null; + OutputStream os = null; + + EveCharacterSheet retval = null; + + try { + http = (HttpConnection) Connector.open(kCharacterSheetXMLURL + kURLSuffix); + http.setRequestMethod(HttpConnection.POST); + http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + http.setRequestProperty("Accept-Encoding", "gzip"); + + os = http.openOutputStream(); + os.write(("userID=" + userid + "&apiKey=" + key + "&characterID=" + charid).getBytes()); + + int rc = http.getResponseCode(); + if (rc != HttpConnection.HTTP_OK) { + // er, what now? + return null; + } + + InputStream is; + if (http.getHeaderField("Content-Encoding").indexOf("gzip") != -1) { + is = new GZIPInputStream(http.openInputStream()); + } else { + is = http.openInputStream(); + } + + retval = new EveCharacterSheet(); + + QDParser sax = new QDParser(); + DocHandler handler = new CharacterSheetXMLHandler(retval); + sax.parse(handler, new InputStreamReader(is)); + + http.close(); + } catch (Exception ex) { + EveBerry.debug("Exception caught! " + ex); + retval = null; + } + + return retval; + } + + public static EveSkillInTraining GetSkillInTraining(String userid, String key, long charid) { + HttpConnection http = null; + OutputStream os = null; + + EveSkillInTraining retval = null; + + try { + http = (HttpConnection) Connector.open(kSkillInTrainingXMLURL + kURLSuffix); + http.setRequestMethod(HttpConnection.POST); + http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + http.setRequestProperty("Accept-Encoding", "gzip"); + + os = http.openOutputStream(); + os.write(("userID=" + userid + "&apiKey=" + key + "&characterID=" + charid).getBytes()); + + int rc = http.getResponseCode(); + if (rc != HttpConnection.HTTP_OK) { + // er, what now? + return null; + } + + InputStream is; + if (http.getHeaderField("Content-Encoding").indexOf("gzip") != -1) { + is = new GZIPInputStream(http.openInputStream()); + } else { + is = http.openInputStream(); + } + + retval = new EveSkillInTraining(); + + QDParser sax = new QDParser(); + DocHandler handler = new SkillInTrainingXMLHandler(retval); + sax.parse(handler, new InputStreamReader(is)); + + http.close(); + } catch (Exception ex) { + EveBerry.debug("Exception caught! " + ex); + retval = null; + } + + return retval; + } + + public static ByteVector GetCharacterImageData(long charid) { + // check the bitmap cache first + try { + long tstart = System.currentTimeMillis(); + + HttpConnection http = (HttpConnection) Connector.open(kCharacterImageURL + charid + kURLSuffix); + int len = (int) http.getLength(); + + ByteVector data = new ByteVector(len); + DataInputStream dis = http.openDataInputStream(); + dis.readFully(data.getArray()); + http.close(); + + EveBerry.debug("NNN GetCharacterImageData network took " + (System.currentTimeMillis() - tstart) + " ms"); + + return data; + } catch (Exception ex) { + EveBerry.debug("Exception caught! " + ex); + } + + return null; + } + + /* XML SAX handlers */ + + static class GenericEveAPIHandler extends DefaultDocHandler { + boolean mInCachedUntil; + String mCachedUntilText; + long mCachedUntil; + + boolean mInError; + int mErrorCode; + String mErrorString; + + GenericEveAPIHandler() { + mInCachedUntil = false; + mCachedUntilText = ""; + mCachedUntil = 0; + + mInError = false; + mErrorCode = 0; + mErrorString = ""; + } + + public static long DateStringToSeconds(String s) { + // EVE API dates are in the format: + // "YYYY-MM-DD HH:MM:SS" in GMT. Unfortunately, + // RIM doesn't provide a SimpleDateFormat that can parse. Therefore: + //SimpleDateFormat eveDateFormat = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss"); + //Date d = eveDateFormat.parse(s); + //Calendar c = new GregorianCalendar(TimeZone.getTimeZone("GMT")); + + if (s.length() != 19) + return -1; + + try { + int y = Integer.parseInt(s.substring(0,4)); + int mo = Integer.parseInt(s.substring(5,7)); + int d = Integer.parseInt(s.substring(8,10)); + int h = Integer.parseInt(s.substring(11,13)); + int m = Integer.parseInt(s.substring(14,16)); + int sec = Integer.parseInt(s.substring(17,19)); + + Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + c.set(Calendar.YEAR, y); + c.set(Calendar.MONTH, mo-1); // months are 0-based + c.set(Calendar.DATE, d); // day-of-month is 1-based + c.set(Calendar.HOUR_OF_DAY, h); + c.set(Calendar.MINUTE, m); + c.set(Calendar.SECOND, sec); + + return c.getTime().getTime() / 1000; + } catch (Exception e) { + // + } + + return -1; + } + + boolean GenericStartElement(String tag, Hashtable attributes) + throws Exception + { + if (tag.equalsIgnoreCase("cachedUntil")) { + mInCachedUntil = true; + mCachedUntilText = ""; + return true; + } + + if (tag.equalsIgnoreCase("error")) { + mInError = true; + mErrorCode = Integer.parseInt((String) attributes.get("code")); + return true; + } + + return false; + } + + public boolean GenericEndElement(String tag) { + if (mInCachedUntil) { + mCachedUntil = DateStringToSeconds(mCachedUntilText); + mInCachedUntil = false; + return true; + } + + if (mInError) { + mInError = false; + return true; + } + + return false; + } + + public boolean GenericText(String str) { + if (mInCachedUntil) { + mCachedUntilText += str; + return true; + } + + if (mInError) { + mErrorString += str; + return true; + } + + return false; + } + + public void GenericEndDocument() + throws Exception + { + if (mErrorCode != 0) + throw new Exception(mErrorString); + } + + public void GenericEndDocument(EveCacheableItem eci) + throws Exception + { + GenericEndDocument(); + + eci.cachedUntil = mCachedUntil; + } + + public void startElement(String tag, Hashtable attributes) + throws Exception + { + GenericStartElement(tag, attributes); + } + + public void endElement(String tag) + throws Exception + { + GenericEndElement(tag); + } + + public void text(String str) + throws Exception + { + GenericText(str); + } + + public void endDocument() + throws Exception + { + GenericEndDocument(); + } + } + + static class CharactersXMLHandler extends GenericEveAPIHandler { + String mCharacterNames[]; + long mCharacterIDs[]; + String mCorporationNames[]; + long mCorporationIDs[]; + + int mCharsFound; + + EveCharacterList mList; + + public CharactersXMLHandler(EveCharacterList list) { + mList = list; + + mCharacterNames = new String[3]; + mCharacterIDs = new long[3]; + + mCorporationNames = new String[3]; + mCorporationIDs = new long[3]; + + mCharsFound = 0; + } + + public void startElement(String tag, Hashtable attributes) + throws Exception + { + if (GenericStartElement(tag, attributes)) + return; + + if (tag.equalsIgnoreCase("row")) { + mCharacterNames[mCharsFound] = (String) attributes.get("name"); + mCharacterIDs[mCharsFound] = Long.parseLong((String) attributes.get("characterID")); + mCorporationNames[mCharsFound] = (String) attributes.get("corporationName"); + mCorporationIDs[mCharsFound] = Long.parseLong((String) attributes.get("corporationID")); + mCharsFound++; + } + } + + public void endDocument() + throws Exception + { + GenericEndDocument(mList); + + mList.CharacterNames = new String[mCharsFound]; + mList.CharacterIDs = new long[mCharsFound]; + + for (int i = 0; i < mCharsFound; i++) { + mList.CharacterNames[i] = mCharacterNames[i]; + mList.CharacterIDs[i] = mCharacterIDs[i]; + } + } + } + + + static class CharacterSheetXMLHandler extends GenericEveAPIHandler { + EveCharacterSheet mSheet; + + String mStr; + + boolean mInResult; + + boolean mInAttributes; + boolean mInSkills; + boolean mInAttributeEnhancers; + + boolean mInDataField; + + public CharacterSheetXMLHandler(EveCharacterSheet sheet) { + mSheet = sheet; + + mInResult = false; + + mInAttributes = false; + mInSkills = false; + mInAttributeEnhancers = false; + + mInDataField = false; + } + + public void startElement(String tag, Hashtable attributes) + throws Exception + { + if (GenericStartElement(tag, attributes)) + return; + + if (!mInResult) { + if (tag.equalsIgnoreCase("result")) + mInResult = true; + return; + } + + if (tag.equalsIgnoreCase("characterid") || + tag.equalsIgnoreCase("name") || + tag.equalsIgnoreCase("race") || + tag.equalsIgnoreCase("corporationname") || + tag.equalsIgnoreCase("corporationid") || + tag.equalsIgnoreCase("balance") || + (mInAttributes && ( + tag.equalsIgnoreCase("intelligence") || + tag.equalsIgnoreCase("memory") || + tag.equalsIgnoreCase("charisma") || + tag.equalsIgnoreCase("perception") || + tag.equalsIgnoreCase("willpower"))) + ) + { + mInDataField = true; + mStr = ""; + } else if (tag.equalsIgnoreCase("attributes")) { + mInAttributes = true; + } else if (tag.equalsIgnoreCase("attributeenhancers")) { + mInAttributeEnhancers = true; + } else if (tag.equalsIgnoreCase("rowset") && ((String) attributes.get("name")) == "skills") { + mInSkills = true; + } + } + + public void text(String str) + throws Exception + { + if (GenericText(str)) + return; + + if (mInDataField) + mStr += str; + } + + public void endElement(String tag) + throws Exception + { + if (GenericEndElement(tag)) + return; + + if (!mInResult) + return; + + if (tag.equalsIgnoreCase("result")) { + mInResult = false; + return; + } + + if (tag.equalsIgnoreCase("attributes")) { + mInAttributes = false; + return; + } + + if (tag.equalsIgnoreCase("attributeenhancers")) { + mInAttributeEnhancers = false; + return; + } + + if (mInSkills && tag.equalsIgnoreCase("rowset")) { + mInSkills = false; + return; + } + + if (mInDataField) { + if (tag.equalsIgnoreCase("characterid")) { + mSheet.id = Long.parseLong(mStr); + } else if (tag.equalsIgnoreCase("name")) { + mSheet.name = mStr; + } else if (tag.equalsIgnoreCase("race")) { + mSheet.race = mStr; + } else if (tag.equalsIgnoreCase("corporationname")) { + mSheet.corporationName = mStr; + } else if (tag.equalsIgnoreCase("corporationid")) { + mSheet.corporationID = Long.parseLong(mStr); + } else if (tag.equalsIgnoreCase("balance")) { + mSheet.balance = Double.parseDouble(mStr); + } else if (mInAttributes) { + if (tag.equalsIgnoreCase("intelligence")) { + mSheet.intelligence = Integer.parseInt(mStr); + } else if (tag.equalsIgnoreCase("memory")) { + mSheet.memory = Integer.parseInt(mStr); + } else if (tag.equalsIgnoreCase("charisma")) { + mSheet.charisma = Integer.parseInt(mStr); + } else if (tag.equalsIgnoreCase("perception")) { + mSheet.perception = Integer.parseInt(mStr); + } else if (tag.equalsIgnoreCase("willpower")) { + mSheet.willpower = Integer.parseInt(mStr); + } + } + + mInDataField = false; + } + } + } + + static class SkillInTrainingXMLHandler extends GenericEveAPIHandler { + EveSkillInTraining mSkill; + + String mStr; + + boolean mInResult; + + public SkillInTrainingXMLHandler(EveSkillInTraining skill) { + mSkill = skill; + + mInResult = false; + } + + public void startElement(String tag, Hashtable attributes) + throws Exception + { + if (GenericStartElement(tag, attributes)) + return; + + if (!mInResult) { + if (tag.equalsIgnoreCase("result")) + mInResult = true; + return; + } + + mStr = ""; + } + + public void text(String str) + throws Exception + { + if (GenericText(str)) + return; + + if (mStr != null) + mStr += str; + } + + public void endElement(String tag) + throws Exception + { + if (GenericEndElement(tag)) + return; + + if (!mInResult) + return; + + if (tag.equalsIgnoreCase("result")) { + mInResult = false; + return; + } + + + if (tag.equalsIgnoreCase("currenttqtime")) { + // nothing + } else if (tag.equalsIgnoreCase("trainingendtime")) { + mSkill.endTime = DateStringToSeconds(mStr); + } else if (tag.equalsIgnoreCase("trainingstarttime")) { + mSkill.startTime = DateStringToSeconds(mStr); + } else if (tag.equalsIgnoreCase("trainingtypeid")) { + mSkill.typeID = Long.parseLong(mStr); + } else if (tag.equalsIgnoreCase("trainingstartsp")) { + mSkill.startSP = Long.parseLong(mStr); + } else if (tag.equalsIgnoreCase("trainingdestinationsp")) { + mSkill.destinationSP = Long.parseLong(mStr); + } else if (tag.equalsIgnoreCase("trainingtolevel")) { + mSkill.destinationLevel = Integer.parseInt(mStr); + } else if (tag.equalsIgnoreCase("skillintraining")) { + if (Integer.parseInt(mStr) == 1) + mSkill.skillInTraining = true; + else + mSkill.skillInTraining = false; + } + } + } +} diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 src/org/mrrupert/eveberry/EveBerry.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/mrrupert/eveberry/EveBerry.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,237 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is EveBerry. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +package org.mrrupert.eveberry; + +import net.rim.device.api.ui.*; +import net.rim.device.api.ui.component.*; +import net.rim.device.api.ui.container.*; +import net.rim.device.api.i18n.*; +import net.rim.device.api.system.*; +import net.rim.device.api.notification.*; +import net.rim.device.api.collection.util.*; + +import java.util.*; + +/** + * + * @author vladimir + */ +public class EveBerry extends UiApplication +{ + public static EveBerry sApp; + + // the bits needed for notification + // com.mrrupert.eveberry.autostartup + public static final long sNotificationID = 0x1bd75a04705f6c35L; + public static final Object sNotificationEvent = new Object() { + public String toString() { + return "EVE Skill Training Complete"; + } + }; + + + public static void main(String[] args) { + System.out.println("EveBerry main()"); + if (args.length > 0 && args[0].equals("autostartup")) { + // auto startup + ///*Q*/NotificationsManager.registerSource(sNotificationID, sNotificationEvent, NotificationsConstants.DEFAULT_LEVEL); + + // kick off the backround runnable + //EveBerryBackground.StartBackgroundRunnable(); + } else { + System.out.println("EveBerry starting background runnable"); + EveBerryBackground.StartBackgroundRunnable(); + + System.out.println("EveBerry starting event dispatcher"); + sApp = new EveBerry(); + sApp.enterEventDispatcher(); + } + } + + public EveBerryScreen mScreen; + public KickerRunnable mKicker; + + /** Creates a new instance of EveBerry */ + public EveBerry() { + mScreen = new EveBerryScreen(); + pushScreen(mScreen); + } + + static class KickerRunnable implements Runnable { + public boolean mFinished; + EveBerry mBerry; + + public KickerRunnable(EveBerry berry) { + mBerry = berry; + mFinished = false; + } + + public void run() { + while (!mFinished) { + EveBerry.sApp.invokeLater(new Runnable() { + public void run() { + mBerry.mScreen.forceUpdate(); + }}); + + try { + Thread.sleep(1000); + } catch(InterruptedException ex) { } + } + } + } + + public void activate() { + EveBerry.debug("activate!"); + + synchronized(this) { + if (mKicker != null) { + mKicker.mFinished = true; + } + + // start the kicker thread + mKicker = new KickerRunnable(this); + new Thread(mKicker).start(); + } + + super.activate(); + } + + public void deactivate() { + EveBerry.debug("deactivate!"); + + if (mKicker != null) + mKicker.mFinished = true; + + super.deactivate(); + } + + public static void debug(String s) { + System.out.println(s); + } +} + +final class EveBerryScreen extends MainScreen implements EveCharacterListener +{ + EveCharacterListField mCharacterList; + + public EveBerryScreen() { + super(DEFAULT_MENU | DEFAULT_CLOSE); + + setTitle(new LabelField("EveBerry", LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH)); + + mCharacterList = new EveCharacterListField(); + + add(mCharacterList); + + EveCharacterManager mgr = EveCharacterManager.Manager(); + synchronized(mgr) { + // go through any existing characters + Enumeration iter = mgr.enumerateCharacters(); + while (iter.hasMoreElements()) { + EveCharacterInfo eci = (EveCharacterInfo) iter.nextElement(); + mCharacterList.addCharacter(eci); + } + + EveCharacterManager.Manager().addListener(this); + } + + //EveCharacterManager.Manager().addCharacter("test", "test", "Tester Alice", 0); + //EveCharacterManager.Manager().addCharacter("test", "test", "Tester Bob", 1); + //EveCharacterManager.Manager().addCharacter("test", "test", "Tester Frankindapinapolopoplogoposlotous Really Long Name", 2); + } + + protected void makeMenu(Menu menu, int instance) { + super.makeMenu(menu, instance); + + if (mCharacterList.getSelectedIndex() != -1) { + menu.add(new MenuItem("Update Character", 5, 5) { + public void run() { + EveCharacterInfo eci = mCharacterList.charInfoAt(mCharacterList.getSelectedIndex()); + EveBerryBackground.GetBackgroundRunnable().requestCharacterUpdate(eci); + } + }); + + menu.addSeparator(); + + menu.add(new MenuItem("Remove Character", 20, 10) { + public void run() { + EveCharacterInfo eci = mCharacterList.charInfoAt(mCharacterList.getSelectedIndex()); + EveCharacterManager.Manager().deleteCharacter(eci.ID); + } + }); + } + + + menu.add(new MenuItem("Add Character", 10, 10) { + public void run() { + EveEditCharacterScreen ecs = new EveEditCharacterScreen(); + EveBerry.sApp.pushScreen(ecs); + } + }); + } + + public boolean onClose() { + System.out.println("EveBerry: onClose"); + EveBerryBackground.StopBackgroundRunnable(); + + System.exit(0); + return true; + } + + public boolean keyChar(char key, int status, int time) { + //intercept the ESC key - exit the app on its receipt + boolean retval = false; + + switch (key) { + case Characters.ESCAPE: + onClose(); + retval = true; + break; + } + + return retval; + } + + // EveCharacterListener + public void onCharacterAdded(long id) { + EveBerry.debug("onCharacterAdded!"); + + EveCharacterInfo eci = EveCharacterManager.Manager().getCharacter(id); + mCharacterList.addCharacter(eci); + EveBerryBackground.GetBackgroundRunnable().requestCharacterUpdate(eci); + } + + public void onCharacterRemoved(long id) { + mCharacterList.removeCharacter(id); + } + + public void onCharacterUpdated(long id) { + mCharacterList.invalidate(); + } + + public void forceUpdate() { + mCharacterList.updateCharacters(); + } +} diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 src/org/mrrupert/eveberry/EveBerryBackground.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/mrrupert/eveberry/EveBerryBackground.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,381 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is EveBerry. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +package org.mrrupert.eveberry; + +import net.rim.device.api.ui.*; +import net.rim.device.api.ui.component.*; +import net.rim.device.api.ui.container.*; + +import net.rim.device.api.i18n.*; +import net.rim.device.api.system.*; + +import net.rim.device.api.collection.util.*; + +import net.rim.device.api.util.*; + +import net.rim.device.api.notification.*; + +import javax.microedition.io.*; +import java.util.*; +import java.io.*; +import java.lang.*; + +interface EveBerryBackgroundActionListener { + public void onActionComplete(Object result, Object token); +} + +class EveBerryBackground implements Runnable { + static int ITEM_CHARACTER_UPDATE = 0; + static int ITEM_CHARACTER_LIST_REQUEST = 1; + + static boolean sFinished = false; + static EveBerryBackground sRunnable = null; + static Thread sThread = null; + + long mNotificationTimeMS = 60*10*1000; // 10 minutes + long mUpdateTimeMS = 60*60*1000; // one hour + boolean mRunning; + + // this should be a Queue, but here we are + Vector mWorkQueue; + LongHashtable mAlreadyNotified; + + static final class WorkItem { + public int WorkType; + public Object Item; + public EveBerryBackgroundActionListener Listener; + public Object Closure; + + public WorkItem(int worktype, Object theItem, EveBerryBackgroundActionListener theListener, Object theClosure) { + WorkType = worktype; + Item = theItem; + Listener = theListener; + Closure = theClosure; + } + } + + EveBerryBackground() { + mRunning = false; + mWorkQueue = new Vector(); + mAlreadyNotified = new LongHashtable(); + } + + public static void StartBackgroundRunnable() { + if (sRunnable == null) { + sRunnable = new EveBerryBackground(); + sThread = new Thread(sRunnable); + sThread.start(); + } + } + + public static void StopBackgroundRunnable() { + if (sRunnable != null) { + sRunnable.sFinished = true; + synchronized(sRunnable) { + sRunnable.notify(); + } + EveBerry.debug("joining thread..."); + try { + sThread.join(); + } catch (Exception e) { } + } + } + + public static EveBerryBackground GetBackgroundRunnable() { + StartBackgroundRunnable(); + return sRunnable; + } + + public static void endBackgroundRunnable() { + sFinished = true; + if (sRunnable != null) + sRunnable.notify(); + } + + public synchronized void requestCharacterUpdate(EveCharacterInfo eci) { + requestCharacterUpdate(eci, null, null); + } + + public synchronized void requestCharacterUpdate(EveCharacterInfo eci, + EveBerryBackgroundActionListener listener, + Object closure) + { + queueCharacterUpdate(eci, listener, closure); + + // tell the thread to wake up + if (sRunnable != null) + sRunnable.notify(); + } + + public synchronized void queueCharacterUpdate(EveCharacterInfo eci, + EveBerryBackgroundActionListener listener, + Object closure) + { + // check if the work queue contains the thing already; + // note that this method is synchronized on this object, which is what + // all access to the work queue is under. + + for (int i = 0; i < mWorkQueue.size(); i++) { + WorkItem wi = (WorkItem) mWorkQueue.elementAt(i); + if (wi.WorkType == ITEM_CHARACTER_UPDATE && + wi.Item == eci) + { + return; + } + } + + eci.UpdateInProgress = true; + + mWorkQueue.addElement(new WorkItem(ITEM_CHARACTER_UPDATE, eci, listener, closure)); + } + + public synchronized void requestCharacterList(String uid, String key, + EveBerryBackgroundActionListener listener, + Object closure) + { + String [] strs = new String[2]; + strs[0] = uid; + strs[1] = key; + + mWorkQueue.addElement(new WorkItem(ITEM_CHARACTER_LIST_REQUEST, strs, listener, closure)); + + // tell the thread to wake up + if (sRunnable != null) + sRunnable.notify(); + } + + public void run() { + mRunning = true; + + while (!sFinished) { + EveCharacterManager mgr = EveCharacterManager.Manager(); + + synchronized(this) { + // do the entire work queue at once + for (int i = 0; i < mWorkQueue.size(); i++) { + final WorkItem wi = (WorkItem) mWorkQueue.elementAt(i); + if (wi.WorkType == ITEM_CHARACTER_UPDATE) { + final EveCharacterInfo eci = (EveCharacterInfo) wi.Item; + + eci.UpdateInProgress = true; + UpdateCharacterInfo(eci); + mgr.getBitmapPortraitForCharacter(eci.ID); + eci.UpdateInProgress = false; + + EveBerry.sApp.invokeLater(new Runnable() { + public void run() { + EveCharacterManager.Manager().characterUpdated(eci); + + // this is kind of stupid, since we force a characterUpdated bit above, but meh. + if (wi.Listener != null) + wi.Listener.onActionComplete(eci, wi.Closure); + }}); + } else if (wi.WorkType == ITEM_CHARACTER_LIST_REQUEST) { + String [] auth = (String []) wi.Item; + + final EveCharacterList ecl = EveAPI.GetCharacters(auth[0], auth[1]); + + if (wi.Listener != null) { + EveBerry.sApp.invokeLater(new Runnable() { + public void run() { + wi.Listener.onActionComplete(ecl, wi.Closure); + }}); + } + } + } + + mWorkQueue.removeAllElements(); + + long nextUpdateDelay = computeUpdateTimes(); + + if (nextUpdateDelay == 0) { + synchronized(mgr) { + Enumeration iter = mgr.enumerateCharacters(); + while (iter.hasMoreElements()) { + EveCharacterInfo eci = (EveCharacterInfo) iter.nextElement(); + EveBerry.debug("++++ Background: queuing update for " + eci.Name); + queueCharacterUpdate(eci, null, null); + } + } + } + + // check if we need to notify anything + checkAndDispatchNotifications(); + + EveBerry.debug("XXXXXXX nextUpdateDelay in: " + nextUpdateDelay); + + // don't wait if we're sFinished + if (sFinished) + break; + + try { + if (nextUpdateDelay > 0) { + // wait the given ms + wait(nextUpdateDelay); + } else if (nextUpdateDelay == -1) { + // wait until we're notified; there are no + // characters. + wait(); + } + } catch (Exception e) { } + } + } + + mRunning = false; + } + + static void UpdateCharacterInfo(EveCharacterInfo eci) { + try { + EveCharacterSheet ecs = EveAPI.GetCharacterSheet(eci.UserID, eci.UserKey, eci.ID); + EveSkillInTraining est = EveAPI.GetSkillInTraining(eci.UserID, eci.UserKey, eci.ID); + + eci.Name = ecs.name; + eci.Corporation = ecs.corporationName; + eci.Balance = ecs.balance; + eci.SkillPoints = 0; // XXX todo + + if (est.skillInTraining) { + eci.SkillInTraining = EveSkills.IdToSkillName((int) est.typeID); + eci.SkillRank = EveSkills.IdToSkillRank((int) est.typeID); + eci.SkillTargetLevel = est.destinationLevel; + eci.SkillStartSP = est.startSP; + eci.SkillEndSP = est.destinationSP; + eci.SkillStartTime = est.startTime; + eci.SkillEndTime = est.endTime; + } else { + eci.SkillInTraining = null; + } + + eci.LastUpdateTime = System.currentTimeMillis(); + } catch (Exception ex) { + EveBerry.debug("Exception caught in UpdateCharacterInfo! " + ex); + } + } + + void checkAndDispatchNotifications() { + EveCharacterManager mgr = EveCharacterManager.Manager(); + synchronized (mgr) { + Enumeration iter = mgr.enumerateCharacters(); + while (iter.hasMoreElements()) { + EveCharacterInfo eci = (EveCharacterInfo) iter.nextElement(); + boolean doNotify = false; + + if (!eci.NotificationEnabled) + continue; + + if (eci.UpdateInProgress) + continue; + + if (eci.SkillInTraining != null) { + long leftms = eci.getTrainingTimeRemaining() * 1000; + + EveBerry.debug("XXX leftms notify: " + leftms); + + if (leftms <= mNotificationTimeMS) { + // did we already notify about this? + if (!mAlreadyNotified.containsKey(eci.ID) || + !eci.SkillInTraining.equals((String) mAlreadyNotified.get(eci.ID))) + { + doNotify = true; + } + } + } else { + // there's nothing training; we should notify on this as well + if (!mAlreadyNotified.containsKey(eci.ID) || + !((String) mAlreadyNotified.get(eci.ID)).equals("")) + { + doNotify = true; + } + } + + if (doNotify) { + EveBerry.debug("Doing notify for " + eci.Name + "!"); + + /*Q*/NotificationsManager.triggerImmediateEvent(EveBerry.sNotificationID, 0, eci, null); + if (eci.SkillInTraining != null) + mAlreadyNotified.put(eci.ID, eci.SkillInTraining); + else + mAlreadyNotified.put(eci.ID, ""); + } + } + } + } + + long computeUpdateTimes() { + // figure out the next time we need to update each char; + // synchronize on the mgr to ensure that noone else is + // modifying the manager at the same time + + long now = System.currentTimeMillis(); + long doUpdateIn = mUpdateTimeMS; + + EveCharacterManager mgr = EveCharacterManager.Manager(); + synchronized (mgr) { + Enumeration iter = mgr.enumerateCharacters(); + + // no elements? + if (!iter.hasMoreElements()) + return -1; + + while (iter.hasMoreElements()) { + EveCharacterInfo eci = (EveCharacterInfo) iter.nextElement(); + long thisUpdateIn = mUpdateTimeMS; + + if (eci.LastUpdateTime == 0) { + // do an update now + thisUpdateIn = 0; + } else { + // ms = time between now and last update time + long ms = now - eci.LastUpdateTime; + + EveBerry.debug("+++ elapsed " + ms + " since last update"); + + // check skill completion + if (eci.SkillInTraining != null) { + long msleft = eci.getTrainingTimeRemaining()*1000; + + EveBerry.debug("+++ left " + msleft + " to skill completion"); + + // do an update when we're supposed to notify + if (msleft > mNotificationTimeMS) { + thisUpdateIn = Math.min(msleft - mNotificationTimeMS, thisUpdateIn); + } else if (ms > mUpdateTimeMS) { + thisUpdateIn = 0; + } + } else if (ms > mUpdateTimeMS) { + thisUpdateIn = 0; + } + + EveBerry.debug("+++ thisUpdateIn " + thisUpdateIn); + } + + eci.NextUpdateTime = now + thisUpdateIn; + doUpdateIn = Math.min(thisUpdateIn, doUpdateIn); + } + } + + return doUpdateIn; + } +} \ No newline at end of file diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 src/org/mrrupert/eveberry/EveCacheableItem.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/mrrupert/eveberry/EveCacheableItem.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,29 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is EveBerry. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +package org.mrrupert.eveberry; + +public class EveCacheableItem { + public long cachedUntil; +} diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 src/org/mrrupert/eveberry/EveCharacterInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/mrrupert/eveberry/EveCharacterInfo.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,225 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is EveBerry. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +package org.mrrupert.eveberry; + +import net.rim.device.api.ui.*; +import net.rim.device.api.ui.component.*; +import net.rim.device.api.ui.container.*; +import net.rim.device.api.i18n.*; +import net.rim.device.api.system.*; +import net.rim.device.api.util.*; +import net.rim.device.api.collection.util.*; + +import java.util.*; + +class EveCharacterInfo implements Persistable +{ + public long ID; + + public String UserID; + public String UserKey; + + public String Name; + public String Corporation; + public double Balance; + public long SkillPoints; + + public String SkillInTraining; + public int SkillRank; + + public long SkillStartTime; // seconds since epoch + public long SkillEndTime; + public long SkillStartSP; // SP at SkillStartTime + public long SkillEndSP; + + public int SkillTargetLevel; + + public long LastUpdateTime; + public long NextUpdateTime; + + public boolean UpdateInProgress; + + public boolean NotificationEnabled; + + EveCharacterInfo(long aid, String uid, String key) { + ID = aid; + + UserID = uid; + UserKey = key; + + LastUpdateTime = 0; + NextUpdateTime = 0; + + UpdateInProgress = false; + + NotificationEnabled = true; + } + + public Bitmap getCharPortrait() { + return EveCharacterManager.Manager().getCachedBitmapPortraitForCharacter(ID); + } + + // using CurSP, LastUpdateTime, and SkillInTrainingRemaining, + // figure out how many SP are in the skill now + public long getTrainingCurrentSP() { + if (SkillInTraining == null) + return 0; + + long trainingSeconds = SkillEndTime - SkillStartTime; + long trainingSP = SkillEndSP - SkillStartSP; + double spPerSecond = trainingSP / (double) trainingSeconds; + + long elapsed = (System.currentTimeMillis() / 1000) - SkillStartTime; + if (elapsed < 0) + elapsed = 0; + + float percent = elapsed / (float) trainingSeconds; + if (percent >= 1.0) + return SkillEndSP; + + return SkillStartSP + (long) (trainingSP * percent); + } + + public double getTrainingTimePercentComplete() { + if (SkillInTraining == null) + return 1.0; + + long trainingSeconds = SkillEndTime - SkillStartTime; + long elapsed = (System.currentTimeMillis() / 1000) - SkillStartTime; + if (elapsed < 0) + elapsed = 0; + + return elapsed / (float) trainingSeconds; + } + + public String getTrainingLevelString() { + if (SkillTargetLevel == 1) return "I"; + if (SkillTargetLevel == 2) return "II"; + if (SkillTargetLevel == 3) return "III"; + if (SkillTargetLevel == 4) return "IV"; + if (SkillTargetLevel == 5) return "V"; + return "(?)"; + } + + public long getTrainingTimeRemaining() { + if (SkillInTraining == null) + return 0; + + long trainingSeconds = SkillEndTime - SkillStartTime; + long elapsed = (System.currentTimeMillis() / 1000) - SkillStartTime; + if (elapsed < 0) + elapsed = 0; + + return trainingSeconds - elapsed; + } + + public String getTrainingTimeString() { + int left = (int) getTrainingTimeRemaining(); + + if (left <= 0) + return "Complete"; + + int days = left / (60*60*24); + left = left % (60*60*24); + + int hours = left / (60*60); + left = left % (60*60); + + int minutes = left / 60; + left = left % 60; + + int seconds = left; + + String s = ""; + + if (days != 0) { + s += days + " days"; + if (hours != 0 || minutes != 0 || seconds != 0) + s += ", "; + } + + if (hours != 0) { + s += hours + " hours"; + if (minutes != 0 || seconds != 0) + s += ", "; + } + + if (minutes != 0) { + s += minutes + " minutes"; + if (seconds != 0) + s += ", "; + } + + if (seconds != 0) { + s += seconds + " seconds"; + } + + return s; + } + + public String getTrainingTimeShortString() { + int left = (int) getTrainingTimeRemaining(); + + if (left <= 0) + return "Complete"; + + int days = left / (60*60*24); + left = left % (60*60*24); + + int hours = left / (60*60); + left = left % (60*60); + + int minutes = left / 60; + left = left % 60; + + int seconds = left; + + String s = ""; + + if (days != 0) { + s += days + "d"; + if (hours != 0 || minutes != 0 || seconds != 0) + s += " "; + } + + if (hours != 0) { + s += hours + "h"; + if (minutes != 0 || seconds != 0) + s += " "; + } + + if (minutes != 0) { + s += minutes + "m"; + if (seconds != 0) + s += " "; + } + + if (seconds != 0) { + s += seconds + "s"; + } + + return s; + } +} diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 src/org/mrrupert/eveberry/EveCharacterList.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/mrrupert/eveberry/EveCharacterList.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,30 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is EveBerry. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +package org.mrrupert.eveberry; + +public class EveCharacterList extends EveCacheableItem { + public String CharacterNames[]; + public long CharacterIDs[]; +} diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 src/org/mrrupert/eveberry/EveCharacterListField.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/mrrupert/eveberry/EveCharacterListField.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,445 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is EveBerry. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +package org.mrrupert.eveberry; + +import net.rim.device.api.ui.*; +import net.rim.device.api.ui.component.*; +import net.rim.device.api.ui.container.*; +import net.rim.device.api.i18n.*; +import net.rim.device.api.system.*; + +import net.rim.device.api.collection.util.*; + +import java.util.*; +import java.lang.*; + +class EveCharacterField extends Field +{ + public static int kPortraitSize = 64; + public static int kDefaultHeight = kPortraitSize+2; + public static int kBarWidth = 60; + + public EveCharacterInfo CharacterInfo; + + Font mFont; + int mCharNameWidth, mFontHeight; + boolean mDidLayout; + + public EveCharacterField(EveCharacterInfo eci) { + CharacterInfo = eci; + mDidLayout = false; + } + + protected void layout(int width, int height) { + mFont = getFont(); + mFontHeight = mFont.getHeight(); + mCharNameWidth = mFont.getAdvance(CharacterInfo.Name); + + setExtent(Math.min(width, getPreferredWidth()), + Math.min(height, getPreferredHeight())); + + mDidLayout = true; + } + + public int getPreferredWidth() { + // we want this thing to be as wide as possible + return 640; + } + + public int getPreferredHeight() { + // we want enough for 3 lines of text + int fheight = mFontHeight * 3; + + // 2 pixels for 1px of padding above and below the rendered area + return Math.max (kPortraitSize + 2, fheight + 2); + } + + // field looks like: + // + // +----+ Character Name 3d 12h 34m + // |....| Shield Operation V [#### ] + // |....| 7,654,123 SP + // +----+ 1,123,456.98 ISK + + protected void paint(Graphics g) { + int w = getWidth(); + int h = getHeight(); + int major, minor; + + int numRows = (h - 2) / mFontHeight; + + if (w > h) { + major = w; + minor = h; + } else { + major = h; + minor = w; + } + + // draw the character portrait + if (CharacterInfo.getCharPortrait() != null) { + g.drawBitmap(1, 1, minor-2, minor-2, CharacterInfo.getCharPortrait(), 0, 0); + } else { + g.setColor(0x00000000); + g.fillRect(1, 1, minor-2, minor-2); + g.setColor(0x00aaaaaa); + g.drawRect(1, 1, minor-2, minor-2); + } + + g.setFont(mFont); + g.setColor(g.BLACK); + + String trainingString = null; + if (CharacterInfo.SkillInTraining != null) + trainingString = CharacterInfo.getTrainingTimeShortString(); + int timeLeftWidth = mFont.getAdvance(trainingString); + int nameWidth = mCharNameWidth; + + w -= minor+2; + major -= minor+2; + + if (CharacterInfo.UpdateInProgress) + timeLeftWidth = 0; + + // first row + g.translate(minor+2, 1); + + // 2 pixels in between + if (mCharNameWidth > w - timeLeftWidth - 2) { + // it's too big; crop the name as the less important bit + nameWidth = w - timeLeftWidth - 2; + if (nameWidth < 0) { + // ok, this is just screwed; chomp both + nameWidth = (w - 1) / 2; + timeLeftWidth = (w - 1) / 2; + } + } + + // draw the character name + g.drawText(CharacterInfo.Name, 0, 0, DrawStyle.ELLIPSIS, nameWidth); + + // draw the time remaining + if (timeLeftWidth != 0) + g.drawText(trainingString, w - timeLeftWidth - 1, 0); + + // second row, if room + if (numRows > 1) { + + g.translate(0, mFontHeight); + + if (CharacterInfo.UpdateInProgress) { + g.setColor(0x00666666); + g.drawText("Updating...", 0, 0); + g.setColor(g.BLACK); + } else if (CharacterInfo.SkillInTraining != null) { + String skillString = CharacterInfo.SkillInTraining + " " + CharacterInfo.getTrainingLevelString(); + int skillStringWidth = mFont.getAdvance(skillString); + + if (skillStringWidth > w - kBarWidth - 2) + skillStringWidth = w - kBarWidth - 2; + + // draw the skill name + level + g.drawText(skillString, 0, 0, DrawStyle.ELLIPSIS, skillStringWidth); + + // draw the progress box + g.setColor(0x00444444); + g.drawRect(w - 1 - kBarWidth, 1, kBarWidth, mFontHeight - 2); + + int borderWidth = 1; + int barWidth; + + // leave a 1px border between the frame and the bar, if we have enough room + if (mFontHeight-2 <= 6) + borderWidth = 0; + + barWidth = (int) Math.floor((kBarWidth-4*borderWidth)*CharacterInfo.getTrainingTimePercentComplete() + 0.5); + + g.fillRect(w - kBarWidth - 1 + 2*borderWidth, + 3, + barWidth, + mFontHeight - 4 - 2*borderWidth); + + g.setColor(g.BLACK); + } else { + g.drawText("NO SKILL IN TRAINING", 1, 1); + g.setColor(0x00ff0000); + g.drawText("NO SKILL IN TRAINING", 0, 0); + g.setColor(g.BLACK); + } + } + + // we're done here if the update is in progress + if (CharacterInfo.UpdateInProgress) + return; + + // third row, if room + // SP if we have 4 rows, otherwise balance + if (numRows > 2) { + g.translate(0, mFontHeight); + + drawFinishTime(g); + + /* + if (numRows > 3) + drawSP(g); + else + drawBalance(g); + */ + } + + // fourth row, if room + if (numRows > 3) { + g.translate(0, mFontHeight); + + // if we have 4 or more rows, we already put the SP on the third row, so put the ISK here + drawBalance(g); + } + } + + void drawFinishTime(Graphics g) { + Date d = new Date(CharacterInfo.SkillEndTime * 1000); + Calendar c = Calendar.getInstance(); + c.setTime(d); + + DateFormat df = DateFormat.getInstance(DateFormat.DATE_LONG | DateFormat.TIME_SHORT); + StringBuffer sb = new StringBuffer(); + df.format(c, sb, null); + + g.drawText(sb.toString(), 0, 0); + } + + void drawBalance(Graphics g) { + String s = FormatDouble(CharacterInfo.Balance) + " ISK"; + g.drawText(s, 0, 0); + } + + void drawSP(Graphics g) { + String s; + + if (CharacterInfo.SkillInTraining != null) + s = FormatLong(CharacterInfo.SkillPoints + (CharacterInfo.getTrainingCurrentSP() - CharacterInfo.SkillStartSP)) + " SP"; + else + s = FormatLong(CharacterInfo.SkillPoints) + " SP"; + + g.drawText(s, 0, 0); + } + + public void updateInfo() { + invalidate(); + } + + // Causes the fields within this row manager to be layed out then + // painted. + public void drawRow(Graphics g, int x, int y, int width, int height) + { + if (!mDidLayout) { + layout(width, height); + } + + // Place this row manager within its enclosing list. + setPosition(x, y); + + // Apply a translating/clipping transformation to the graphics + // context so that this row paints in the right area. + g.pushRegion(getExtent()); + paint(g); + g.popContext(); + } + + static String FormatPad3(long lv, boolean pad) { + if (!pad || lv >= 100) + return Long.toString(lv); + if (lv >= 10) + return "0" + lv; + return "00" + lv; + } + + // this should be elsewhere + static String FormatLong(long lval) { + boolean zeroes = false; + + String sval = ""; + if (lval >= 1000000000000L) { + long left = lval % 1000000000000L; + sval += (lval / 1000000000000L) + ","; + lval = left; + zeroes = true; + } + + if (lval >= 1000000000) { + long left = lval % 1000000000; + sval += FormatPad3(lval / 1000000000L, zeroes) + ","; + lval = left; + zeroes = true; + } else if (zeroes) { + sval += "000,"; + } + + if (lval >= 1000000) { + long left = lval % 1000000; + sval += FormatPad3(lval / 1000000L, zeroes) + ","; + lval = left; + zeroes = true; + } else if (zeroes) { + sval += "000,"; + } + + if (lval >= 1000) { + long left = lval % 1000; + sval += FormatPad3(lval / 1000L, zeroes) + ","; + lval = left; + zeroes = true; + } else if (zeroes) { + sval += "000,"; + } + + if (lval > 0) { + sval += FormatPad3(lval, zeroes); + } else if (zeroes) { + sval += "000"; + } else { + sval += "0"; + } + + return sval; + } + + static String FormatDouble(double d) { + long lval = (long) d; + long frac = (long) ((double)((d - lval) * 100)); + + String sval = FormatLong(lval); + if (frac > 0) { + sval += "." + frac; + } else { + sval += ".00"; + } + + return sval; + } + +} + +class EveCharacterListField extends ListField +{ + private Vector mRows; + + public EveCharacterListField() { + mRows = new Vector(); + setRowHeight(EveCharacterField.kDefaultHeight); + setSize(0); + setCallback(RENDERER); + } + + public EveCharacterInfo charInfoAt(int index) { + return charFieldAt(index).CharacterInfo; + } + + EveCharacterField charFieldAt(int index) { + return (EveCharacterField) mRows.elementAt(index); + } + + public EveCharacterListField(EveCharacterInfo[] characters) { + int numRows = characters.length; + + mRows = new Vector(numRows); + for (int i = 0; i < numRows; i++) { + EveCharacterField ecl = new EveCharacterField(characters[i]); + mRows.addElement(ecl); + } + + setRowHeight(EveCharacterField.kDefaultHeight); + setSize(numRows); + setCallback(RENDERER); + } + + public void updateCharacters() { + for (int i = 0; i < mRows.size(); i++) { + charFieldAt(i).updateInfo(); + } + + invalidate(); + } + + public void addCharacter(EveCharacterInfo eci) { + EveCharacterField ecl = new EveCharacterField(eci); + + mRows.addElement(ecl); + setSize(mRows.size()); + } + + public void removeCharacter(long id) { + for (int i = 0; i < mRows.size(); i++) { + if (charFieldAt(i).CharacterInfo.ID == id) { + mRows.removeElementAt(i); + setSize(mRows.size()); + return; + } + } + } + + private static final ListFieldCallback RENDERER = new ListFieldCallback() + { + public void drawListRow(ListField listField, Graphics graphics, + int index, int y, int width) + { + EveCharacterListField elf = (EveCharacterListField) listField; + EveCharacterField layout = elf.charFieldAt(index); + + layout.drawRow(graphics, 0, y, width, elf.getRowHeight()); + } + + public int getPreferredWidth(ListField listField) { + EveCharacterListField elf = (EveCharacterListField) listField; + int w = 0; + + for (int i = 0; i < elf.mRows.size(); i++) { + int pw = elf.charFieldAt(i).getPreferredWidth(); + if (w < pw) + w = pw; + } + + return w; + } + + public Object get(ListField listField, int index) { + EveCharacterListField elf = (EveCharacterListField) listField; + return elf.charFieldAt(index).CharacterInfo; + } + + // prefix searching is not supported + public int indexOfList(ListField listField, String prefix, int start) + { + EveCharacterListField elf = (EveCharacterListField) listField; + + for (int i = start; i < elf.mRows.size(); i++) { + if (elf.charFieldAt(i).CharacterInfo.Name.startsWith(prefix)) + return i; + } + + return -1; + } + }; +} diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 src/org/mrrupert/eveberry/EveCharacterManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/mrrupert/eveberry/EveCharacterManager.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,228 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is EveBerry. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +package org.mrrupert.eveberry; + +import java.util.*; + +import net.rim.device.api.ui.*; +import net.rim.device.api.ui.component.*; +import net.rim.device.api.ui.container.*; +import net.rim.device.api.i18n.*; +import net.rim.device.api.system.*; +import net.rim.device.api.util.*; + +import net.rim.device.api.collection.util.*; + +interface EveCharacterListener { + public void onCharacterAdded(long id); + public void onCharacterRemoved(long id); + public void onCharacterUpdated(long id); +} + +class EveCharacterManager { + private static EveCharacterManager sManager; + /*Q*/private static PersistentObject sPersistCharacters; + /*Q*/private static PersistentObject sPersistPortraits; + + private static LongHashtable sCharactersTable; + private static LongHashtable sPortraitsTable; + private static LongHashtable sPortraitBitmapsTable; + + // hash of "org.mrrupert.eveberry.CharacterInfoHash" + private static long kCharacterInfoHashKey = 0x4c6f1204bd1d2c0aL; + + // hash of "org.mrrupert.eveberry.CharacterPortraitHash" + private static long kCharacterPortraitHashKey = 0x653d623598cad02eL; + + private static Object sSyncObject; + + static { + sSyncObject = new Object(); + } + + public static EveCharacterManager Manager() { + synchronized(sSyncObject) { + if (sManager == null) { + /*Q*/sPersistCharacters = PersistentStore.getPersistentObject(kCharacterInfoHashKey); + /*Q*/sPersistPortraits = PersistentStore.getPersistentObject(kCharacterPortraitHashKey); + + /*Q*/sCharactersTable = (LongHashtable) sPersistCharacters.getContents(); + /*Q*/sPortraitsTable = (LongHashtable) sPersistPortraits.getContents(); + + if (sCharactersTable == null) { + sCharactersTable = new LongHashtable(); + /*Q*/sPersistCharacters.setContents(sCharactersTable); + + // if the char table got blown away for whatever reason, + // blow away the portraits table as well + sPortraitsTable = null; + } else { + Enumeration iter = sCharactersTable.elements(); + while (iter.hasMoreElements()) { + EveCharacterInfo eci = (EveCharacterInfo) iter.nextElement(); + EveBerry.debug("Found existing character: " + eci.ID + " " + eci.Name); + if (eci.UpdateInProgress) { + EveBerry.debug("... character is in update, that's weird; forcing one"); + eci.LastUpdateTime = 0; + } + } + } + + if (sPortraitsTable == null) { + sPortraitsTable = new LongHashtable(); + /*Q*/sPersistPortraits.setContents(sPortraitsTable); + } + + EveBerry.debug("Character Manager: chars hashtable has " + sCharactersTable.size() + " entries"); + + sPortraitBitmapsTable = new LongHashtable(); + + sManager = new EveCharacterManager(); + } + + return sManager; + } + } + + Vector mListeners; + + EveCharacterManager() { + mListeners = new Vector(); + } + + public synchronized void deleteCharacter(long id) { + // throw? + if (!sCharactersTable.containsKey(id)) + return; + + sCharactersTable.remove(id); + sPortraitsTable.remove(id); + sPortraitBitmapsTable.remove(id); + + Vector tmpListeners = mListeners; + if (tmpListeners != null) + for (int j = 0; j < tmpListeners.size(); j++) + ((EveCharacterListener) tmpListeners.elementAt(j)).onCharacterRemoved(id); + + /*Q*/synchronized (PersistentStore.getSynchObject()) { + /*Q*/ sPersistCharacters.commit(); + /*Q*/ sPersistPortraits.commit(); + /*Q*/} + } + + public void addCharacter(String uid, String key, String charname, long id) { + // throw, character already exists + if (sCharactersTable.containsKey(id)) + return; + + EveCharacterInfo eci = new EveCharacterInfo(id, uid, key); + eci.Name = charname; + + sCharactersTable.put(id, eci); + + Vector tmpListeners = mListeners; + if (tmpListeners != null) + for (int j = 0; j < tmpListeners.size(); j++) + ((EveCharacterListener) tmpListeners.elementAt(j)).onCharacterAdded(id); + + /*Q*/sPersistCharacters.commit(); + } + + public synchronized EveCharacterInfo getCharacter(long id) { + return (EveCharacterInfo) sCharactersTable.get(id); + } + + public synchronized Bitmap getCachedBitmapPortraitForCharacter(long id) { + // do we have a bitmap cached? + if (sPortraitBitmapsTable.containsKey(id)) + return (Bitmap) sPortraitBitmapsTable.get(id); + + // ok, how about an already-downloaded compressed bitmap? + ByteVector data; + if (sPortraitsTable.containsKey(id)) { + data = (ByteVector) sPortraitsTable.get(id); + } else { + return null; + } + + EncodedImage ei = EncodedImage.createEncodedImage(data.getArray(), 0, -1); + Bitmap b = ei.getBitmap(); + sPortraitBitmapsTable.put(id, b); + return b; + } + + public Bitmap getBitmapPortraitForCharacter(long id) { + // do we have a bitmap cached? + Bitmap b = getCachedBitmapPortraitForCharacter(id); + if (b != null) + return b; + + // ok fine, we'll fetch it + ByteVector data = EveAPI.GetCharacterImageData(id); + + if (data != null) { + synchronized(this) { + sPortraitsTable.put(id, data); + /*Q*/sPersistPortraits.commit(); + + EncodedImage ei = EncodedImage.createEncodedImage(data.getArray(), 0, -1); + b = ei.getBitmap(); + sPortraitBitmapsTable.put(id, b); + } + } + + return b; + } + + public void persistAll() { + /*Q*/synchronized (PersistentStore.getSynchObject()) { + /*Q*/ sPersistCharacters.commit(); + /*Q*/ sPersistPortraits.commit(); + /*Q*/} + } + + public void characterUpdated(EveCharacterInfo eci) { + Vector tmpListeners = mListeners; + if (tmpListeners != null) + for (int j = 0; j < tmpListeners.size(); j++) + ((EveCharacterListener) tmpListeners.elementAt(j)).onCharacterUpdated(eci.ID); + + /*Q*/synchronized (PersistentStore.getSynchObject()) { + /*Q*/ sPersistCharacters.commit(); + /*Q*/} + } + + public Enumeration enumerateCharacters() { + return sCharactersTable.elements(); + } + + public synchronized void addListener(EveCharacterListener ecl) { + mListeners = ListenerUtilities.addListener(mListeners, ecl); + } + + public synchronized void removeListener(EveCharacterListener ecl) { + mListeners = ListenerUtilities.removeListener(mListeners, ecl); + } +} diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 src/org/mrrupert/eveberry/EveCharacterSheet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/mrrupert/eveberry/EveCharacterSheet.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,45 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is EveBerry. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +package org.mrrupert.eveberry; + +public class EveCharacterSheet extends EveCacheableItem { + public long id; + public String name; + public String race; + public String corporationName; + public long corporationID; + public double balance; + + public int intelligence; + public int memory; + public int charisma; + public int perception; + public int willpower; + + /* TODO implants */ + + /* TODO skills */ +} + diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 src/org/mrrupert/eveberry/EveEditCharacterScreen.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/mrrupert/eveberry/EveEditCharacterScreen.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,174 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is EveBerry. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +package org.mrrupert.eveberry; + +import net.rim.device.api.ui.*; +import net.rim.device.api.ui.component.*; +import net.rim.device.api.ui.container.*; +import net.rim.device.api.i18n.*; +import net.rim.device.api.system.*; + +import net.rim.device.api.collection.util.*; + +import java.io.*; + +final class EveEditCharacterScreen extends MainScreen +{ + BasicEditField mUserIDField; + BasicEditField mUserKeyField; + + ObjectChoiceField mChoiceField; + + EveCharacterList mCharList; + + LabelField mLoginStatusField; + + public EveEditCharacterScreen() { + super(DEFAULT_MENU | DEFAULT_CLOSE); + + setTitle(new LabelField("Enter EVE account information", LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH)); + + mUserIDField = new BasicEditField("User ID:", "", BasicEditField.DEFAULT_MAXCHARS, + BasicEditField.NO_COMPLEX_INPUT | + BasicEditField.NO_LEARNING | + BasicEditField.NO_NEWLINE); + + mUserKeyField = new BasicEditField("API Key:", "", BasicEditField.DEFAULT_MAXCHARS, + BasicEditField.NO_COMPLEX_INPUT | + BasicEditField.NO_LEARNING | + BasicEditField.NO_NEWLINE); + + add(mUserIDField); + add(mUserKeyField); + + add(new SeparatorField()); + + final EveEditCharacterScreen self = this; + + LabelField fetchCharacters = new RunnableLabelField("Fetch Characters...", Field.FOCUSABLE) { + public void run() { + EveBerryBackgroundActionListener bal = new EveBerryBackgroundActionListener() { + public void onActionComplete(Object result, Object token) { + EveCharacterList ecl = (EveCharacterList) result; + EveEditCharacterScreen ecs = (EveEditCharacterScreen) token; + + synchronized (Application.getEventLock()) { + if (ecl == null) { + ecs.mLoginStatusField.setText("Error logging in! (Check uid/key!)"); + mChoiceField.setChoices(null); + } else { + ecs.mLoginStatusField.setText("Login success!"); + mChoiceField.setChoices(ecl.CharacterNames); + mChoiceField.setDirty(true); + + mCharList = ecl; + } + } + } + }; + + mLoginStatusField.setText("Retrieving characters..."); + + EveBerryBackground.GetBackgroundRunnable().requestCharacterList(mUserIDField.getText(), + mUserKeyField.getText(), + bal, + self); + } + }; + + add(fetchCharacters); + + mLoginStatusField = new LabelField("", LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH | LabelField.NON_FOCUSABLE); + + add(mLoginStatusField); + + add(new SeparatorField()); + + mChoiceField = new ObjectChoiceField("Choose Character", null); + + add(mChoiceField); + } + + public void save() throws IOException { + // ok, we're being asked to save + + EveBerry.debug("We're in save()"); + + // ignore, XXX do something + if (mCharList == null) + return; + + int idx = mChoiceField.getSelectedIndex(); + if (idx == -1) + return; + + EveBerry.debug("Calling addCharacter: " + mUserIDField.getText() + " " + mUserKeyField.getText() + " " + mCharList.CharacterNames[idx] + " " + mCharList.CharacterIDs[idx]); + + EveCharacterManager.Manager().addCharacter(mUserIDField.getText(), + mUserKeyField.getText(), + mCharList.CharacterNames[idx], + mCharList.CharacterIDs[idx]); + } + + static class RunnableLabelField extends LabelField implements Runnable { + RunnableLabelField() { + super(); + } + + RunnableLabelField(Object s) { + super(s); + } + + RunnableLabelField(Object s, int offset, int len, long style) { + super(s, offset, len, style); + } + + RunnableLabelField(Object s, long style) { + super(s, style); + } + + protected boolean navigationClick(int status, int time) { + run(); + return true; + } + + public boolean keyChar(char key, int status, int time) { + boolean retval = false; + + switch (key) { + case Characters.ENTER: + run(); + retval = true; + break; + } + + return retval; + } + + public void run () { + // nothing by default + } + } +} diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 src/org/mrrupert/eveberry/EveSkillInTraining.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/mrrupert/eveberry/EveSkillInTraining.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,39 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is EveBerry. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +package org.mrrupert.eveberry; + +public class EveSkillInTraining extends EveCacheableItem { + public boolean skillInTraining; + + // seconds since epoch GMT + public long startTime; + public long endTime; + + public long typeID; + public long startSP; + public long destinationSP; + public int destinationLevel; +} + diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 src/org/mrrupert/eveberry/EveSkills.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/mrrupert/eveberry/EveSkills.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,467 @@ +package org.mrrupert.eveberry; + +import net.rim.device.api.util.*; + +import java.util.*; + +class EveSkill { + public String Name; + public int ID; + public int Rank; + public int Category; + + public EveSkill(String n, int i, int r, int c) { + Name = n; + ID = i; + Rank = r; + Category = c; + } +} + +class EveSkills { + + static IntHashtable sSkills; + static IntHashtable sCategories; + + static { + sSkills = new IntHashtable(360); + sCategories = new IntHashtable(15); + + InitSkills(); + } + + static EveSkill IdToSkill(int id) { + try { + return (EveSkill) sSkills.get(id); + } catch (Exception ex) { + // nothing + } + + return null; + } + + static String IdToSkillName(int id) { + try { + return IdToSkill(id).Name; + } catch (Exception ex) { + // nothing + } + + return Integer.toString(id); + } + + + static int IdToSkillRank(int id) { + try { + return IdToSkill(id).Rank; + } catch (Exception ex) { + // nothing + } + + return 0; + } + + static String CategoryIdToName(int catid) { + try { + return (String) sCategories.get(catid); + } catch (Exception ex) { + // nothing + } + return Integer.toString(catid); + } + + static int SkillSPForIdAndLevel(int id, int level) { + int rank = IdToSkill(id).Rank; + + return SkillSPForRankAndLevel(rank, level); + } + + static int SkillSPForRankAndLevel(int rank, int level) { + if (level == 0) return 0; + if (level == 1) return 250 * rank; + if (level == 2) return (1414 - 250) * rank; + if (level == 3) return (8000 - 1414) * rank; + if (level == 4) return (45255 - 8000) * rank; + if (level == 5) return (256000 - 45255) * rank; + + return -1; + } + + static void InitSkills() { +sCategories.put(255,"Gunnery"); +sCategories.put(256,"Missile Launcher Operation"); +sCategories.put(257,"Spaceship Command"); +sCategories.put(258,"Leadership"); +sCategories.put(266,"Corporation Management"); +sCategories.put(267,"Learning"); +sCategories.put(268,"Industry"); +sCategories.put(269,"Mechanic"); +sCategories.put(270,"Science"); +sCategories.put(271,"Engineering"); +sCategories.put(272,"Electronics"); +sCategories.put(273,"Drones"); +sCategories.put(274,"Trade"); +sCategories.put(275,"Navigation"); +sCategories.put(278,"Social"); +sSkills.put(11082, new EveSkill("Small Railgun Specialization",11082,255,3)); +sSkills.put(11083, new EveSkill("Small Beam Laser Specialization",11083,255,3)); +sSkills.put(11084, new EveSkill("Small Autocannon Specialization",11084,255,3)); +sSkills.put(11207, new EveSkill("Advanced Weapon Upgrades",11207,255,6)); +sSkills.put(11395, new EveSkill("Deep Core Mining",11395,268,6)); +sSkills.put(11433, new EveSkill("High Energy Physics",11433,270,5)); +sSkills.put(11441, new EveSkill("Plasma Physics",11441,270,5)); +sSkills.put(11442, new EveSkill("Nanite Engineering",11442,270,5)); +sSkills.put(11443, new EveSkill("Hydromagnetic Physics",11443,270,5)); +sSkills.put(11444, new EveSkill("Amarrian Starship Engineering",11444,270,5)); +sSkills.put(11445, new EveSkill("Minmatar Starship Engineering",11445,270,5)); +sSkills.put(11446, new EveSkill("Graviton Physics",11446,270,5)); +sSkills.put(11447, new EveSkill("Laser Physics",11447,270,5)); +sSkills.put(11448, new EveSkill("Electromagnetic Physics",11448,270,5)); +sSkills.put(11449, new EveSkill("Rocket Science",11449,270,5)); +sSkills.put(11450, new EveSkill("Gallentean Starship Engineering",11450,270,5)); +sSkills.put(11451, new EveSkill("Nuclear Physics",11451,270,5)); +sSkills.put(11452, new EveSkill("Mechanical Engineering",11452,270,5)); +sSkills.put(11453, new EveSkill("Electronic Engineering",11453,270,5)); +sSkills.put(11454, new EveSkill("Caldari Starship Engineering",11454,270,5)); +sSkills.put(11455, new EveSkill("Quantum Physics",11455,270,5)); +sSkills.put(11487, new EveSkill("Astronautic Engineering",11487,270,5)); +sSkills.put(11529, new EveSkill("Molecular Engineering",11529,270,5)); +sSkills.put(11566, new EveSkill("Thermic Shield Compensation",11566,271,2)); +sSkills.put(11569, new EveSkill("Armored Warfare Specialist",11569,258,5)); +sSkills.put(11572, new EveSkill("Skirmish Warfare Specialist",11572,258,5)); +sSkills.put(11574, new EveSkill("Wing Command",11574,258,8)); +sSkills.put(11579, new EveSkill("Cloaking",11579,272,6)); +sSkills.put(11584, new EveSkill("Anchoring",11584,266,3)); +sSkills.put(12092, new EveSkill("Interceptors",12092,257,4)); +sSkills.put(12093, new EveSkill("Covert Ops",12093,257,4)); +sSkills.put(12095, new EveSkill("Assault Ships",12095,257,4)); +sSkills.put(12096, new EveSkill("Logistics",12096,257,6)); +sSkills.put(12097, new EveSkill("Destroyers",12097,257,2)); +sSkills.put(12098, new EveSkill("Interdictors",12098,257,5)); +sSkills.put(12099, new EveSkill("Battlecruisers",12099,257,6)); +sSkills.put(12179, new EveSkill("Research Project Management",12179,270,8)); +sSkills.put(12180, new EveSkill("Arkonor Processing",12180,268,4)); +sSkills.put(12181, new EveSkill("Bistot Processing",12181,268,4)); +sSkills.put(12182, new EveSkill("Crokite Processing",12182,268,4)); +sSkills.put(12183, new EveSkill("Dark Ochre Processing",12183,268,3)); +sSkills.put(12184, new EveSkill("Gneiss Processing",12184,268,3)); +sSkills.put(12185, new EveSkill("Hedbergite Processing",12185,268,3)); +sSkills.put(12186, new EveSkill("Hemorphite Processing",12186,268,2)); +sSkills.put(12187, new EveSkill("Jaspet Processing",12187,268,2)); +sSkills.put(12188, new EveSkill("Kernite Processing",12188,268,2)); +sSkills.put(12189, new EveSkill("Mercoxit Processing",12189,268,5)); +sSkills.put(12190, new EveSkill("Omber Processing",12190,268,2)); +sSkills.put(12191, new EveSkill("Plagioclase Processing",12191,268,1)); +sSkills.put(12192, new EveSkill("Pyroxeres Processing",12192,268,1)); +sSkills.put(12193, new EveSkill("Scordite Processing",12193,268,1)); +sSkills.put(12194, new EveSkill("Spodumain Processing",12194,268,3)); +sSkills.put(12195, new EveSkill("Veldspar Processing",12195,268,1)); +sSkills.put(12196, new EveSkill("Scrapmetal Processing",12196,268,5)); +sSkills.put(12201, new EveSkill("Small Artillery Specialization",12201,255,3)); +sSkills.put(12202, new EveSkill("Medium Artillery Specialization",12202,255,5)); +sSkills.put(12203, new EveSkill("Large Artillery Specialization",12203,255,8)); +sSkills.put(12204, new EveSkill("Medium Beam Laser Specialization",12204,255,5)); +sSkills.put(12205, new EveSkill("Large Beam Laser Specialization",12205,255,8)); +sSkills.put(12206, new EveSkill("Medium Railgun Specialization",12206,255,5)); +sSkills.put(12207, new EveSkill("Large Railgun Specialization",12207,255,8)); +sSkills.put(12208, new EveSkill("Medium Autocannon Specialization",12208,255,5)); +sSkills.put(12209, new EveSkill("Large Autocannon Specialization",12209,255,8)); +sSkills.put(12210, new EveSkill("Small Blaster Specialization",12210,255,3)); +sSkills.put(12211, new EveSkill("Medium Blaster Specialization",12211,255,5)); +sSkills.put(12212, new EveSkill("Large Blaster Specialization",12212,255,8)); +sSkills.put(12213, new EveSkill("Small Pulse Laser Specialization",12213,255,3)); +sSkills.put(12214, new EveSkill("Medium Pulse Laser Specialization",12214,255,5)); +sSkills.put(12215, new EveSkill("Large Pulse Laser Specialization",12215,255,8)); +sSkills.put(12241, new EveSkill("Sovereignty",12241,266,8)); +sSkills.put(12305, new EveSkill("Drone Navigation",12305,273,1)); +sSkills.put(12365, new EveSkill("EM Shield Compensation",12365,271,2)); +sSkills.put(12366, new EveSkill("Kinetic Shield Compensation",12366,271,2)); +sSkills.put(12367, new EveSkill("Explosive Shield Compensation",12367,271,2)); +sSkills.put(12376, new EveSkill("Logic",12376,267,3)); +sSkills.put(12383, new EveSkill("Presence",12383,267,3)); +sSkills.put(12385, new EveSkill("Eidetic Memory",12385,267,3)); +sSkills.put(12386, new EveSkill("Focus",12386,267,3)); +sSkills.put(12387, new EveSkill("Clarity",12387,267,3)); +sSkills.put(12441, new EveSkill("Missile Bombardment",12441,256,2)); +sSkills.put(12442, new EveSkill("Missile Projection",12442,256,4)); +sSkills.put(12484, new EveSkill("Amarr Drone Specialization",12484,273,5)); +sSkills.put(12485, new EveSkill("Minmatar Drone Specialization",12485,273,5)); +sSkills.put(12486, new EveSkill("Gallente Drone Specialization",12486,273,5)); +sSkills.put(12487, new EveSkill("Caldari Drone Specialization",12487,273,5)); +sSkills.put(13278, new EveSkill("Archaeology",13278,270,3)); +sSkills.put(13280, new EveSkill("Gunnery Interfaces",13280,270,4)); +sSkills.put(16069, new EveSkill("Remote Armor Repair Systems",16069,269,2)); +sSkills.put(16281, new EveSkill("Ice Harvesting",16281,268,1)); +sSkills.put(16546, new EveSkill("Bureaucratic Connections",16546,278,1)); +sSkills.put(16547, new EveSkill("Financial Connections",16547,278,1)); +sSkills.put(16548, new EveSkill("Political Connections",16548,278,1)); +sSkills.put(16549, new EveSkill("Military Connections",16549,278,1)); +sSkills.put(16550, new EveSkill("Labor Connections",16550,278,1)); +sSkills.put(16551, new EveSkill("Trade Connections",16551,278,1)); +sSkills.put(16552, new EveSkill("High Tech Connections",16552,278,1)); +sSkills.put(16591, new EveSkill("Heavy Assault Ships",16591,257,6)); +sSkills.put(16594, new EveSkill("Procurement",16594,274,3)); +sSkills.put(16595, new EveSkill("Daytrading",16595,274,1)); +sSkills.put(16596, new EveSkill("Wholesale",16596,274,4)); +sSkills.put(16597, new EveSkill("Margin Trading",16597,274,3)); +sSkills.put(16598, new EveSkill("Marketing",16598,274,3)); +sSkills.put(16622, new EveSkill("Accounting",16622,274,3)); +sSkills.put(17940, new EveSkill("Mining Barge",17940,257,4)); +sSkills.put(18025, new EveSkill("Ice Processing",18025,268,5)); +sSkills.put(18580, new EveSkill("Tycoon",18580,274,6)); +sSkills.put(19719, new EveSkill("Transport Ships",19719,257,6)); +sSkills.put(19759, new EveSkill("Long Distance Jamming",19759,272,4)); +sSkills.put(19760, new EveSkill("Frequency Modulation",19760,272,3)); +sSkills.put(19761, new EveSkill("Signal Dispersion",19761,272,5)); +sSkills.put(19766, new EveSkill("Signal Suppression",19766,272,5)); +sSkills.put(19767, new EveSkill("Turret Destabilization",19767,272,5)); +sSkills.put(19921, new EveSkill("Target Painting",19921,272,3)); +sSkills.put(19922, new EveSkill("Signature Focusing",19922,272,5)); +sSkills.put(20209, new EveSkill("Rocket Specialization",20209,256,3)); +sSkills.put(20210, new EveSkill("Standard Missile Specialization",20210,256,3)); +sSkills.put(20211, new EveSkill("Heavy Missile Specialization",20211,256,5)); +sSkills.put(20212, new EveSkill("Cruise Missile Specialization",20212,256,8)); +sSkills.put(20213, new EveSkill("Torpedo Specialization",20213,256,8)); +sSkills.put(20312, new EveSkill("Guided Missile Precision",20312,256,5)); +sSkills.put(20314, new EveSkill("Target Navigation Prediction",20314,256,2)); +sSkills.put(20315, new EveSkill("Warhead Upgrades",20315,256,5)); +sSkills.put(20327, new EveSkill("Capital Energy Turret",20327,255,7)); +sSkills.put(20342, new EveSkill("Advanced Spaceship Command",20342,257,5)); +sSkills.put(20433, new EveSkill("Talocan Technology",20433,270,5)); +sSkills.put(20494, new EveSkill("Armored Warfare",20494,258,2)); +sSkills.put(20495, new EveSkill("Information Warfare",20495,258,2)); +sSkills.put(20524, new EveSkill("Amarr Freighter",20524,257,10)); +sSkills.put(20525, new EveSkill("Amarr Dreadnought",20525,257,12)); +sSkills.put(20526, new EveSkill("Caldari Freighter",20526,257,10)); +sSkills.put(20527, new EveSkill("Gallente Freighter",20527,257,10)); +sSkills.put(20528, new EveSkill("Minmatar Freighter",20528,257,10)); +sSkills.put(20530, new EveSkill("Caldari Dreadnought",20530,257,12)); +sSkills.put(20531, new EveSkill("Gallente Dreadnought",20531,257,12)); +sSkills.put(20532, new EveSkill("Minmatar Dreadnought",20532,257,12)); +sSkills.put(20533, new EveSkill("Capital Ships",20533,257,14)); +sSkills.put(21059, new EveSkill("Shield Compensation",21059,271,2)); +sSkills.put(21071, new EveSkill("Rapid Launch",21071,256,2)); +sSkills.put(21603, new EveSkill("Cynosural Field Theory",21603,272,5)); +sSkills.put(21610, new EveSkill("Jump Fuel Conservation",21610,275,8)); +sSkills.put(21611, new EveSkill("Jump Drive Calibration",21611,275,9)); +sSkills.put(21666, new EveSkill("Capital Hybrid Turret",21666,255,7)); +sSkills.put(21667, new EveSkill("Capital Projectile Turret",21667,255,7)); +sSkills.put(21668, new EveSkill("Citadel Torpedoes",21668,256,7)); +sSkills.put(21718, new EveSkill("Hacking",21718,270,3)); +sSkills.put(21789, new EveSkill("Sleeper Technology",21789,270,5)); +sSkills.put(21790, new EveSkill("Caldari Encryption Methods",21790,270,5)); +sSkills.put(21791, new EveSkill("Minmatar Encryption Methods",21791,270,5)); +sSkills.put(21802, new EveSkill("Capital Shield Operation",21802,271,8)); +sSkills.put(21803, new EveSkill("Capital Repair Systems",21803,269,8)); +sSkills.put(22043, new EveSkill("Tactical Weapon Reconfiguration",22043,255,8)); +sSkills.put(22242, new EveSkill("Capital Ship Construction",22242,269,14)); +sSkills.put(22536, new EveSkill("Mining Foreman",22536,258,2)); +sSkills.put(22551, new EveSkill("Exhumers",22551,257,5)); +sSkills.put(22552, new EveSkill("Mining Director",22552,258,5)); +sSkills.put(22578, new EveSkill("Mining Upgrades",22578,268,4)); +sSkills.put(22761, new EveSkill("Recon Ships",22761,257,6)); +sSkills.put(22806, new EveSkill("EM Armor Compensation",22806,269,2)); +sSkills.put(22807, new EveSkill("Explosive Armor Compensation",22807,269,2)); +sSkills.put(22808, new EveSkill("Kinetic Armor Compensation",22808,269,2)); +sSkills.put(22809, new EveSkill("Thermic Armor Compensation",22809,269,2)); +sSkills.put(23069, new EveSkill("Fighters",23069,273,12)); +sSkills.put(23087, new EveSkill("Amarr Encryption Methods",23087,270,5)); +sSkills.put(23121, new EveSkill("Gallente Encryption Methods",23121,270,5)); +sSkills.put(23123, new EveSkill("Takmahl Technology",23123,270,5)); +sSkills.put(23124, new EveSkill("Yan Jung Technology",23124,270,5)); +sSkills.put(23566, new EveSkill("Electronic Warfare Drone Interfacing",23566,273,5)); +sSkills.put(23594, new EveSkill("Sentry Drone Interfacing",23594,273,5)); +sSkills.put(23606, new EveSkill("Drone Sharpshooting",23606,273,1)); +sSkills.put(23618, new EveSkill("Drone Durability",23618,273,5)); +sSkills.put(23950, new EveSkill("Command Ships",23950,257,8)); +sSkills.put(24241, new EveSkill("Combat Drone Operation",24241,273,2)); +sSkills.put(24242, new EveSkill("Infomorph Psychology",24242,270,1)); +sSkills.put(24268, new EveSkill("Supply Chain Management",24268,268,3)); +sSkills.put(24270, new EveSkill("Scientific Networking",24270,270,3)); +sSkills.put(24311, new EveSkill("Amarr Carrier",24311,257,14)); +sSkills.put(24312, new EveSkill("Caldari Carrier",24312,257,14)); +sSkills.put(24313, new EveSkill("Gallente Carrier",24313,257,14)); +sSkills.put(24314, new EveSkill("Minmatar Carrier",24314,257,14)); +sSkills.put(24562, new EveSkill("Jump Portal Generation",24562,270,14)); +sSkills.put(24563, new EveSkill("Doomsday Operation",24563,270,14)); +sSkills.put(24568, new EveSkill("Capital Remote Armor Repair Systems",24568,269,10)); +sSkills.put(24571, new EveSkill("Capital Shield Emission Systems",24571,271,10)); +sSkills.put(24572, new EveSkill("Capital Energy Emission Systems",24572,271,10)); +sSkills.put(24606, new EveSkill("Cloning Facility Operation",24606,270,10)); +sSkills.put(24613, new EveSkill("Advanced Drone Interfacing",24613,273,8)); +sSkills.put(24624, new EveSkill("Advanced Laboratory Operation",24624,270,8)); +sSkills.put(24625, new EveSkill("Advanced Mass Production",24625,268,8)); +sSkills.put(24764, new EveSkill("Fleet Command",24764,258,12)); +sSkills.put(25233, new EveSkill("Corporation Contracting",25233,274,3)); +sSkills.put(25235, new EveSkill("Contracting",25235,274,1)); +sSkills.put(25530, new EveSkill("Neurotoxin Recovery",25530,270,5)); +sSkills.put(25538, new EveSkill("Nanite Control",25538,270,2)); +sSkills.put(25544, new EveSkill("Gas Cloud Harvesting",25544,268,1)); +sSkills.put(25718, new EveSkill("Heavy Assault Missile Specialization",25718,256,5)); +sSkills.put(25719, new EveSkill("Heavy Assault Missiles",25719,256,3)); +sSkills.put(25739, new EveSkill("Signal Acquisition",25739,270,8)); +sSkills.put(25810, new EveSkill("Astrometric Pinpointing",25810,270,5)); +sSkills.put(25811, new EveSkill("Astrometric Triangulation",25811,270,5)); +sSkills.put(25863, new EveSkill("Salvaging",25863,269,3)); +sSkills.put(26224, new EveSkill("Drug Manufacturing",26224,268,2)); +sSkills.put(26252, new EveSkill("Jury Rigging",26252,269,2)); +sSkills.put(26253, new EveSkill("Armor Rigging",26253,269,3)); +sSkills.put(26254, new EveSkill("Astronautics Rigging",26254,269,3)); +sSkills.put(26255, new EveSkill("Drones Rigging",26255,269,3)); +sSkills.put(26256, new EveSkill("Electronic Superiority Rigging",26256,269,3)); +sSkills.put(26257, new EveSkill("Projectile Weapon Rigging",26257,269,3)); +sSkills.put(26258, new EveSkill("Energy Weapon Rigging",26258,269,3)); +sSkills.put(26259, new EveSkill("Hybrid Weapon Rigging",26259,269,3)); +sSkills.put(26260, new EveSkill("Launcher Rigging",26260,269,3)); +sSkills.put(26261, new EveSkill("Shield Rigging",26261,269,3)); +sSkills.put(27902, new EveSkill("Remote Hull Repair Systems",27902,269,2)); +sSkills.put(27906, new EveSkill("Tactical Logistics Reconfiguration",27906,269,8)); +sSkills.put(27911, new EveSkill("Projected Electronic Counter Measures",27911,272,8)); +sSkills.put(27936, new EveSkill("Capital Remote Hull Repair Systems",27936,269,10)); +sSkills.put(28073, new EveSkill("Bomb Deployment",28073,256,4)); +sSkills.put(28164, new EveSkill("Thermodynamics",28164,270,3)); +sSkills.put(28374, new EveSkill("Capital Industrial Ships",28374,257,12)); +sSkills.put(28585, new EveSkill("Industrial Reconfiguration",28585,268,8)); +sSkills.put(28609, new EveSkill("Heavy Interdictors",28609,257,6)); +sSkills.put(28615, new EveSkill("Electronic Attack Ships",28615,257,4)); +sSkills.put(28656, new EveSkill("Black Ops",28656,257,10)); +sSkills.put(28667, new EveSkill("Marauders",28667,257,10)); +sSkills.put(28879, new EveSkill("Nanite Operation",28879,269,2)); +sSkills.put(28880, new EveSkill("Nanite Interfacing",28880,269,3)); +sSkills.put(29029, new EveSkill("Jump Freighters",29029,257,14)); +sSkills.put(3300, new EveSkill("Gunnery",3300,255,1)); +sSkills.put(3301, new EveSkill("Small Hybrid Turret",3301,255,1)); +sSkills.put(3302, new EveSkill("Small Projectile Turret",3302,255,1)); +sSkills.put(3303, new EveSkill("Small Energy Turret",3303,255,1)); +sSkills.put(3304, new EveSkill("Medium Hybrid Turret",3304,255,3)); +sSkills.put(3305, new EveSkill("Medium Projectile Turret",3305,255,3)); +sSkills.put(3306, new EveSkill("Medium Energy Turret",3306,255,3)); +sSkills.put(3307, new EveSkill("Large Hybrid Turret",3307,255,5)); +sSkills.put(3308, new EveSkill("Large Projectile Turret",3308,255,5)); +sSkills.put(3309, new EveSkill("Large Energy Turret",3309,255,5)); +sSkills.put(3310, new EveSkill("Rapid Firing",3310,255,2)); +sSkills.put(3311, new EveSkill("Sharpshooter",3311,255,2)); +sSkills.put(3312, new EveSkill("Motion Prediction",3312,255,2)); +sSkills.put(3315, new EveSkill("Surgical Strike",3315,255,4)); +sSkills.put(3316, new EveSkill("Controlled Bursts",3316,255,2)); +sSkills.put(3317, new EveSkill("Trajectory Analysis",3317,255,5)); +sSkills.put(3318, new EveSkill("Weapon Upgrades",3318,255,2)); +sSkills.put(3319, new EveSkill("Missile Launcher Operation",3319,256,1)); +sSkills.put(3320, new EveSkill("Rockets",3320,256,1)); +sSkills.put(3321, new EveSkill("Standard Missiles",3321,256,2)); +sSkills.put(3322, new EveSkill("FoF Missiles",3322,256,3)); +sSkills.put(3323, new EveSkill("Defender Missiles",3323,256,2)); +sSkills.put(3324, new EveSkill("Heavy Missiles",3324,256,3)); +sSkills.put(3325, new EveSkill("Torpedoes",3325,256,4)); +sSkills.put(3326, new EveSkill("Cruise Missiles",3326,256,5)); +sSkills.put(3327, new EveSkill("Spaceship Command",3327,257,1)); +sSkills.put(3328, new EveSkill("Gallente Frigate",3328,257,2)); +sSkills.put(3329, new EveSkill("Minmatar Frigate",3329,257,2)); +sSkills.put(3330, new EveSkill("Caldari Frigate",3330,257,2)); +sSkills.put(3331, new EveSkill("Amarr Frigate",3331,257,2)); +sSkills.put(3332, new EveSkill("Gallente Cruiser",3332,257,5)); +sSkills.put(3333, new EveSkill("Minmatar Cruiser",3333,257,5)); +sSkills.put(3334, new EveSkill("Caldari Cruiser",3334,257,5)); +sSkills.put(3335, new EveSkill("Amarr Cruiser",3335,257,5)); +sSkills.put(3336, new EveSkill("Gallente Battleship",3336,257,8)); +sSkills.put(3337, new EveSkill("Minmatar Battleship",3337,257,8)); +sSkills.put(3338, new EveSkill("Caldari Battleship",3338,257,8)); +sSkills.put(3339, new EveSkill("Amarr Battleship",3339,257,8)); +sSkills.put(3340, new EveSkill("Gallente Industrial",3340,257,4)); +sSkills.put(3341, new EveSkill("Minmatar Industrial",3341,257,4)); +sSkills.put(3342, new EveSkill("Caldari Industrial",3342,257,4)); +sSkills.put(3343, new EveSkill("Amarr Industrial",3343,257,4)); +sSkills.put(3344, new EveSkill("Gallente Titan",3344,257,16)); +sSkills.put(3345, new EveSkill("Minmatar Titan",3345,257,16)); +sSkills.put(3346, new EveSkill("Caldari Titan",3346,257,16)); +sSkills.put(3347, new EveSkill("Amarr Titan",3347,257,16)); +sSkills.put(3348, new EveSkill("Leadership",3348,258,1)); +sSkills.put(3349, new EveSkill("Skirmish Warfare",3349,258,2)); +sSkills.put(3350, new EveSkill("Siege Warfare",3350,258,2)); +sSkills.put(3351, new EveSkill("Siege Warfare Specialist",3351,258,5)); +sSkills.put(3352, new EveSkill("Information Warfare Specialist",3352,258,5)); +sSkills.put(3354, new EveSkill("Warfare Link Specialist",3354,258,6)); +sSkills.put(3355, new EveSkill("Social",3355,278,1)); +sSkills.put(3356, new EveSkill("Negotiation",3356,278,2)); +sSkills.put(3357, new EveSkill("Diplomacy",3357,278,1)); +sSkills.put(3358, new EveSkill("Fast talk",3358,278,4)); +sSkills.put(3359, new EveSkill("Connections",3359,278,3)); +sSkills.put(3361, new EveSkill("Criminal Connections",3361,278,3)); +sSkills.put(3362, new EveSkill("DED Connections",3362,278,1)); +sSkills.put(3363, new EveSkill("Corporation Management",3363,266,1)); +sSkills.put(3368, new EveSkill("Ethnic Relations",3368,266,2)); +sSkills.put(3369, new EveSkill("CFO Training",3369,266,3)); +sSkills.put(3373, new EveSkill("Starbase Defense Management",3373,266,7)); +sSkills.put(3374, new EveSkill("Learning",3374,267,1)); +sSkills.put(3375, new EveSkill("Iron Will",3375,267,1)); +sSkills.put(3376, new EveSkill("Empathy",3376,267,1)); +sSkills.put(3377, new EveSkill("Analytical Mind",3377,267,1)); +sSkills.put(3378, new EveSkill("Instant Recall",3378,267,1)); +sSkills.put(3379, new EveSkill("Spatial Awareness",3379,267,1)); +sSkills.put(3380, new EveSkill("Industry",3380,268,1)); +sSkills.put(3385, new EveSkill("Refining",3385,268,1)); +sSkills.put(3386, new EveSkill("Mining",3386,268,1)); +sSkills.put(3387, new EveSkill("Mass Production",3387,268,2)); +sSkills.put(3388, new EveSkill("Production Efficiency",3388,268,3)); +sSkills.put(3389, new EveSkill("Refinery Efficiency",3389,268,3)); +sSkills.put(3392, new EveSkill("Mechanic",3392,269,1)); +sSkills.put(3393, new EveSkill("Repair Systems",3393,269,1)); +sSkills.put(3394, new EveSkill("Hull Upgrades",3394,269,2)); +sSkills.put(3395, new EveSkill("Frigate Construction",3395,269,2)); +sSkills.put(3396, new EveSkill("Industrial Construction",3396,269,3)); +sSkills.put(3397, new EveSkill("Cruiser Construction",3397,269,5)); +sSkills.put(3398, new EveSkill("Battleship Construction",3398,269,8)); +sSkills.put(3400, new EveSkill("Outpost Construction",3400,269,16)); +sSkills.put(3402, new EveSkill("Science",3402,270,1)); +sSkills.put(3403, new EveSkill("Research",3403,270,1)); +sSkills.put(3404, new EveSkill("Genetic Engineering",3404,270,4)); +sSkills.put(3405, new EveSkill("Biology",3405,270,1)); +sSkills.put(3406, new EveSkill("Laboratory Operation",3406,270,1)); +sSkills.put(3409, new EveSkill("Metallurgy",3409,270,3)); +sSkills.put(3410, new EveSkill("Astrogeology",3410,270,3)); +sSkills.put(3411, new EveSkill("Cybernetics",3411,270,3)); +sSkills.put(3412, new EveSkill("Astrometrics",3412,270,3)); +sSkills.put(3413, new EveSkill("Engineering",3413,271,1)); +sSkills.put(3416, new EveSkill("Shield Operation",3416,271,1)); +sSkills.put(3417, new EveSkill("Energy Systems Operation",3417,271,1)); +sSkills.put(3418, new EveSkill("Energy Management",3418,271,3)); +sSkills.put(3419, new EveSkill("Shield Management",3419,271,3)); +sSkills.put(3420, new EveSkill("Tactical Shield Manipulation",3420,271,4)); +sSkills.put(3421, new EveSkill("Energy Pulse Weapons",3421,271,2)); +sSkills.put(3422, new EveSkill("Shield Emission Systems",3422,271,2)); +sSkills.put(3423, new EveSkill("Energy Emission Systems",3423,271,2)); +sSkills.put(3424, new EveSkill("Energy Grid Upgrades",3424,271,2)); +sSkills.put(3425, new EveSkill("Shield Upgrades",3425,271,2)); +sSkills.put(3426, new EveSkill("Electronics",3426,272,1)); +sSkills.put(3427, new EveSkill("Electronic Warfare",3427,272,2)); +sSkills.put(3428, new EveSkill("Long Range Targeting",3428,272,2)); +sSkills.put(3429, new EveSkill("Targeting",3429,272,1)); +sSkills.put(3430, new EveSkill("Multitasking",3430,272,3)); +sSkills.put(3431, new EveSkill("Signature Analysis",3431,272,1)); +sSkills.put(3432, new EveSkill("Electronics Upgrades",3432,272,2)); +sSkills.put(3433, new EveSkill("Sensor Linking",3433,272,3)); +sSkills.put(3434, new EveSkill("Weapon Disruption",3434,272,3)); +sSkills.put(3435, new EveSkill("Propulsion Jamming",3435,272,3)); +sSkills.put(3436, new EveSkill("Drones",3436,273,1)); +sSkills.put(3437, new EveSkill("Scout Drone Operation",3437,273,1)); +sSkills.put(3438, new EveSkill("Mining Drone Operation",3438,273,2)); +sSkills.put(3439, new EveSkill("Repair Drone Operation",3439,273,3)); +sSkills.put(3441, new EveSkill("Heavy Drone Operation",3441,273,5)); +sSkills.put(3442, new EveSkill("Drone Interfacing",3442,273,5)); +sSkills.put(3443, new EveSkill("Trade",3443,274,1)); +sSkills.put(3444, new EveSkill("Retail",3444,274,2)); +sSkills.put(3446, new EveSkill("Broker Relations",3446,274,2)); +sSkills.put(3447, new EveSkill("Visibility",3447,274,3)); +sSkills.put(3449, new EveSkill("Navigation",3449,275,1)); +sSkills.put(3450, new EveSkill("Afterburner",3450,275,1)); +sSkills.put(3451, new EveSkill("Fuel Conservation",3451,275,2)); +sSkills.put(3452, new EveSkill("Acceleration Control",3452,275,4)); +sSkills.put(3453, new EveSkill("Evasive Maneuvering",3453,275,2)); +sSkills.put(3454, new EveSkill("High Speed Maneuvering",3454,275,5)); +sSkills.put(3455, new EveSkill("Warp Drive Operation",3455,275,1)); +sSkills.put(3456, new EveSkill("Jump Drive Operation",3456,275,5)); +sSkills.put(3551, new EveSkill("Survey",3551,272,1)); +sSkills.put(3731, new EveSkill("Megacorp Management",3731,266,3)); +sSkills.put(3732, new EveSkill("Empire Control",3732,266,5)); + } +} \ No newline at end of file diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 src/org/mrrupert/eveberry/QDParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/mrrupert/eveberry/QDParser.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,321 @@ +package org.mrrupert.eveberry; + +import java.io.*; +import java.util.*; + + +// Quick and Dirty xml parser. This parser is, like the SAX parser, +// an event based parser, but with much less functionality. +// +// Based on java tip at http://www.javaworld.com/javatips/jw-javatip128_p.html +// because RIM's SAX parser seems ludicrously slow + +public class QDParser { + private static int popMode(Stack st) { + if(!st.empty()) + return ((Integer)st.pop()).intValue(); + else + return PRE; + } + private final static int + TEXT = 1, + ENTITY = 2, + OPEN_TAG = 3, + CLOSE_TAG = 4, + START_TAG = 5, + ATTRIBUTE_LVALUE = 6, + ATTRIBUTE_EQUAL = 9, + ATTRIBUTE_RVALUE = 10, + QUOTE = 7, + IN_TAG = 8, + SINGLE_TAG = 12, + COMMENT = 13, + DONE = 11, + DOCTYPE = 14, + PRE = 15, + CDATA = 16; + public static void parse(DocHandler doc,Reader r) throws Exception { + Stack st = new Stack(); + int depth = 0; + int mode = PRE; + int c = 0; + int quotec = '"'; + depth = 0; + StringBuffer sb = new StringBuffer(); + StringBuffer etag = new StringBuffer(); + String tagName = null; + String lvalue = null; + String rvalue = null; + Hashtable attrs = null; + st = new Stack(); + doc.startDocument(); + int line=1, col=0; + boolean eol = false; + while((c = r.read()) != -1) { + + // We need to map \r, \r\n, and \n to \n + // See XML spec section 2.11 + if(c == '\n' && eol) { + eol = false; + continue; + } else if(eol) { + eol = false; + } else if(c == '\n') { + line++; + col=0; + } else if(c == '\r') { + eol = true; + c = '\n'; + line++; + col=0; + } else { + col++; + } + + if(mode == DONE) { + doc.endDocument(); + return; + + // We are between tags collecting text. + } else if(mode == TEXT) { + if(c == '<') { + st.push(new Integer(mode)); + mode = START_TAG; + if(sb.length() > 0) { + doc.text(sb.toString()); + sb.setLength(0); + } + } else if(c == '&') { + st.push(new Integer(mode)); + mode = ENTITY; + etag.setLength(0); + } else + sb.append((char)c); + + // we are processing a closing tag: e.g. + } else if(mode == CLOSE_TAG) { + if(c == '>') { + mode = popMode(st); + tagName = sb.toString(); + sb.setLength(0); + depth--; + if(depth==0) + mode = DONE; + doc.endElement(tagName); + } else { + sb.append((char)c); + } + + // we are processing CDATA + } else if(mode == CDATA) { + if(c == '>' + && sb.toString().endsWith("]]")) { + sb.setLength(sb.length()-2); + doc.text(sb.toString()); + sb.setLength(0); + mode = popMode(st); + } else + sb.append((char)c); + + // we are processing a comment. We are inside + // the looking for the -->. + } else if(mode == COMMENT) { + if(c == '>' + && sb.toString().endsWith("--")) { + sb.setLength(0); + mode = popMode(st); + } else + sb.append((char)c); + + // We are outside the root tag element + } else if(mode == PRE) { + if(c == '<') { + mode = TEXT; + st.push(new Integer(mode)); + mode = START_TAG; + } + + // We are inside one of these + // or one of these + } else if(mode == DOCTYPE) { + if(c == '>') { + mode = popMode(st); + if(mode == TEXT) mode = PRE; + } + + // we have just seen a < and + // are wondering what we are looking at + // , , , etc. + } else if(mode == START_TAG) { + mode = popMode(st); + if(c == '/') { + st.push(new Integer(mode)); + mode = CLOSE_TAG; + } else if (c == '?') { + mode = DOCTYPE; + } else { + st.push(new Integer(mode)); + mode = OPEN_TAG; + tagName = null; + attrs = new Hashtable(); + sb.append((char)c); + } + + // we are processing an entity, e.g. <, », etc. + } else if(mode == ENTITY) { + if(c == ';') { + mode = popMode(st); + String cent = etag.toString(); + etag.setLength(0); + if(cent.equals("lt")) + sb.append('<'); + else if(cent.equals("gt")) + sb.append('>'); + else if(cent.equals("amp")) + sb.append('&'); + else if(cent.equals("quot")) + sb.append('"'); + else if(cent.equals("apos")) + sb.append('\''); + // Could parse hex entities if we wanted to + //else if(cent.startsWith("#x")) + //sb.append((char)Integer.parseInt(cent.substring(2),16)); + else if(cent.startsWith("#")) + sb.append((char)Integer.parseInt(cent.substring(1))); + // Insert custom entity definitions here + else + exc("Unknown entity: &"+cent+";",line,col); + } else { + etag.append((char)c); + } + + // we have just seen something like this: + // . + } else if(mode == SINGLE_TAG) { + if(tagName == null) + tagName = sb.toString(); + if(c != '>') + exc("Expected > for tag: <"+tagName+"/>",line,col); + doc.startElement(tagName,attrs); + doc.endElement(tagName); + if(depth==0) { + doc.endDocument(); + return; + } + sb.setLength(0); + attrs = new Hashtable(); + tagName = null; + mode = popMode(st); + + // we are processing something + // like this . It could + // still be a or something. + } else if(mode == OPEN_TAG) { + if(c == '>') { + if(tagName == null) + tagName = sb.toString(); + sb.setLength(0); + depth++; + doc.startElement(tagName,attrs); + tagName = null; + attrs = new Hashtable(); + mode = popMode(st); + } else if(c == '/') { + mode = SINGLE_TAG; + } else if(c == '-' && sb.toString().equals("!-")) { + mode = COMMENT; + } else if(c == '[' && sb.toString().equals("![CDATA")) { + mode = CDATA; + sb.setLength(0); + } else if(c == 'E' && sb.toString().equals("!DOCTYP")) { + sb.setLength(0); + mode = DOCTYPE; + } else if(c == ' ' || c == '\t') { + tagName = sb.toString(); + sb.setLength(0); + mode = IN_TAG; + } else { + sb.append((char)c); + } + + // We are processing the quoted right-hand side + // of an element's attribute. + } else if(mode == QUOTE) { + if(c == quotec) { + rvalue = sb.toString(); + sb.setLength(0); + attrs.put(lvalue,rvalue); + mode = IN_TAG; + // See section the XML spec, section 3.3.3 + // on normalization processing. + } else if(" \r\n\u0009".indexOf(c)>=0) { + sb.append(' '); + } else if(c == '&') { + st.push(new Integer(mode)); + mode = ENTITY; + etag.setLength(0); + } else { + sb.append((char)c); + } + + } else if(mode == ATTRIBUTE_RVALUE) { + if(c == '"' || c == '\'') { + quotec = c; + mode = QUOTE; + } else if(c == ' ' || c == '\t') { + ; + } else { + exc("Error in attribute processing",line,col); + } + + } else if(mode == ATTRIBUTE_LVALUE) { + if(c == ' ' || c == '\t') { + lvalue = sb.toString(); + sb.setLength(0); + mode = ATTRIBUTE_EQUAL; + } else if(c == '=') { + lvalue = sb.toString(); + sb.setLength(0); + mode = ATTRIBUTE_RVALUE; + } else { + sb.append((char)c); + } + + } else if(mode == ATTRIBUTE_EQUAL) { + if(c == '=') { + mode = ATTRIBUTE_RVALUE; + } else if(c == ' ' || c == '\t') { + ; + } else { + exc("Error in attribute processing.",line,col); + } + + } else if(mode == IN_TAG) { + if(c == '>') { + mode = popMode(st); + doc.startElement(tagName,attrs); + depth++; + tagName = null; + attrs = new Hashtable(); + } else if(c == '/') { + mode = SINGLE_TAG; + } else if(c == ' ' || c == '\t') { + ; + } else { + mode = ATTRIBUTE_LVALUE; + sb.append((char)c); + } + } + } + if(mode == DONE) + doc.endDocument(); + else + exc("missing end tag",line,col); + } + private static void exc(String s,int line,int col) + throws Exception + { + throw new Exception(s+" near line "+line+", column "+col); + } +} diff -r 0000000000000000000000000000000000000000 -r 6cd2588ce0555efb9f975728ad0d3be99f3aeb95 test/EveAPITest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/EveAPITest.java Tue Dec 25 16:33:54 2007 -0800 @@ -0,0 +1,24 @@ +package org.mrrupert.eveberry; + +import org.mrrupert.eveberry.*; + +class EveAPITest { + public static void main(String args[]) { + EveCharacterList ecl = EveAPI.GetCharacters(args[0], args[1]); + + System.out.println(ecl.CharacterNames[0]); + + EveCharacterSheet ecs = EveAPI.GetCharacterSheet(args[0], args[1], ecl.CharacterIDs[0]); + + System.out.println("Balance: " + ecs.balance); + System.out.println("Corporation: " + ecs.corporationName); + System.out.println("Perception: " + ecs.perception); + + EveSkillInTraining est; + + est = EveAPI.GetSkillInTraining(args[0], args[1], ecl.CharacterIDs[0]); + System.out.println("Training: " + est.skillInTraining); + System.out.println("endtime: " + est.endTime); + System.out.println("destinationLevel: " + est.destinationLevel); + } +} \ No newline at end of file