Skip to content
This repository was archived by the owner on Aug 9, 2023. It is now read-only.

Commit 3a24930

Browse files
committed
Initial Commit
0 parents  commit 3a24930

7 files changed

Lines changed: 95769 additions & 0 deletions

File tree

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.DS_Store
2+
*.pyc
3+
build
4+
dist
5+
*.swp

cargoscanner.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
An Eve Online Cargo Scanner
4+
"""
5+
import memcache
6+
import json
7+
import urllib2
8+
import xml.etree.ElementTree as ET
9+
import humanize
10+
11+
from flask import Flask, request, session, g, redirect, url_for, abort, \
12+
render_template, flash, _app_ctx_stack
13+
14+
# configuration
15+
DEBUG = True
16+
MARKET_URL = 'http://api.eve-central.com/api'
17+
MEMCACHE_PREFIX = 'cargoscanner'
18+
TYPES = json.loads(open('data/types.json').read())
19+
20+
app = Flask(__name__)
21+
app.config.from_object(__name__)
22+
23+
24+
@app.template_filter('format_isk')
25+
def format_isk(value):
26+
return "{:,.2f} ISK".format(value)
27+
28+
29+
@app.template_filter('format_isk_human')
30+
def format_isk_human(value):
31+
return "%s ISK" % humanize.intword(value, format='%.2f')
32+
33+
34+
def memcache_type_key(typeId):
35+
return "%s:prices:%s" % (app.config['MEMCACHE_PREFIX'], typeId)
36+
37+
38+
def get_cache():
39+
top = _app_ctx_stack.top
40+
if not hasattr(top, 'memcache'):
41+
top.memcache = memcache.Client(['127.0.0.1:11211'], debug=0)
42+
return top.memcache
43+
44+
45+
def get_cached_values(typeIds):
46+
mc = get_cache()
47+
found = {}
48+
not_found = []
49+
for typeId in typeIds:
50+
key = memcache_type_key(typeId)
51+
obj = mc.get(key)
52+
if obj:
53+
found[typeId] = obj
54+
else:
55+
print("Cache Miss. typeId: %s" % typeId)
56+
not_found.append(typeId)
57+
return found, not_found
58+
59+
60+
def set_cache_value(typeId, value):
61+
mc = get_cache()
62+
key = memcache_type_key(typeId)
63+
mc.set(key, value)
64+
65+
66+
def get_market_values(typeIds):
67+
typeIds_str = ','.join(str(x) for x in typeIds)
68+
url = "%s/marketstat?typeid=%s" % (app.config['MARKET_URL'], typeIds_str)
69+
response = urllib2.urlopen(url).read()
70+
stats = ET.fromstring(response).findall("./marketstat/type")
71+
market_prices = {}
72+
for marketstat in stats:
73+
k = int(marketstat.attrib.get('id'))
74+
v = {}
75+
for stat_type in ['sell', 'buy', 'all']:
76+
props = {}
77+
for stat in marketstat.find('%s' % stat_type):
78+
props[stat.tag] = float(stat.text)
79+
v[stat_type] = props
80+
set_cache_value(k, v)
81+
market_prices[k] = v
82+
return market_prices
83+
84+
85+
def parse_scan_items(scan_result):
86+
"Takes a scan result and returns {'name': {details}, ...} "
87+
lines = scan_result.splitlines()
88+
lines = [line.strip() for line in scan_result.splitlines() if line.strip()]
89+
90+
results = {}
91+
for line in lines:
92+
try:
93+
count, name = line.split(' ', 1)
94+
count = int(count)
95+
except ValueError:
96+
count, name = 1, line
97+
name = name.lower()
98+
if name in results:
99+
results[name] += count
100+
else:
101+
results[name] = count
102+
103+
typed_results = {}
104+
for name, count in results.iteritems():
105+
details = app.config['TYPES'].get(name)
106+
if details:
107+
typed_results[details['typeID']] = \
108+
dict(details.items() + [('count', count)])
109+
110+
return typed_results
111+
112+
113+
@app.route('/estimate', methods=['POST'])
114+
def estimate_cost():
115+
# - Format name, quantity (string manipulation)
116+
results = parse_scan_items(request.form['scan_result'])
117+
found, not_found = get_cached_values(results.keys())
118+
prices = dict(found.items() + get_market_values(not_found).items())
119+
totals = {'sell': 0, 'buy': 0, 'all': 0}
120+
for typeId, price_data in prices.iteritems():
121+
price_data = dict(price_data.items() + results[typeId].items())
122+
results[typeId] = price_data
123+
results[typeId]['totals'] = {}
124+
for total_key in ['sell', 'buy', 'all']:
125+
_total = price_data[total_key]['avg'] * price_data['count']
126+
results[typeId]['totals'][total_key] = _total
127+
totals[total_key] += _total
128+
129+
sorted_line_items = sorted(results.values(),
130+
key=lambda k: -k['totals']['all'])
131+
scan_results = {
132+
'totals': totals,
133+
'line_items': sorted_line_items,
134+
}
135+
if request.form.get('load_full'):
136+
return render_template('index.html', scan_results=scan_results)
137+
else:
138+
return render_template('scan_results.html', scan_results=scan_results)
139+
140+
141+
@app.route('/', methods=['GET', 'POST'])
142+
def index():
143+
return render_template('index.html')
144+
145+
146+
if __name__ == '__main__':
147+
app.run()

0 commit comments

Comments
 (0)