Skip to content

Instantly share code, notes, and snippets.

@blitzmann
Last active December 27, 2018 02:41
Show Gist options
  • Select an option

  • Save blitzmann/8cff8bed2a0c1313689d3b7e65c7b207 to your computer and use it in GitHub Desktop.

Select an option

Save blitzmann/8cff8bed2a0c1313689d3b7e65c7b207 to your computer and use it in GitHub Desktop.
Explanation of how eos works within pyfa, and how to use it as a standalone library

So, quick rundown on eos:

There are two datasources: game data (eve.db) and user data (saveddata.db). Tables for these databases are defined in eos.db.(gamedata/saveddata). Most of the tables also have a class mapped to them that handles the business logic of the entity. For game data, they all reside in eos.gamedata - most of them are skeleton objects, since most eve data is simply there to provide lookup of values and not necessarily do anything. The interesting objects here are Item and Effect.

The tables for the user's data are mapped to classes defined in eos.saveddata, and this is the majority of where the logic for the calculation engine lies, and many helper functions. For example, the Module class contains logic on what a module should do (for example, it has a method isValidCharge which checks to see if a passed in Charge object is valid for the module).

A quick how to stand up a bare bones Rifter fit with an Afterburner and a 200mm Autocannon with EMP S:

from eos.db import getItem  # there's a bunch of functions that act as helper functions, see `queries.py`
from eos.saveddata.ship import Ship
from eos.saveddata.module import Module, State
from eos.saveddata.fit import Fit
from eos.saveddata.character import Character

# need to get a character, in this case it's easy to get the all 5 character.
char = Character.getAll5()  # this will create all 5 if it's not already avaialble

rifterItem = getItem(587)  # get the rifter item. This will return a `eos.gamedata.Item` class
rifterShip = Ship(rifterItem) # Load the rifter item into a Ship class

abItem = getItem(439)
abMod = Module(abItem) 

acItem = getItem(486)  # 200mm AC Item
acMod = Module(acItem) 

empItem = getItem(185)  # EMP S

rifterFit = Fit(rifterShip, "MyRifterFit")  # create fit

if empItem.isCharge and acMod.isValidCharge(empItem): # make sure we're setting correct items
    acMod.charge = empItem  # set the charge to the 200mm AC

# fit the two modules to the fit
if acMod.fits(rifterFit):  # returns false if there's a hardpoint limit, max group limit, etc
    rifterFit.modules.append(acMod)
    acMod.owner = rifterFit  # not actually sure why this doesn't get set automatically... Think it might have something to do with the fact that we aren't actually saving this fit tot he database? Or legacy code! 
if abMod.fits(rifterFit): 
    rifterFit.modules.append(abMod)
    
# set the character fopr the fit
rifterFit.character = char 

# we have the modules fitted, however the calculations are not applied until you call the Calc function
print(rifterFit.maxSpeed)
print(rifterFit.weaponDPS)

rifterFit.calculateModifiedAttributes()

print(rifterFit.maxSpeed)
print(rifterFit.weaponDPS)

# we can see that the max speed increased, but the weapon dps didn't. That';s cecuase we didn't actually turn on any of the modules (the speed increase is due to character skills applying)

acMod.state = State.ACTIVE
abMod.state = State.ACTIVE

# recalc
rifterFit.calculateModifiedAttributes()

print(rifterFit.maxSpeed)
print(rifterFit.weaponDPS)

There's obviously more to it than that - there's a lot of other little things that happen, but this will hopefully give you an idea on how everything plays together. If you're interested in a specific attribute for an item, you can do something like this:

rifterFit.ship.getModifiedItemAttr("maxVelocity")

.ship is the Item representing that ship (in this case Rifter). getModifiedItemAttr() is a helper function that is seen everywhere throughout the code - it's gets the value of the attribute with it's calculated modifications. In fact, this is almost exactly how Fit.maxSpeed is defined (which itself is simply a helper to get to this attribute):

```
@property
def maxSpeed(self):
    speedLimit = self.ship.getModifiedItemAttr("speedLimit")
    if speedLimit and self.ship.getModifiedItemAttr("maxVelocity") > speedLimit:
        return speedLimit

    return self.ship.getModifiedItemAttr("maxVelocity")
```

Of course, if you're interested in seeing what other things are on these objects interactively, dir() works well. And of course, there's a lot of other things not covered here, like projected modules, fleet boosts, setting up a real character, etc. There's also ways to save this to the database using eos.db.save(rifterFit), but didn't test this.

One place I would look if you're not sure how something is set or toggled on a fit is to look in gui.fitCommands.calc these have files for our new command pattern that bundle in self contained logic on how to Add a module, remove module, change charge, set projected, etc etc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment