LMeve dev-blog: Bugfixes and POS tracking improvements

Hi space friends!

More and more of you have already tried LMeve, which I am incredibly grateful for. This means more people are testing the app and I get more feedback, which is awesome. I also get a lot of questions which I try to answer the best I can and in a timely fashion.

Remember: by trying and using LMeve you help developing it!

Few players also caught some bugs, that I’m happy to announce, have been properly squashed in the 0.1.52 release.

  • Bug fix in db.php “Notice: LM_dbhost is not defined” – added $LM_dbhost to global declaration in db.php
  • Bug fix in Database – “function eregi() is deprecated” – replaced with preg_match()
  • Bug fix in YAML updater – changed ‘DROP TABLE’ to ‘DROP TABLE IF EXISTS’ to prevent errors if the table was not created yet.

One bug was found by my trusty Aideron Technologies beta testers:

  • Non-recurring Tasks (singleton) bug fix – one-time tasks did not display correctly due to a mistake in SQL query

What’s new besides Bugfixes?

  • Poller now fetches StarbaseDetails.xml and CREST industry cost indexes

The first API feed is used by POS tracking code to display accurate and up-to-date fuel levels in LMeve Inventory. The second CREST feed provides NPC cost index to the build cost estimation formula (I currently use an average system index, so you might pay more or less than what LMeve uses for price estimates).

In the next release I will add a “Industry home system” field in Settings, where you will choose your home system. LMeve will then use this system’s cost index in all it’s calculations.

  • New POS management screen – displays fuel amounts and how long it will last
  • There is now a notification when any tower has less than 48 hours of fuel left

new-pos-screen

  • Tech III invention added. You can now add Tech III invention tasks and get price estimates for Tech III
  • New global setting for the default Relic type for use with Tech III Invention (Intact, Malfunctioning or Wrecked)

Download LMeve here

https://github.com/roxlukas/lmeve/

If you are updating from a previous release, please remember to create new tables included in this release using /data/schema-delta-0.1.51-0.1.52.sql

Try-before-you-buy

Well, LMeve is free software, so you don’t have to buy it 🙂 (donations are of course welcome!). But let’s get back to business. Installation requires some technical knowledge, so to make it easier for you guys to try it out, I have prepared a pre-installed Virtual Machine with LMeve, which runs on free VMware Player. You can download the image here: https://pozniak.pl/lmeve-vm/ 

  • it contains LMeve 0.1.52
  • static data is updated to Scylla
  • after booting it shows the IP address to point your web browser to:

lmeve_vm

Yearly aggregated stats CREST endpoint coming soon

Right now in Reykjavik CCP Quant and CCP FoxFour are in the middle of a presentation, and they are showing a new CREST endpoint, which returns aggregate statistic data for your characters. For example, you will now be able to see how much damage your toon dealt last year, and how that compares to a year before! Of course this applies to a range of possible metrics, including, but not limited to:

  • number of ships built
  • number of BPOs researched
  • number of pod kills in wormhole space
  • number of characters typed in chat
  • number of stargate jumps in high security space
  • damage your character dealt with projectile weapons
  • number of times your toon was tackled
  • many, many more

Ready to see how you did in 2014?

Just open this page and follow instructions: https://pozniak.pl/yearly-stats (by the way this app is mobile device friendly).

slack_for_ios_upload_1024 Screenshot_2015-03-18-14-20-25IMG_1818 IMG_1820

Feel free to check Bellatroix and Aaeriele projects as well. They have pretty graphs!

Technical details

A few weeks before Fanfest 2015, CCP FoxFour asked on forums if there are any third party devs who would be willing to work on a “secret project”. Few familiar faces turned up, and after some time three web apps have been built:

pasted_image_at_2015_03_17_03_20_pm_1024

Unfortunately due to RL I was only able to work on my prototype app for several hours, but it has the core functionality of showing the most interesting statistics in a readable way 😉

Now speaking about the technical details, this new endpoint will be available as authenticated CREST, which means you have to use SSO mechanism first to obtain a Bearer Token (see this news item about authenticated CREST for reference). Only then it is possible to access these new endpoint on the CREST API server. Data itself is returned as a JSON object, so using it in JavaScript and PHP is trivial.

The URL where the data is stored looks like this:

https://<CREST_API_SERVER>/characters/<characterID>/statistics/year/<year>/

