Browse Source

Add individual values to campaign item board.

master
Ben Kurtovic 8 years ago
parent
commit
bb51e2ab1e
7 changed files with 57 additions and 33 deletions
  1. +10
    -2
      calefaction/format.py
  2. +12
    -10
      calefaction/modules/campaigns/database.py
  3. +15
    -13
      calefaction/modules/campaigns/update.py
  4. +1
    -0
      config/modules/campaigns.yml.sample
  5. +1
    -0
      data/schema_campaigns.sql
  6. +5
    -2
      static/main.css
  7. +13
    -6
      templates/campaigns/renderers.mako

+ 10
- 2
calefaction/format.py View File

@@ -2,8 +2,16 @@ from datetime import datetime, timedelta


import humanize import humanize


__all__ = ["format_isk", "format_isk_compact", "format_utctime",
"format_utctime_compact", "format_security", "get_security_class"]
__all__ = [
"format_quantity", "format_isk", "format_isk_compact", "format_utctime",
"format_utctime_compact", "format_security", "get_security_class"
]

def format_quantity(value):
"""Nicely format an integer quantity."""
if value < 10**6:
return "{:,}".format(value)
return humanize.intword(value, "%.2f")


def format_isk(value): def format_isk(value):
"""Nicely format an ISK value.""" """Nicely format an ISK value."""


+ 12
- 10
calefaction/modules/campaigns/database.py View File

@@ -187,7 +187,7 @@ class CampaignDB:


The data should be a multi-layered dictionary. It maps operation names The data should be a multi-layered dictionary. It maps operation names
to a dict that maps character IDs to a dict that maps type IDs to to a dict that maps character IDs to a dict that maps type IDs to
integer counts.
tuples of integer counts and float values.
""" """
with self._conn as conn: with self._conn as conn:
cur = conn.execute("BEGIN TRANSACTION") cur = conn.execute("BEGIN TRANSACTION")
@@ -195,29 +195,31 @@ class CampaignDB:
cur.execute(query, (campaign,)) cur.execute(query, (campaign,))


query = """INSERT INTO oper_item ( query = """INSERT INTO oper_item (
oi_campaign, oi_operation, oi_character, oi_type, oi_count)
VALUES (?, ?, ?, ?, ?)"""
oi_campaign, oi_operation, oi_character, oi_type, oi_count,
oi_value)
VALUES (?, ?, ?, ?, ?, ?)"""
cur.executemany(query, [ cur.executemany(query, [
(campaign, operation, int(char_id), int(type_id), int(count))
(campaign, operation, int(char_id), int(type_id), int(count),
float(value))
for operation, chars in data.items() for operation, chars in data.items()
for char_id, types in chars.items() for char_id, types in chars.items()
for type_id, count in types.items()])
for type_id, (count, value) in types.items()])


def get_associated_items(self, campaign, operation, limit=5, offset=0): def get_associated_items(self, campaign, operation, limit=5, offset=0):
"""Return a list of items associated with a campaign/operation. """Return a list of items associated with a campaign/operation.


Items are returned as 2-tuples of (item_type, item_count), most recent
first, up to a limit. Use -1 for no limit.
Items are returned as 2-tuples of (item_type, item_count), most
valuable first, up to a limit. Use -1 for no limit.
""" """
if not isinstance(limit, int): if not isinstance(limit, int):
raise ValueError(limit) raise ValueError(limit)
if not isinstance(offset, int): if not isinstance(offset, int):
raise ValueError(offset) raise ValueError(offset)


query = """SELECT oi_type, SUM(oi_count) as total_count
query = """SELECT oi_type, SUM(oi_count), TOTAL(oi_value) as total_val
FROM oper_item FROM oper_item
WHERE oi_campaign = ? AND oi_operation = ? WHERE oi_campaign = ? AND oi_operation = ?
GROUP BY oi_type ORDER BY total_count DESC LIMIT {} OFFSET {}"""
GROUP BY oi_type ORDER BY total_val DESC LIMIT {} OFFSET {}"""
qform = query.format(limit, offset) qform = query.format(limit, offset)
res = self._conn.execute(qform, (campaign, operation)).fetchall() res = self._conn.execute(qform, (campaign, operation)).fetchall()
return [(type_id, count or 0) for type_id, count in res]
return [(type_id, count or 0, value) for type_id, count, value in res]

+ 15
- 13
calefaction/modules/campaigns/update.py View File

@@ -81,23 +81,22 @@ def _update_killboard_operations(cname, opnames, min_kill_id):
secondary = None secondary = None
_save_operation(cname, opname, primary, secondary, key=max_kill_id) _save_operation(cname, opname, primary, secondary, key=max_kill_id)


def _get_prices():
"""Return a dict mapping type IDs to ISK prices."""
pricelist = g.eve.esi().v1.markets.prices.get()
return {entry["type_id"]: entry["average_price"]
for entry in pricelist if "average_price" in entry}

def _save_collection_overview(cname, opnames, data): def _save_collection_overview(cname, opnames, data):
"""Save collection overview data to the database.""" """Save collection overview data to the database."""
operations = config["campaigns"][cname]["operations"] operations = config["campaigns"][cname]["operations"]
if any(operations[opname].get("isk", True) for opname in opnames):
pricelist = g.eve.esi().v1.markets.prices.get()
prices = {entry["type_id"]: entry["average_price"]
for entry in pricelist if "average_price" in entry}
else:
prices = {}

