A corporation manager and dashboard for EVE Online
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

122 lines
4.7 KiB

  1. # -*- coding: utf-8 -*-
  2. import sys
  3. import textwrap
  4. from flask import g
  5. from .._provided import config, logger
  6. __all__ = ["update_operation"]
  7. def _save_operation(cname, opname, primary, secondary, key=None):
  8. """Save the given campaign/operation overview info in the database."""
  9. secstr = "" if secondary is None else (" secondary=%d" % secondary)
  10. logger.debug("Setting overview primary=%d%s campaign=%s operation=%s",
  11. primary, secstr, cname, opname)
  12. g.campaign_db.set_overview(cname, opname, primary, secondary)
  13. g.campaign_db.touch_operation(cname, opname, key=key)
  14. def _build_filter(qualifiers):
  15. """Given a qualifiers string from the config, return a filter function.
  16. This function is extremely sensitive since it executes arbitrary Python
  17. code. It should never be run with a user-provided argument! We trust the
  18. contents of a config file because it originates from a known place on the
  19. filesystem.
  20. """
  21. namespace = {"g": g}
  22. body = "def _func(kill):\n" + textwrap.indent(qualifiers, " " * 4)
  23. exec(body, namespace)
  24. return namespace["_func"]
  25. def _store_kill(cname, opnames, kill):
  26. """Store the given kill and its associations into the database."""
  27. kid = kill["killID"]
  28. if g.campaign_db.has_kill(kid):
  29. current = g.campaign_db.get_kill_associations(cname, kid)
  30. opnames -= set(current)
  31. if opnames:
  32. logger.debug("Adding operations=%s to kill id=%d campaign=%s",
  33. ",".join(opnames), kid, cname)
  34. else:
  35. logger.debug("Adding kill id=%d campaign=%s operations=%s", kid, cname,
  36. ",".join(opnames))
  37. g.campaign_db.add_kill(kill)
  38. g.campaign_db.associate_kill(cname, kid, opnames)
  39. def _update_killboard_operations(cname, opnames, min_kill_id):
  40. """Update all killboard-type operations in the given campaign subset."""
  41. operations = config["campaigns"][cname]["operations"]
  42. filters = []
  43. for opname in opnames:
  44. qualif = operations[opname]["qualifiers"]
  45. filters.append((_build_filter(qualif), opname))
  46. args = ["kills", "corporationID", g.config.get("corp.id"), "no-items",
  47. "no-attackers", "orderDirection", "asc"]
  48. if min_kill_id > 0:
  49. args += ["afterKillID", min_kill_id]
  50. max_kill_id = min_kill_id
  51. for kill in g.eve.zkill.iter_killmails(*args):
  52. kid = kill["killID"]
  53. ktime = kill["killTime"]
  54. logger.debug("Evaluating kill date=%s id=%d for campaign=%s "
  55. "operations=%s", ktime, kid, cname, ",".join(opnames))
  56. max_kill_id = max(max_kill_id, kid)
  57. ops = set()
  58. for filt, opname in filters:
  59. if filt(kill):
  60. ops.add(opname)
  61. if ops:
  62. _store_kill(cname, ops, kill)
  63. for opname in opnames:
  64. primary, secondary = g.campaign_db.count_kills(cname, opname)
  65. show_isk = operations[opname].get("isk", True)
  66. if not show_isk:
  67. secondary = None
  68. _save_operation(cname, opname, primary, secondary, key=max_kill_id)
  69. def _update_collection_operations(cname, opnames):
  70. """Update all collection-type operations in the given campaign subset."""
  71. campaign = config["campaigns"][cname]
  72. for opname in opnames:
  73. operation = campaign["operations"][opname]
  74. show_isk = operation.get("isk", True)
  75. # store per-user counts; update for all users in corp who have fresh
  76. # API keys and leave other data stale
  77. ...
  78. primary = __import__("random").randint(10, 99)
  79. secondary = __import__("random").randint(10000000, 5000000000) / 100 \
  80. if show_isk else None
  81. _save_operation(cname, opname, primary, secondary)
  82. def update_operation(cname, opname, new=False):
  83. """Update a campaign/operation. Assumes a thread-exclusive lock is held."""
  84. campaign = config["campaigns"][cname]
  85. operations = campaign["operations"]
  86. optype = operations[opname]["type"]
  87. opnames = [opn for opn in campaign["enabled"]
  88. if operations[opn]["type"] == optype]
  89. if optype == "killboard":
  90. opsubset = []
  91. min_key = 0 if new else sys.maxsize
  92. for opname in opnames:
  93. last_updated, key = g.campaign_db.check_operation(cname, opname)
  94. if new and last_updated is None:
  95. opsubset.append(opname)
  96. elif not new and last_updated is not None:
  97. min_key = min(min_key, key)
  98. opsubset.append(opname)
  99. _update_killboard_operations(cname, opsubset, min_key)
  100. elif optype == "collection":
  101. _update_collection_operations(cname, opnames)
  102. else:
  103. raise RuntimeError("Unknown operation type: %s" % optype)