where CREST_API_SERVER is either api-sisi.testeveonline.com or api.eveonline.com,

characterID – is the ID of the character (obtained from SSO process)

year – is either 2013, 2014 or 2015 (only these three years are available)

If everything goes fine, you will get a JSON file like this one:

{"combatDeathsPodTotal": 0,
 "combatDamageFromPlayersFighterMissileNumShots": 0,
"combatWebifyingPC": 0,
"socialAddedAsContactNeutral": 0
...}

Once you have the data it’s up to you how you want to display them.

CCP WebGL updated!

This is probably one of the best news for T’Amber and me in a long time: a CCP dev Filipp (we don’t know his CCP nickname yet) has updated CCP WebGL library to use V4 shaders, and moreover he did a complete model export up to date with EVE Tiamat release. What this means is that third-party projects like LMeve and Jeremy can again display all ships in EVE in full glory with up to date shaders and models!

The new webGL library is a little different from the previous one, because it is using the new SOF mechanism (Space Object Factory) instead of plain .red files.

For example, to load an Onyx heavy dictor, old javascript call looked like this:

var ship = scene.loadShip('res:/dx9/model/ship/caldari/Cruiser/CC2/Kaalakiota/CC2_T2a_Kaalakiota.red', undefined);

and new call is a little different:

var ship = scene.loadShip('cc2_t2a:kaalakiota:caldari', undefined);

You probably noticed that instead of a file name we have three “ship DNA” strings now. The mapping between ship’s typeID and the corresponding SOF entries are stored in graphicIDs.yaml, which is available in Static Data Export:

graphicID description sofFactionName sofHullName sofRaceName
10 Moon NULL NULL NULL
38 Caldari Frigate Bantam caldaribase cf1_t1 caldari
39 Caldari Frigate Condor caldaribase cf2_t1 caldari
40 Caldari Frigate Griffin caldaribase cf4_t1 caldari
41 Caldari Cruiser Osprey caldaribase cc1_t1 caldari
42 Caldari Cruiser Caracal caldaribase cc3_t1 caldari
43 Caldari Battleship Raven caldaribase cb1_t1 caldari
44 Minmatar Frigate Slasher minmatarbase mf1_t1 minmatar

I have already updated LMeve to use the new library, but because of a small issue (more on that below), it currently only works if your LMeve is served using HTTP.

Updated Onyx model

Public LMeve Database has been updated as well. Here’s an example page with the Amarr Confessor (please note you must press “3D” button for the WebGL preview to load).

All roses have thorns

Unfortunately the current version of the CCP webGL library has some drawbacks, too:

  • there are two model/texture sources now (so a simple reverse proxy like the one I’ve developed for LMeve won’t handle it)
  • both sources use HTTP, so modern browsers like Chrome will trigger a security error when trying to load HTTP based resources from HTTPS based website.

The latter is a very simple thing and I’m sure Filipp will be able to correct it. With CORS headers now properly set on CCP CDN we no longer need a proxy to serve models and textures.

New version of Jeremy in the making

With the new webGL library T’Amber sees a lot of potential to improve Jeremy. the new version would be using dynamically generated list of ships (instead of hardcoded list maintained by T’Amber). I will help with all the backend work (for example serving all SOF and invTypes data by JSON API).

Here’s a little teaser:

Stay tuned, because we are working hard to deliver you the best possible out of game ship spinning experience 🙂

AVvDxvj cpj6GjW

LMeve dev blog: important fix in dates, proxy and one more thing

Hi space-friends!

I won’t lie to you, I haven’t been playing much EVE lately. All the spare time that I was able to find was used to improve and fix LMeve. And Aideron Technologies found a big-badda-bug this time.

On the last saturday of January, a corpmate asked me why he can’t see the effect of his fire sales on the corp wallet graph in LMeve. It was the last day of January, and all graphs showed an empty bar for January 31st.

First I thought that poller might have stopped and we don’t get up to date API data. But I was quickly proven wrong, because I could clearly see all the recent market transactions in the database. “Must be a mistake in code that feeds database values to the graph” I thought. But when I checked that code, it only confirmed what I saw on the graph: that the value for the last day is indeed equal zero.

If the data is in the database, then it must be some kind of a presentation error; there is simply no way last day should show zero!

Let’s have a look at the database query used to retrieve the wallet data for a specific month. The clue must be there!

SELECT SUM(awj.amount)/1000000 AS income,date_format(awj.date, '%e') AS day FROM
apiwalletjournal awj
JOIN apireftypes art
ON awj.refTypeID=art.refTypeID
WHERE awj.date BETWEEN '${year}-${month}-01' AND LAST_DAY('${year}-${month}-01')
AND awj.corporationID=${corp['corporationID']}
AND awj.refTypeID <> 37
AND awj.amount > 0
GROUP BY date_format(awj.date, '%e')
ORDER BY date_format(awj.date, '%e');

Everything looks good from here, we SUM all transactions with positive “amount” field, and group them by the “day”. Of course I want output in millions of ISK, so I divide it by 1 000 000. Then we only select records between ‘$year-$month-01’ and the last day of the same month. Everything else is just filtering the correct corporation (because one instance of LMeve can monitor many corps at a time), filtering out player donations (refTypeID 37) and ordering the output by day, so we get a list of values for an entire month, from 1st day till the last.

How come this query will always return zero for the last day? Maybe that LAST_DAY() function actually returns last-but-one day?

SELECT LAST_DAY('2015-01-01');
2015-01-31
one row selected

Hmmm, it works exactly as advertized…

Or does it? Records in the wallet journal table don’t just have a DATE of the transaction, they have a full DATETIME! And what LAST_DAY() returns, is midnight on the last day of month! The entire timespan from midnight of that day until 23:59 that day is… well… filtered out. That explains why the last day was always missing.

How to fix it then?

Well, since we’re missing exactly 24 hours, it’s as simple as adding 1 day interval to the output of LAST_DAY():

WHERE awj.date BETWEEN '${year}-${month}-01' AND DATE_ADD(LAST_DAY('${year}-${month}-01'), INTERVAL 1 day)

LMeve CDN proxy

Now something else. As you know, I am now hosting T’Ambers ship painting tool – caldariprimeponyclub.com. In short, the problem was with the CCP CDN not setting Access-Control-Allow-Origin * in the header for users in AU and NZ regions (or some transparent proxy on the way stripped that header). Regardless, the end result was that T’Amber’s tool was unable to fetch 3D models and textures and ended up with a blank screen. I had a similar issue in LMeve a while back, and I made a very simple proxy in PHP, which would fetch the file from CCP CDN using curl, add the necessary CORS headers, and then send it back to the user.

The original proxy was really crude and could cause unnecessary network traffic, because every time user asked for file ‘A.png’ I would download file ‘A.png’ from CCP CDN, even if I have downloaded this file five seconds ago! Couldn’t I just save the file on disk, so I only retrieve each file once? Well, I’ve added the necessary logic, and the file is now saved in a cache, so I only retrieve each and every file once.

Now the second thing we needed was Analytics. It is a simple thing really: it’s statistics and visibility. I keep a log that contains information about the file (filename, path and its size in bytes) if the file was served from my local cache or retrieved from CCP servers, when it was retrieved, and the IP address of the client (which makes pretty much a standard proxy log). Once I have all this information, I can plot pretty graphs showing how many unique users were there on any given day, how many files they retrieved, and how much traffic they created:

lmeve-cdn-stats-solarized-light

Happy ship painting!

quafe-domi

One more thing

As you have noticed on that last screenshot, LMeve has a brand new skin. That skin is not just a random beige palette. I recently learned of a color scheme which improves readability in text and programming editors, dubbed “Solarized“. That colour set contains 8 monotones and 8 accent colours which have several unique properties. First, they cause much less stress on the eyes, and second, they are displayed correctly on old and new displays, even on intentionally miscalibrated ones.

These two new skins have been added under Settings -> Preferences: solarized-light.css (above) and solarized-dark.css (best for night owls). They are way more minimalistic than original LMeve skins, and they don’t contain too many images, which makes them “work-safe”.

lmeve-cdn-stats-solarized-dark

Hint: you can go further and remove all the images from LMeve. To do that, simply make a copy of your favourite skin .css file (they are in /wwwroot/css/ directory) and add this code:

img {
visibility: hidden;
}

This will hide all the images (character portraits, item icons and so on), but will retain the space that these images would normally occupy. This way LMeve remains completely usable, but becomes a “text only” application, that looks like everything but game 😉

