예제 #1
0
파일: general.py 프로젝트: rico0821/pubgi
def close_db_session(exception=None):
    """Close DB session at request teardown."""
    
    try:
        dao.remove()
    except Exception as e:
        Log.error(str(e))
예제 #2
0
def _getRequest(region, query_type, query_filter, query, api_key):
    """
    Use URL to send request to API.
    
    ARGS: region, query_type, query_filter, query, api_key
    
    """

    url = _make_url(region, query_type, query_filter, query)

    headers = {"Authorization": api_key, "Accept": "application/vnd.api+json"}

    try:
        Log.info('Sent API request to %s' % url)
        start_time = time.time()
        result = requests.get(url, headers=headers)
        Log.info('Received API request %r: took %f sec' %
                 (result, time.time() - start_time))
        result = result.json()

    except Exception as e:

        result = None

    return result
예제 #3
0
def _processPlayerId(data):
    """
    Find player ID from player data.
    
    ARGS: data
    
    """

    try:
        player_id = data['data'][0]['id']

    except Exception as e:
        Log.error(str(e))
        player_id = None

    return player_id
예제 #4
0
def getTelemetry(url):
    """
    Get telemetry data using asset URL.
    
    ARGS: url
    
    """

    headers = {"Accept": "application/vnd.api+json"}
    result = None

    try:
        Log.info('Sent API request to %s' % url)
        start_time = time.time()
        result = requests.get(url, headers=headers)
        Log.info('Received API request %r: took %f sec' %
                 (result, time.time() - start_time))
        if result:
            result = result.json()

    except Exception as e:
        raise e

    return result
예제 #5
0
def getPlayerStats(region, player, api_key, last_match_id):
    """
    Get a tuple containing player id, match id, match stats.
    
    ARGS: region, player, api_key, last_match_id
    
    """

    player_id = getPlayerId(region, player, api_key)
    player_data = _getPlayerData(region, player, api_key)
    match_ids = list(_processMatchIds(player_data))

    try:
        if last_match_id:
            try:
                upto = match_ids.index(last_match_id) + 1
            except:
                upto = 0
                Log.error('Something went wrong with finding match index.')
        else:
            upto = 0
            Log.info(
                'No recent matches were recorded for player %r [region: %r]' %
                (player, region))

        for match_id in match_ids[upto:]:
            match_data = _getMatch(region, match_id, api_key)
            match_info = _processMatchData(match_data)
            match_stats = _processParticipantData(match_data, player_id)
            roster_data = _processRosterData(match_data, player_id)
            telemetry_url = _processTelemetryURL(match_data)
            yield (match_id, match_stats, match_info, roster_data,
                   telemetry_url)

    except Exception as e:
        raise e
        Log.error('Error finding matches found for player %r [region: %r]' %
                  (player, region))
        return False
예제 #6
0
파일: profile.py 프로젝트: rico0821/pubgi
def show_profile(player_name):
    """
    Show player profile page.
    
    ARGS: player_name, region
    
    1. Check whether player name and region are correctly given. 
        i) If not so: abort.
    2. Check if player with given name and region exists in DB.
        i) If not so:
            (a) Find PUBG player ID using API. If not found, render page for not found.
            (b) Create new player with stats for each game mode, append them accordingly and commit.
            (c) Render profile page for player created.
        ii) If so: render profile page for player found.
    3. Check whether stats exist for current season. 
        i) If not so:
            (a) Create new stats for each game mode, for current season.
            (b) Add all, append and then commit.
            
    """

    api_key = current_app.config['API_KEY']
    season = current_app.config['CURRENT_SEASON']
    region = request.args.get('region', '')

    if not (player_name or region):
        abort(404)

    player = dao.query(Player).filter_by(name=player_name).\
                               filter_by(region=region).first()

    if not player:

        api = PUBG(api_key, shardDict(region))
        pubg_player = api.players.filter(player_names=[player_name])
        #pubg_id = getPlayerId(region, player_name, api_key[region])

        if not pubg_id:
            return render_template('search.html',
                                   results=None,
                                   query=player_name)
        try:
            player = Player(player_name, pubg_id, region)
            soloStats = SoloStats(season)
            duoStats = DuoStats(season)
            squadStats = SquadStats(season)
            dao.add_all([player, soloStats, duoStats, squadStats])

            player.solo.append(soloStats)
            player.duo.append(duoStats)
            player.squad.append(squadStats)

            dao.commit()

            Log.info('New player %r added.' % player)

        except Exception as e:
            dao.rollback()
            Log.error(str(e))
            raise e

        else:
            return render_template('profile_overview.html', player=player)

    stats_exist = any(x.season == season for x in player.solo)

    if not stats_exist:
        try:
            soloStats = SoloStats(season)
            duoStats = DuoStats(season)
            squadStats = SquadStats(season)
            dao.add_all([soloStats, duoStats, squadStats])

            player.solo.append(soloStats)
            player.duo.append(duoStats)
            player.squad.append(squadStats)

            dao.commit()
            Log.info('New season stats for player %r added.' % player)

        except Exception as e:
            dao.rollback()
            Log.error(str(e))
            raise e

    return render_template('profile_overview.html', player=player)
