This commit is contained in:
Vyacheslav Anzhiganov 2017-10-23 02:41:54 +03:00
parent a8b73c3ad5
commit dfb7f1288e
18 changed files with 456 additions and 29 deletions

2
.gitignore vendored
View file

@ -4,4 +4,4 @@ celerybeat-schendule
tmp/associations/ tmp/associations/
tmp/nonces/ tmp/nonces/
celerybeat.pid celerybeat.pid
celerybeat-schendule celerybeat-schedule

View file

@ -0,0 +1,26 @@
"""empty message
Revision ID: 43d399aefb51
Revises: 92040f86c12b
Create Date: 2017-10-22 04:03:08.207413
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import JSONB
# revision identifiers, used by Alembic.
revision = '43d399aefb51'
down_revision = '92040f86c12b'
branch_labels = None
depends_on = None
def upgrade():
op.add_column('rush_accounts', sa.Column('finish_data', JSONB, nullable=True))
op.add_column('rush_accounts', sa.Column('start_data', JSONB, nullable=True))
def downgrade():
op.drop_column('rush_accounts', 'start_data')
op.drop_column('rush_accounts', 'finish_data')

View file

@ -0,0 +1,42 @@
"""empty message
Revision ID: a0c2b2ad3a28
Revises: 43d399aefb51
Create Date: 2017-10-23 02:39:35.899706
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = 'a0c2b2ad3a28'
down_revision = '43d399aefb51'
branch_labels = None
depends_on = None
def upgrade():
op.create_table(
'user_wallet',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user', sa.Integer(), nullable=False),
sa.Column('balance', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['user'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table(
'user_wallet_transactions',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.Column('status', sa.String(length=32), nullable=False),
sa.Column('amount', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['user'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
def downgrade():
op.drop_table('user_wallet_transactions')
op.drop_table('user_wallet')

3
run_celery_beat.sh Normal file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env python
celery beat -A run_celery.celery -l debug

3
run_celery_worker.sh Normal file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env python
celery worker -A run_celery.celery -l debug

View file

@ -1,4 +1,5 @@
import re import re
import requests
def parse_wargaming_openid_url(url): def parse_wargaming_openid_url(url):
@ -9,3 +10,15 @@ def parse_wargaming_openid_url(url):
""" """
pattern = '^https?.*id\/([0-9]+)-(\w+)\/$' pattern = '^https?.*id\/([0-9]+)-(\w+)\/$'
return re.findall(pattern, url)[0] return re.findall(pattern, url)[0]
def get_player_personal_data(application_id, user_id):
url = "https://api.worldoftanks.ru/wot/account/info/"
payload = {
# "application_id": current_app.config['WG_APPLICATION_ID'],
"application_id": application_id,
"account_id": user_id
}
__ = requests.get(url, params=payload).json()
return __.get('data', {}).get(user_id)

View file

@ -1,5 +1,6 @@
from .user import User from .user import User
from .userwallet import UserWallet, UserWalletTransactions
from .userwottokens import UserWotTokens from .userwottokens import UserWotTokens
from .userwotdetails import UserWotDetails from .userwotdetails import UserWotDetails
# from .userwotstats import UserWotStats # from .userwotstats import UserWotStats

View file

@ -15,4 +15,6 @@ class Rush(db.Model):
pass pass
def __repr__(self): def __repr__(self):
return '<Rush id={}>'.format(self.id) return '<Rush id={} at_start={} at_finish={} bet={} status={}>'.format(
self.id, self.at_start, self.at_finish, self.bet, self.status
)

View file

@ -1,4 +1,5 @@
from sqlalchemy.dialects.postgresql import JSONB
from wotstats.database import db from wotstats.database import db
@ -6,8 +7,13 @@ class RushAccounts(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
rush_id = db.Column(db.Integer, db.ForeignKey('rush.id'), nullable=False) rush_id = db.Column(db.Integer, db.ForeignKey('rush.id'), nullable=False)
account_id = db.Column(db.Integer, db.ForeignKey('wot_accounts.account_id'), nullable=False) account_id = db.Column(db.Integer, db.ForeignKey('wot_accounts.account_id'), nullable=False)
# {"battles": 0, "draws": 0, "wins": 0, "loses": 0}
start_data = db.Column(JSONB, nullable=True, default={})
# {"battles": 0, "draws": 0, "wins": 0, "loses": 0}
finish_data = db.Column(JSONB, nullable=True, default={})
def __init__(self, account_id, nickname):
def __init__(self, account_id, rush_id):
self.account_id = account_id self.account_id = account_id
self.rush_id = rush_id self.rush_id = rush_id

View file

@ -0,0 +1,25 @@
from sqlalchemy.dialects.postgresql import ARRAY, HSTORE
from wotstats.database import db
class UserWallet(db.Model):
id = db.Column(db.Integer, primary_key=True)
user = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
balance = db.Column(db.Integer, default=0)
# def __init__(self):
# pass
def __repr__(self):
return '<UserWallet id={} user={} balance={}>'.format(
self.id, self.user, self.balance
)
class UserWalletTransactions(db.Model):
id = db.Column(db.Integer, primary_key=True)
user = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
created_at = db.Column(db.DateTime, nullable=False)
status = db.Column(db.String(32), nullable=False)
amount = db.Column(db.Integer)

View file

@ -1,9 +1,12 @@
import time import time
from datetime import timedelta import requests
import json
from datetime import timedelta, datetime
from flask import current_app from flask import current_app
from wotstats.pending_tasks import celery from wotstats.pending_tasks import celery
from wotstats.database import db
from wotstats.models import UserWotTokens from wotstats.models import UserWotTokens
from wotstats.models import Rush, RushAccounts
@celery.task(name='wotstats.tasks.tokens_prolongate') @celery.task(name='wotstats.tasks.tokens_prolongate')
@ -25,11 +28,106 @@ def get_stats_tokenized_users():
@celery.task(name='wotstats.tasks.hello') @celery.task(name='wotstats.tasks.hello')
def hello(): def hello():
time.sleep(3) if Rush.query.filter_by(status='preparation').count() == 0:
now = datetime.now().replace(minute=0, second=0)
new_rush = Rush()
try:
new_rush.at_start = now + timedelta(hours=1)
new_rush.at_finish = now + timedelta(hours=24)
db.session.add(new_rush)
db.session.commit()
except Exception as e:
print e
db.session.rollback()
to_start = Rush.query.filter(
Rush.status == 'preparation',
Rush.at_start <= datetime.now()
)
if to_start.count() > 0:
p = to_start.first()
# Count
rush_accounts = RushAccounts.query.filter(
RushAccounts.rush_id == p.id
)
if rush_accounts.count() == 0:
p.status = 'canceled'
db.session.commit()
else:
for ra in rush_accounts.all():
# Get current stats by ra.account_id
# Save battle stats to database
#
app_id = current_app.config['WG_APPLICATION_ID']
url = 'https://api.worldoftanks.ru/wot/account/info/'
__ = requests.get('{}?application_id={}&account_id={}'.format(url, app_id, ra.account_id)).json()
account_statistics = __.get('data', {}).get("{}".format(ra.account_id)).get('statistics', {})
account_data = __['data']["{}".format(ra.account_id)]['statistics']['all']
data = {
'battles': account_data['battles'],
'wins': account_data['wins'],
'losses': account_data['losses'],
'draws': account_data['draws'],
}
xx = RushAccounts.query.filter(
RushAccounts.rush_id == p.id,
RushAccounts.account_id == ra.account_id
).first()
xx.start_data = data
db.session.commit()
pass
p.status = 'started'
db.session.commit()
to_finish = Rush.query.filter(
Rush.status == 'started',
Rush.at_finish <= datetime.now()
)
if to_finish.count() > 0:
p = to_finish.first()
# Harvert stats for all rush members
for ra in RushAccounts.query.filter(RushAccounts.rush_id == p.id):
# TODO: Get WOT accoount data
# TODO: Get Stats from WOT server
# TODO: Save Stats
print ra.account_id
# Get current stats by ra.account_id
# Save battle stats to database
#
app_id = current_app.config['WG_APPLICATION_ID']
url = 'https://api.worldoftanks.ru/wot/account/info/'
__ = requests.get('{}?application_id={}&account_id={}'.format(url, app_id, ra.account_id)).json()
account_statistics = __.get('data', {}).get("{}".format(ra.account_id)).get('statistics', {})
account_data = __['data']["{}".format(ra.account_id)]['statistics']['all']
data = {
'battles': account_data['battles'],
'wins': account_data['wins'],
'losses': account_data['losses'],
'draws': account_data['draws'],
}
xx = RushAccounts.query.filter(
RushAccounts.rush_id == p.id,
RushAccounts.account_id == ra.account_id
).first()
xx.finish_data = data
db.session.commit()
pass
# TODO: ...
p.status = 'finished'
db.session.commit()
# time.sleep(3)
# current_app.log.error('wdwqd') # current_app.log.error('wdwqd')
# with current_app.test_request_context() as request: # with current_app.test_request_context() as request:
# print('Hello {0!r}'.format(request)) # print('Hello {0!r}'.format(request))
print 111 # print 111
@celery.task @celery.task

View file

@ -0,0 +1,31 @@
{% extends 'layouts/main.html' %}
{% block content %}
<h2>Турниры</h2>
<div class="mui-row">
<div class="mui-col-md-12">
<table class="mui-table mui-table--bordered">
<thead>
<tr>
<th>ID</th>
<th>Старт</th>
<th>Финиш</th>
<th>Ставка</th>
<th>Статус</th>
</tr>
</thead>
<tr>
<td>{{ rush.id }}</td>
<td>{{ rush.at_start }}</td>
<td>{{ rush.at_finish }}</td>
<td>{{ rush.bet }} рублей</td>
<td>{{ rush.status }}</td>
</tr>
</table>
<form action="{{ url_for('pages_rush.apply') }}" method="post">
<button class="mui-btn mui-btn--primary mui-btn--raised">Участвовать</button>
</form>
</div>
</div>
{% endblock %}

View file

@ -2,4 +2,94 @@
{% block content %} {% block content %}
<h2>Турниры</h2> <h2>Турниры</h2>
<div class="mui-row">
<div class="mui-col-md-12">
<table class="mui-table mui-table--bordered">
<thead>
<tr>
<th>ID</th>
<th>Старт</th>
<th>Финиш</th>
<th>Ставка</th>
<th>Статус</th>
</tr>
</thead>
{% for r in rush_list %}
{% if r.status == "preparation" %}
<tr>
<td>{{ r.id }}</td>
<td>{{ r.at_start }}</td>
<td>{{ r.at_finish }}</td>
<td>{{ r.bet }} рублей</td>
<td>{{ r.status }}</td>
</tr>
{% endif %}
{% endfor %}
</table>
<div>
<h3>Участники</h3>
{% set allow_apply = 'true' %}
{% for u in rush_list_accounts %}
{% if u.account_id|int == account_id|int %}
{% set allow_apply = 'false' %}
{{ u.account_id }}
{% endif %}
{% endfor %}
</div>
{% if allow_apply == 'true' %}
<a href="{{ url_for('pages_rush.apply') }}" class="mui-btn mui-btn--primary mui-btn--raised">Участвовать</a>
{% else %}
<h3>Вы участвуете, вам необходимо совершить максимальное кол-во побед за время турнира</h3>
{% endif %}
</div>
<div class="mui-col-md-12">
<h3>Текущий</h3>
<table class="mui-table mui-table--bordered">
<thead>
<tr>
<th>ID</th>
<th>Старт</th>
<th>Финиш</th>
<th>Ставка</th>
<th>Статус</th>
</tr>
</thead>
{% for r in rush_list %}
{% if r.status == "started" %}
<tr>
<td>{{ r.id }}</td>
<td>{{ r.at_start }}</td>
<td>{{ r.at_finish }}</td>
<td>{{ r.bet }} рублей</td>
<td>{{ r.status }}</td>
</tr>
{% endif %}
{% endfor %}
</table>
<h3>Завершены</h3>
<table class="mui-table mui-table--bordered">
<thead>
<tr>
<th>ID</th>
<th>Старт</th>
<th>Финиш</th>
<th>Ставка</th>
<th>Статус</th>
</tr>
</thead>
{% for r in rush_list %}
{% if r.status in ["finished", "canceled"] %}
<tr>
<td>{{ r.id }}</td>
<td>{{ r.at_start }}</td>
<td>{{ r.at_finish }}</td>
<td>{{ r.bet }} рублей</td>
<td>{{ r.status }}</td>
</tr>
{% endif %}
{% endfor %}
</table>
</div>
</div>
{% endblock %} {% endblock %}

View file

@ -1,13 +1,16 @@
{% extends 'layouts/main.html' %} {% extends 'layouts/main.html' %}
{% block content %} {% block content %}
<h2>My Wallet</h2> <h2>Кошелёк</h2>
<p>Cash: $100500</p> <p>Баланс: $100500</p>
<h2>Add Money</h2> <h2>Пополнить баланс</h2>
<form action="" method="post" class="mui-form"> <form action="" method="post" class="mui-form">
<div class="mui-textfield"> <div class="mui-textfield">
<input type='text' name="" value="" placeholder="100" /> <input type='text' name="" value="" placeholder="100" />
</div> </div>
<input type='submit' value="pay" class="mui-btn mui-btn--raised" /> <input type='submit' value="pay" class="mui-btn mui-btn--raised" />
</form> </form>
<h2>История</h2>
{% endblock %} {% endblock %}

View file

@ -9,30 +9,19 @@ from wotstats.openid import oid
from wotstats.log import log from wotstats.log import log
from wotstats.database import db from wotstats.database import db
from wotstats.models import User from wotstats.models import User
from wotstats.lib import parse_wargaming_openid_url from wotstats.lib import parse_wargaming_openid_url, get_player_personal_data
pages_account = Blueprint('pages_account', __name__, url_prefix='/account', template_folder='templates') pages_account = Blueprint('pages_account', __name__, url_prefix='/account', template_folder='templates')
def __get_player_personal_data():
log.debug(session)
user_id = parse_wargaming_openid_url(session['openid'])[0]
url = "https://api.worldoftanks.ru/wot/account/info/"
payload = {
"application_id": current_app.config['WG_APPLICATION_ID'],
"account_id": user_id
}
__ = requests.get(url, params=payload).json()
return __.get('data', {}).get(user_id)
@pages_account.route('/') @pages_account.route('/')
def index(): def index():
if not g.user: if not g.user:
return redirect(url_for('pages_home.index')) return redirect(url_for('pages_home.index'))
account_statistics = __get_player_personal_data() user_id = parse_wargaming_openid_url(session['openid'])[0]
account_statistics = get_player_personal_data(current_app.config['WG_APPLICATION_ID'], user_id)
return render_template( return render_template(
'pages/account/index.html', 'pages/account/index.html',
account_statistics=account_statistics) account_statistics=account_statistics)

View file

@ -11,6 +11,7 @@ from jinja2 import TemplateNotFound
from wotstats.openid import oid from wotstats.openid import oid
from wotstats.database import db from wotstats.database import db
from wotstats.models import * from wotstats.models import *
from wotstats.lib import parse_wargaming_openid_url
# from wotstats.tasks import get_stats # from wotstats.tasks import get_stats
pages_home = Blueprint('pages_home', __name__, template_folder='templates') pages_home = Blueprint('pages_home', __name__, template_folder='templates')
@ -21,7 +22,6 @@ pages_home = Blueprint('pages_home', __name__, template_folder='templates')
@pages_home.route('/', defaults={'page': 'index'}) @pages_home.route('/', defaults={'page': 'index'})
@pages_home.route('/<page>') @pages_home.route('/<page>')
def index(page): def index(page):
print session
return render_template('pages/index.html') return render_template('pages/index.html')
@ -143,6 +143,9 @@ def token():
@oid.after_login @oid.after_login
def create_or_login(resp): def create_or_login(resp):
# resp
# 'aim', 'blog', 'country', 'date_of_birth', 'email', 'extensions', 'fullname', 'gender', 'icq', 'identity_url', 'image', 'jabber', 'language', 'month_of_birth', 'msn', 'nickname', 'phone', 'postcode', 'skype', 'timezone', 'website', 'yahoo', 'year_of_birth'
session['openid'] = resp.identity_url session['openid'] = resp.identity_url
session['token'] = None session['token'] = None
session['user'] = None session['user'] = None
@ -156,6 +159,19 @@ def create_or_login(resp):
name=resp.fullname or resp.nickname, name=resp.fullname or resp.nickname,
email=resp.email)) email=resp.email))
wot_account_id, wot_account_nickname = parse_wargaming_openid_url(resp.identity_url)
user_wot_account = WotAccounts.query.filter_by(account_id=wot_account_id).first()
if not user_wot_account:
x = WotAccounts(account_id=wot_account_id, nickname=wot_account_nickname)
x.user = user.id
db.session.add(x)
db.session.commit()
else:
if user_wot_account.user != user.id:
user_wot_account.user = user.id
db.session.commit()
session['user'] = user.id session['user'] = user.id
# flash(u'Successfully signed in') # flash(u'Successfully signed in')

View file

@ -7,8 +7,8 @@ from jinja2 import TemplateNotFound
from wotstats.openid import oid from wotstats.openid import oid
from wotstats.database import db from wotstats.database import db
from wotstats.models import Rush from wotstats.models import Rush, RushAccounts, WotAccounts
# from wotstats.lib import parse_wargaming_openid_url from wotstats.lib import parse_wargaming_openid_url
pages_rush = Blueprint( pages_rush = Blueprint(
'pages_rush', __name__, 'pages_rush', __name__,
@ -21,6 +21,85 @@ def index():
if not g.user: if not g.user:
return redirect(url_for('pages_home.index')) return redirect(url_for('pages_home.index'))
rush_list = Rush.query.all()
rush_preparation = Rush.query.filter(Rush.status == 'preparation').first()
rush_list_accounts = RushAccounts.query.filter(RushAccounts.rush_id == rush_preparation.id).all()
account_id, account_nickname = parse_wargaming_openid_url(session['openid'])
# #
# app_id = current_app.config['WG_APPLICATION_ID']
# url = 'https://api.worldoftanks.ru/wot/account/info/'
# __ = requests.get('{}?application_id={}&account_id={}'.format(url, app_id, account_id)).json()
# # if not __.get('data', {}).get("{}".format(account_id)):
# # print('account_id: {} SKIPPED'.format(account_id))
# # continue
# # copy results
# account_statistics = __.get('data', {}).get("{}".format(account_id)).get('statistics', {})
# account_data = __['data']["{}".format(account_id)]['statistics']['all']
#
# data = {
# 'battles': account_data['battles'],
# 'wins': account_data['wins'],
# 'losses': account_data['losses'],
# 'draws': account_data['draws'],
# }
# account_data.pop('statistics', None)
# db.session.add(WotAccounts(account_id=account_id, nickname=account_data.get('nickname')))
# db.session.commit()
# db.session.flush()
# ws = WotAccountsStats()
# ws.account_id = account_id
# ws.created_at = datetime.now()
# try:
# ws.last_battle_time = datetime.fromtimestamp(int(account_data.get('last_battle_time'))).strftime('%Y-%m-%d %H:%M:%S')
# except Exception as e:
# print('>> Error: {}'.format(e))
# ws.data = account_data
# ws.statistics = account_statistics
# db.session.add(ws)
# db.session.commit()
# db.session.flush()
return render_template( return render_template(
'pages/rush/index.html' 'pages/rush/index.html',
rush_list=rush_list,
rush_list_accounts=rush_list_accounts,
account_id=account_id, account_nickname=account_nickname
) )
@pages_rush.route('/apply.html')
def apply():
if not g.user:
return redirect(url_for('pages_home.index'))
rush_prep = Rush.query.filter(Rush.status == 'preparation').first()
return render_template(
'pages/rush/apply.html',
rush=rush_prep
)
@pages_rush.route('/apply.html', methods=['POST'])
def apply_post():
if not g.user:
return redirect(url_for('pages_home.index'))
r = Rush.query.filter(Rush.status == 'preparation').first()
wa = WotAccounts.query.filter(WotAccounts.user == session['user']).first()
ra = RushAccounts(rush_id=r.id, account_id=wa.account_id)
ra.start_data = {}
ra.finish_data = {}
db.session.add(ra)
db.session.commit()
return redirect(url_for('pages_rush.apply'))