LMeve dev blog: POCO details page and client list!

In November 2013 CCP has allowed high sec NPC Customs Offices owned by Interbus to be destroyed and then replaced with player owned ones. Previously only low-sec Customs Offices were vulnerable. Of course having POCOs makes a very nice passive source of ISK (you don’t have to do anything, apart from an occassional call to arms to defend them). But have you ever wondered how much you earn through your POCO network or who is using them?

In a previous update of LMeve I have added the ability to visualize which POCOs earn the most ISK, and in this iteration I continue the trend to show even more details. You can now choose a specific POCO and see a Details page for it. This page shows how much this specific Customs Office earned in the last 30 days – counting between 30 days ago and today, income in the last calendar month, and in the current one, so you can see trends).

What’s another new thing is the list of your customers. Corp Wallet Journal entries for planetary taxes show the client’s name and planets ID, so by running an aggregate query on that you can see:

  • who is using a specific POCO
  • how often they use it
  • how much they pay in taxes (so you can approach them and offer a discount in exchange for let’s say blue status)

Note: due to this information being obtained from corp Wallet Journal, it won’t show characters who have 0% tax rate, as these people will only pay the NPC tax, and no taxes to your corp at all (so no records are added to corporation Wallet Journal).

PI new planet detail screen

If you have ideas for more features in LMeve, please feel free to contact me. The best way is to raise an Issue on project’s Github page: https://github.com/roxlukas/lmeve. Choose an appropriate category (bug fix, enhacement or question) and write down what you need, or what needs fixing. I can’t guarantee that all requests will result in that feature being added to LMeve, but if the feature looks useful, won’t take forever to code and most importantly, the information required to make it is in the EVE API, it has a high chance of being included in one of the future releases.

Tweetfleet Slack

Just one more thing. Ashterothi, ex-member of Aideron Robotics and well-known host of podcasts such as High Drag and Hydrostatic Podcast, has recently created a Slack team for Tweetfleet. Slack is generally a communications platform aimed at companies, but it has a very nice real time chat (plus a dedicated app for iOS & Android). It is very useful, and a dedicated #devfleet channel also exists, so feel free to drop by and chat with fellow players, CCP devs and third party devs. It’s really fun!

To get invited, simply head to https://www.aideronrobotics.com/tweetfleet/ and fill in the form.

Tweetfleet Slack itself is here: https://tweetfleet.slack.com/

LMeve dev blog: Big POCO update coming

Just as promised in the previous LMeve dev blog, I have recently added the ability to track income from individual planets. Moreover, with the new percentage bars, you will know what are your best planets simply by looking at the table. To check how much a specific planet earned you in the last 30 days, simply hover your mouse above that planet’s name to see a tooltip with the exact number.

lmeve-poco-update

But this is not the only thing added in this release. Some pages require crunching a lot of data, which means they render rather slowly. Most of this data doesn’t change very often, so it seems to be a good idea to generate them once, and then save a cached copy. Then every time users come back to this page, a cached version is displayed, saving everyones time.

One of the pages, the Profit Chart can have several hundred records, which need their manufacturing and invention prices calculated, and it can load for as long as few minutes (depending on individual configuration of course). I used a different approach here: a lazy loader. Instead of one big 2 minute request, I display the page immediately, and as user is scrolling, more data is being loaded into the table in packs of 10 rows.

How to link POCOs with planets & income?

It’s not trivial, but far from impossible. Let’s have a look at columns returned by the /corp/CustomsOffices.xml.aspx API:

<row itemID="101296791423" solarSystemID="30004295" solarSystemName="Keba" reinforceHour="19" allowAlliance="True" allowStandings="True" standingLevel="-10" taxRateAlliance="0" taxRateCorp="0" taxRateStandingHigh="0" taxRateStandingGood="0.05" taxRateStandingNeutral="0.07" taxRateStandingBad="0.1" taxRateStandingHorrible="0.15" />

There is POCO itemID, which stays the same in all API endpoints, there is solarSystemID and system name. And of course the tax settings. But there is nothing about planet itemID here. Maybe /corp/Locations.xml.aspx endpoint will reveal a bit more?

<row itemID="101296791423" itemName="Customs Office (Keba I)" x="58598019193.2515" y="-5937030740.62145" z="-3890977687.95432" />