예제 #7
0
파일: update.py 프로젝트: rico0821/pubgi
def update(player_id):
    """
    Update player's matches.
    
    ARGS: player_id
    
    1. Check if player with given ID exists.
        i) If not so, abort.
    2. Check if the player has been recently updated.
        i) If so, redirect to profile page for player with given name and region.
    3. Check season.
        i) If new season, create new player stats for each game mode, append them and commit.
    4. Find the PUBG match ID of the latest record and use it to get data from API on matches since.
    5. For each match data:
        i) Check if record with PUBG match ID for player with given ID exists in DB. 
            (a) If so: nothing happens.
        ii) Check if match with PUBG match ID exists in DB.
            (a) If not so: create one and its match info and save telemetry data to mongoDB.
        iii) Check if roster with PUBG roster ID exists in DB. If not so, create one and append to match.
        iv) Check match season.
        v) Create record and match stats and append them accordingly.
        vi) Check game mode and aggregate player stats accordingly.
        vii) Set player's update time to now and finally commit.
    6. Return jsonified signal for success or failure
    
    """

    api_key = current_app.config['API_KEY']
    season = current_app.config['CURRENT_SEASON']
    season_update = current_app.config['SEASON_UPDATE']

    player = dao.query(Player).get(player_id)

    if not player:
        abort(404)

    diff = datetime.utcnow() - player.updateTime

    if diff.seconds < current_app.config['UPDATE_WAIT_TIME']:
        return redirect(
            url_for('.show_profile',
                    player_name=player.name,
                    region=player.region))

    stats_exist = any(x.season == season for x in player.solo)

    if not stats_exist:
        try:
            new_soloStats = SoloStats(season)
            new_duoStats = DuoStats(season)
            new_squadStats = SquadStats(season)
            dao.add_all([new_soloStats, new_duoStats, new_squadStats])

            player.solo.append(new_soloStats)
            player.duo.append(new_duoStats)
            player.squad.append(new_squadStats)

            dao.commit()
            Log.info('New season stats for player %r added.' % player)

        except Exception as e:
            dao.rollback()
            Log.error(str(e) + " in check1")
            raise e

    last_match_id = None

    if player.records:
        last_match_id = player.records[-1].pubgMatchID
    player_stats = getPlayerStats(player.region, player.name, api_key,
                                  last_match_id)
    # player_stats = (match_id, match_stats, match_info, roster_data, telemetry_url)
    for data in player_stats:

        pubg_match_id = data[0]

        record_exist = dao.query(Record).filter_by(playerID=player.id).\
                        filter_by(pubgMatchID=pubg_match_id).first()

        try:
            if not record_exist:
                match_exist = dao.query(Match).filter_by(
                    pubgID=pubg_match_id).first()

                if not match_exist:
                    match_exist = Match(pubg_match_id)
                    match_info = MatchInfo(data[2])
                    dao.add_all([match_exist, match_info])

                    match_exist.info = match_info
                    """
                        telemetry_data = getTelemetry(data[4])
                        tele_exist = mongo.db.matches.find_one({'matchID' : pubg_match_id})
                        if not tele_exist:
                            filter_tele = filterTelemetry(telemetry_data, ["LogItemPickup", "LogPlayerPosition", "LogGameStatePeriodic", "LogPlayerKill"])
                            mongo.db.matches.insert({'matchID' : pubg_match_id, 
                                                              'map' : match_info.mapName,
                                                              'data' : telemetry_data})
                            Log.info('Telemetry data added for match %r' % match_exist)

                        """
                roster = dao.query(Roster).filter_by(
                    pubgRosterID=data[3]).first()

                if not roster:
                    roster = Roster(data[3])
                    dao.add(roster)

                    match_exist.rosters.append(roster)

                timestamp = match_exist.info.createdAt
                createdAt = datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%SZ')
                match_season = season
                if createdAt < season_update:
                    match_season = season - 1

                record = Record(pubg_match_id, match_season)
                match_stats = MatchStats(data[1])
                dao.add_all([match_stats, record])

                roster.participants.append(record)
                record.stats = match_stats
                player.records.append(record)

                info = roster.match.info
                if info.gameMode == 'solo':
                    next(stats for stats in player.solo
                         if stats.season == match_season).aggregate(data[1])
                elif info.gameMode == 'duo':
                    next(stats for stats in player.duo
                         if stats.season == match_season).aggregate(data[1])
                elif info.gameMode == 'squad':
                    next(stats for stats in player.squad
                         if stats.season == match_season).aggregate(data[1])
                else:
                    player.event_games += 1

                dao.commit()
                Log.info('%r with %r added to %r' %
                         (record, match_stats, player))

        except Exception as e:
            dao.rollback()
            Log.error(str(e))
            return jsonify(result=False)

    player.updateTime = datetime.utcnow()
    dao.commit()

    return jsonify(result=True)
