Browse Source

Bugfixes & Hitbox.tv field in User model

master
Brandon Cornejo 10 years ago
parent
commit
de5e8ad946
  1. 53
      app/analytics.py
  2. 1
      app/forms.py
  3. 21
      app/models.py
  4. 6
      app/teamspeak.py
  5. 6
      app/templates/index.html
  6. 4
      app/templates/settings.html
  7. 8
      app/views.py

53
app/analytics.py

@ -1,7 +1,7 @@
import requests import requests
from time import sleep, mktime from time import sleep, mktime
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from datetime import datetime
from datetime import datetime, timedelta
from app import app, db, models from app import app, db, models
@ -14,10 +14,15 @@ def collect_match_results(dotabuff_id, num_matches):
page += 1 page += 1
url = "http://dotabuff.com/players/{}/matches/?page={}".format(dotabuff_id, page) url = "http://dotabuff.com/players/{}/matches/?page={}".format(dotabuff_id, page)
data = requests.get(url).text 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 break
else:
# Catch last page
if 'sorry' in soup.tr.td.text.lower():
break
# Parse the matches on current page # Parse the matches on current page
for row in soup.find_all('tr'): for row in soup.find_all('tr'):
# Pass over bot matches and other 'inactive' games # Pass over bot matches and other 'inactive' games
@ -43,7 +48,7 @@ def apply_window(results, window_size=50):
windows = [] windows = []
# Compute the initial window # Compute the initial window
win_rate = 0.00 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 += 1 if results[idx]['win'] else 0
win_rate /= window_size win_rate /= window_size
windows.append(win_rate) windows.append(win_rate)
@ -59,18 +64,38 @@ def apply_window(results, window_size=50):
windows.append(win_rate) windows.append(win_rate)
return windows 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(): def calculate_winrates():
users_analyzed = 0 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] 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']) 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)) 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 return users_analyzed

1
app/forms.py

@ -6,6 +6,7 @@ class SettingsForm(Form):
public = BooleanField('public', default=True) public = BooleanField('public', default=True)
logo = BooleanField('biglogo', default=True) logo = BooleanField('biglogo', default=True)
twitch = TextField('twitch') twitch = TextField('twitch')
hitbox = TextField('hitbox')
bio_text = TextAreaField('bio_text') bio_text = TextAreaField('bio_text')
class EnableStatsForm(Form): class EnableStatsForm(Form):

21
app/models.py

@ -28,8 +28,11 @@ class Json(db.TypeDecorator):
return value return value
def process_result_value(self, value, dialect): 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 return value
# Mongoness factor - phase 2 # Mongoness factor - phase 2
@ -72,6 +75,7 @@ class User(db.Model):
created = db.Column(db.DateTime) created = db.Column(db.DateTime)
last_seen = db.Column(db.DateTime) last_seen = db.Column(db.DateTime)
twitch = db.Column(db.String(60)) twitch = db.Column(db.String(60))
hitbox = db.Column(db.String(60))
random_heroes = db.Column(MutableDict.as_mutable(Json)) random_heroes = db.Column(MutableDict.as_mutable(Json))
az_completions = db.Column(db.Integer) az_completions = db.Column(db.Integer)
@ -95,6 +99,19 @@ class User(db.Model):
def get_or_create(self, steam_id): def get_or_create(self, steam_id):
return get_or_create_instance(db.session, User, steam_id=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): def __init__(self, steam_id):
self.steam_id = steam_id self.steam_id = steam_id
self.random_heroes = {'current':None, 'completed':[]} self.random_heroes = {'current':None, 'completed':[]}

6
app/teamspeak.py

@ -361,11 +361,11 @@ def award_idle_ts3_points(server):
if client['cid'] not in exempt_cids: if client['cid'] not in exempt_cids:
try: try:
doob = models.User.query.filter_by(teamspeak_id=client['client_unique_identifier']).first() doob = models.User.query.filter_by(teamspeak_id=client['client_unique_identifier']).first()
if doob:
doob.update_connection()
active_users.add(doob)
except KeyError: except KeyError:
pass pass
if doob:
doob.update_connection()
active_users.add(doob)
doobs = set(models.User.query.filter(models.User.ts3_starttime != None).all()) doobs = set(models.User.query.filter(models.User.ts3_starttime != None).all())
for doob in doobs.intersection(active_users): for doob in doobs.intersection(active_users):
doob.finalize_connection() doob.finalize_connection()

6
app/templates/index.html

@ -75,7 +75,8 @@ $(document).ready(function() {
// Add the twitch streams // Add the twitch streams
var stream_url = "https://api.twitch.tv/kraken/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) { for (var idx in channels) {
$.getJSON(stream_url+channels[idx]+"?callback=?", function(data) { $.getJSON(stream_url+channels[idx]+"?callback=?", function(data) {
if (data.stream) { if (data.stream) {
@ -107,7 +108,8 @@ $(document).ready(function() {
// Add the hitbox streams // Add the hitbox streams
var stream_url = "http://api.hitbox.tv/media/live/"; 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) { for (var idx in channels) {
$.getJSON(stream_url+channels[idx], function(data) { $.getJSON(stream_url+channels[idx], function(data) {
var livestream = data.livestream[0]; var livestream = data.livestream[0];

4
app/templates/settings.html

@ -25,6 +25,10 @@
<label class="uk-form-label">Twitch.tv Username:</label> <br/> <label class="uk-form-label">Twitch.tv Username:</label> <br/>
{{ form.twitch(placeholder="e.g. shaneomad") }} {{ form.twitch(placeholder="e.g. shaneomad") }}
</div> </div>
<div class="uk-form-row">
<label class="uk-form-label">Hitbox.tv Username:</label> <br/>
{{ form.hitbox(placeholder="e.g. shaneomad") }}
</div>
<div class="uk-form-row"> <div class="uk-form-row">
<label class="uk-form-label">Biography text:</label><br/> <label class="uk-form-label">Biography text:</label><br/>
{{ form.bio_text(rows=14, class='uk-width-1-1', data=g.user.bio_text, placedholder='What you place here is displayed in your profile when other users view it.') }} {{ form.bio_text(rows=14, class='uk-width-1-1', data=g.user.bio_text, placedholder='What you place here is displayed in your profile when other users view it.') }}

8
app/views.py

@ -41,7 +41,8 @@ def flash_form_errors(form):
def index(): def index():
active = Event.query.filter(Event.start_time <= datetime.utcnow(), Event.end_time > datetime.utcnow()).all() active = Event.query.filter(Event.start_time <= datetime.utcnow(), Event.end_time > datetime.utcnow()).all()
upcoming = Event.query.filter(Event.start_time > datetime.utcnow()).limit(2).all() upcoming = Event.query.filter(Event.start_time > datetime.utcnow()).limit(2).all()
return render_template("index.html", active_events=active, upcoming_events=upcoming)
channels = User.get_streaming_users()
return render_template("index.html", active_events=active, upcoming_events=upcoming, streamers=channels)
@app.route('/login') @app.route('/login')
@oid.loginhandler @oid.loginhandler
@ -79,6 +80,11 @@ def teamspeak():
def friends(): def friends():
return render_template('friends.html') return render_template('friends.html')
# Stream pages
@app.route('/shaneomad')
def twitch_shaneomad():
return render_template('potatr.html', twitch_id=app.config.TWITCH_CLIENT_ID)
# User profile page # User profile page
@app.route('/user/<int:userid>') @app.route('/user/<int:userid>')
def user_profile(userid): def user_profile(userid):

Loading…
Cancel
Save