queries.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. from collections import defaultdict
  2. import operator
  3. import db
  4. def search(q):
  5. like_str = '{}%'.format(q)
  6. with db.cursor() as c:
  7. alliances = db.query(c, '''
  8. SELECT DISTINCT alliance_id, alliance_name FROM characters
  9. WHERE alliance_name LIKE ? LIMIT 25
  10. ''', like_str)
  11. corps = db.query(c, '''
  12. SELECT DISTINCT corporation_id, corporation_name FROM characters
  13. WHERE corporation_name LIKE ? LIMIT 25
  14. ''', like_str)
  15. chars = db.query(c, '''
  16. SELECT DISTINCT character_id, character_name FROM characters
  17. WHERE character_name LIKE ? LIMIT 25
  18. ''', like_str)
  19. return {'alliances': alliances, 'corporations': corps, 'characters': chars}
  20. def kill_list(entity_type, entity_id):
  21. with db.cursor() as c:
  22. # the combination of DISTINCT and and ORDER BY means we can't join kills or we get filesort
  23. # get kill_ids from chars, then get kill data on those ids
  24. kills = db.query(c, '''
  25. SELECT DISTINCT kill_id FROM characters
  26. WHERE {}_id = ? ORDER BY kill_id DESC LIMIT 50
  27. '''.format(entity_type), entity_id)
  28. if len(kills) == 0:
  29. return None
  30. kill_ids = list(map(operator.itemgetter('kill_id'), kills))
  31. kills = db.query(c, '''
  32. SELECT kills.kill_id, kill_time, cost,
  33. solarSystemName AS system_name, security, regionName AS region
  34. FROM kills
  35. JOIN kill_costs ON kill_costs.kill_id = kills.kill_id
  36. JOIN eve.mapSolarSystems ON solar_system_id = solarSystemID
  37. JOIN eve.mapRegions ON mapSolarSystems.regionID = mapRegions.regionID
  38. WHERE kills.kill_id IN ({})
  39. '''.format(','.join(map(str, kill_ids))))
  40. char_rows = db.query(c, '''
  41. SELECT
  42. kill_id, victim, final_blow,
  43. character_id, character_name, corporation_id, corporation_name, alliance_id, alliance_name, faction_id, faction_name,
  44. ship_type_id, typeName AS ship_name
  45. FROM characters
  46. JOIN eve.invTypes ON ship_type_id = typeID
  47. WHERE kill_id IN ({})
  48. '''.format(','.join(map(str, kill_ids))))
  49. characters = defaultdict(dict)
  50. entity_name = None
  51. for kill_id in kill_ids:
  52. characters[kill_id]['attackers'] = 1 # count final_blow now
  53. for char in char_rows:
  54. kill_id = char['kill_id']
  55. if char['victim']:
  56. characters[kill_id]['victim'] = char
  57. elif char['final_blow']:
  58. characters[kill_id]['final_blow'] = char
  59. else:
  60. characters[kill_id]['attackers'] += 1
  61. if entity_name is None and char[entity_type + '_id'] == entity_id:
  62. entity_name = char[entity_type + '_name']
  63. kills.sort(key=operator.itemgetter('kill_id'), reverse=True)
  64. for kill in kills:
  65. kill['kill_time'] = _format_kill_time(kill['kill_time'])
  66. kill['security_status'] = _security_status(kill['system_name'], kill['security'])
  67. chars = characters[kill['kill_id']]
  68. kill['victim'] = chars['victim']
  69. kill['final_blow'] = chars['final_blow']
  70. kill['attackers'] = chars['attackers']
  71. return {'entity_name': entity_name, 'kills': kills}
  72. def kill(kill_id):
  73. with db.cursor() as c:
  74. try:
  75. kill = db.get(c, '''
  76. SELECT kill_time, cost, solarSystemName AS system_name, security FROM kills
  77. JOIN kill_costs ON kill_costs.kill_id = kills.kill_id
  78. JOIN eve.mapSolarSystems ON solar_system_id = solarSystemID
  79. WHERE kills.kill_id = ?
  80. ''', kill_id)
  81. except db.NoRowsException:
  82. return None
  83. kill['kill_time'] = _format_kill_time(kill['kill_time'])
  84. kill['security_status'] = _security_status(kill['system_name'], kill['security'])
  85. characters = db.query(c, '''
  86. SELECT character_id, character_name, damage, victim, final_blow,
  87. corporation_id, corporation_name, alliance_id, alliance_name, faction_id, faction_name,
  88. ship_type_id, weapon_type_id,
  89. ship.typeName AS ship_name, weapon.typeName AS weapon_name
  90. FROM characters
  91. JOIN eve.invTypes AS ship ON ship_type_id = ship.typeID
  92. LEFT JOIN eve.invTypes AS weapon ON weapon_type_id = weapon.typeID
  93. WHERE kill_id = ?
  94. ''', kill_id)
  95. attackers = []
  96. for char in characters:
  97. if char['victim']:
  98. victim = char
  99. elif char['final_blow']:
  100. final_blow = char
  101. else:
  102. attackers.append(char)
  103. try:
  104. ship_cost = db.get(c, 'SELECT cost FROM item_costs WHERE type_id = ?',
  105. victim['ship_type_id'])
  106. victim['ship_cost'] = ship_cost['cost']
  107. except db.NoRowsException:
  108. victim['ship_cost'] = 0
  109. # see update_costs for an explanation of the ORDER BY
  110. item_rows = db.query(c, '''
  111. SELECT items.type_id, flag, dropped, destroyed, singleton,
  112. cost, typeName AS item_name
  113. FROM items
  114. JOIN item_costs ON item_costs.type_id = items.type_id
  115. JOIN eve.invTypes ON items.type_id = typeID
  116. WHERE kill_id = ?
  117. ORDER BY (cost * (dropped + destroyed) / (singleton * 499.5 + 1)) DESC
  118. ''', kill_id)
  119. items = defaultdict(list)
  120. for item in item_rows:
  121. flag = item['flag']
  122. if 125 <= flag <= 132:
  123. slot = 'subsystem'
  124. elif 27 <= flag <= 34:
  125. slot = 'high'
  126. elif 19 <= flag <= 26:
  127. slot = 'medium'
  128. elif 11 <= flag <= 18:
  129. slot = 'low'
  130. elif 92 <= flag <= 99:
  131. slot = 'rig'
  132. elif flag == 87:
  133. slot = 'drone bay'
  134. elif flag == 5:
  135. slot = 'cargo'
  136. elif 133 <= flag <= 143:
  137. slot = 'special hold'
  138. elif flag == 90:
  139. slot = 'ship hangar'
  140. elif flag == 155:
  141. slot = 'fleet hangar'
  142. elif flag == 89:
  143. slot = 'implant'
  144. else:
  145. slot = '???'
  146. items[slot].append(item)
  147. module_slots = ['high', 'medium', 'low']
  148. fitting_items = set()
  149. for slot in module_slots:
  150. fitting_items.update(map(operator.itemgetter('type_id'), items[slot]))
  151. # 11: requires low, 12: requires high, 13: requires medium; :CCP:
  152. modules = db.query(c, '''
  153. SELECT DISTINCT typeID AS type_id FROM eve.dgmTypeEffects
  154. WHERE typeID IN ({}) and effectID IN (11, 12, 13)
  155. '''.format(','.join(map(str, fitting_items))))
  156. module_ids = set(map(operator.itemgetter('type_id'), modules))
  157. for slot in module_slots:
  158. for item in items[slot]:
  159. if item['type_id'] not in module_ids:
  160. item['charge'] = True
  161. slot_rows = db.query(c, '''
  162. SELECT attributeID, valueInt, valueFloat FROM eve.dgmTypeAttributes
  163. WHERE typeID = ? AND attributeID IN (12, 13, 14, 1137, 1367)
  164. AND (valueInt != 0 OR valueFloat != 0.0)
  165. ''', victim['ship_type_id'])
  166. slot_mapping = {12: 'low', 13: 'medium', 14: 'high', 1137: 'rig', 1367: 'subsystem'}
  167. slots = dict.fromkeys(slot_mapping.values(), 0)
  168. for attr in slot_rows:
  169. slot = slot_mapping[attr['attributeID']]
  170. slots[slot] = attr['valueInt'] or int(attr['valueFloat']) # wtf CCP
  171. if slots['subsystem']:
  172. sub_ids = map(lambda s: str(s['type_id']), items['subsystem'])
  173. modifier_rows = db.query(c, '''
  174. SELECT attributeID, valueFloat FROM eve.dgmTypeAttributes
  175. WHERE typeID IN ({}) AND attributeID in (1374, 1375, 1376) and valueFloat != 0.0
  176. '''.format(','.join(sub_ids)))
  177. slot_mapping = {1374: 'high', 1375: 'medium', 1376: 'low'} # that's right, it's backwards for subs!
  178. for modifier in modifier_rows:
  179. slot = slot_mapping[modifier['attributeID']]
  180. slots[slot] += int(modifier['valueFloat']) # strangely, an improvement
  181. return {
  182. 'kill': kill,
  183. 'victim': victim,
  184. 'final_blow': final_blow,
  185. 'attackers': attackers,
  186. 'items': items,
  187. 'slots': slots,
  188. }
  189. def top_cost():
  190. with db.cursor() as c:
  191. kills = db.query(c, '''
  192. SELECT kills.kill_id, cost,
  193. ship_type_id, typeName as ship_name,
  194. solarSystemName AS system_name, security
  195. FROM kills
  196. JOIN kill_costs ON kill_costs.kill_id = kills.kill_id
  197. JOIN characters ON characters.kill_id = kills.kill_id
  198. JOIN eve.invTypes ON typeID = ship_type_id
  199. JOIN eve.mapSolarSystems ON solar_system_id = solarSystemID
  200. WHERE victim = 1
  201. ORDER BY cost DESC
  202. LIMIT 25
  203. ''')
  204. for kill in kills:
  205. kill['security_status'] = _security_status(kill['system_name'], kill['security'])
  206. return kills
  207. def _format_kill_time(kill_time):
  208. return kill_time.strftime('%Y-%m-%d %H:%M')
  209. def _security_status(system_name, security):
  210. wspace = False
  211. if system_name[0] == 'J':
  212. try:
  213. int(system_name[1:])
  214. wspace = True
  215. except ValueError:
  216. pass
  217. if wspace:
  218. security_status = '?'
  219. elif security >= 0.5:
  220. security_status = 'high'
  221. elif security > 0.0:
  222. security_status = 'low'
  223. else:
  224. security_status = 'null'
  225. return security_status