for opname in opnames: for opname in opnames:
primary = sum(sum(d.values()) for d in data[opname].values())
primary = sum(count for d in data[opname].values()
for (count, _) in d.values())
show_isk = operations[opname].get("isk", True) show_isk = operations[opname].get("isk", True)
if show_isk: if show_isk:
secondary = sum(prices.get(typeid, 0.0) * count
for d in data[opname].values()
for typeid, count in d.items())
secondary = sum(value for d in data[opname].values()
for (_, value) in d.values())
else: else:
secondary = None secondary = None
_save_operation(cname, opname, primary, secondary) _save_operation(cname, opname, primary, secondary)
@@ -110,6 +109,7 @@ def _update_collection_operations(cname, opnames):
qualif = operations[opname]["qualifiers"] qualif = operations[opname]["qualifiers"]
filters.append((_build_filter(qualif, "asset"), opname)) filters.append((_build_filter(qualif, "asset"), opname))


prices = _get_prices()
data = {opname: {} for opname in opnames} data = {opname: {} for opname in opnames}


for char_id, token in g.auth.get_valid_characters(): for char_id, token in g.auth.get_valid_characters():
@@ -131,11 +131,13 @@ def _update_collection_operations(cname, opnames):
if filt(asset): if filt(asset):
typeid = asset["type_id"] typeid = asset["type_id"]
count = 1 if asset["is_singleton"] else asset["quantity"] count = 1 if asset["is_singleton"] else asset["quantity"]
value = prices.get(typeid, 0.0)
char = data[opname][char_id] char = data[opname][char_id]
if typeid in char: if typeid in char:
char[typeid] += count
char[typeid][0] += count
char[typeid][1] += count * value
else: else:
char[typeid] = count
char[typeid] = [count, count * value]


g.campaign_db.update_items(cname, data) g.campaign_db.update_items(cname, data)
_save_collection_overview(cname, opnames, data) _save_collection_overview(cname, opnames, data)


+ 1
- 0
config/modules/campaigns.yml.sample View File

@@ -47,6 +47,7 @@ campaigns:
isk: false isk: false
# Report as "10 units" / "1 unit" of Tritanium # Report as "10 units" / "1 unit" of Tritanium
unit: unit|units unit: unit|units
# Python function to filter items:
qualifiers: |- qualifiers: |-
type = g.eve.universe.type(asset["type_id"]) type = g.eve.universe.type(asset["type_id"])
return type.name == "Tritanium" return type.name == "Tritanium"


+ 1
- 0
data/schema_campaigns.sql View File

@@ -60,6 +60,7 @@ CREATE TABLE oper_item (
oi_character INTEGER, oi_character INTEGER,
oi_type INTEGER, oi_type INTEGER,
oi_count INTEGER, oi_count INTEGER,
oi_value REAL,
UNIQUE (oi_campaign, oi_operation, oi_character, oi_type) UNIQUE (oi_campaign, oi_operation, oi_character, oi_type)
); );




+ 5
- 2
static/main.css View File

@@ -519,13 +519,16 @@ h2 .disabled-info {
border-bottom: none; border-bottom: none;
} }


.operation .itemboard .num {
.operation .itemboard td:last-child {
padding-left: 0.5em; padding-left: 0.5em;
text-align: right; text-align: right;
}

.operation .itemboard .count {
font-weight: bold; font-weight: bold;
} }


.operation .itemboard .num::before {
.operation .itemboard .count::before {
content: "×"; content: "×";
font-weight: normal; font-weight: normal;
color: #AAA; color: #AAA;


+ 13
- 6
templates/campaigns/renderers.mako View File

@@ -1,7 +1,7 @@
<%! <%!
from calefaction.format import ( from calefaction.format import (
format_isk_compact, format_utctime_compact, format_security,
get_security_class)
format_quantity, format_isk_compact, format_utctime_compact,
format_security, get_security_class)
%> %>
<%def name="_killboard_kill(kill)"> <%def name="_killboard_kill(kill)">
<% <%
@@ -56,13 +56,20 @@
</%def> </%def>
<%def name="_itemboard_item(item)"> <%def name="_itemboard_item(item)">
<% <%
type_id, count = item
type_id, count, value = item
type = g.eve.universe.type(type_id) type = g.eve.universe.type(type_id)
%> %>
<tr> <tr>
<td class="icon"><img title="${type.name | h}" alt="" src="${g.eve.image.inventory(type_id, 64)}"/></td>
<td><a href="https://eve-central.com/home/quicklook.html?typeid=${type_id | u}">${type.name | h}</a></td>
<td class="num">${count | h}</td>
<td class="icon">
<img title="${type.name | h}" alt="" src="${g.eve.image.inventory(type_id, 64)}"/>
</td>
<td>
<a href="https://eve-central.com/home/quicklook.html?typeid=${type_id | u}">${type.name | h}</a>
</td>
<td>
<span class="count">${format_quantity(count) | h}</span><br/>
<abbr class="price" title="${"{:,.2f}".format(value)} ISK">${format_isk_compact(value) | h}</abbr>
</td>
</tr> </tr>
</%def> </%def>
<%def name="_killboard_recent(summary)"> <%def name="_killboard_recent(summary)">


Loading…
Cancel
Save