Ejemplo n.º 1
0
async def get_units_trained(keys, context):
    """Get counts of units trained bucketed by interval."""
    where, values = compound_where(keys, ('match_id', 'player_number'))
    query = """
        select player_number, x.match_id, objects.id as object_id, name, count, inter as timestamp, extract(epoch from inter)::integer as timestamp_secs
        from
        (
            select oi.match_id, player_number, ois.dataset_id,
            case
                when ois.object_id=any(:villager_ids) then :normalized_villager_id
                when ois.object_id=any(:monk_ids) then :normalized_monk_id
                else ois.object_id
            end as obj_id,
            to_timestamp(floor((extract('epoch' from created) / :interval )) * :interval) as inter,
            count(ois.instance_id) as count
            from object_instance_states as ois join
            (
                select min(id) as id,min(timestamp) from object_instance_states
                where ({}) and player_number > 0 and class_id=70 and not (object_id=any(:herdable_ids))
                group by instance_id
            ) as s on ois.id=s.id
            join object_instances as oi on ois.instance_id=oi.instance_id and oi.match_id=ois.match_id
            where oi.created > '00:00:10'
            group by player_number, obj_id, ois.dataset_id, oi.match_id, inter
            order by count desc
        ) as x join objects on x.obj_id=objects.id and x.dataset_id=objects.dataset_id
        order by timestamp, name
    """.format(where)
    results = await context.database.fetch_all(query, values=dict(values, interval=300, **NORMALIZE_VALUES))
    return by_key(results, ('match_id', 'player_number'))
Ejemplo n.º 2
0
async def odds_query(database,
                     teams,
                     type_id,
                     match_filters=None,
                     civ_filter=False,
                     user_filter=False):  # pylint: disable=too-many-arguments, too-many-locals
    """Run a query with odds constraints."""
    start_time = time.time()
    team_size = 'v'.join(str(len(t)) for t in teams.values())
    values = {'team_size': team_size, 'type_id': type_id}

    match_query = """
        select matches.id, players.winner, players.{}
            from matches join players on matches.id=players.match_id
    """
    for i, team in teams.items():
        if user_filter and civ_filter:
            key = 'civilization_id'
            keys = [(p['user_id'], p['civilization_id']) for p in team]
            player_filters, player_values = compound_where(
                keys, ('players.user_id', 'players.civilization_id'))
            values.update(player_values)

        elif civ_filter:
            key = 'civilization_id'
            player_filters = " players.civilization_id=any(:civilization_ids_{})".format(
                i)
            values.update({
                'civilization_ids_{}'.format(i):
                [p['civilization_id'] for p in team]
            })

        elif user_filter:
            key = 'user_id'
            player_filters = " players.user_id=any(:user_ids_{})".format(i)
            values.update(
                {'user_ids_{}'.format(i): [p['user_id'] for p in team]})

        team_query = """
            select match_id from players
            where {}
            group by match_id, team_id
            having count(distinct players.{}) = {}
        """.format(player_filters, key, len({p[key]
                                             for p in team}))
        match_query += " join ({0}) as t{1} on matches.id=t{1}.match_id".format(
            team_query, i)

    match_query += " where matches.team_size=:team_size and matches.type_id=:type_id"
    match_query = match_query.format(key)

    if match_filters is not None:
        match_query += ' and ' + match_filters[0]
        values.update(match_filters[1])

    result = await database.fetch_all(match_query, values=values)
    result = compute_odds(by_key(result, 'id').values(), key, teams)
    LOGGER.debug("computed odds in %f", time.time() - start_time)
    return result
Ejemplo n.º 3
0
async def get_research_by_player(keys, context):
    """Get researches."""
    where, values = compound_where(keys, ('match_id', 'player_number'))
    query = """
        select name, started::interval(0), finished::interval(0), player_number, match_id,
        extract(epoch from started)::integer as started_secs, extract(epoch from finished)::integer as finished_secs
        from research join technologies on research.technology_id=technologies.id and research.dataset_id=technologies.dataset_id
        where {}
        order by started
    """.format(where)
    results = await context.database.fetch_all(query, values=values)
    return by_key(results, ('match_id', 'player_number'))
