Replace submodules with actual files
Submodules never were actually useful
This commit is contained in:
7
eos/__init__.py
Executable file
7
eos/__init__.py
Executable file
@@ -0,0 +1,7 @@
|
||||
version = "0.2.3"
|
||||
tag = "git"
|
||||
|
||||
def test():
|
||||
import tests.runTests
|
||||
import unittest
|
||||
unittest.main(defaultTest="discover", testLoader=tests.runTests.loader)
|
||||
204
eos/capSim.py
Executable file
204
eos/capSim.py
Executable file
@@ -0,0 +1,204 @@
|
||||
import heapq
|
||||
from math import sqrt, exp
|
||||
import time
|
||||
|
||||
|
||||
DAY = 24 * 60 * 60 * 1000
|
||||
|
||||
def lcm(a,b):
|
||||
n = a*b
|
||||
while b:
|
||||
a, b = b, a % b
|
||||
return n / a
|
||||
|
||||
|
||||
class CapSimulator(object):
|
||||
"""Entity's EVE Capacitor Simulator"""
|
||||
|
||||
def __init__(self):
|
||||
# simulator defaults (change in instance, not here)
|
||||
|
||||
self.capacitorCapacity = 100
|
||||
self.capacitorRecharge = 1000
|
||||
|
||||
# max simulated time.
|
||||
self.t_max = DAY
|
||||
|
||||
# take reloads into account?
|
||||
self.reload = False
|
||||
|
||||
# stagger activations of identical modules?
|
||||
self.stagger = False
|
||||
|
||||
# scale activation duration and capNeed to values that ease the
|
||||
# calculation at the cost of accuracy?
|
||||
self.scale = False
|
||||
|
||||
# millisecond resolutions for scaling
|
||||
self.scale_resolutions = (100, 50, 25, 10)
|
||||
|
||||
# relevant decimal digits of capacitor for LCM period optimization
|
||||
self.stability_precision = 1
|
||||
|
||||
|
||||
def scale_activation(self, duration, capNeed):
|
||||
for res in self.scale_resolutions:
|
||||
mod = duration % res
|
||||
if mod:
|
||||
if mod > res/2.0:
|
||||
mod = res-mod
|
||||
else:
|
||||
mod = -mod
|
||||
|
||||
if abs(mod) <= duration/100.0:
|
||||
# only adjust if the adjustment is less than 1%
|
||||
duration += mod
|
||||
capNeed += float(mod)/duration * capNeed
|
||||
break
|
||||
|
||||
return duration, capNeed
|
||||
|
||||
def init(self, modules):
|
||||
"""prepare modules. a list of (duration, capNeed, clipSize) tuples is
|
||||
expected, with clipSize 0 if the module has infinite ammo.
|
||||
"""
|
||||
mods = {}
|
||||
for module in modules:
|
||||
if module in mods:
|
||||
mods[module] += 1
|
||||
else:
|
||||
mods[module] = 1
|
||||
|
||||
self.modules = mods
|
||||
|
||||
|
||||
def reset(self):
|
||||
"""Reset the simulator state"""
|
||||
self.state = []
|
||||
period = 1
|
||||
disable_period = False
|
||||
|
||||
for (duration, capNeed, clipSize), amount in self.modules.iteritems():
|
||||
if self.scale:
|
||||
duration, capNeed = self.scale_activation(duration, capNeed)
|
||||
|
||||
if self.stagger:
|
||||
duration = int(duration/amount)
|
||||
else:
|
||||
capNeed *= amount
|
||||
|
||||
period = lcm(period, duration)
|
||||
|
||||
# set clipSize to infinite if reloads are disabled unless it's
|
||||
# a cap booster module.
|
||||
if not self.reload and capNeed > 0:
|
||||
clipSize = 0
|
||||
|
||||
# period optimization doesn't work when reloads are active.
|
||||
if clipSize:
|
||||
disable_period = True
|
||||
|
||||
heapq.heappush(self.state, [0, duration, capNeed, 0, clipSize])
|
||||
|
||||
|
||||
if disable_period:
|
||||
self.period = self.t_max
|
||||
else:
|
||||
self.period = period
|
||||
|
||||
|
||||
def run(self):
|
||||
"""Run the simulation"""
|
||||
|
||||
start = time.time()
|
||||
|
||||
self.reset()
|
||||
|
||||
push = heapq.heappush
|
||||
pop = heapq.heappop
|
||||
|
||||
state = self.state
|
||||
stability_precision = self.stability_precision
|
||||
period = self.period
|
||||
|
||||
iterations = 0
|
||||
|
||||
capCapacity = self.capacitorCapacity
|
||||
tau = self.capacitorRecharge / 5.0
|
||||
|
||||
cap_wrap = capCapacity # cap value at last period
|
||||
cap_lowest = capCapacity # lowest cap value encountered
|
||||
cap_lowest_pre = capCapacity # lowest cap value before activations
|
||||
cap = capCapacity # current cap value
|
||||
t_wrap = self.period # point in time of next period
|
||||
|
||||
t_now = t_last = 0
|
||||
t_max = self.t_max
|
||||
|
||||
while 1:
|
||||
activation = pop(state)
|
||||
t_now, duration, capNeed, shot, clipSize = activation
|
||||
if t_now >= t_max:
|
||||
break
|
||||
|
||||
cap = ((1.0+(sqrt(cap/capCapacity)-1.0)*exp((t_last-t_now)/tau))**2)*capCapacity
|
||||
|
||||
if t_now != t_last:
|
||||
if cap < cap_lowest_pre:
|
||||
cap_lowest_pre = cap
|
||||
if t_now == t_wrap:
|
||||
# history is repeating itself, so if we have more cap now than last
|
||||
# time this happened, it is a stable setup.
|
||||
if cap >= cap_wrap:
|
||||
break
|
||||
cap_wrap = round(cap, stability_precision)
|
||||
t_wrap += period
|
||||
|
||||
cap -= capNeed
|
||||
if cap > capCapacity:
|
||||
cap = capCapacity
|
||||
|
||||
iterations += 1
|
||||
|
||||
if cap < cap_lowest:
|
||||
if cap < 0.0:
|
||||
break
|
||||
cap_lowest = cap
|
||||
|
||||
t_last = t_now
|
||||
|
||||
# queue the next activation of this module
|
||||
t_now += duration
|
||||
shot += 1
|
||||
if clipSize:
|
||||
if shot % clipSize == 0:
|
||||
shot = 0
|
||||
t_now += 10000 # include reload time
|
||||
activation[0] = t_now
|
||||
activation[3] = shot
|
||||
|
||||
push(state, activation)
|
||||
push(state, activation)
|
||||
|
||||
# update instance with relevant results.
|
||||
self.t = t_last
|
||||
self.iterations = iterations
|
||||
|
||||
# calculate EVE's stability value
|
||||
try:
|
||||
avgDrain = reduce(float.__add__, map(lambda x: x[2]/x[1], self.state), 0.0)
|
||||
self.cap_stable_eve = 0.25 * (1.0 + sqrt(-(2.0 * avgDrain * tau - capCapacity)/capCapacity)) ** 2
|
||||
except ValueError:
|
||||
self.cap_stable_eve = 0.0
|
||||
|
||||
|
||||
if cap > 0.0:
|
||||
# capacitor low/high water marks
|
||||
self.cap_stable_low = cap_lowest
|
||||
self.cap_stable_high = cap_lowest_pre
|
||||
else:
|
||||
self.cap_stable_low =\
|
||||
self.cap_stable_high = 0.0
|
||||
|
||||
|
||||
self.runtime = time.time()-start
|
||||
11
eos/config.py
Executable file
11
eos/config.py
Executable file
@@ -0,0 +1,11 @@
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
debug = False
|
||||
gamedataCache = True
|
||||
saveddataCache = True
|
||||
gamedata_connectionstring = 'sqlite:///' + os.path.expanduser(os.path.join("~", ".pyfa","eve.db"))
|
||||
saveddata_connectionstring = 'sqlite:///:memory:'
|
||||
|
||||
#Autodetect path, only change if the autodetection bugs out.
|
||||
path = os.path.dirname(unicode(__file__, sys.getfilesystemencoding()))
|
||||
77
eos/db/__init__.py
Executable file
77
eos/db/__init__.py
Executable file
@@ -0,0 +1,77 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
import threading
|
||||
|
||||
from sqlalchemy import MetaData, create_engine
|
||||
from sqlalchemy.orm import sessionmaker, scoped_session
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy import pool
|
||||
|
||||
from eos import config
|
||||
import migration
|
||||
|
||||
class ReadOnlyException(Exception):
|
||||
pass
|
||||
|
||||
gamedata_connectionstring = config.gamedata_connectionstring
|
||||
if callable(gamedata_connectionstring):
|
||||
gamedata_engine = create_engine("sqlite://", creator=gamedata_connectionstring, echo = config.debug)
|
||||
else:
|
||||
gamedata_engine = create_engine(gamedata_connectionstring, echo = config.debug)
|
||||
|
||||
gamedata_meta = MetaData()
|
||||
gamedata_meta.bind = gamedata_engine
|
||||
gamedata_session = sessionmaker(bind=gamedata_engine, autoflush=False, expire_on_commit=False)()
|
||||
|
||||
saveddata_connectionstring = config.saveddata_connectionstring
|
||||
if saveddata_connectionstring is not None:
|
||||
if callable(saveddata_connectionstring):
|
||||
saveddata_engine = create_engine(creator=saveddata_connectionstring, echo=config.debug)
|
||||
else:
|
||||
saveddata_engine = create_engine(saveddata_connectionstring, echo=config.debug)
|
||||
|
||||
saveddata_meta = MetaData()
|
||||
saveddata_meta.bind = saveddata_engine
|
||||
migration.update(saveddata_engine)
|
||||
saveddata_session = sessionmaker(bind=saveddata_engine, autoflush=False, expire_on_commit=False)()
|
||||
|
||||
# Lock controlling any changes introduced to session
|
||||
sd_lock = threading.Lock()
|
||||
|
||||
#Import all the definitions for all our database stuff
|
||||
from eos.db.gamedata import *
|
||||
from eos.db.saveddata import *
|
||||
|
||||
#Import queries
|
||||
from eos.db.gamedata.queries import getItem, searchItems, getVariations, getItemsByCategory, directAttributeRequest, \
|
||||
getMarketGroup, getGroup, getCategory, getAttributeInfo, getMetaData, getMetaGroup
|
||||
from eos.db.saveddata.queries import getUser, getCharacter, getFit, getFitsWithShip, countFitsWithShip, searchFits, \
|
||||
getCharacterList, getPrice, getDamagePatternList, getDamagePattern, \
|
||||
getFitList, getFleetList, getFleet, save, remove, commit, add, \
|
||||
getCharactersForUser, getMiscData, getSquadsIDsWithFitID, getWing, \
|
||||
getSquad
|
||||
|
||||
#If using in memory saveddata, you'll want to reflect it so the data structure is good.
|
||||
if config.saveddata_connectionstring == "sqlite:///:memory:":
|
||||
saveddata_meta.create_all()
|
||||
|
||||
def rollback():
|
||||
with sd_lock:
|
||||
saveddata_session.rollback()
|
||||
2
eos/db/gamedata/__init__.py
Executable file
2
eos/db/gamedata/__init__.py
Executable file
@@ -0,0 +1,2 @@
|
||||
__all__ = ["attribute", "category", "effect", "group", "metaData",
|
||||
"icon", "item", "marketGroup", "metaGroup", "unit"]
|
||||
59
eos/db/gamedata/attribute.py
Executable file
59
eos/db/gamedata/attribute.py
Executable file
@@ -0,0 +1,59 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, Float, Unicode, ForeignKey, String, Boolean
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from eos.types import Attribute, Icon, AttributeInfo, Unit
|
||||
from eos.db import gamedata_meta
|
||||
typeattributes_table = Table("dgmtypeattribs", gamedata_meta,
|
||||
Column("value", Float),
|
||||
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True, index=True),
|
||||
Column("attributeID", ForeignKey("dgmattribs.attributeID"), primary_key=True))
|
||||
|
||||
attributes_table = Table("dgmattribs", gamedata_meta,
|
||||
Column("attributeID", Integer, primary_key = True),
|
||||
Column("attributeName", String),
|
||||
Column("defaultValue", Float),
|
||||
Column("description", Unicode),
|
||||
Column("published", Boolean),
|
||||
Column("displayName", String),
|
||||
Column("highIsGood", Boolean),
|
||||
Column("iconID", Integer, ForeignKey("icons.iconID")),
|
||||
Column("unitID", Integer, ForeignKey("dgmunits.unitID")))
|
||||
|
||||
mapper(Attribute, typeattributes_table,
|
||||
properties = {"info": relation(AttributeInfo, lazy=False)})
|
||||
|
||||
mapper(AttributeInfo, attributes_table,
|
||||
properties = {"icon" : relation(Icon),
|
||||
"unit": relation(Unit),
|
||||
"ID": synonym("attributeID"),
|
||||
"name": synonym("attributeName"),
|
||||
"description" : deferred(attributes_table.c.description)})
|
||||
|
||||
Attribute.ID = association_proxy("info", "attributeID")
|
||||
Attribute.name = association_proxy("info", "attributeName")
|
||||
Attribute.description = association_proxy("info", "description")
|
||||
Attribute.published = association_proxy("info", "published")
|
||||
Attribute.displayName = association_proxy("info", "displayName")
|
||||
Attribute.highIsGood = association_proxy("info", "highIsGood")
|
||||
Attribute.iconID = association_proxy("info", "iconID")
|
||||
Attribute.icon = association_proxy("info", "icon")
|
||||
Attribute.unit = association_proxy("info", "unit")
|
||||
37
eos/db/gamedata/category.py
Executable file
37
eos/db/gamedata/category.py
Executable file
@@ -0,0 +1,37 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Column, String, Integer, ForeignKey, Boolean, Table
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Category, Icon
|
||||
|
||||
categories_table = Table("invcategories", gamedata_meta,
|
||||
Column("categoryID", Integer, primary_key = True),
|
||||
Column("categoryName", String),
|
||||
Column("description", String),
|
||||
Column("published", Boolean),
|
||||
Column("iconID", Integer, ForeignKey("icons.iconID")))
|
||||
|
||||
mapper(Category, categories_table,
|
||||
properties = {"icon" : relation(Icon),
|
||||
"ID" : synonym("categoryID"),
|
||||
"name" : synonym("categoryName"),
|
||||
"description" : deferred(categories_table.c.description)})
|
||||
50
eos/db/gamedata/effect.py
Executable file
50
eos/db/gamedata/effect.py
Executable file
@@ -0,0 +1,50 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Column, String, Integer, Boolean, Table, ForeignKey
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from sqlalchemy.orm import mapper, synonym, relation, deferred
|
||||
from eos.types import Effect, EffectInfo
|
||||
from eos.db import gamedata_meta
|
||||
|
||||
typeeffects_table = Table("dgmtypeeffects", gamedata_meta,
|
||||
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True, index=True),
|
||||
Column("effectID", Integer, ForeignKey("dgmeffects.effectID"), primary_key=True))
|
||||
|
||||
effects_table = Table("dgmeffects", gamedata_meta,
|
||||
Column("effectID", Integer, primary_key = True),
|
||||
Column("effectName", String),
|
||||
Column("description", String),
|
||||
Column("published", Boolean),
|
||||
Column("isAssistance", Boolean),
|
||||
Column("isOffensive", Boolean))
|
||||
|
||||
|
||||
mapper(EffectInfo, effects_table,
|
||||
properties = {"ID" : synonym("effectID"),
|
||||
"name" : synonym("effectName"),
|
||||
"description" : deferred(effects_table.c.description)})
|
||||
|
||||
mapper(Effect, typeeffects_table,
|
||||
properties = {"ID": synonym("effectID"),
|
||||
"info": relation(EffectInfo, lazy=False)})
|
||||
|
||||
Effect.name = association_proxy("info", "name")
|
||||
Effect.description = association_proxy("info", "description")
|
||||
Effect.published = association_proxy("info", "published")
|
||||
39
eos/db/gamedata/group.py
Executable file
39
eos/db/gamedata/group.py
Executable file
@@ -0,0 +1,39 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Column, String, Integer, Boolean, ForeignKey, Table
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Group, Icon, Category
|
||||
|
||||
groups_table = Table("invgroups", gamedata_meta,
|
||||
Column("groupID", Integer, primary_key = True),
|
||||
Column("groupName", String),
|
||||
Column("description", String),
|
||||
Column("published", Boolean),
|
||||
Column("categoryID", Integer, ForeignKey("invcategories.categoryID")),
|
||||
Column("iconID", Integer, ForeignKey("icons.iconID")))
|
||||
|
||||
mapper(Group, groups_table,
|
||||
properties = {"category" : relation(Category, backref = "groups"),
|
||||
"icon" : relation(Icon),
|
||||
"ID" : synonym("groupID"),
|
||||
"name" : synonym("groupName"),
|
||||
"description" : deferred(groups_table.c.description)})
|
||||
33
eos/db/gamedata/icon.py
Executable file
33
eos/db/gamedata/icon.py
Executable file
@@ -0,0 +1,33 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Column, String, Integer, Table
|
||||
from sqlalchemy.orm import mapper, synonym, deferred
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Icon
|
||||
|
||||
icons_table = Table("icons", gamedata_meta,
|
||||
Column("iconID", Integer, primary_key = True),
|
||||
Column("description", String),
|
||||
Column("iconFile", String))
|
||||
|
||||
mapper(Icon, icons_table,
|
||||
properties = {"ID" : synonym("iconID"),
|
||||
"description" : deferred(icons_table.c.description)})
|
||||
57
eos/db/gamedata/item.py
Executable file
57
eos/db/gamedata/item.py
Executable file
@@ -0,0 +1,57 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Column, String, Integer, Boolean, ForeignKey, Table, Float
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Icon, Attribute, Item, Effect, MetaType, Group
|
||||
|
||||
items_table = Table("invtypes", gamedata_meta,
|
||||
Column("typeID", Integer, primary_key = True),
|
||||
Column("typeName", String, index=True),
|
||||
Column("description", String),
|
||||
Column("raceID", Integer),
|
||||
Column("volume", Float),
|
||||
Column("mass", Float),
|
||||
Column("capacity", Float),
|
||||
Column("published", Boolean),
|
||||
Column("marketGroupID", Integer, ForeignKey("invmarketgroups.marketGroupID")),
|
||||
Column("iconID", Integer, ForeignKey("icons.iconID")),
|
||||
Column("groupID", Integer, ForeignKey("invgroups.groupID"), index=True))
|
||||
|
||||
|
||||
|
||||
from .metaGroup import metatypes_table
|
||||
|
||||
mapper(Item, items_table,
|
||||
properties = {"group" : relation(Group, backref = "items"),
|
||||
"icon" : relation(Icon),
|
||||
"_Item__attributes" : relation(Attribute, collection_class = attribute_mapped_collection('name')),
|
||||
"effects" : relation(Effect, collection_class = attribute_mapped_collection('name')),
|
||||
"metaGroup" : relation(MetaType,
|
||||
primaryjoin = metatypes_table.c.typeID == items_table.c.typeID,
|
||||
uselist = False),
|
||||
"ID" : synonym("typeID"),
|
||||
"name" : synonym("typeName"),
|
||||
"description" : deferred(items_table.c.description)})
|
||||
|
||||
Item.category = association_proxy("group", "category")
|
||||
40
eos/db/gamedata/marketGroup.py
Executable file
40
eos/db/gamedata/marketGroup.py
Executable file
@@ -0,0 +1,40 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Column, String, Integer, Boolean, ForeignKey, Table
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Item, MarketGroup, Icon
|
||||
|
||||
marketgroups_table = Table("invmarketgroups", gamedata_meta,
|
||||
Column("marketGroupID", Integer, primary_key = True),
|
||||
Column("marketGroupName", String),
|
||||
Column("description", String),
|
||||
Column("hasTypes", Boolean),
|
||||
Column("parentGroupID", Integer, ForeignKey("invmarketgroups.marketGroupID", initially="DEFERRED", deferrable=True)),
|
||||
Column("iconID", Integer, ForeignKey("icons.iconID")))
|
||||
|
||||
mapper(MarketGroup, marketgroups_table,
|
||||
properties = {"items" : relation(Item, backref = "marketGroup"),
|
||||
"parent" : relation(MarketGroup, backref = "children", remote_side = [marketgroups_table.c.marketGroupID]),
|
||||
"icon" : relation(Icon),
|
||||
"ID" : synonym("marketGroupID"),
|
||||
"name" : synonym("marketGroupName"),
|
||||
"description" : deferred(marketgroups_table.c.description)})
|
||||
29
eos/db/gamedata/metaData.py
Executable file
29
eos/db/gamedata/metaData.py
Executable file
@@ -0,0 +1,29 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Column, Table, String
|
||||
from sqlalchemy.orm import mapper
|
||||
from eos.types import MetaData
|
||||
from eos.db import gamedata_meta
|
||||
|
||||
metadata_table = Table("metadata", gamedata_meta,
|
||||
Column("fieldName", String, primary_key=True),
|
||||
Column("fieldValue", String))
|
||||
|
||||
mapper(MetaData, metadata_table)
|
||||
47
eos/db/gamedata/metaGroup.py
Executable file
47
eos/db/gamedata/metaGroup.py
Executable file
@@ -0,0 +1,47 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, String
|
||||
from sqlalchemy.orm import relation, mapper, synonym
|
||||
from eos.db import gamedata_meta
|
||||
from eos.db.gamedata.item import items_table
|
||||
from eos.types import MetaGroup, Item, MetaType
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
|
||||
metagroups_table = Table("invmetagroups", gamedata_meta,
|
||||
Column("metaGroupID", Integer, primary_key = True),
|
||||
Column("metaGroupName", String))
|
||||
|
||||
metatypes_table = Table("invmetatypes", gamedata_meta,
|
||||
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key = True),
|
||||
Column("parentTypeID", Integer, ForeignKey("invtypes.typeID")),
|
||||
Column("metaGroupID", Integer, ForeignKey("invmetagroups.metaGroupID")))
|
||||
|
||||
mapper(MetaGroup, metagroups_table,
|
||||
properties = {"ID" : synonym("metaGroupID"),
|
||||
"name" : synonym("metaGroupName")})
|
||||
|
||||
mapper(MetaType, metatypes_table,
|
||||
properties = {"ID" : synonym("metaGroupID"),
|
||||
"parent" : relation(Item, primaryjoin = metatypes_table.c.parentTypeID == items_table.c.typeID),
|
||||
"items" : relation(Item, primaryjoin = metatypes_table.c.typeID == items_table.c.typeID),
|
||||
"info": relation(MetaGroup, lazy=False)})
|
||||
|
||||
MetaType.name = association_proxy("info", "name")
|
||||
|
||||
251
eos/db/gamedata/queries.py
Executable file
251
eos/db/gamedata/queries.py
Executable file
@@ -0,0 +1,251 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from eos.db import gamedata_session
|
||||
from eos.db.gamedata.metaGroup import metatypes_table, items_table
|
||||
from sqlalchemy.sql import and_, or_, select, func
|
||||
from sqlalchemy.orm import join, exc
|
||||
from eos.types import Item, Category, Group, MarketGroup, AttributeInfo, MetaData, MetaGroup
|
||||
from eos.db.util import processEager, processWhere
|
||||
import eos.config
|
||||
|
||||
configVal = getattr(eos.config, "gamedataCache", None)
|
||||
if configVal is True:
|
||||
def cachedQuery(amount, *keywords):
|
||||
def deco(function):
|
||||
cache = {}
|
||||
def checkAndReturn(*args, **kwargs):
|
||||
useCache = kwargs.pop("useCache", True)
|
||||
cacheKey = []
|
||||
cacheKey.extend(args)
|
||||
for keyword in keywords:
|
||||
cacheKey.append(kwargs.get(keyword))
|
||||
|
||||
cacheKey = tuple(cacheKey)
|
||||
handler = cache.get(cacheKey)
|
||||
if handler is None or not useCache:
|
||||
handler = cache[cacheKey] = function(*args, **kwargs)
|
||||
|
||||
return handler
|
||||
|
||||
return checkAndReturn
|
||||
return deco
|
||||
|
||||
elif callable(configVal):
|
||||
cachedQuery = eos.config.gamedataCache
|
||||
else:
|
||||
def cachedQuery(amount, *keywords):
|
||||
def deco(function):
|
||||
def checkAndReturn(*args, **kwargs):
|
||||
return function(*args, **kwargs)
|
||||
|
||||
return checkAndReturn
|
||||
return deco
|
||||
|
||||
def sqlizeString(line):
|
||||
# Escape backslashes first, as they will be as escape symbol in queries
|
||||
# Then escape percent and underscore signs
|
||||
# Finally, replace generic wildcards with sql-style wildcards
|
||||
line = line.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_").replace("*", "%")
|
||||
return line
|
||||
|
||||
itemNameMap = {}
|
||||
@cachedQuery(1, "lookfor")
|
||||
def getItem(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
item = gamedata_session.query(Item).get(lookfor)
|
||||
else:
|
||||
item = gamedata_session.query(Item).options(*processEager(eager)).filter(Item.ID == lookfor).first()
|
||||
elif isinstance(lookfor, basestring):
|
||||
if lookfor in itemNameMap:
|
||||
id = itemNameMap[lookfor]
|
||||
if eager is None:
|
||||
item = gamedata_session.query(Item).get(id)
|
||||
else:
|
||||
item = gamedata_session.query(Item).options(*processEager(eager)).filter(Item.ID == id).first()
|
||||
else:
|
||||
# Item names are unique, so we can use first() instead of one()
|
||||
item = gamedata_session.query(Item).options(*processEager(eager)).filter(Item.name == lookfor).first()
|
||||
itemNameMap[lookfor] = item.ID
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return item
|
||||
|
||||
groupNameMap = {}
|
||||
@cachedQuery(1, "lookfor")
|
||||
def getGroup(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
group = gamedata_session.query(Group).get(lookfor)
|
||||
else:
|
||||
group = gamedata_session.query(Group).options(*processEager(eager)).filter(Group.ID == lookfor).first()
|
||||
elif isinstance(lookfor, basestring):
|
||||
if lookfor in groupNameMap:
|
||||
id = groupNameMap[lookfor]
|
||||
if eager is None:
|
||||
group = gamedata_session.query(Group).get(id)
|
||||
else:
|
||||
group = gamedata_session.query(Group).options(*processEager(eager)).filter(Group.ID == id).first()
|
||||
else:
|
||||
# Group names are unique, so we can use first() instead of one()
|
||||
group = gamedata_session.query(Group).options(*processEager(eager)).filter(Group.name == lookfor).first()
|
||||
groupNameMap[lookfor] = group.ID
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return group
|
||||
|
||||
categoryNameMap = {}
|
||||
@cachedQuery(1, "lookfor")
|
||||
def getCategory(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
category = gamedata_session.query(Category).get(lookfor)
|
||||
else:
|
||||
category = gamedata_session.query(Category).options(*processEager(eager)).filter(Category.ID == lookfor).first()
|
||||
elif isinstance(lookfor, basestring):
|
||||
if lookfor in categoryNameMap:
|
||||
id = categoryNameMap[lookfor]
|
||||
if eager is None:
|
||||
category = gamedata_session.query(Category).get(id)
|
||||
else:
|
||||
category = gamedata_session.query(Category).options(*processEager(eager)).filter(Category.ID == id).first()
|
||||
else:
|
||||
# Category names are unique, so we can use first() instead of one()
|
||||
category = gamedata_session.query(Category).options(*processEager(eager)).filter(Category.name == lookfor).first()
|
||||
categoryNameMap[lookfor] = category.ID
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return category
|
||||
|
||||
metaGroupNameMap = {}
|
||||
@cachedQuery(1, "lookfor")
|
||||
def getMetaGroup(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
metaGroup = gamedata_session.query(MetaGroup).get(lookfor)
|
||||
else:
|
||||
metaGroup = gamedata_session.query(MetaGroup).options(*processEager(eager)).filter(MetaGroup.ID == lookfor).first()
|
||||
elif isinstance(lookfor, basestring):
|
||||
if lookfor in metaGroupNameMap:
|
||||
id = metaGroupNameMap[lookfor]
|
||||
if eager is None:
|
||||
metaGroup = gamedata_session.query(MetaGroup).get(id)
|
||||
else:
|
||||
metaGroup = gamedata_session.query(MetaGroup).options(*processEager(eager)).filter(MetaGroup.ID == id).first()
|
||||
else:
|
||||
# MetaGroup names are unique, so we can use first() instead of one()
|
||||
metaGroup = gamedata_session.query(MetaGroup).options(*processEager(eager)).filter(MetaGroup.name == lookfor).first()
|
||||
metaGroupNameMap[lookfor] = metaGroup.ID
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return metaGroup
|
||||
|
||||
@cachedQuery(1, "lookfor")
|
||||
def getMarketGroup(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
marketGroup = gamedata_session.query(MarketGroup).get(lookfor)
|
||||
else:
|
||||
marketGroup = gamedata_session.query(MarketGroup).options(*processEager(eager)).filter(MarketGroup.ID == lookfor).first()
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
return marketGroup
|
||||
|
||||
@cachedQuery(2, "where", "filter")
|
||||
def getItemsByCategory(filter, where=None, eager=None):
|
||||
if isinstance(filter, int):
|
||||
filter = Category.ID == filter
|
||||
elif isinstance(filter, basestring):
|
||||
filter = Category.name == filter
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
|
||||
filter = processWhere(filter, where)
|
||||
return gamedata_session.query(Item).options(*processEager(eager)).join(Item.group, Group.category).filter(filter).all()
|
||||
|
||||
@cachedQuery(3, "where", "nameLike", "join")
|
||||
def searchItems(nameLike, where=None, join=None, eager=None):
|
||||
if not isinstance(nameLike, basestring):
|
||||
raise TypeError("Need string as argument")
|
||||
# Prepare our string for request
|
||||
nameLike = u"%{0}%".format(sqlizeString(nameLike))
|
||||
|
||||
if join is None:
|
||||
join = tuple()
|
||||
|
||||
if not hasattr(join, "__iter__"):
|
||||
join = (join,)
|
||||
|
||||
filter = processWhere(Item.name.like(nameLike, escape="\\"), where)
|
||||
items = gamedata_session.query(Item).options(*processEager(eager)).join(*join).filter(filter).all()
|
||||
return items
|
||||
|
||||
@cachedQuery(2, "where", "itemids")
|
||||
def getVariations(itemids, where=None, eager=None):
|
||||
for itemid in itemids:
|
||||
if not isinstance(itemid, int):
|
||||
raise TypeError("All passed item IDs must be integers")
|
||||
# Get out if list of provided IDs is empty
|
||||
if len(itemids) == 0:
|
||||
return []
|
||||
|
||||
itemfilter = or_(*(metatypes_table.c.parentTypeID == itemid for itemid in itemids))
|
||||
filter = processWhere(itemfilter, where)
|
||||
joinon = items_table.c.typeID == metatypes_table.c.typeID
|
||||
vars = gamedata_session.query(Item).options(*processEager(eager)).join((metatypes_table, joinon)).filter(filter).all()
|
||||
return vars
|
||||
|
||||
@cachedQuery(1, "attr")
|
||||
def getAttributeInfo(attr, eager=None):
|
||||
if isinstance(attr, basestring):
|
||||
filter = AttributeInfo.name == attr
|
||||
elif isinstance(attr, int):
|
||||
filter = AttributeInfo.ID == attr
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
try:
|
||||
result = gamedata_session.query(AttributeInfo).options(*processEager(eager)).filter(filter).one()
|
||||
except exc.NoResultFound:
|
||||
result = None
|
||||
return result
|
||||
|
||||
@cachedQuery(1, "field")
|
||||
def getMetaData(field):
|
||||
if isinstance(field, basestring):
|
||||
data = gamedata_session.query(MetaData).get(field)
|
||||
else:
|
||||
raise TypeError("Need string as argument")
|
||||
return data
|
||||
|
||||
@cachedQuery(2, "itemIDs", "attributeID")
|
||||
def directAttributeRequest(itemIDs, attrIDs):
|
||||
for itemID in itemIDs:
|
||||
if not isinstance(itemID, int):
|
||||
raise TypeError("All attrIDs must be integer")
|
||||
for itemID in itemIDs:
|
||||
if not isinstance(itemID, int):
|
||||
raise TypeError("All itemIDs must be integer")
|
||||
|
||||
q = select((eos.types.Item.typeID, eos.types.Attribute.attributeID, eos.types.Attribute.value),
|
||||
and_(eos.types.Attribute.attributeID.in_(attrIDs), eos.types.Item.typeID.in_(itemIDs)),
|
||||
from_obj=[join(eos.types.Attribute, eos.types.Item)])
|
||||
|
||||
result = gamedata_session.execute(q).fetchall()
|
||||
return result
|
||||
33
eos/db/gamedata/unit.py
Executable file
33
eos/db/gamedata/unit.py
Executable file
@@ -0,0 +1,33 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Column, Table, Integer, String
|
||||
from sqlalchemy.orm import mapper, synonym
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Unit
|
||||
|
||||
groups_table = Table("dgmunits", gamedata_meta,
|
||||
Column("unitID", Integer, primary_key = True),
|
||||
Column("unitName", String),
|
||||
Column("displayName", String))
|
||||
|
||||
mapper(Unit, groups_table,
|
||||
properties = {"ID" : synonym("unitID"),
|
||||
"name" : synonym("unitName")})
|
||||
20
eos/db/migration.py
Executable file
20
eos/db/migration.py
Executable file
@@ -0,0 +1,20 @@
|
||||
import sqlalchemy
|
||||
|
||||
def update(saveddata_engine):
|
||||
checkPriceFailures(saveddata_engine)
|
||||
|
||||
def checkPriceFailures(saveddata_engine):
|
||||
# Check if we have 'failed' column
|
||||
try:
|
||||
saveddata_engine.execute("SELECT failed FROM prices")
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
# As we don't have any important data there, let's just drop
|
||||
# and recreate whole table
|
||||
from eos.db.saveddata.price import prices_table
|
||||
# Attempt to drop/create table only if it's already there
|
||||
try:
|
||||
prices_table.drop(saveddata_engine)
|
||||
prices_table.create(saveddata_engine)
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
pass
|
||||
|
||||
3
eos/db/saveddata/__init__.py
Executable file
3
eos/db/saveddata/__init__.py
Executable file
@@ -0,0 +1,3 @@
|
||||
__all__ = ["character", "fit", "module", "user", "skill", "price",
|
||||
"booster", "drone", "implant", "fleet", "damagePattern",
|
||||
"miscData"]
|
||||
47
eos/db/saveddata/booster.py
Executable file
47
eos/db/saveddata/booster.py
Executable file
@@ -0,0 +1,47 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, ForeignKey, Integer, UniqueConstraint, Boolean
|
||||
from sqlalchemy.orm import mapper, relation
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Booster
|
||||
|
||||
boosters_table = Table("boosters", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("itemID", Integer),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable = False),
|
||||
Column("active", Boolean),
|
||||
UniqueConstraint("itemID", "fitID"))
|
||||
|
||||
activeSideEffects_table = Table("boostersActiveSideEffects", saveddata_meta,
|
||||
Column("boosterID", ForeignKey("boosters.ID"), primary_key = True),
|
||||
Column("effectID", Integer, primary_key = True))
|
||||
|
||||
class ActiveSideEffectsDummy(object):
|
||||
def __init__(self, effectID):
|
||||
self.effectID = effectID
|
||||
|
||||
|
||||
mapper(ActiveSideEffectsDummy, activeSideEffects_table)
|
||||
mapper(Booster, boosters_table,
|
||||
properties = {"_Booster__activeSideEffectDummies" : relation(ActiveSideEffectsDummy)})
|
||||
|
||||
Booster._Booster__activeSideEffectIDs = association_proxy("_Booster__activeSideEffectDummies", "effectID")
|
||||
42
eos/db/saveddata/character.py
Executable file
42
eos/db/saveddata/character.py
Executable file
@@ -0,0 +1,42 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, String
|
||||
from sqlalchemy.orm import relation, mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.db.saveddata.implant import charImplants_table
|
||||
from eos.types import Character, User, Skill, Implant
|
||||
from eos.effectHandlerHelpers import HandledImplantBoosterList
|
||||
|
||||
characters_table = Table("characters", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("name", String, nullable = False),
|
||||
Column("apiID", Integer),
|
||||
Column("apiKey", String),
|
||||
Column("defaultLevel", Integer, nullable=True),
|
||||
Column("ownerID", ForeignKey("users.ID"), nullable = True))
|
||||
|
||||
mapper(Character, characters_table,
|
||||
properties = {"_Character__owner" : relation(User, backref = "characters"),
|
||||
"_Character__skills" : relation(Skill, backref="character", cascade = "all,delete-orphan"),
|
||||
"_Character__implants" : relation(Implant, collection_class = HandledImplantBoosterList, cascade='all,delete-orphan', single_parent=True,
|
||||
primaryjoin = charImplants_table.c.charID == characters_table.c.ID,
|
||||
secondaryjoin = charImplants_table.c.implantID == Implant.ID,
|
||||
secondary = charImplants_table),})
|
||||
35
eos/db/saveddata/damagePattern.py
Executable file
35
eos/db/saveddata/damagePattern.py
Executable file
@@ -0,0 +1,35 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, String
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import DamagePattern
|
||||
|
||||
damagePatterns_table = Table("damagePatterns", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("name", String),
|
||||
Column("emAmount", Integer),
|
||||
Column("thermalAmount", Integer),
|
||||
Column("kineticAmount", Integer),
|
||||
Column("explosiveAmount", Integer),
|
||||
Column("ownerID", ForeignKey("users.ID"), nullable=True))
|
||||
|
||||
mapper(DamagePattern, damagePatterns_table)
|
||||
33
eos/db/saveddata/drone.py
Executable file
33
eos/db/saveddata/drone.py
Executable file
@@ -0,0 +1,33 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean
|
||||
from sqlalchemy.orm import mapper
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Drone
|
||||
|
||||
drones_table = Table("drones", saveddata_meta,
|
||||
Column("groupID", Integer, primary_key=True),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable = False, index = True),
|
||||
Column("itemID", Integer, nullable = False),
|
||||
Column("amount", Integer, nullable = False),
|
||||
Column("amountActive", Integer, nullable = False),
|
||||
Column("projected", Boolean, default = False))
|
||||
|
||||
mapper(Drone, drones_table)
|
||||
68
eos/db/saveddata/fit.py
Executable file
68
eos/db/saveddata/fit.py
Executable file
@@ -0,0 +1,68 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, String
|
||||
from sqlalchemy.orm import relation, mapper
|
||||
from sqlalchemy.sql import and_
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.db.saveddata.module import modules_table
|
||||
from eos.db.saveddata.drone import drones_table
|
||||
from eos.db.saveddata.implant import fitImplants_table
|
||||
from eos.types import Fit, Module, User, Booster, Drone, Implant, Character, DamagePattern
|
||||
from eos.effectHandlerHelpers import HandledModuleList, HandledDroneList, \
|
||||
HandledImplantBoosterList, HandledProjectedModList, HandledProjectedDroneList, \
|
||||
HandledProjectedFitList
|
||||
fits_table = Table("fits", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("ownerID", ForeignKey("users.ID"), nullable = True, index = True),
|
||||
Column("shipID", Integer, nullable = False, index = True),
|
||||
Column("name", String, nullable = False),
|
||||
Column("timestamp", Integer, nullable = False),
|
||||
Column("characterID", ForeignKey("characters.ID"), nullable = True),
|
||||
Column("damagePatternID", ForeignKey("damagePatterns.ID"), nullable=True))
|
||||
|
||||
projectedFits_table = Table("projectedFits", saveddata_meta,
|
||||
Column("sourceID", ForeignKey("fits.ID"), primary_key = True),
|
||||
Column("victimID", ForeignKey("fits.ID"), primary_key = True),
|
||||
Column("amount", Integer))
|
||||
mapper(Fit, fits_table,
|
||||
properties = {"_Fit__modules" : relation(Module, collection_class = HandledModuleList,
|
||||
primaryjoin = and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False),
|
||||
order_by = modules_table.c.position, cascade='all, delete, delete-orphan'),
|
||||
"_Fit__projectedModules" : relation(Module, collection_class = HandledProjectedModList, cascade='all, delete, delete-orphan', single_parent=True,
|
||||
primaryjoin = and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)),
|
||||
"owner" : relation(User, backref = "fits"),
|
||||
"_Fit__boosters" : relation(Booster, collection_class = HandledImplantBoosterList, cascade='all, delete, delete-orphan', single_parent=True),
|
||||
"_Fit__drones" : relation(Drone, collection_class = HandledDroneList, cascade='all, delete, delete-orphan', single_parent=True,
|
||||
primaryjoin = and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)),
|
||||
"_Fit__projectedDrones" : relation(Drone, collection_class = HandledProjectedDroneList, cascade='all, delete, delete-orphan', single_parent=True,
|
||||
primaryjoin = and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)),
|
||||
"_Fit__implants" : relation(Implant, collection_class = HandledImplantBoosterList, cascade='all, delete, delete-orphan', single_parent=True,
|
||||
primaryjoin = fitImplants_table.c.fitID == fits_table.c.ID,
|
||||
secondaryjoin = fitImplants_table.c.implantID == Implant.ID,
|
||||
secondary = fitImplants_table),
|
||||
"_Fit__character" : relation(Character, backref = "fits"),
|
||||
"_Fit__damagePattern" : relation(DamagePattern),
|
||||
"_Fit__projectedFits" : relation(Fit,
|
||||
primaryjoin = projectedFits_table.c.victimID == fits_table.c.ID,
|
||||
secondaryjoin = fits_table.c.ID == projectedFits_table.c.sourceID,
|
||||
secondary = projectedFits_table,
|
||||
collection_class = HandledProjectedFitList)
|
||||
})
|
||||
66
eos/db/saveddata/fleet.py
Executable file
66
eos/db/saveddata/fleet.py
Executable file
@@ -0,0 +1,66 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, String
|
||||
from sqlalchemy.orm import mapper, relation
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Fleet, Wing, Squad, Fit
|
||||
from eos.db.saveddata.fit import fits_table
|
||||
|
||||
gangs_table = Table("gangs", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("leaderID", ForeignKey("fits.ID")),
|
||||
Column("boosterID", ForeignKey("fits.ID")),
|
||||
Column("name", String))
|
||||
|
||||
wings_table = Table("wings", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("gangID", ForeignKey("gangs.ID")),
|
||||
Column("boosterID", ForeignKey("fits.ID")),
|
||||
Column("leaderID", ForeignKey("fits.ID")))
|
||||
|
||||
squads_table = Table("squads", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("wingID", ForeignKey("wings.ID")),
|
||||
Column("leaderID", ForeignKey("fits.ID")),
|
||||
Column("boosterID", ForeignKey("fits.ID")))
|
||||
|
||||
squadmembers_table = Table("squadmembers", saveddata_meta,
|
||||
Column("squadID", ForeignKey("squads.ID"), primary_key = True),
|
||||
Column("memberID", ForeignKey("fits.ID"), primary_key = True))
|
||||
|
||||
mapper(Fleet, gangs_table,
|
||||
properties = {"wings" : relation(Wing, backref="gang"),
|
||||
"leader" : relation(Fit, primaryjoin = gangs_table.c.leaderID == fits_table.c.ID),
|
||||
"booster": relation(Fit, primaryjoin = gangs_table.c.boosterID == fits_table.c.ID)})
|
||||
|
||||
mapper(Wing, wings_table,
|
||||
properties = {"squads" : relation(Squad, backref="wing"),
|
||||
"leader" : relation(Fit, primaryjoin = wings_table.c.leaderID == fits_table.c.ID),
|
||||
"booster": relation(Fit, primaryjoin = wings_table.c.boosterID == fits_table.c.ID)})
|
||||
|
||||
mapper(Squad, squads_table,
|
||||
properties = {"leader" : relation(Fit, primaryjoin = squads_table.c.leaderID == fits_table.c.ID),
|
||||
"booster" : relation(Fit, primaryjoin = squads_table.c.boosterID == fits_table.c.ID),
|
||||
"members" : relation(Fit,
|
||||
primaryjoin = squads_table.c.ID == squadmembers_table.c.squadID,
|
||||
secondaryjoin = squadmembers_table.c.memberID == fits_table.c.ID,
|
||||
secondary = squadmembers_table)})
|
||||
|
||||
39
eos/db/saveddata/implant.py
Executable file
39
eos/db/saveddata/implant.py
Executable file
@@ -0,0 +1,39 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Implant
|
||||
|
||||
implants_table = Table("implants", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("itemID", Integer),
|
||||
Column("active", Boolean))
|
||||
|
||||
fitImplants_table = Table("fitImplants", saveddata_meta,
|
||||
Column("fitID", ForeignKey("fits.ID"), index = True),
|
||||
Column("implantID", ForeignKey("implants.ID"), primary_key = True))
|
||||
|
||||
charImplants_table = Table("charImplants", saveddata_meta,
|
||||
Column("charID", ForeignKey("characters.ID"), index = True),
|
||||
Column("implantID", ForeignKey("implants.ID"), primary_key = True))
|
||||
|
||||
mapper(Implant, implants_table)
|
||||
29
eos/db/saveddata/miscData.py
Executable file
29
eos/db/saveddata/miscData.py
Executable file
@@ -0,0 +1,29 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2011 Anton Vorobyov
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Column, Table, String
|
||||
from sqlalchemy.orm import mapper
|
||||
from eos.types import MiscData
|
||||
from eos.db import saveddata_meta
|
||||
|
||||
miscdata_table = Table("miscdata", saveddata_meta,
|
||||
Column("fieldName", String, primary_key=True),
|
||||
Column("fieldValue", String))
|
||||
|
||||
mapper(MiscData, miscdata_table)
|
||||
39
eos/db/saveddata/module.py
Executable file
39
eos/db/saveddata/module.py
Executable file
@@ -0,0 +1,39 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, CheckConstraint, Boolean
|
||||
from sqlalchemy.orm import relation, mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Module, Fit
|
||||
|
||||
modules_table = Table("modules", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable = False, index = True),
|
||||
Column("itemID", Integer, nullable = True),
|
||||
Column("dummySlot", Integer, nullable = True, default = None),
|
||||
Column("chargeID", Integer),
|
||||
Column("state", Integer, CheckConstraint("state >= -1"), CheckConstraint("state <= 2")),
|
||||
Column("projected", Boolean, default = False, nullable = False),
|
||||
Column("position", Integer),
|
||||
CheckConstraint('("dummySlot" = NULL OR "itemID" = NULL) AND "dummySlot" != "itemID"'))
|
||||
|
||||
mapper(Module, modules_table,
|
||||
properties = {"owner" : relation(Fit)})
|
||||
|
||||
31
eos/db/saveddata/price.py
Executable file
31
eos/db/saveddata/price.py
Executable file
@@ -0,0 +1,31 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Float, Integer
|
||||
from sqlalchemy.orm import mapper
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Price
|
||||
|
||||
prices_table = Table("prices", saveddata_meta,
|
||||
Column("typeID", Integer, primary_key=True),
|
||||
Column("price", Float),
|
||||
Column("time", Integer, nullable = False),
|
||||
Column("failed", Integer))
|
||||
|
||||
mapper(Price, prices_table)
|
||||
365
eos/db/saveddata/queries.py
Executable file
365
eos/db/saveddata/queries.py
Executable file
@@ -0,0 +1,365 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from eos.db.util import processEager, processWhere
|
||||
from eos.db import saveddata_session, sd_lock
|
||||
from eos.types import User, Character, Fit, Price, DamagePattern, Fleet, MiscData, Wing, Squad
|
||||
from eos.db.saveddata.fleet import squadmembers_table
|
||||
from sqlalchemy.sql import and_
|
||||
import eos.config
|
||||
|
||||
configVal = getattr(eos.config, "saveddataCache", None)
|
||||
if configVal is True:
|
||||
import weakref
|
||||
itemCache = {}
|
||||
queryCache = {}
|
||||
def cachedQuery(type, amount, *keywords):
|
||||
itemCache[type] = localItemCache = weakref.WeakValueDictionary()
|
||||
queryCache[type] = typeQueryCache = {}
|
||||
def deco(function):
|
||||
localQueryCache = typeQueryCache[function] = {}
|
||||
def setCache(cacheKey, args, kwargs):
|
||||
items = function(*args, **kwargs)
|
||||
IDs = set()
|
||||
localQueryCache[cacheKey] = (isinstance(items, list), IDs)
|
||||
stuff = items if isinstance(items, list) else (items,)
|
||||
for item in stuff:
|
||||
ID = getattr(item, "ID", None)
|
||||
if ID is None:
|
||||
#Some uncachable data, don't cache this query
|
||||
del localQueryCache[cacheKey]
|
||||
break
|
||||
localItemCache[ID] = item
|
||||
IDs.add(ID)
|
||||
|
||||
return items
|
||||
|
||||
def checkAndReturn(*args, **kwargs):
|
||||
useCache = kwargs.pop("useCache", True)
|
||||
cacheKey = []
|
||||
cacheKey.extend(args)
|
||||
for keyword in keywords:
|
||||
cacheKey.append(kwargs.get(keyword))
|
||||
|
||||
cacheKey = tuple(cacheKey)
|
||||
info = localQueryCache.get(cacheKey)
|
||||
if info is None or not useCache:
|
||||
items = setCache(cacheKey, args, kwargs)
|
||||
else:
|
||||
l, IDs = info
|
||||
if l:
|
||||
items = []
|
||||
for ID in IDs:
|
||||
data = localItemCache.get(ID)
|
||||
if data is None:
|
||||
#Fuck, some of our stuff isn't cached it seems.
|
||||
items = setCache(cacheKey, args, kwargs)
|
||||
break
|
||||
items.append(data)
|
||||
else:
|
||||
for ID in IDs:
|
||||
items = localItemCache.get(ID)
|
||||
if items is None:
|
||||
items = setCache(cacheKey, args, kwargs)
|
||||
break
|
||||
|
||||
return items
|
||||
return checkAndReturn
|
||||
return deco
|
||||
|
||||
def removeCachedEntry(type, ID):
|
||||
if not type in queryCache:
|
||||
return
|
||||
functionCache = queryCache[type]
|
||||
for _, localCache in functionCache.iteritems():
|
||||
toDelete = set()
|
||||
for cacheKey, info in localCache.iteritems():
|
||||
IDs = info[1]
|
||||
if ID in IDs:
|
||||
toDelete.add(cacheKey)
|
||||
|
||||
for cacheKey in toDelete:
|
||||
del localCache[cacheKey]
|
||||
|
||||
if ID in itemCache[type]:
|
||||
del itemCache[type][ID]
|
||||
|
||||
elif callable(configVal):
|
||||
cachedQuery, removeCachedEntry = eos.config.gamedataCache
|
||||
else:
|
||||
def cachedQuery(amount, *keywords):
|
||||
def deco(function):
|
||||
def checkAndReturn(*args, **kwargs):
|
||||
return function(*args, **kwargs)
|
||||
|
||||
return checkAndReturn
|
||||
return deco
|
||||
|
||||
def removeCachedEntry(*args, **kwargs):
|
||||
return
|
||||
|
||||
def sqlizeString(line):
|
||||
# Escape backslashes first, as they will be as escape symbol in queries
|
||||
# Then escape percent and underscore signs
|
||||
# Finally, replace generic wildcards with sql-style wildcards
|
||||
line = line.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_").replace("*", "%")
|
||||
return line
|
||||
|
||||
@cachedQuery(User, 1, "lookfor")
|
||||
def getUser(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
with sd_lock:
|
||||
user = saveddata_session.query(User).get(lookfor)
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
user = saveddata_session.query(User).options(*eager).filter(User.ID == lookfor).first()
|
||||
elif isinstance(lookfor, basestring):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
user = saveddata_session.query(User).options(*eager).filter(User.username == lookfor).first()
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return user
|
||||
|
||||
@cachedQuery(Character, 1, "lookfor")
|
||||
def getCharacter(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
with sd_lock:
|
||||
character = saveddata_session.query(Character).get(lookfor)
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
character = saveddata_session.query(Character).options(*eager).filter(Character.ID == lookfor).first()
|
||||
elif isinstance(lookfor, basestring):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
character = saveddata_session.query(Character).options(*eager).filter(Character.name == lookfor).first()
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return character
|
||||
|
||||
def getCharacterList(eager=None):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
characters = saveddata_session.query(Character).options(*eager).all()
|
||||
return characters
|
||||
|
||||
def getCharactersForUser(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
characters = saveddata_session.query(Character).options(*eager).filter(Character.ownerID == lookfor).all()
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
return characters
|
||||
|
||||
@cachedQuery(Fit, 1, "lookfor")
|
||||
def getFit(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
with sd_lock:
|
||||
fit = saveddata_session.query(Fit).get(lookfor)
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
fit = saveddata_session.query(Fit).options(*eager).filter(Fit.ID == fitID).first()
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
return fit
|
||||
|
||||
@cachedQuery(Fleet, 1, "fleetID")
|
||||
def getFleet(fleetID, eager=None):
|
||||
if isinstance(fleetID, int):
|
||||
if eager is None:
|
||||
with sd_lock:
|
||||
fleet = saveddata_session.query(Fleet).get(fleetID)
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
fleet = saveddata_session.query(Fleet).options(*eager).filter(Fleet.ID == fleetID).first()
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
return fleet
|
||||
|
||||
@cachedQuery(Wing, 1, "wingID")
|
||||
def getWing(wingID, eager=None):
|
||||
if isinstance(wingID, int):
|
||||
if eager is None:
|
||||
with sd_lock:
|
||||
wing = saveddata_session.query(Wing).get(wingID)
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
wing = saveddata_session.query(Wing).options(*eager).filter(Wing.ID == wingID).first()
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
return wing
|
||||
|
||||
@cachedQuery(Squad, 1, "squadID")
|
||||
def getSquad(squadID, eager=None):
|
||||
if isinstance(squadID, int):
|
||||
if eager is None:
|
||||
with sd_lock:
|
||||
squad = saveddata_session.query(Squad).get(squadID)
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
squad = saveddata_session.query(Squad).options(*eager).filter(Fleet.ID == squadID).first()
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
return squad
|
||||
|
||||
def getFitsWithShip(shipID, ownerID=None, where=None, eager=None):
|
||||
"""
|
||||
Get all the fits using a certain ship.
|
||||
If no user is passed, do this for all users.
|
||||
"""
|
||||
if isinstance(shipID, int):
|
||||
if ownerID is not None and not isinstance(ownerID, int):
|
||||
raise TypeError("OwnerID must be integer")
|
||||
filter = Fit.shipID == shipID
|
||||
if ownerID is not None:
|
||||
filter = and_(filter, Fit.ownerID == ownerID)
|
||||
|
||||
filter = processWhere(filter, where)
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
fits = saveddata_session.query(Fit).options(*eager).filter(filter).all()
|
||||
else:
|
||||
raise TypeError("ShipID must be integer")
|
||||
return fits
|
||||
|
||||
def countFitsWithShip(shipID, ownerID=None, where=None, eager=None):
|
||||
"""
|
||||
Get all the fits using a certain ship.
|
||||
If no user is passed, do this for all users.
|
||||
"""
|
||||
if isinstance(shipID, int):
|
||||
if ownerID is not None and not isinstance(ownerID, int):
|
||||
raise TypeError("OwnerID must be integer")
|
||||
filter = Fit.shipID == shipID
|
||||
if ownerID is not None:
|
||||
filter = and_(filter, Fit.ownerID == ownerID)
|
||||
|
||||
filter = processWhere(filter, where)
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
count = saveddata_session.query(Fit).options(*eager).filter(filter).count()
|
||||
else:
|
||||
raise TypeError("ShipID must be integer")
|
||||
return count
|
||||
|
||||
def getFitList(eager=None):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
fits = saveddata_session.query(Fit).options(*eager).all()
|
||||
return fits
|
||||
|
||||
def getFleetList(eager=None):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
fleets = saveddata_session.query(Fleet).options(*eager).all()
|
||||
return fleets
|
||||
|
||||
@cachedQuery(Price, 1, "typeID")
|
||||
def getPrice(typeID):
|
||||
if isinstance(typeID, int):
|
||||
with sd_lock:
|
||||
price = saveddata_session.query(Price).get(typeID)
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
return price
|
||||
|
||||
def getMiscData(field):
|
||||
if isinstance(field, basestring):
|
||||
with sd_lock:
|
||||
data = saveddata_session.query(MiscData).get(field)
|
||||
else:
|
||||
raise TypeError("Need string as argument")
|
||||
return data
|
||||
|
||||
def getDamagePatternList(eager=None):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
patterns = saveddata_session.query(DamagePattern).options(*eager).all()
|
||||
return patterns
|
||||
|
||||
@cachedQuery(DamagePattern, 1, "lookfor")
|
||||
def getDamagePattern(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
with sd_lock:
|
||||
pattern = saveddata_session.query(DamagePattern).get(lookfor)
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
pattern = saveddata_session.query(DamagePattern).options(*eager).filter(DamagePattern.ID == lookfor).first()
|
||||
elif isinstance(lookfor, basestring):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
pattern = saveddata_session.query(DamagePattern).options(*eager).filter(DamagePattern.name == lookfor).first()
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return pattern
|
||||
|
||||
def searchFits(nameLike, where=None, eager=None):
|
||||
if not isinstance(nameLike, basestring):
|
||||
raise TypeError("Need string as argument")
|
||||
# Prepare our string for request
|
||||
nameLike = u"%{0}%".format(sqlizeString(nameLike))
|
||||
|
||||
#Add any extra components to the search to our where clause
|
||||
filter = processWhere(Fit.name.like(nameLike, escape="\\"), where)
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
fits = saveddata_session.query(Fit).options(*eager).filter(filter).all()
|
||||
return fits
|
||||
|
||||
def getSquadsIDsWithFitID(fitID):
|
||||
if isinstance(fitID, int):
|
||||
with sd_lock:
|
||||
squads = saveddata_session.query(squadmembers_table.c.squadID).filter(squadmembers_table.c.memberID == fitID).all()
|
||||
squads = tuple(entry[0] for entry in squads)
|
||||
return squads
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
|
||||
|
||||
def add(stuff):
|
||||
with sd_lock:
|
||||
saveddata_session.add(stuff)
|
||||
|
||||
def save(stuff):
|
||||
add(stuff)
|
||||
commit()
|
||||
|
||||
def remove(stuff):
|
||||
removeCachedEntry(type(stuff), stuff.ID)
|
||||
with sd_lock:
|
||||
saveddata_session.delete(stuff)
|
||||
commit()
|
||||
|
||||
|
||||
def commit():
|
||||
with sd_lock:
|
||||
saveddata_session.commit()
|
||||
saveddata_session.flush()
|
||||
31
eos/db/saveddata/skill.py
Executable file
31
eos/db/saveddata/skill.py
Executable file
@@ -0,0 +1,31 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Skill
|
||||
|
||||
skills_table = Table("characterSkills", saveddata_meta,
|
||||
Column("characterID", ForeignKey("characters.ID"), primary_key = True, index = True),
|
||||
Column("itemID", Integer, primary_key = True),
|
||||
Column("_Skill__level", Integer, nullable = True))
|
||||
|
||||
mapper(Skill, skills_table)
|
||||
32
eos/db/saveddata/user.py
Executable file
32
eos/db/saveddata/user.py
Executable file
@@ -0,0 +1,32 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, String, Boolean
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import User
|
||||
|
||||
users_table = Table("users", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("username", String, nullable = False, unique = True),
|
||||
Column("password", String, nullable = False),
|
||||
Column("admin", Boolean, nullable = False))
|
||||
|
||||
mapper(User, users_table)
|
||||
68
eos/db/util.py
Executable file
68
eos/db/util.py
Executable file
@@ -0,0 +1,68 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy.orm import eagerload
|
||||
from sqlalchemy.sql import and_
|
||||
|
||||
replace = {"attributes": "_Item__attributes",
|
||||
"modules": "_Fit__modules",
|
||||
"projectedModules": "_Fit__projectedModules",
|
||||
"boosters": "_Fit__boosters",
|
||||
"drones": "_Fit__drones",
|
||||
"projectedDrones": "_Fit__projectedDrones",
|
||||
"implants": "_Fit__implants",
|
||||
"character": "_Fit__character",
|
||||
"damagePattern": "_Fit__damagePattern",
|
||||
"projectedFits": "_Fit__projectedFits"}
|
||||
|
||||
def processEager(eager):
|
||||
if eager == None:
|
||||
return tuple()
|
||||
else:
|
||||
l = []
|
||||
if isinstance(eager, basestring):
|
||||
eager = (eager,)
|
||||
|
||||
for e in eager:
|
||||
l.append(eagerload(_replacements(e)))
|
||||
|
||||
return l
|
||||
|
||||
def _replacements(eagerString):
|
||||
splitEager = eagerString.split(".")
|
||||
for i in xrange(len(splitEager)):
|
||||
part = splitEager[i]
|
||||
replacement = replace.get(part)
|
||||
if replacement:
|
||||
splitEager[i] = replacement
|
||||
|
||||
return ".".join(splitEager)
|
||||
|
||||
def processWhere(clause, where):
|
||||
if where is not None:
|
||||
if not hasattr(where, "__iter__"):
|
||||
where = (where,)
|
||||
|
||||
try:
|
||||
for extraClause in where:
|
||||
clause = and_(clause, extraClause)
|
||||
except NotImplementedError:
|
||||
clause = and_(clause, where)
|
||||
|
||||
return clause
|
||||
270
eos/effectHandlerHelpers.py
Executable file
270
eos/effectHandlerHelpers.py
Executable file
@@ -0,0 +1,270 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
import eos.db
|
||||
import eos.types
|
||||
|
||||
class HandledList(list):
|
||||
def filteredItemPreAssign(self, filter, *args, **kwargs):
|
||||
for element in self:
|
||||
try:
|
||||
if filter(element):
|
||||
element.preAssignItemAttr(*args, **kwargs)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def filteredItemIncrease(self, filter, *args, **kwargs):
|
||||
for element in self:
|
||||
try:
|
||||
if filter(element):
|
||||
element.increaseItemAttr(*args, **kwargs)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def filteredItemMultiply(self, filter, *args, **kwargs):
|
||||
for element in self:
|
||||
try:
|
||||
if filter(element):
|
||||
element.multiplyItemAttr(*args, **kwargs)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def filteredItemBoost(self, filter, *args, **kwargs):
|
||||
for element in self:
|
||||
try:
|
||||
if filter(element):
|
||||
element.boostItemAttr(*args, **kwargs)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def filteredItemForce(self, filter, *args, **kwargs):
|
||||
for element in self:
|
||||
try:
|
||||
if filter(element):
|
||||
element.forceItemAttr(*args, **kwargs)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def filteredChargePreAssign(self, filter, *args, **kwargs):
|
||||
for element in self:
|
||||
try:
|
||||
if filter(element):
|
||||
element.preAssignChargeAttr(*args, **kwargs)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def filteredChargeIncrease(self, filter, *args, **kwargs):
|
||||
for element in self:
|
||||
try:
|
||||
if filter(element):
|
||||
element.increaseChargeAttr(*args, **kwargs)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def filteredChargeMultiply(self, filter, *args, **kwargs):
|
||||
for element in self:
|
||||
try:
|
||||
if filter(element):
|
||||
element.multiplyChargeAttr(*args, **kwargs)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def filteredChargeBoost(self, filter, *args, **kwargs):
|
||||
for element in self:
|
||||
try:
|
||||
if filter(element):
|
||||
element.boostChargeAttr(*args, **kwargs)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def filteredChargeForce(self, filter, *args, **kwargs):
|
||||
for element in self:
|
||||
try:
|
||||
if filter(element):
|
||||
element.forceChargeAttr(*args, **kwargs)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
class HandledModuleList(HandledList):
|
||||
def append(self, mod):
|
||||
emptyPosition = float("Inf")
|
||||
for i in xrange(len(self)):
|
||||
currMod = self[i]
|
||||
if currMod.isEmpty and not mod.isEmpty and currMod.slot == mod.slot:
|
||||
currPos = mod.position or i
|
||||
if currPos < emptyPosition:
|
||||
emptyPosition = currPos
|
||||
|
||||
if emptyPosition < len(self):
|
||||
del self[emptyPosition]
|
||||
mod.position = emptyPosition
|
||||
HandledList.insert(self, emptyPosition, mod)
|
||||
return
|
||||
|
||||
mod.position = len(self)
|
||||
HandledList.append(self, mod)
|
||||
|
||||
def insert(self, index, mod):
|
||||
mod.position = index
|
||||
i = index
|
||||
while i < len(self):
|
||||
self[i].position += 1
|
||||
i += 1
|
||||
HandledList.insert(self, index, mod)
|
||||
|
||||
def remove(self, mod):
|
||||
HandledList.remove(self, mod)
|
||||
oldPos = mod.position
|
||||
|
||||
mod.position = None
|
||||
for i in xrange(oldPos, len(self)):
|
||||
self[i].position -= 1
|
||||
|
||||
def toDummy(self, index):
|
||||
mod = self[index]
|
||||
if not mod.isEmpty:
|
||||
dummy = eos.types.Module.buildEmpty(mod.slot)
|
||||
dummy.position = index
|
||||
self[index] = dummy
|
||||
|
||||
def freeSlot(self, slot):
|
||||
for i in range(len(self) -1, -1, -1):
|
||||
mod = self[i]
|
||||
if mod.getModifiedItemAttr("subSystemSlot") == slot:
|
||||
del self[i]
|
||||
|
||||
class HandledDroneList(HandledList):
|
||||
def find(self, item):
|
||||
for d in self:
|
||||
if d.item == item:
|
||||
yield d
|
||||
|
||||
def findFirst(self, item):
|
||||
for d in self.find(item):
|
||||
return d
|
||||
|
||||
def append(self, drone):
|
||||
list.append(self, drone)
|
||||
|
||||
def remove(self, drone):
|
||||
HandledList.remove(self, drone)
|
||||
|
||||
def appendItem(self, item, amount = 1):
|
||||
if amount < 1: ValueError("Amount of drones to add should be >= 1")
|
||||
d = self.findFirst(item)
|
||||
|
||||
if d is None:
|
||||
d = eos.types.Drone(item)
|
||||
self.append(d)
|
||||
|
||||
d.amount += amount
|
||||
return d
|
||||
|
||||
def removeItem(self, item, amount):
|
||||
if amount < 1: ValueError("Amount of drones to remove should be >= 1")
|
||||
d = self.findFirst(item)
|
||||
if d is None: return
|
||||
d.amount -= amount
|
||||
if d.amount <= 0:
|
||||
self.remove(d)
|
||||
return None
|
||||
|
||||
return d
|
||||
|
||||
|
||||
class HandledImplantBoosterList(HandledList):
|
||||
def __init__(self):
|
||||
self.__slotCache = {}
|
||||
|
||||
def append(self, implant):
|
||||
if self.__slotCache.has_key(implant.slot):
|
||||
raise ValueError("Implant/Booster slot already in use, remove the old one first or set replace = True")
|
||||
self.__slotCache[implant.slot] = implant
|
||||
HandledList.append(self, implant)
|
||||
|
||||
def remove(self, implant):
|
||||
HandledList.remove(self, implant)
|
||||
del self.__slotCache[implant.slot]
|
||||
# While we deleted this implant, in edge case seems like not all references
|
||||
# to it are removed and object still lives in session; forcibly remove it,
|
||||
# or otherwise when adding the same booster twice booster's table (typeID, fitID)
|
||||
# constraint will report database integrity error
|
||||
# TODO: make a proper fix, probably by adjusting fit-boosters sqlalchemy relationships
|
||||
eos.db.remove(implant)
|
||||
|
||||
def freeSlot(self, slot):
|
||||
if hasattr(slot, "slot"):
|
||||
slot = slot.slot
|
||||
|
||||
try:
|
||||
implant = self.__slotCache[slot]
|
||||
except KeyError:
|
||||
return False
|
||||
try:
|
||||
self.remove(implant)
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
|
||||
class HandledProjectedModList(HandledList):
|
||||
def append(self, proj):
|
||||
proj.projected = True
|
||||
HandledList.append(self, proj)
|
||||
|
||||
class HandledProjectedDroneList(HandledDroneList):
|
||||
def append(self, proj):
|
||||
proj.projected = True
|
||||
list.append(self, proj)
|
||||
|
||||
class HandledProjectedFitList(HandledList):
|
||||
def append(self, proj):
|
||||
proj.projected = True
|
||||
list.append(self, proj)
|
||||
|
||||
class HandledItem(object):
|
||||
def preAssignItemAttr(self, *args, **kwargs):
|
||||
self.itemModifiedAttributes.preAssign(*args, **kwargs)
|
||||
|
||||
def increaseItemAttr(self, *args, **kwargs):
|
||||
self.itemModifiedAttributes.increase(*args, **kwargs)
|
||||
|
||||
def multiplyItemAttr(self, *args, **kwargs):
|
||||
self.itemModifiedAttributes.multiply(*args, **kwargs)
|
||||
|
||||
def boostItemAttr(self, *args, **kwargs):
|
||||
self.itemModifiedAttributes.boost(*args, **kwargs)
|
||||
|
||||
def forceItemAttr(self, *args, **kwargs):
|
||||
self.itemModifiedAttributes.force(*args, **kwargs)
|
||||
|
||||
class HandledCharge(object):
|
||||
def preAssignChargeAttr(self, *args, **kwargs):
|
||||
self.chargeModifiedAttributes.preAssign(*args, **kwargs)
|
||||
|
||||
def increaseChargeAttr(self, *args, **kwargs):
|
||||
self.chargeModifiedAttributes.increase(*args, **kwargs)
|
||||
|
||||
def multiplyChargeAttr(self, *args, **kwargs):
|
||||
self.chargeModifiedAttributes.multiply(*args, **kwargs)
|
||||
|
||||
def boostChargeAttr(self, *args, **kwargs):
|
||||
self.chargeModifiedAttributes.boost(*args, **kwargs)
|
||||
|
||||
def forceChargeAttr(self, *args, **kwargs):
|
||||
self.chargeModifiedAttributes.force(*args, **kwargs)
|
||||
19
eos/effects/__init__.py
Executable file
19
eos/effects/__init__.py
Executable file
@@ -0,0 +1,19 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
# 2010 Anton Vorobyov
|
||||
#
|
||||
# This file, as well as all files in this folder, are part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Modules named like: Dynamic Fuel Valve (8 of 8)
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Propulsion Module",
|
||||
"capacitorNeed", container.getModifiedItemAttr("capNeedBonus"))
|
||||
8
eos/effects/accerationcontrolskillabmwdspeedboost.py
Executable file
8
eos/effects/accerationcontrolskillabmwdspeedboost.py
Executable file
@@ -0,0 +1,8 @@
|
||||
# Used by:
|
||||
# Implant: Zor's Custom Navigation Hyper-Link
|
||||
# Skill: Acceleration Control
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Propulsion Module",
|
||||
"speedFactor", container.getModifiedItemAttr("speedFBonus") * level)
|
||||
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Rogue' Acceleration Control AC (6 of 6)
|
||||
type = "passive"
|
||||
def handler(fit, implant, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Propulsion Module",
|
||||
"speedFactor", implant.getModifiedItemAttr("speedFBonus"))
|
||||
8
eos/effects/accessdifficultybonusmodifierrequiringarchaelogy.py
Executable file
8
eos/effects/accessdifficultybonusmodifierrequiringarchaelogy.py
Executable file
@@ -0,0 +1,8 @@
|
||||
# Used by:
|
||||
# Modules named like: Emission Scope Sharpener (8 of 8)
|
||||
# Implant: Poteque 'Prospector' Archaeology AC-905
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
fit.modules.filteredItemIncrease(lambda module: module.item.requiresSkill("Archaeology"),
|
||||
"accessDifficultyBonus",
|
||||
container.getModifiedItemAttr("accessDifficultyBonusModifier"), position="post")
|
||||
8
eos/effects/accessdifficultybonusmodifierrequiringhacking.py
Executable file
8
eos/effects/accessdifficultybonusmodifierrequiringhacking.py
Executable file
@@ -0,0 +1,8 @@
|
||||
# Used by:
|
||||
# Modules named like: Memetic Algorithm Bank (8 of 8)
|
||||
# Implant: Poteque 'Prospector' Hacking HC-905
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
fit.modules.filteredItemIncrease(lambda c: c.item.requiresSkill("Hacking"),
|
||||
"accessDifficultyBonus",
|
||||
container.getModifiedItemAttr("accessDifficultyBonusModifier"), position="post")
|
||||
8
eos/effects/adaptivearmorhardener.py
Executable file
8
eos/effects/adaptivearmorhardener.py
Executable file
@@ -0,0 +1,8 @@
|
||||
# Used by:
|
||||
# Module: Reactive Armor Hardener
|
||||
type = "active"
|
||||
def handler(fit, module, context):
|
||||
for type in ("kinetic", "thermal", "explosive", "em"):
|
||||
attr = "armor%sDamageResonance" % type.capitalize()
|
||||
fit.ship.multiplyItemAttr(attr, module.getModifiedItemAttr(attr),
|
||||
stackingPenalties=True, penaltyGroup="preMul")
|
||||
5
eos/effects/addtosignatureradius2.py
Executable file
5
eos/effects/addtosignatureradius2.py
Executable file
@@ -0,0 +1,5 @@
|
||||
# Used by:
|
||||
# Modules from group: Shield Extender (37 of 37)
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
fit.ship.increaseItemAttr("signatureRadius", module.getModifiedItemAttr("signatureRadiusAdd"))
|
||||
6
eos/effects/advanceddroneinterfacingmaxgroupdcuskilllevel.py
Executable file
6
eos/effects/advanceddroneinterfacingmaxgroupdcuskilllevel.py
Executable file
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Skill: Advanced Drone Interfacing
|
||||
type = "passive"
|
||||
def handler(fit, skill, context):
|
||||
fit.modules.filteredItemIncrease(lambda mod: mod.item.group.name == "Drone Control Unit",
|
||||
"maxGroupActive", skill.level)
|
||||
@@ -0,0 +1,9 @@
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Rogue' Afterburner AB (6 of 6)
|
||||
# Implant: Zor's Custom Navigation Link
|
||||
# Skill: Afterburner
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Afterburner"),
|
||||
"duration", container.getModifiedItemAttr("durationBonus") * level)
|
||||
9
eos/effects/agilitymultipliereffect.py
Executable file
9
eos/effects/agilitymultipliereffect.py
Executable file
@@ -0,0 +1,9 @@
|
||||
# Used by:
|
||||
# Modules from group: Inertia Stabilizer (12 of 12)
|
||||
# Modules from group: Nanofiber Internal Structure (14 of 14)
|
||||
# Modules from group: Reinforced Bulkhead (12 of 12)
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
fit.ship.boostItemAttr("agility",
|
||||
module.getModifiedItemAttr("agilityMultiplier"),
|
||||
stackingPenalties = True)
|
||||
5
eos/effects/agilitymultipliereffectpassive.py
Executable file
5
eos/effects/agilitymultipliereffectpassive.py
Executable file
@@ -0,0 +1,5 @@
|
||||
# Used by:
|
||||
# Modules named like: Polycarbon Engine Housing (8 of 8)
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
fit.ship.boostItemAttr("agility", module.getModifiedItemAttr("agilityMultiplier"), stackingPenalties = True)
|
||||
10
eos/effects/ammofallofmultiplier.py
Executable file
10
eos/effects/ammofallofmultiplier.py
Executable file
@@ -0,0 +1,10 @@
|
||||
# Used by:
|
||||
# Charges from group: Advanced Artillery Ammo (6 of 6)
|
||||
# Charges from group: Advanced Autocannon Ammo (6 of 6)
|
||||
# Charges from group: Advanced Beam Laser Crystal (6 of 6)
|
||||
# Charges from group: Advanced Blaster Charge (6 of 6)
|
||||
# Charges from group: Advanced Pulse Laser Crystal (6 of 6)
|
||||
# Charges from group: Advanced Railgun Charge (6 of 6)
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
module.multiplyItemAttr("falloff", module.getModifiedChargeAttr("fallofMultiplier") or 1)
|
||||
9
eos/effects/ammoinfluencecapneed.py
Executable file
9
eos/effects/ammoinfluencecapneed.py
Executable file
@@ -0,0 +1,9 @@
|
||||
# Used by:
|
||||
# Items from category: Charge (458 of 824)
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
# Dirty hack to work around cap charges setting cap booster
|
||||
# injection amount to zero
|
||||
rawAttr = module.item.getAttribute("capacitorNeed")
|
||||
if rawAttr is not None and rawAttr >= 0:
|
||||
module.boostItemAttr("capacitorNeed", module.getModifiedChargeAttr("capNeedBonus") or 0)
|
||||
5
eos/effects/ammoinfluencerange.py
Executable file
5
eos/effects/ammoinfluencerange.py
Executable file
@@ -0,0 +1,5 @@
|
||||
# Used by:
|
||||
# Items from category: Charge (559 of 824)
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
module.multiplyItemAttr("maxRange", module.getModifiedChargeAttr("weaponRangeMultiplier"))
|
||||
7
eos/effects/ammospeedmultiplier.py
Executable file
7
eos/effects/ammospeedmultiplier.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# Used by:
|
||||
# Charges from group: Festival Charges (4 of 4)
|
||||
# Charges from group: Survey Probe (3 of 3)
|
||||
# Charge: Warp Disrupt Probe
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
module.multiplyItemAttr("speed", module.getModifiedChargeAttr("speedMultiplier") or 1)
|
||||
11
eos/effects/ammotrackingmultiplier.py
Executable file
11
eos/effects/ammotrackingmultiplier.py
Executable file
@@ -0,0 +1,11 @@
|
||||
# Used by:
|
||||
# Charges from group: Advanced Artillery Ammo (6 of 6)
|
||||
# Charges from group: Advanced Autocannon Ammo (6 of 6)
|
||||
# Charges from group: Advanced Beam Laser Crystal (6 of 6)
|
||||
# Charges from group: Advanced Blaster Charge (6 of 6)
|
||||
# Charges from group: Advanced Pulse Laser Crystal (6 of 6)
|
||||
# Charges from group: Advanced Railgun Charge (6 of 6)
|
||||
# Charges from group: Projectile Ammo (129 of 129)
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
module.multiplyItemAttr("trackingSpeed", module.getModifiedChargeAttr("trackingSpeedMultiplier"))
|
||||
9
eos/effects/angelsetbonus.py
Executable file
9
eos/effects/angelsetbonus.py
Executable file
@@ -0,0 +1,9 @@
|
||||
# Used by:
|
||||
# Implants named like: Halo (12 of 12)
|
||||
runTime = "early"
|
||||
type = "passive"
|
||||
def handler(fit, implant, context):
|
||||
fit.implants.filteredItemMultiply(
|
||||
lambda implant: "signatureRadiusBonus" in implant.itemModifiedAttributes and "implantSetAngel" in implant.itemModifiedAttributes,
|
||||
"signatureRadiusBonus",
|
||||
implant.getModifiedItemAttr("implantSetAngel"))
|
||||
5
eos/effects/antiwarpscramblingpassive.py
Executable file
5
eos/effects/antiwarpscramblingpassive.py
Executable file
@@ -0,0 +1,5 @@
|
||||
# Used by:
|
||||
# Modules from group: Warp Core Stabilizer (8 of 8)
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
fit.ship.increaseItemAttr("warmScrambleStatus", module.getModifiedItemAttr("warpScrambleStrength"))
|
||||
9
eos/effects/archaeologyskillvirusbonus.py
Normal file
9
eos/effects/archaeologyskillvirusbonus.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# Used by:
|
||||
# Modules named like: Emission Scope Sharpener (8 of 8)
|
||||
# Implant: Poteque 'Prospector' Archaeology AC-905
|
||||
# Skill: Archaeology
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill("Archaeology"),
|
||||
"virusCoherence", container.getModifiedItemAttr("virusCoherenceBonus") * level)
|
||||
6
eos/effects/armorallrepairsystemsamountbonuspassive.py
Executable file
6
eos/effects/armorallrepairsystemsamountbonuspassive.py
Executable file
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Implants named like: Exile Booster (4 of 4)
|
||||
type = "passive"
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Systems"),
|
||||
"armorDamageAmount", booster.getModifiedItemAttr("armorDamageAmountBonus"))
|
||||
@@ -0,0 +1,7 @@
|
||||
# Used by:
|
||||
# Modules named like: Auxiliary Nano Pump (8 of 8)
|
||||
type = "passive"
|
||||
def handler(fit, implant, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Repair Systems"),
|
||||
"armorDamageAmount", implant.getModifiedItemAttr("repairBonus"),
|
||||
stackingPenalties = True)
|
||||
6
eos/effects/armoredwarfaremindlink.py
Executable file
6
eos/effects/armoredwarfaremindlink.py
Executable file
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Implant: Armored Warfare Mindlink
|
||||
type = "passive"
|
||||
def handler(fit, implant, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Warfare Specialist"),
|
||||
"commandBonus", implant.getModifiedItemAttr("mindlinkBonus"))
|
||||
5
eos/effects/armorhpbonusadd.py
Executable file
5
eos/effects/armorhpbonusadd.py
Executable file
@@ -0,0 +1,5 @@
|
||||
# Used by:
|
||||
# Modules from group: Armor Reinforcer (57 of 57)
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
fit.ship.increaseItemAttr("armorHP", module.getModifiedItemAttr("armorHPBonusAdd"))
|
||||
5
eos/effects/armorhpbonusaddpassive.py
Executable file
5
eos/effects/armorhpbonusaddpassive.py
Executable file
@@ -0,0 +1,5 @@
|
||||
# Used by:
|
||||
# Subsystems from group: Defensive Systems (16 of 16)
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
fit.ship.increaseItemAttr("armorHP", module.getModifiedItemAttr("armorHPBonusAdd"))
|
||||
7
eos/effects/armorhpmultiply.py
Executable file
7
eos/effects/armorhpmultiply.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# Used by:
|
||||
# Modules from group: Armor Coating (202 of 202)
|
||||
# Modules from group: Armor Plating Energized (187 of 187)
|
||||
# Modules named like: QA Multiship Module Players (4 of 4)
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
fit.ship.multiplyItemAttr("armorHP", module.getModifiedItemAttr("armorHPMultiplier"))
|
||||
5
eos/effects/armorreinforcermassadd.py
Executable file
5
eos/effects/armorreinforcermassadd.py
Executable file
@@ -0,0 +1,5 @@
|
||||
# Used by:
|
||||
# Modules from group: Armor Reinforcer (57 of 57)
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
fit.ship.increaseItemAttr("mass", module.getModifiedItemAttr("massAddition"))
|
||||
8
eos/effects/armorrepair.py
Executable file
8
eos/effects/armorrepair.py
Executable file
@@ -0,0 +1,8 @@
|
||||
# Used by:
|
||||
# Modules from group: Armor Repair Unit (100 of 100)
|
||||
runTime = "late"
|
||||
type = "active"
|
||||
def handler(fit, module, context):
|
||||
amount = module.getModifiedItemAttr("armorDamageAmount")
|
||||
speed = module.getModifiedItemAttr("duration") / 1000.0
|
||||
fit.extraAttributes.increase("armorRepair", amount / speed)
|
||||
9
eos/effects/armorrepairprojectormaxrangebonus.py
Executable file
9
eos/effects/armorrepairprojectormaxrangebonus.py
Executable file
@@ -0,0 +1,9 @@
|
||||
# Used by:
|
||||
# Ship: Augoror
|
||||
# Ship: Exequror
|
||||
# Ship: Inquisitor
|
||||
# Ship: Navitas
|
||||
type = "passive"
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Armor Repair Projector",
|
||||
"maxRange", ship.getModifiedItemAttr("maxRangeBonus"))
|
||||
7
eos/effects/armortankinggang.py
Executable file
7
eos/effects/armortankinggang.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# Used by:
|
||||
# Skill: Armored Warfare
|
||||
type = "gang"
|
||||
gangBoost = "armorHP"
|
||||
gangBonus = "armorHpBonus"
|
||||
def handler(fit, skill, context):
|
||||
fit.ship.boostItemAttr(gangBoost, skill.getModifiedItemAttr(gangBonus) * skill.level)
|
||||
8
eos/effects/armortankinggang2.py
Executable file
8
eos/effects/armortankinggang2.py
Executable file
@@ -0,0 +1,8 @@
|
||||
# Used by:
|
||||
# Implant: Armored Warfare Mindlink
|
||||
type = "gang", "active"
|
||||
gangBonus = "armorHpBonus2"
|
||||
gangBoost = "armorHP"
|
||||
def handler(fit, module, context):
|
||||
if "gang" not in context: return
|
||||
fit.ship.boostItemAttr("armorHP", module.getModifiedItemAttr("armorHpBonus2"))
|
||||
7
eos/effects/armorupgradesmasspenaltyreductionbonus.py
Executable file
7
eos/effects/armorupgradesmasspenaltyreductionbonus.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# Used by:
|
||||
# Skill: Armor Honeycombing
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
level = container.level
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Armor Reinforcer",
|
||||
"massAddition", container.getModifiedItemAttr("massPenaltyReduction") * level)
|
||||
@@ -0,0 +1,10 @@
|
||||
# Used by:
|
||||
# Implants named like: Inherent Implants 'Highwall' Mining MX (3 of 3)
|
||||
# Implant: Michi's Excavation Augmentor
|
||||
# Skill: Astrogeology
|
||||
# Skill: Mining
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining"),
|
||||
"miningAmount", container.getModifiedItemAttr("miningAmountBonus") * level)
|
||||
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Variations of module: Scan Pinpointing Array I (2 of 2)
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Astrometrics"),
|
||||
"baseMaxScanDeviation", module.getModifiedItemAttr("maxScanDeviationModifierModule"))
|
||||
9
eos/effects/basemaxscandeviationmodifierrequiringastrometrics.py
Executable file
9
eos/effects/basemaxscandeviationmodifierrequiringastrometrics.py
Executable file
@@ -0,0 +1,9 @@
|
||||
# Used by:
|
||||
# Implants named like: Poteque 'Prospector' Astrometric Pinpointing AP (3 of 3)
|
||||
# Skill: Astrometric Pinpointing
|
||||
# Skill: Astrometrics
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Astrometrics"),
|
||||
"baseMaxScanDeviation", container.getModifiedItemAttr("maxScanDeviationModifier") * level)
|
||||
6
eos/effects/basesensorstrengthmodifiermodule.py
Normal file
6
eos/effects/basesensorstrengthmodifiermodule.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Variations of module: Scan Rangefinding Array I (2 of 2)
|
||||
type = "passive"
|
||||
def handler(fit, module, context):
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Astrometrics"),
|
||||
"baseSensorStrength", module.getModifiedItemAttr("scanStrengthBonusModule"))
|
||||
12
eos/effects/basesensorstrengthmodifierrequiringastrometrics.py
Executable file
12
eos/effects/basesensorstrengthmodifierrequiringastrometrics.py
Executable file
@@ -0,0 +1,12 @@
|
||||
# Used by:
|
||||
# Modules from group: Scan Probe Launcher (4 of 7)
|
||||
# Implants named like: Low grade Virtue (5 of 6)
|
||||
# Implants named like: Poteque 'Prospector' Astrometric Rangefinding AR (3 of 3)
|
||||
# Modules named like: Gravity Capacitor Upgrade (8 of 8)
|
||||
# Skill: Astrometric Rangefinding
|
||||
# Skill: Astrometrics
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Astrometrics"),
|
||||
"baseSensorStrength", container.getModifiedItemAttr("scanStrengthBonus") * level)
|
||||
6
eos/effects/bclargeenergyturretcapacitorneedbonus.py
Executable file
6
eos/effects/bclargeenergyturretcapacitorneedbonus.py
Executable file
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Ship: Oracle
|
||||
type = "passive"
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Energy Turret"),
|
||||
"capacitorNeed", ship.getModifiedItemAttr("bcLargeTurretCap"))
|
||||
6
eos/effects/bclargeenergyturretcpuneedbonus.py
Executable file
6
eos/effects/bclargeenergyturretcpuneedbonus.py
Executable file
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Ship: Oracle
|
||||
type = "passive"
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Energy Turret"),
|
||||
"cpu", ship.getModifiedItemAttr("bcLargeTurretCPU"))
|
||||
6
eos/effects/bclargeenergyturretpowerneedbonus.py
Executable file
6
eos/effects/bclargeenergyturretpowerneedbonus.py
Executable file
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Ship: Oracle
|
||||
type = "passive"
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Energy Turret"),
|
||||
"power", ship.getModifiedItemAttr("bcLargeTurretPower"))
|
||||
7
eos/effects/bclargehybridturretcapacitorneedbonus.py
Executable file
7
eos/effects/bclargehybridturretcapacitorneedbonus.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# Used by:
|
||||
# Ship: Naga
|
||||
# Ship: Talos
|
||||
type = "passive"
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Hybrid Turret"),
|
||||
"capacitorNeed", ship.getModifiedItemAttr("bcLargeTurretCap"))
|
||||
7
eos/effects/bclargehybridturretcpuneedbonus.py
Executable file
7
eos/effects/bclargehybridturretcpuneedbonus.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# Used by:
|
||||
# Ship: Naga
|
||||
# Ship: Talos
|
||||
type = "passive"
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Hybrid Turret"),
|
||||
"cpu", ship.getModifiedItemAttr("bcLargeTurretCPU"))
|
||||
7
eos/effects/bclargehybridturretpowerneedbonus.py
Executable file
7
eos/effects/bclargehybridturretpowerneedbonus.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# Used by:
|
||||
# Ship: Naga
|
||||
# Ship: Talos
|
||||
type = "passive"
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Hybrid Turret"),
|
||||
"power", ship.getModifiedItemAttr("bcLargeTurretPower"))
|
||||
6
eos/effects/bclargeprojectileturretcpuneedbonus.py
Executable file
6
eos/effects/bclargeprojectileturretcpuneedbonus.py
Executable file
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Ship: Tornado
|
||||
type = "passive"
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Projectile Turret"),
|
||||
"cpu", ship.getModifiedItemAttr("bcLargeTurretCPU"))
|
||||
6
eos/effects/bclargeprojectileturretpowerneedbonus.py
Executable file
6
eos/effects/bclargeprojectileturretpowerneedbonus.py
Executable file
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Ship: Tornado
|
||||
type = "passive"
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Projectile Turret"),
|
||||
"power", ship.getModifiedItemAttr("bcLargeTurretPower"))
|
||||
7
eos/effects/biologytimebonusfixed.py
Executable file
7
eos/effects/biologytimebonusfixed.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Alchemist' Biology BY (2 of 2)
|
||||
# Skill: Biology
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.boosters.filteredItemBoost(lambda bst: True, "boosterDuration", container.getModifiedItemAttr("durationBonus") * level)
|
||||
8
eos/effects/blockaderunnercloakcpupercentbonus.py
Executable file
8
eos/effects/blockaderunnercloakcpupercentbonus.py
Executable file
@@ -0,0 +1,8 @@
|
||||
# Used by:
|
||||
# Ships from group: Blockade Runner (4 of 4)
|
||||
type = "passive"
|
||||
runTime = "early"
|
||||
def handler(fit, ship, context):
|
||||
level = fit.character.getSkill("Transport Ships").level
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Cloaking Device",
|
||||
"cpu", ship.getModifiedItemAttr("eliteIndustrialCovertCloakBonus") * level)
|
||||
5
eos/effects/boosterarmorhppenalty.py
Executable file
5
eos/effects/boosterarmorhppenalty.py
Executable file
@@ -0,0 +1,5 @@
|
||||
# Used by:
|
||||
# Implants from group: Booster (12 of 37)
|
||||
type = "boosterSideEffect"
|
||||
def handler(fit, booster, context):
|
||||
fit.ship.boostItemAttr("armorHP", booster.getModifiedItemAttr("boosterArmorHPPenalty"))
|
||||
6
eos/effects/boosterarmorrepairamountpenalty.py
Executable file
6
eos/effects/boosterarmorrepairamountpenalty.py
Executable file
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Implants from group: Booster (9 of 37)
|
||||
type = "boosterSideEffect"
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Armor Repair Unit",
|
||||
"armorDamageAmount", booster.getModifiedItemAttr("boosterArmorRepairAmountPenalty"))
|
||||
6
eos/effects/boostercapacitorcapacitypenalty.py
Executable file
6
eos/effects/boostercapacitorcapacitypenalty.py
Executable file
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Implants named like: Blue Pill Booster (3 of 5)
|
||||
# Implants named like: Exile Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
def handler(fit, booster, context):
|
||||
fit.ship.boostItemAttr("capacitorCapacity", booster.getModifiedItemAttr("boosterCapacitorCapacityPenalty"))
|
||||
5
eos/effects/boostermaxvelocitypenalty.py
Executable file
5
eos/effects/boostermaxvelocitypenalty.py
Executable file
@@ -0,0 +1,5 @@
|
||||
# Used by:
|
||||
# Implants from group: Booster (12 of 37)
|
||||
type = "boosterSideEffect"
|
||||
def handler(fit, booster, context):
|
||||
fit.ship.boostItemAttr("maxVelocity", booster.getModifiedItemAttr("boosterMaxVelocityPenalty"))
|
||||
7
eos/effects/boostermissileexplosioncloudpenaltyfixed.py
Executable file
7
eos/effects/boostermissileexplosioncloudpenaltyfixed.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# Used by:
|
||||
# Implants named like: Exile Booster (3 of 4)
|
||||
# Implants named like: Mindflood Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
|
||||
"aoeCloudSize", booster.getModifiedItemAttr("boosterMissileAOECloudPenalty"))
|
||||
6
eos/effects/boostermissileexplosionvelocitypenalty.py
Executable file
6
eos/effects/boostermissileexplosionvelocitypenalty.py
Executable file
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Implants named like: Blue Pill Booster (3 of 5)
|
||||
type = "boosterSideEffect"
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
|
||||
"aoeVelocity", booster.getModifiedItemAttr("boosterAOEVelocityPenalty"))
|
||||
7
eos/effects/boostermissilevelocitypenalty.py
Executable file
7
eos/effects/boostermissilevelocitypenalty.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# Used by:
|
||||
# Implants named like: Crash Booster (3 of 4)
|
||||
# Implants named like: X Instinct Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
|
||||
"maxVelocity", "boosterMissileVelocityPenalty")
|
||||
11
eos/effects/boostermodifyboosterarmorpenalties.py
Executable file
11
eos/effects/boostermodifyboosterarmorpenalties.py
Executable file
@@ -0,0 +1,11 @@
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Alchemist' Nanite Control NC (2 of 2)
|
||||
# Implants named like: Low grade Edge (5 of 6)
|
||||
# Skill: Nanite Control
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
attrs = ("boosterArmorHPPenalty", "boosterArmorRepairAmountPenalty")
|
||||
for attr in attrs:
|
||||
fit.boosters.filteredItemBoost(lambda booster: True, attr,
|
||||
container.getModifiedItemAttr("boosterAttributeModifier") * level)
|
||||
11
eos/effects/boostermodifyboostermaxvelocityandcapacitorpenalty.py
Executable file
11
eos/effects/boostermodifyboostermaxvelocityandcapacitorpenalty.py
Executable file
@@ -0,0 +1,11 @@
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Alchemist' Nanite Control NC (2 of 2)
|
||||
# Implants named like: Low grade Edge (5 of 6)
|
||||
# Skill: Nanite Control
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
attrs = ("boosterCapacitorCapacityPenalty", "boosterMaxVelocityPenalty")
|
||||
for attr in attrs:
|
||||
fit.boosters.filteredItemBoost(lambda booster: True, attr,
|
||||
container.getModifiedItemAttr("boosterAttributeModifier") * level)
|
||||
11
eos/effects/boostermodifyboostermissilepenalty.py
Executable file
11
eos/effects/boostermodifyboostermissilepenalty.py
Executable file
@@ -0,0 +1,11 @@
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Alchemist' Nanite Control NC (2 of 2)
|
||||
# Implants named like: Low grade Edge (5 of 6)
|
||||
# Skill: Nanite Control
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
attrs = ("boosterAOEVelocityPenalty", "boosterMissileAOECloudPenalty", "boosterMissileVelocityPenalty")
|
||||
for attr in attrs:
|
||||
fit.boosters.filteredItemBoost(lambda booster: True, attr,
|
||||
container.getModifiedItemAttr("boosterAttributeModifier") * level)
|
||||
13
eos/effects/boostermodifyboostershieldpenalty.py
Executable file
13
eos/effects/boostermodifyboostershieldpenalty.py
Executable file
@@ -0,0 +1,13 @@
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Alchemist' Nanite Control NC (2 of 2)
|
||||
# Implants named like: Low grade Edge (5 of 6)
|
||||
# Skill: Nanite Control
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
attrs = ("boosterShieldBoostAmountPenalty", "boosterShieldCapacityPenalty", "shieldBoostMultiplier")
|
||||
for attr in attrs:
|
||||
# shieldBoostMultiplier can be positive (Blue Pill) and negative value (other boosters)
|
||||
# We're interested in decreasing only side-effects
|
||||
fit.boosters.filteredItemBoost(lambda booster: booster.getModifiedItemAttr(attr) < 0,
|
||||
attr, container.getModifiedItemAttr("boosterAttributeModifier") * level)
|
||||
11
eos/effects/boostermodifyboosterturretpenalty.py
Executable file
11
eos/effects/boostermodifyboosterturretpenalty.py
Executable file
@@ -0,0 +1,11 @@
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Alchemist' Nanite Control NC (2 of 2)
|
||||
# Implants named like: Low grade Edge (5 of 6)
|
||||
# Skill: Nanite Control
|
||||
type = "passive"
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
attrs = ("boosterTurretFalloffPenalty", "boosterTurretOptimalRange", "boosterTurretTrackingPenalty")
|
||||
for attr in attrs:
|
||||
fit.boosters.filteredItemBoost(lambda booster: True, attr,
|
||||
container.getModifiedItemAttr("boosterAttributeModifier") * level)
|
||||
5
eos/effects/boostershieldcapacitypenalty.py
Executable file
5
eos/effects/boostershieldcapacitypenalty.py
Executable file
@@ -0,0 +1,5 @@
|
||||
# Used by:
|
||||
# Implants from group: Booster (12 of 37)
|
||||
type = "boosterSideEffect"
|
||||
def handler(fit, booster, context):
|
||||
fit.ship.boostItemAttr("shieldCapacity", booster.getModifiedItemAttr("boosterShieldCapacityPenalty"))
|
||||
7
eos/effects/boosterturretfalloffpenalty.py
Executable file
7
eos/effects/boosterturretfalloffpenalty.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# Used by:
|
||||
# Implants named like: Drop Booster (3 of 4)
|
||||
# Implants named like: X Instinct Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Gunnery"),
|
||||
"falloff", booster.getModifiedItemAttr("boosterTurretFalloffPenalty"))
|
||||
6
eos/effects/boosterturretoptimalrangepenalty.py
Executable file
6
eos/effects/boosterturretoptimalrangepenalty.py
Executable file
@@ -0,0 +1,6 @@
|
||||
# Used by:
|
||||
# Implants from group: Booster (9 of 37)
|
||||
type = "boosterSideEffect"
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Gunnery"),
|
||||
"maxRange", booster.getModifiedItemAttr("boosterTurretOptimalRange"))
|
||||
7
eos/effects/boosterturrettrackingpenalty.py
Executable file
7
eos/effects/boosterturrettrackingpenalty.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# Used by:
|
||||
# Implants named like: Exile Booster (3 of 4)
|
||||
# Implants named like: Frentix Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Gunnery"),
|
||||
"trackingSpeed", booster.getModifiedItemAttr("boosterTurretTrackingPenalty"))
|
||||
8
eos/effects/caldarisetbonus3.py
Executable file
8
eos/effects/caldarisetbonus3.py
Executable file
@@ -0,0 +1,8 @@
|
||||
# Used by:
|
||||
# Implants named like: Talon (6 of 12)
|
||||
runTime = "early"
|
||||
type = "passive"
|
||||
def handler(fit, implant, context):
|
||||
fit.implants.filteredItemMultiply(lambda implant: "implantSetCaldariNavy" in implant.itemModifiedAttributes and\
|
||||
"scanGravimetricStrengthPercent" in implant.itemModifiedAttributes,
|
||||
"scanGravimetricStrengthPercent", implant.getModifiedItemAttr("implantSetCaldariNavy"))
|
||||
7
eos/effects/caldarisetlgbonus.py
Executable file
7
eos/effects/caldarisetlgbonus.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# Used by:
|
||||
# Implants named like: Low grade Talon (6 of 6)
|
||||
runTime = "early"
|
||||
type = "passive"
|
||||
def handler(fit, item, context):
|
||||
fit.implants.filteredItemMultiply(lambda implant: "scanGravimetricStrengthModifier" in implant.itemModifiedAttributes,
|
||||
"scanGravimetricStrengthModifier", item.getModifiedItemAttr("implantSetLGCaldariNavy"))
|
||||
8
eos/effects/caldarishipecmburstoptimalrangecb3.py
Executable file
8
eos/effects/caldarishipecmburstoptimalrangecb3.py
Executable file
@@ -0,0 +1,8 @@
|
||||
# Used by:
|
||||
# Ship: Scorpion
|
||||
# Ship: Scorpion Ishukone Watch
|
||||
type = "passive"
|
||||
def handler(fit, ship, context):
|
||||
level = fit.character.getSkill("Caldari Battleship").level
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "ECM Burst",
|
||||
"ecmBurstRange", ship.getModifiedItemAttr("shipBonusCB3") * level)
|
||||
8
eos/effects/caldarishipewcapacitorneedcc.py
Executable file
8
eos/effects/caldarishipewcapacitorneedcc.py
Executable file
@@ -0,0 +1,8 @@
|
||||
# Used by:
|
||||
# Ship: Falcon
|
||||
# Ship: Rook
|
||||
type = "passive"
|
||||
def handler(fit, ship, context):
|
||||
level = fit.character.getSkill("Caldari Cruiser").level
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "ECM",
|
||||
"capacitorNeed", ship.getModifiedItemAttr("shipBonusCC") * level)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user