Okay, so now we have x, y, z coordinates, and POCOs name. In the first version of POCO management screen I simply cut planet name out of this using a regular expression. But to link it with other data we still need the planet itemID. How do we find it? Well, POCO is orbiting a planet, right? And we have cooridnates of all planets in the Static Data Export database – in the mapDenormalize table. What are we waiting for?

CREATE FUNCTION `findNearest`(`x1` DOUBLE, `y1` DOUBLE, `z1` DOUBLE, `solarSystemID1` INT) RETURNS int(11)
 READS SQL DATA
 RETURN (
 SELECT a.itemID FROM
 (SELECT SQRT(POW(x1-x,2)+POW(y1-y,2)+POW(z1-z,2)) AS dist,itemID
 FROM mapDenormalize
 WHERE `solarSystemID`=solarSystemID1
 ORDER BY dist ASC
 LIMIT 1) a
 )

40271955

Bingo! The function returns the closest solar body, in this case, itemID of the planet. We just have to JOIN two other tables from SDE: invNames to convert the planet ID we just got into planet name, Keba I, and invItems to find it’s typeID (Temperate, Barren, Oceanic, etc.).

Ok, now on to income for this specific POCO. For this, we will need  /corp/WalletJournal.xml.aspx endpoint, which contains all the transactions of a corp. The records we are looking for will have refTypeID equal to 96 and 97 (import/export taxes) and the planet itemID will be in argID1 field. Once all joins are in place, we simply have to filter last thirty days and SUM all the amount values.

As usual, the current LMeve version can be downloaded from https://github.com/roxlukas/lmeve

New third party page: evelexicon.com