예제 #8
0
파일: update.py 프로젝트: rico0821/pubgi
def update_winner():
    """
    Update winner average statistics.

    """

    api_key = current_app.config['API_KEY']
    regions = current_app.config['REGIONS']
    modes = current_app.config['MODES']
    mapNames = current_app.config['MAP_NAMES']

    random_pick = dao.query(WinnerAverage).first()

    if not random_pick:
        new_average = [
            WinnerAverage(region, mode, mapName) for region in regions
            for mode in modes for mapName in mapNames
        ]
        try:
            dao.add_all(new_average)
            dao.commit()
            Log.info('New winner average stats added to DB!')

        except Exception as e:
            dao.rollback()
            Log.error(str(e))
            return jsonify(result=False)

    else:
        diff = datetime.utcnow() - random_pick.updateTime
        if diff.seconds < 82800:
            pass
            #return jsonify(result=False)

    averages = dao.query(WinnerAverage).all()

    winner_data = [(region, getWinnerData(region, api_key))
                   for region in regions]

    final_data = [{
        'region': data1[0],
        'mode': data2['gameMode'],
        'mapName': data2['mapName'],
        'kills': data2['kills'],
        'damage': data2['damageDealt'],
        'distance': data2['walkDistance'] + data2['rideDistance']
    } for data1 in winner_data for data2 in data1[1]]

    map_keys = [('Erangel_Main', 'erangel'), ('Desert_Main', 'miramar'),
                ('Savage_Main', 'sanhok')]

    df = pd.DataFrame(final_data)
    print(df)
    """     
    for region_winners in winner_data:
        for winner in region_winners:
            for mode in modes:
                for map_key in map_keys:
                    if winner[1]['gameMode']==mode and winner[1]['mapName']==map_key[0]:
                        average = dao.query(WinnerAverage).\
                                      filter_by(mode=mode).\
                             filter_by(mapName=map_key[1]).first()
    """

    return jsonify(result=True)
예제 #9
0
# -*- coding: utf-8 -*-
"""
    pubgi.pubgi_blueprint
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Module for pubgi Flask blueprint.
    
    :copyright: (c) 2018 by rico0821.
    
"""
from flask import Blueprint

from pubgi.pubgi_logger import Log


pubgi = Blueprint('pubgi', __name__, template_folder='../templates', static_folder='../static')

