diff --git a/app/analytics.py b/app/analytics.py
index bb28d46..179e680 100644
--- a/app/analytics.py
+++ b/app/analytics.py
@@ -1,7 +1,7 @@
import requests
from time import sleep, mktime
from bs4 import BeautifulSoup
-from datetime import datetime
+from datetime import datetime, timedelta
from app import app, db, models
@@ -14,10 +14,15 @@ def collect_match_results(dotabuff_id, num_matches):
page += 1
url = "http://dotabuff.com/players/{}/matches/?page={}".format(dotabuff_id, page)
data = requests.get(url).text
- soup = BeautifulSoup(data).article.table.tbody
- # Catch last page
- if 'sorry' in soup.tr.td.text.lower():
+ try:
+ soup = BeautifulSoup(data).article.table.tbody
+ except:
break
+ else:
+ # Catch last page
+ if 'sorry' in soup.tr.td.text.lower():
+ break
+
# Parse the matches on current page
for row in soup.find_all('tr'):
# Pass over bot matches and other 'inactive' games
@@ -43,7 +48,7 @@ def apply_window(results, window_size=50):
windows = []
# Compute the initial window
win_rate = 0.00
- for idx in range(0, window_size):
+ for idx in range(0, window_size-1):
win_rate += 1 if results[idx]['win'] else 0
win_rate /= window_size
windows.append(win_rate)
@@ -59,18 +64,38 @@ def apply_window(results, window_size=50):
windows.append(win_rate)
return windows
+# Single user alternative for testing/calculating on demand
+def calculate_winrate(user_id):
+ user = models.User.query.get(user_id)
+ db_id = requests.get("http://dotabuff.com/search?q="+user.steam_id).url.split("/")[-1]
+ result = collect_match_results(db_id, app.config['ANALYTICS_WINRATE_NUM_MATCHES'])
+ windowed = apply_window(result, app.config['ANALYTICS_WINRATE_WINDOW'])
+ date_nums = map(lambda x: mktime(x['datetime'].timetuple()),\
+ result[app.config['ANALYTICS_WINRATE_WINDOW']-1:])
+ winrate = {'total_games': len(result), 'data': zip(date_nums, windowed) }
+ user.winrate_data = winrate
+ db.session.commit()
+
def calculate_winrates():
users_analyzed = 0
- for user in models.User.query.all():
+ delta = datetime.utcnow() - timedelta(weeks=4)
+ print "Starting winrate calculation"
+ for user in models.User.query.filter(models.User.last_seen > delta).all():
+ print "Begin calculating winrate for {}".format(user.nickname.encode('utf-8'))
db_id = requests.get("http://dotabuff.com/search?q="+user.steam_id).url.split("/")[-1]
result = collect_match_results(db_id, app.config['ANALYTICS_WINRATE_NUM_MATCHES'])
- windowed = apply_window(result, app.config['ANALYTICS_WINRATE_WINDOW'])
- date_nums = map(lambda x: mktime(x['datetime'].timetuple()),\
- result[app.config['ANALYTICS_WINRATE_WINDOW']-1:])
- winrate = {'total_games': len(result), 'data': zip(date_nums, windowed) }
- user.winrate_data = winrate
- db.session.commit()
- users_analyzed += 1
- sleep(60)
+ if len(result):
+ windowed = apply_window(result, app.config['ANALYTICS_WINRATE_WINDOW'])
+ date_nums = map(lambda x: mktime(x['datetime'].timetuple()),\
+ result[app.config['ANALYTICS_WINRATE_WINDOW']-1:])
+ winrate = {'total_games': len(result), 'data': zip(date_nums, windowed) }
+ user.winrate_data = winrate
+ db.session.commit()
+ users_analyzed += 1
+ print "Finished winrate calculation for {} ({} total games)".format(user.nickname.encode('utf-8'), winrate['total_games'])
+ sleep(60)
+ else:
+ print "DotaBuff unable to access match statistics for {}".format(user.nickname.encode('utf-8'))
app.logger.info("Calculated win rate numbers for {} doobs.".format(users_analyzed))
+ print "Calculated win rate numbers for {} doobs.".format(users_analyzed)
return users_analyzed
diff --git a/app/forms.py b/app/forms.py
index a38f303..e700558 100644
--- a/app/forms.py
+++ b/app/forms.py
@@ -6,6 +6,7 @@ class SettingsForm(Form):
public = BooleanField('public', default=True)
logo = BooleanField('biglogo', default=True)
twitch = TextField('twitch')
+ hitbox = TextField('hitbox')
bio_text = TextAreaField('bio_text')
class EnableStatsForm(Form):
diff --git a/app/models.py b/app/models.py
index 6645d5a..00336f4 100644
--- a/app/models.py
+++ b/app/models.py
@@ -28,8 +28,11 @@ class Json(db.TypeDecorator):
return value
def process_result_value(self, value, dialect):
- if value is not None:
- value = json.loads(value)
+ try:
+ if value is not None:
+ value = json.loads(value)
+ except ValueError:
+ return {}
return value
# Mongoness factor - phase 2
@@ -72,6 +75,7 @@ class User(db.Model):
created = db.Column(db.DateTime)
last_seen = db.Column(db.DateTime)
twitch = db.Column(db.String(60))
+ hitbox = db.Column(db.String(60))
random_heroes = db.Column(MutableDict.as_mutable(Json))
az_completions = db.Column(db.Integer)
@@ -95,6 +99,19 @@ class User(db.Model):
def get_or_create(self, steam_id):
return get_or_create_instance(db.session, User, steam_id=steam_id)
+ @classmethod
+ def get_streaming_users(self):
+ twitch_streams = []
+ hitbox_streams = []
+ for user in User.query.all():
+ if user.points_from_events + user.points_from_ts3 + user.points_from_forum < 5: continue
+ if user.twitch:
+ twitch_streams.append(user.twitch)
+ if user.hitbox:
+ hitbox_streams.append(user.hitbox)
+
+ return {'twitch': twitch_streams, 'hitbox': hitbox_streams}
+
def __init__(self, steam_id):
self.steam_id = steam_id
self.random_heroes = {'current':None, 'completed':[]}
diff --git a/app/teamspeak.py b/app/teamspeak.py
index 802cda7..c0c607b 100644
--- a/app/teamspeak.py
+++ b/app/teamspeak.py
@@ -361,11 +361,11 @@ def award_idle_ts3_points(server):
if client['cid'] not in exempt_cids:
try:
doob = models.User.query.filter_by(teamspeak_id=client['client_unique_identifier']).first()
+ if doob:
+ doob.update_connection()
+ active_users.add(doob)
except KeyError:
pass
- if doob:
- doob.update_connection()
- active_users.add(doob)
doobs = set(models.User.query.filter(models.User.ts3_starttime != None).all())
for doob in doobs.intersection(active_users):
doob.finalize_connection()
diff --git a/app/templates/index.html b/app/templates/index.html
index 2861a71..3a5e7a7 100644
--- a/app/templates/index.html
+++ b/app/templates/index.html
@@ -75,7 +75,8 @@ $(document).ready(function() {
// Add the twitch streams
var stream_url = "https://api.twitch.tv/kraken/streams/";
- var channels = ["dotanoobs", "bearhugdota", "kreejaffakree", "prettypenguins", "shaneomad"];
+ // var channels = ["dotanoobs", "bearhugdota", "kreejaffakree", "prettypenguins", "shaneomad"];
+ var channels = {{ streamers['twitch']|tojson|safe }};
for (var idx in channels) {
$.getJSON(stream_url+channels[idx]+"?callback=?", function(data) {
if (data.stream) {
@@ -107,7 +108,8 @@ $(document).ready(function() {
// Add the hitbox streams
var stream_url = "http://api.hitbox.tv/media/live/";
- var channels = ["Bandita", "Gibb3d"];
+ //var channels = ["Bandita", "Gibb3d"];
+ var channels = {{ streamers['hitbox']|tojson|safe }};
for (var idx in channels) {
$.getJSON(stream_url+channels[idx], function(data) {
var livestream = data.livestream[0];
diff --git a/app/templates/settings.html b/app/templates/settings.html
index ee5a578..ba12dbe 100644
--- a/app/templates/settings.html
+++ b/app/templates/settings.html
@@ -25,6 +25,10 @@
{{ form.twitch(placeholder="e.g. shaneomad") }}
+