@Fuzzysteve (Steve Ronuken, member of CSM #9 and the guy behind the most popular SDE-to-MySQL and SQLite conversions) has surprised the community today with a very nice simple website:

What does it do? You’ve guessed it, it’s a simple wiki-like vocabulary for EVE Online. Everyone is welcome to add new definitions to it. How do you log on? Simple: Eve Lexicon is using EVE SSO, so go on, log in using your EVE Online credentials, and add some definitions!

The site is written in PHP with a tiny bit of JQuery to make it pretty. EVE SSO integrations are now possible thanks to the new Third Party Developers Portal. A sample SSO library for developers (also by @Fuzzysteve) is available at github.com.

LMeve dev blog: Catching up with Phoebe. Bonus: setting up SSO

Good news! Last monday I had a day off, so I finally caught up with all outstanding tasks, including making LMeve Phoebe-compatible. In the meantime, I started tinkering with the following features:

Vagrantfile, bootstrap.sh

These two files make it easier to set up a host for any app. Trent Bartlem suggested to me on Github to include these files back in August. While the files themselves are pretty straightforward to prepare, I have to install LMeve from scratch somewhere to make sure I included all the necessary packages required to run LMeve. It’s on my to do list, and it should happen sooner than soon™.

Page Caching

Another idea I have is to make the longest loading pages cached (and maybe – just maybe – refreshed in the background, for example by the poller). Code to make this kind of caching possible is already written, and two sample pages (Inventory, Profit Chart) have been added as well. I use AJAX call to request the cached page, and if  cached version is not available (or has expired) I display a “Loading…” sign and prepare a refreshed version of the page. I was thinking about adding a “Force refresh” button, so users can force LMeve to refresh a cached page.

I still evaluate how this improves performance, but it looks pretty good and should become public soon.

PoCo module

lmeve-pocoLast one on the To Do list is expanding PoCo module. It has been recently revamped with features such as displaying last month’s income and current month income prediction. Judging by the talk I had with Dracoth Simertet from RvB (they have a huge PoCo network) and CCP FoxFour, there is a demand for a tool for managing PoCo networks. But what features would you need to monitor your PoCos?

  • Last month income per PoCo (currently only a sum for entire corp is displayed)
  • Planet type the PoCo is orbiting
  • Number of interactions
  • Client list per PoCo (by corp, by char)
  • Reinforced status
  • Do you have more ideas? Please leave a comment if you do!
    • We are only limited with what’s available in the API

SSO integration

I have mentioned a few times already that LMeve can benefit from EVE SSO, but some players were not sure how to set it up. Don’t worry! I’ve got you covered! Here’s a quick guide.

  • Secondly, click “Create new application”
    developers-02
    developers-03
  • Fill in the form. Application Name can be for example “LMeve – <your corporation name here>”
  • Now make sure to fill in Callback URL field correctly. If your LMeve address is https://myhostname.com/lmeve/, then the correct callback will be https://myhostname.com/lmeve/ssologin.php
  • Save the changes.

Once the application has been created, open it again by clicking the “View application” button, and write down these two values:

  • Client ID
  • Secret Key

developers-04

they will be required to complete setup on the LMeve side.

  • Log in to your web server host, open up config/config.php in your LMeve directory.
  • Find these variables, enter your callback URL and the values written down in previous step:
//use EVE SSO - see https://wiki.eveonline.com/en/wiki/EVE_SSO_Documentation
$SSOENABLED=TRUE; 
$SSO_REDIRECT_URL='https://myhostname.com/ssologin.php';
$SSO_CLIENT_ID='sso_client_id';
$SSO_CLIENT_SECRET='sso_client_secret';
//Auth server can be either login.eveonline.com for Tranquility, or sisilogin.testeveonline.com when trying to use Sisi.
$SSO_AUTH_SERVER='login.testeveonline.com';
  • Make sure characters are connected to LMeve usernames. This is crucial for the SSO to work!
    • Go to “Characters” module in LMeve and check if your characters are there.

lmeve-sso

Now you are ready to use EVE SSO to login to your LMeve instance!

Evernus – third party market tracking app

I have recently stumbled upon a third party program, which in my opinion, deserves a spotlight.

Evernus is a market tracking app made for Windows, but it is open source and written in Qt, which means with a little effort it can be compiled for Linux and Mac as well (there’s actually a .dmg ready for download). This is something worth noting, because there is almost no EVE apps for Mac or Linux at the moment.

What does it do?

Evernus is basically a market/margin trading tracker application, so it is focused on prices comparison and buy/sell order tracking. It takes character skills into account when calculating profits and taxes, so it is pretty accurate. Of course to track orders and automatically update your character’s skills, you need to supply the app with your API key.

If your character doesn’t have all trade skills at level 5 yet, but you would like to experiment and see if training them to 5 is worth it, you can manually tune all relevant skill levels as well.

evernus-character-full1Of course Evernus shows pretty graphs, so at a glance you know if you’re making profit or not.

evernus-basic-statistics-full1
Don’t like graphs? Want exact values? You’re covered, simply view it as a table.

evernus-assets-full2 evernus-orders-full2Evernus can use price data from several sources. First, it’s your EVE client’s market exports. Secondly, it can scrape client cache (but please mind CCP considers it a breach of EULA, and Evernus shows a proper warning, if you try to enable this feature), or from internet. Lastly, you can also import your data from other apps such as EVE Mentat.

What’s also a very useful feature is in-game browser integration. Evernus can run a tiny web server on your PC, and you can access it directly from the inside of the EVE client, simply by opening in-game browser and pointing it to your own computer’s address, plus a port number which you set in options.

evernus-igb-full1

One more thing

Evernus is being actively developed by Pete Butcher, a member of polish EVE Online community. New features come out literally DAILY. Moreover, Pete contacted me, and LMeve integration is coming soon as well (Evernus will be able to access LMeve’s features like Industry Task tracking and item manufacturing costs).

All in all, if you’re a station trader, Evernus is a tool really worth looking into.

Crius API changes

industryAs per this dev blog by CCP FoxFour (@regnerBA), industry changes in Crius will also change the way Industry API works.

There will be no new endpoints, but old endpoints will be changed instead. This means old tools will no longer work unless their developers adapt them. But fear not, #devfleet has you covered!

Lockefox (@HLIBindustry) has published tools and sample API data to help other third party devs adapt their apps.

You can find his github repository here: https://github.com/lockefox/CriusDev

  • scripts which handle the new BPO data (to use on this file: <sisi client path>\bin\staticdata\blueprint.db from your Sisi client)
  • sample API outputs from the modified endpoints
    • corp/facilities.xml
    • char/industryJobs.xml
    • char/industryJobsHistory.xml

Great job Lockefox! It’s much appreciated!

PS. I will do my best to add these changes to LMeve before Crius deployment, but due to summer holiday season this might take a few days longer. Stay tuned!