Log.info('static folder: %s' % pubgi.static_folder)
Log.info('template folder: %s' % pubgi.template_folder)
예제 #10
0
파일: __init__.py 프로젝트: rico0821/pubgi
def create_app(config_filepath='resource/config.cfg'):
    """
    Create Flask application for pubgi. 
    
    ARGS: config_filepath 
    
    """

    app = Flask(__name__)

    # CONFIG
    from pubgi.pubgi_config import pubgiConfig
    app.config.from_object(pubgiConfig)
    app.config.from_pyfile(config_filepath, silent=True)
    print_settings(app.config.items())

    # Initialise Log
    from pubgi.pubgi_logger import Log
    log_filepath = os.path.join(app.root_path, app.config['LOG_FILE_PATH'])
    Log.init(log_filepath=log_filepath)

    # Load SQLAlchemy DB, Migrate
    from flask_migrate import Migrate
    from pubgi.database import DBManager, dao
    db_filepath = os.path.join(app.root_path, app.config['DB_FILE_PATH'])
    db_url = app.config['DB_URL'] + db_filepath
    DBManager.init(db_url, eval(app.config['DB_LOG_FLAG']))
    DBManager.init_db()
    migrate = Migrate(app, dao)

    # Load MongoDB
    from pubgi.database import mongo
    mongo.init_app(app)

    # Load view functions
    from pubgi.controller import general
    from pubgi.controller import map_analysis
    from pubgi.controller import profile
    from pubgi.controller import search
    from pubgi.controller import statistics
    from pubgi.controller import update

    # Register blueprint
    from pubgi.pubgi_blueprint import pubgi
    app.register_blueprint(pubgi)

    # Register SessionInterface
    from pubgi.cache_session import SimpleCacheSessionInterface
    app.session_interface = SimpleCacheSessionInterface()

    # Common error handlers
    app.register_error_handler(404, not_found)
    app.register_error_handler(500, server_error)

    # Jinja methods and filters
    import pubgi.pubgi_jinja as pj
    app.jinja_env.globals['url_for_other_page'] = pj.url_for_other_page
    app.jinja_env.filters['translate_mode'] = pj.translate_mode
    app.jinja_env.filters['translate_map'] = pj.translate_map
    app.jinja_env.filters['datetimeformat'] = pj.format_datetime
    app.jinja_env.filters['timesince'] = pj.timesince
    app.jinja_env.filters['numberformat'] = pj.format_number
    app.jinja_env.filters['recently_updated'] = pj.recently_updated
    app.jinja_env.filters['grade'] = pj.grade

    return app
예제 #11
0
파일: search.py 프로젝트: rico0821/pubgi
def search():
    """
    Search for a player.
    
    FORM: search_word, region
    
    1. For each region:
        i) Check whether PUBG player ID for player with given name and region exists:
            (a) If so: check whether the player exists in DB.
        ii) If player is not found in DB:
            (a) Create new player and stats, append accordingly.
            (b) Commit.
    2. Search DB for players with given name, ignoring case sensitivity. 
        i) If length = 1, return redirect to profile page for that player.
    3. Render template for search page, passing in results.
    
    """

    api_key = current_app.config['API_KEY']
    regions = current_app.config['REGIONS']
    season = current_app.config['CURRENT_SEASON']
    query = request.form['search_word']
    region = request.form['region']

    query_lower = query.lower()

    exist = False
    player_id = getPlayerId(region, query, api_key)

    if player_id:
        exist = dao.query(Player).filter_by(pubgID=player_id).\
                                  filter_by(region=region).first()

    if player_id and not exist:
        try:
            new_player = Player(query, player_id, region)
            new_soloStats = SoloStats(season)
            new_duoStats = DuoStats(season)
            new_squadStats = SquadStats(season)
            dao.add_all(
                [new_player, new_soloStats, new_duoStats, new_squadStats])

            new_player.solo.append(new_soloStats)
            new_player.duo.append(new_duoStats)
            new_player.squad.append(new_squadStats)

            dao.commit()

            Log.info('New player %r added.' % new_player)

        except Exception as e:
            dao.rollback()
            Log.error(str(e))
            raise e

    results = dao.query(Player).filter(func.lower(Player.name)==query_lower).\
                                filter_by(region=region).all()

    if len(results) == 1:
        player = results[0]
        return redirect(
            url_for('.show_profile',
                    player_name=player.name,
                    region=player.region))

    return render_template('search.html', results=results, query=query)