diff --git a/.gitignore b/.gitignore index 2a1c46f..150600a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ celerybeat-schendule tmp/associations/ tmp/nonces/ celerybeat.pid -celerybeat-schendule +celerybeat-schedule diff --git a/migrations/versions/43d399aefb51_.py b/migrations/versions/43d399aefb51_.py new file mode 100644 index 0000000..f8d894b --- /dev/null +++ b/migrations/versions/43d399aefb51_.py @@ -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') diff --git a/migrations/versions/a0c2b2ad3a28_.py b/migrations/versions/a0c2b2ad3a28_.py new file mode 100644 index 0000000..72e2e85 --- /dev/null +++ b/migrations/versions/a0c2b2ad3a28_.py @@ -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') diff --git a/run_celery_beat.sh b/run_celery_beat.sh new file mode 100644 index 0000000..3423a62 --- /dev/null +++ b/run_celery_beat.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env python + +celery beat -A run_celery.celery -l debug diff --git a/run_celery_worker.sh b/run_celery_worker.sh new file mode 100644 index 0000000..aa8f67d --- /dev/null +++ b/run_celery_worker.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env python + +celery worker -A run_celery.celery -l debug diff --git a/wotstats/lib/__init__.py b/wotstats/lib/__init__.py index 9b1fef0..b22c506 100644 --- a/wotstats/lib/__init__.py +++ b/wotstats/lib/__init__.py @@ -1,4 +1,5 @@ import re +import requests def parse_wargaming_openid_url(url): @@ -9,3 +10,15 @@ def parse_wargaming_openid_url(url): """ pattern = '^https?.*id\/([0-9]+)-(\w+)\/$' 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) diff --git a/wotstats/models/__init__.py b/wotstats/models/__init__.py index 3968c4a..44d90a4 100644 --- a/wotstats/models/__init__.py +++ b/wotstats/models/__init__.py @@ -1,5 +1,6 @@ from .user import User +from .userwallet import UserWallet, UserWalletTransactions from .userwottokens import UserWotTokens from .userwotdetails import UserWotDetails # from .userwotstats import UserWotStats diff --git a/wotstats/models/rush.py b/wotstats/models/rush.py index be17ef1..3195b76 100644 --- a/wotstats/models/rush.py +++ b/wotstats/models/rush.py @@ -15,4 +15,6 @@ class Rush(db.Model): pass def __repr__(self): - return ''.format(self.id) + return ''.format( + self.id, self.at_start, self.at_finish, self.bet, self.status + ) diff --git a/wotstats/models/rushaccounts.py b/wotstats/models/rushaccounts.py index b0c408a..e6f1a4e 100644 --- a/wotstats/models/rushaccounts.py +++ b/wotstats/models/rushaccounts.py @@ -1,4 +1,5 @@ +from sqlalchemy.dialects.postgresql import JSONB from wotstats.database import db @@ -6,8 +7,13 @@ class RushAccounts(db.Model): id = db.Column(db.Integer, primary_key=True) 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) + # {"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.rush_id = rush_id diff --git a/wotstats/models/userwallet.py b/wotstats/models/userwallet.py new file mode 100644 index 0000000..10c6b65 --- /dev/null +++ b/wotstats/models/userwallet.py @@ -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 ''.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) diff --git a/wotstats/models/wallet.py b/wotstats/models/wallet.py deleted file mode 100644 index e69de29..0000000 diff --git a/wotstats/tasks/__init__.py b/wotstats/tasks/__init__.py index 9492882..49e5239 100644 --- a/wotstats/tasks/__init__.py +++ b/wotstats/tasks/__init__.py @@ -1,9 +1,12 @@ import time -from datetime import timedelta +import requests +import json +from datetime import timedelta, datetime from flask import current_app from wotstats.pending_tasks import celery +from wotstats.database import db from wotstats.models import UserWotTokens - +from wotstats.models import Rush, RushAccounts @celery.task(name='wotstats.tasks.tokens_prolongate') @@ -25,11 +28,106 @@ def get_stats_tokenized_users(): @celery.task(name='wotstats.tasks.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') # with current_app.test_request_context() as request: # print('Hello {0!r}'.format(request)) - print 111 + # print 111 @celery.task diff --git a/wotstats/templates/pages/rush/apply.html b/wotstats/templates/pages/rush/apply.html new file mode 100644 index 0000000..2f488c8 --- /dev/null +++ b/wotstats/templates/pages/rush/apply.html @@ -0,0 +1,31 @@ +{% extends 'layouts/main.html' %} + +{% block content %} +

Турниры

+
+
+ + + + + + + + + + + + + + + + + +
IDСтартФинишСтавкаСтатус
{{ rush.id }}{{ rush.at_start }}{{ rush.at_finish }}{{ rush.bet }} рублей{{ rush.status }}
+
+ +
+
+
+ +{% endblock %} diff --git a/wotstats/templates/pages/rush/index.html b/wotstats/templates/pages/rush/index.html index 0d25150..b376c82 100644 --- a/wotstats/templates/pages/rush/index.html +++ b/wotstats/templates/pages/rush/index.html @@ -2,4 +2,94 @@ {% block content %}

Турниры

+
+
+ + + + + + + + + + + {% for r in rush_list %} + {% if r.status == "preparation" %} + + + + + + + + {% endif %} + {% endfor %} +
IDСтартФинишСтавкаСтатус
{{ r.id }}{{ r.at_start }}{{ r.at_finish }}{{ r.bet }} рублей{{ r.status }}
+
+

Участники

+ {% 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 %} +
+ {% if allow_apply == 'true' %} + Участвовать + {% else %} +

Вы участвуете, вам необходимо совершить максимальное кол-во побед за время турнира

+ {% endif %} +
+
+

Текущий

+ + + + + + + + + + + {% for r in rush_list %} + {% if r.status == "started" %} + + + + + + + + {% endif %} + {% endfor %} +
IDСтартФинишСтавкаСтатус
{{ r.id }}{{ r.at_start }}{{ r.at_finish }}{{ r.bet }} рублей{{ r.status }}
+

Завершены

+ + + + + + + + + + + {% for r in rush_list %} + {% if r.status in ["finished", "canceled"] %} + + + + + + + + {% endif %} + {% endfor %} +
IDСтартФинишСтавкаСтатус
{{ r.id }}{{ r.at_start }}{{ r.at_finish }}{{ r.bet }} рублей{{ r.status }}
+
+
+ {% endblock %} diff --git a/wotstats/templates/pages/wallet/index.html b/wotstats/templates/pages/wallet/index.html index c0f1ce7..b1853d3 100644 --- a/wotstats/templates/pages/wallet/index.html +++ b/wotstats/templates/pages/wallet/index.html @@ -1,13 +1,16 @@ {% extends 'layouts/main.html' %} {% block content %} -

My Wallet

-

Cash: $100500

-

Add Money

+

Кошелёк

+

Баланс: $100500

+

Пополнить баланс

+ +

История

+ {% endblock %} diff --git a/wotstats/views/account.py b/wotstats/views/account.py index b9108ff..7e339c1 100644 --- a/wotstats/views/account.py +++ b/wotstats/views/account.py @@ -9,30 +9,19 @@ from wotstats.openid import oid from wotstats.log import log from wotstats.database import db 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') -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('/') def index(): if not g.user: 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( 'pages/account/index.html', account_statistics=account_statistics) diff --git a/wotstats/views/home.py b/wotstats/views/home.py index ab5b1d4..0a9a3e4 100644 --- a/wotstats/views/home.py +++ b/wotstats/views/home.py @@ -11,6 +11,7 @@ from jinja2 import TemplateNotFound from wotstats.openid import oid from wotstats.database import db from wotstats.models import * +from wotstats.lib import parse_wargaming_openid_url # from wotstats.tasks import get_stats 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('/') def index(page): - print session return render_template('pages/index.html') @@ -143,6 +143,9 @@ def token(): @oid.after_login 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['token'] = None session['user'] = None @@ -156,6 +159,19 @@ def create_or_login(resp): name=resp.fullname or resp.nickname, 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 # flash(u'Successfully signed in') diff --git a/wotstats/views/rush.py b/wotstats/views/rush.py index 1ed6b98..1ffcc35 100644 --- a/wotstats/views/rush.py +++ b/wotstats/views/rush.py @@ -7,8 +7,8 @@ from jinja2 import TemplateNotFound from wotstats.openid import oid from wotstats.database import db -from wotstats.models import Rush -# from wotstats.lib import parse_wargaming_openid_url +from wotstats.models import Rush, RushAccounts, WotAccounts +from wotstats.lib import parse_wargaming_openid_url pages_rush = Blueprint( 'pages_rush', __name__, @@ -21,6 +21,85 @@ def index(): if not g.user: 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( - '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'))