Ejemplo n.º 4
0
async def get_villager_allocation(keys, context):
    """Get villager allocation per player bucketed by interval."""
    where, values = compound_where(keys, ('match_id', 'player_number'))
    query = """
        select
            vils.match_id, vils.player_number, vils.res as name, buckets.inter as timestamp,
            extract(epoch from buckets.inter)::integer as timestamp_secs, count(distinct vils.instance_id)
        from (
            with subquery as (
                select row_number() over (order by x.instance_id, inter), x.match_id, ois.player_number, x.instance_id, x.inter, objects.name, oi.created, oi.destroyed,
                case
                    when object_id = any(:food_vils) then 'Food'
                    when object_id = any(:wood_vils) then 'Wood'
                    when object_id = any(:gold_vils) then 'Gold'
                    when object_id = any(:stone_vils) then 'Stone'
                    else 'idle'
                end as res
                from (
                    select max(id) as id, match_id, instance_id, make_interval(secs => floor((extract('epoch' from timestamp) / :interval )) * :interval) as inter
                    from object_instance_states
                    where object_id = any(:resource_vils)
                    and ({where})
                    group by instance_id, inter, match_id
                ) as x join object_instance_states as ois on x.match_id=ois.match_id and x.id=ois.id
                join object_instances oi on oi.match_id=ois.match_id and oi.instance_id=ois.instance_id
                join objects on objects.id=ois.object_id and objects.dataset_id=ois.dataset_id
            )
            select f.*, l.inter as next from
            subquery as f left join subquery as l on f.row_number=l.row_number-1 and f.instance_id=l.instance_id
        ) as vils join (
            select make_interval(secs => floor((extract('epoch' from timestamp) / :interval )) * :interval) as inter
            from object_instance_states as ois
            where ({where})
            group by inter
            order by inter
        ) as buckets on
            vils.inter <= buckets.inter and (vils.next is null or vils.next > buckets.inter) and
            vils.created <= (buckets.inter + (:interval * interval '1 second')) and
            (vils.destroyed is null or vils.destroyed >= buckets.inter)
        group by vils.match_id, vils.player_number, vils.res, buckets.inter
        order by buckets.inter, vils.player_number, vils.res
    """.format(where=where)
    results = await context.database.fetch_all(query, values=dict(
        values,
        resource_vils=RESOURCE_VILLAGER_IDS,
        food_vils=FOOD_VILLAGER_IDS,
        wood_vils=WOOD_VILLAGER_IDS,
        gold_vils=GOLD_VILLAGER_IDS,
        stone_vils=STONE_VILLAGER_IDS,
        interval=300
    ))
    return by_key(results, ('match_id', 'player_number'))
Ejemplo n.º 5
0
async def get_transactions(keys, context):
    """Get transactions."""
    where, values = compound_where(keys, ('players.match_id', 'player_number'))
    query = """
        select
            players.match_id, timestamp::interval(0), extract(epoch from timestamp)::integer as timestamp_secs,
            player_number,
            case when action_id=123 then 'Gold' else resources.name end as sold_resource,
            (amount * 100) as sold_amount,
            case when action_id=123 then resources.name else 'Gold' end as bought_resource
        from players left join transactions on transactions.match_id=players.match_id and transactions.player_number = players.number
        join resources on transactions.resource_id=resources.id
        where {}
        order by timestamp
    """.format(where)
    results = await context.database.fetch_all(query, values=values)
    return by_key(results, ('match_id', 'player_number'), defaults=keys)
Ejemplo n.º 6
0
async def get_timeseries(keys, context):
    """Get timeseries data."""
    where, values = compound_where(keys, ('match_id', 'player_number'))
    query = """
        select
            player_number, match_id, timestamp, population, military,
            percent_explored, relic_gold, total_food, total_gold, total_stone,
            total_wood, trade_profit, value_current_units, value_lost_buildings,
            value_lost_units, value_objects_destroyed, value_spent_objects,
            value_spent_research, extract(epoch from timestamp)::integer as timestamp_secs,
            tribute_sent, tribute_received, kills, deaths, razes,
            kills - deaths as  kd_delta,
            case when value_lost_units+value_lost_buildings > 0 then value_objects_destroyed/(value_lost_units+value_lost_buildings)::float else 0.0 end as damage,
            case when value_spent_research > 100 then value_objects_destroyed/(value_spent_research)::float * 100 else 0.0 end as roi
        from timeseries
        where {}
        order by timestamp
    """.format(where)
    results = await context.database.fetch_all(query, values=values)
    return by_key(results, ('match_id', 'player_number'))
Ejemplo n.º 7
0
async def get_player(keys, context):
    """Get basic player data."""
    where, values = compound_where(keys, ('match_id', 'number'))
    query = """
        select
            players.match_id, players.number, players.name, players.winner,  players.color_id,
            players.user_id, players.platform_id, players.user_name
        from players
        where {}
    """.format(where)
    results = await context.database.fetch_all(query, values=values)
    return {(player['match_id'], player['number']):
            dict(match_id=player['match_id'],
                 number=player['number'],
                 name=player['name'],
                 color_id=player['color_id'],
                 winner=player['winner'],
                 user=dict(id=player['user_id'],
                           name=player['user_name'],
                           platform_id=player['platform_id']))
            for player in results}