Esempio n. 1
0
    async def update_attendance_task(self):
        scope = [
            'https://spreadsheets.google.com/feeds',
            'https://www.googleapis.com/auth/drive'
        ]
        creds = ServiceAccountCredentials.from_json_keyfile_name(
            defs.dir_path + '/client_secret.json', scope)
        client = gspread.authorize(creds)
        sheet = client.open("Hive Mind Giga-Sheet").worksheet(
            'Assessment Sheet')

        participants = get_participants()

        to_update = []
        col = raiders.get_col('attendance')

        for name in participants:
            attendance = round(participants[name]['attendance'] * 100)
            sheet_attendance = raiders.getRaiderAttribute(name, 'attendance')
            try:
                sheet_attendance = float(sheet_attendance.replace('%', ''))
            except ValueError:
                sheet_attendance = None
            if attendance != sheet_attendance:
                row = raiders.getRaiderAttribute(name, 'row')
                val = float(attendance) / 100
                to_update.append({'row': row, 'val': val})

        if len(to_update) > 0:
            min_row = min([u['row'] for u in to_update])
            max_row = max([u['row'] for u in to_update])
            first = gspread.utils.rowcol_to_a1(min_row, col)
            last = gspread.utils.rowcol_to_a1(max_row, col)

            cells = sheet.range('{}:{}'.format(first, last))

            for update in to_update:
                row = update['row'] - min_row
                cells[row].value = update['val']

            sheet.update_cells(cells)

        logger.log_event(
            'attendance_update',
            'update_attendance task finished with {} updates.'.format(
                len(to_update)))
Esempio n. 2
0
def get_message_brief(categories):
    message = 'Attendance:\n'
    prev_type = ''
    for category in categories:
        if category['type'] is 'class':
            if prev_type is 'player':
                message += '\n'
            message += '__**{}:**__\n'.format(category['title'])

        for name, player_attendance in category['attendance']:
            if raiders.getRaiderAttribute(name, 'team') == 'team red':
                message += ':red_circle:'
            if raiders.getRaiderAttribute(name, 'team') == 'team blue':
                message += ':blue_circle:'

            if category['type'] is 'player':
                message += '__**{}**__ - '.format(name.capitalize())
            else:
                message += '**{}** - '.format(name.capitalize())

            raids = player_attendance['raids']

            attended_raids = sum(
                [len(raids[raid]['raids']) for raid in raids.keys()])

            if (attended_raids == 0):
                message += 'no raids registered.\n'
            else:
                attendance = round(player_attendance['attendance'] * 100)

                missed_raids = sum([
                    len(raids[raid]['missed_raids']) for raid in raids.keys()
                ])
                signed_raids = sum([
                    len(raids[raid]['signed_raids']) for raid in raids.keys()
                ])

                message += 'attendance: **{}%**, attended raids: **{}**, signed off: **{}**, didn\'t sign off: **{}**\n'.format(
                    attendance, attended_raids, signed_raids, missed_raids)

        if category['type'] is 'class':
            message += '\n'

        prev_type = category['type']
    return message
Esempio n. 3
0
def get_fight_summary(fight, metrics, report_info):
    summary = {
        'fight': fight,
        'parses': {},
        'report': {
            'title': report_info['title'],
            'id': report_info['id'],
            'start': report_info['start']
        }
    }
    for metric in metrics:
        url_dps = 'https://classic.warcraftlogs.com/reports/' + report_info[
            'id'] + '#fight=' + str(
                fight['id']) + '&view=rankings&playermetric=' + metric

        chrome_options = Options()
        chrome_options.add_argument('--headless')
        chrome_options.add_experimental_option('excludeSwitches',
                                               ['enable-logging'])

        print(defs.timestamp(), '*' + url_dps)
        driver = webdriver.Chrome(options=chrome_options)
        driver.get(url_dps)

        element = WebDriverWait(driver, 60).until(
            EC.presence_of_element_located((By.CLASS_NAME, "primary")))
        fight['deaths'] = element.text

        element = WebDriverWait(driver, 60).until(
            EC.presence_of_element_located((By.CLASS_NAME, "player-table")))
        row_elements = element.find_elements_by_tag_name('tr')[1:]

        for row_element in row_elements:
            row_stats = {}
            cell_elements = row_element.find_elements_by_tag_name('td')

            name = cell_elements[4].find_element_by_tag_name(
                'a').get_attribute('innerHTML').lower()
            role = raiders.getRaiderAttribute(name, 'role')

            if ((metric == 'dps' and role in ['melee', 'ranged'])
                    or (metric == 'hps' and role == 'healer')):
                row_stats['percentile'] = int(cell_elements[0].text)
                row_stats['rank'] = cell_elements[1].text
                row_stats['out_of'] = int(cell_elements[2].text.replace(
                    ',', ''))
                row_stats['best_rank'] = cell_elements[3].text
                row_stats['dps'] = float(cell_elements[5].text.replace(
                    ',', ''))
                row_stats['ilvl'] = int(cell_elements[6].text)
                row_stats['ipercentile'] = int(cell_elements[7].text)

                summary['parses'][name] = row_stats

    driver.close()
    driver.quit()
    return summary
Esempio n. 4
0
    async def signoffs(self, ctx, *args):
        logger.log_command(ctx, args)
        try:
            await ctx.message.delete()
        except:
            pass

        if len(args) is 1: query_date = get_date_from_string(args[0])
        elif len(args) is 0:
            query_date = datetime.combine(date.today(), time())
        else:
            await ctx.send(
                'This command takes at most one argument: the date. Use \'!help {}\' for help on how to use this command.'
                .format(ctx.command.name))
            return

        epoch = datetime(1970, 1, 1)
        timestamp = int((query_date - epoch).total_seconds() * 1000)

        signoffs = schedule_file.get('signoffs', on_error=[])

        names = [
            so['name'].lower().capitalize() for so in signoffs
            if so['start'] <= timestamp <= so['end']
        ]

        message = 'Sign offs: ' + ', '.join(names) + '\n'

        roles_so = {}
        for name in names:
            role = raiders.getRaiderAttribute(name, 'role')
            roles_so[role] = roles_so.get(role, 0) + 1

        all_raiders = raiders.getRaiders()
        roles_at = {}
        for raider in all_raiders:
            if not raider.capitalize() in names:
                role = all_raiders[raider]['role']
                roles_at[role] = roles_at.get(role, 0) + 1

        roles = [
            '{}: {}'.format(role.capitalize(), roles_so[role])
            for role in roles_so
        ]
        message += 'Signed off ({}): '.format(sum(
            roles_so.values())) + ', '.join(roles) + '\n'
        roles = [
            '{}: {}'.format(role.capitalize(), roles_at[role])
            for role in roles_at
        ]
        message += 'Attending ({}): '.format(sum(
            roles_at.values())) + ', '.join(roles)

        await ctx.send(message)
Esempio n. 5
0
def make_attendance_plot(participants, figurename):
    attendances = []

    for p in participants:
        attended_raids = len(participants[p]['raids'])
        missed_raids = len(participants[p]['missed_raids'])
        attendance = attended_raids / (attended_raids + missed_raids)

        attendances.append([p, attendance])

    attendances.sort(key=lambda x: x[1], reverse=True)
    names = [entry[0] for entry in attendances]
    attendances = [entry[1] * 100 for entry in attendances]

    cols = [
        defs.colors[raiders.getRaiderAttribute(name, 'class')]
        for name in names
    ]

    y_pos = np.arange(len(names))

    names = [
        '{} ({}%)'.format(name, round(attendances[i], 1))
        for i, name in enumerate(names)
    ]

    _, ax = plt.subplots(figsize=(20, 15))

    ax.barh(y_pos,
            attendances,
            color=cols,
            edgecolor='white',
            linestyle='-',
            linewidth=0)
    ax.set_yticks(y_pos)
    ax.set_yticklabels(names)
    ax.invert_yaxis()  # labels read top-to-bottom
    ax.set_xlabel('Attendance [%]', color='white')

    plt.savefig(defs.dir_path + '/' + figurename)
Esempio n. 6
0
    async def cmd_attendance(self, ctx, *args):
        logger.log_command(ctx, args)
        await ctx.message.delete()
        args = list(args)
        options, args = defs.get_options(args)

        days = None
        months = None

        digits = [i for i, arg in enumerate(args) if arg.isdigit()]

        if len(digits) > 1:
            await ctx.send(
                'Arguments \'{}\' not understood. Please use \'!help {}\' for help on how to use this command.'
                .format(args, ctx.command.name),
                delete_after=self.error_messages_lifetime)
            return

        if (len(args) - 1) in digits:
            months = int(args[-1])
            args = args[:-1]

        if (len(args) - 2) in digits:
            last_arg = args[-1].lower()
            if last_arg in ['day', 'days']:
                days = int(args[-2])
                args = args[:-2]

            elif last_arg in ['month', 'months']:
                months = int(args[-2])
                args = args[:-2]

            else:
                await ctx.send(
                    'Argument \'{}\' not understood. Please use \'!help {}\' for help on how to use this command.'
                    .format(args[-1], ctx.command.name),
                    delete_after=self.error_messages_lifetime)
                return

        team = ''
        if ('-r' in options): team = 'team red'
        if ('-b' in options): team = 'team blue'

        categories = []
        for arg in args:
            if (arg.lower()[-1] is 's') and (arg.lower()[:-1] in defs.classes):
                arg = arg.lower()[:-1]
            if arg.lower() in defs.classes:
                class_raiders = raiders.all_with_attribute(
                    'class', arg.lower())
                class_names = [
                    raider for raider in class_raiders
                    if raiders.getRaiderAttribute(raider, 'team') == team
                    or team == ''
                ]
                category = {
                    'type': 'class',
                    'title': arg.capitalize() + 's',
                    'attendance': class_names
                }
            else:
                category = {'type': 'player', 'attendance': [arg]}
            categories.append(category)

        for category in categories:
            category['attendance'] = [(name,
                                       get_participant(name.capitalize(),
                                                       days=days,
                                                       months=months))
                                      for name in category['attendance']]
            category['attendance'].sort(key=lambda x: len(x[1]['raids']),
                                        reverse=True)
            category['attendance'].sort(key=lambda x: x[1]['attendance'],
                                        reverse=True)

        message = get_message_brief(categories)

        await ctx.send(message)
Esempio n. 7
0
def get_participants(update_attendance=True, days=None, months=None):
    attendance = get_attendance(update_attendance, days, months)
    participants = {}

    # Count attendance
    for report in attendance:
        for participant in report['participants']:
            team = raiders.getRaiderAttribute(participant, 'team')
            if team == report['team']:
                participants.setdefault(participant, {})
                for raidname in report['raids']:
                    participants[participant].setdefault(
                        raidname, {'raids': []})
                    participants[participant][raidname]['raids'].append(
                        report['start'])

    for name in participants:
        for raid in participants[name]:
            participants[name][raid]['first_raid'] = min(
                participants[name][raid]['raids'])

    # Count absence
    for name in participants:
        for raid_name in participants[name]:
            missed_raids = []
            signed_raids = []
            reports = [
                report for report in attendance if raid_name in report['raids']
            ]
            for report in reports:
                start = report['start']
                if not start in participants[name][raid_name]['raids']:
                    if start > participants[name][raid_name]['first_raid']:
                        if (schedule.has_signed_off(name, start)):
                            signed_raids.append(start)
                        else:
                            missed_raids.append(start)
            participants[name][raid_name]['missed_raids'] = missed_raids
            participants[name][raid_name]['signed_raids'] = signed_raids

    result = {}

    for name in participants:
        total_attended = 0
        total_missed = 0
        total_signed = 0

        for raid in participants[name]:
            raid_info = participants[name][raid]

            total_attended += len(raid_info['raids'])
            total_missed += len(raid_info['missed_raids'])
            total_signed += len(raid_info['signed_raids'])

            try:
                raid_info['attendance'] = len(raid_info['raids']) / (
                    len(raid_info['raids']) + len(raid_info['missed_raids']) +
                    len(raid_info['signed_raids']))
            except ZeroDivisionError:
                raid_info['attendance'] = -1

            try:
                raid_info['sign_rate'] = len(raid_info['signed_raids']) / (len(
                    raid_info['signed_raids']))
            except ZeroDivisionError:
                raid_info['sign_rate'] = 1

        try:
            att = total_attended / (total_attended + total_missed +
                                    total_signed)
        except ZeroDivisionError:
            att = -1

        try:
            sr = total_signed / (total_missed + total_signed)
        except ZeroDivisionError:
            sr = 1

        result[name] = {
            'attendance': att,
            'sign_rate': sr,
            'raids': participants[name]
        }

    return result
Esempio n. 8
0
def plot_fight(f, image_path):
    fight = f['fight']
    parses = f['parses']

    melee_parses = []
    ranged_parses = []
    healer_parses = []

    for name in parses:
        if (raiders.getRaiderAttribute(name, 'role') == 'ranged'):
            ranged_parses.append(name)
        elif (raiders.getRaiderAttribute(name, 'role') == 'melee'):
            melee_parses.append(name)
        elif (raiders.getRaiderAttribute(name, 'role') == 'healer'):
            healer_parses.append(name)

    group_names = ['Melee', 'Ranged', 'Healers']
    metric = ['DPS', 'DPS', 'HPS']

    tables = ""
    for i, current_parses in enumerate(
        [melee_parses, ranged_parses, healer_parses]):
        rows = ""
        for j, name in enumerate(current_parses[:3]):
            parse = parses[name]
            percentile = parse['percentile']
            class_color = defs.colors[raiders.getRaiderAttribute(
                name, 'class')]
            rows += ranking_html_factory.get_row(
                number=str(j + 1),
                name=name.capitalize(),
                name_color=class_color,
                parse=str(percentile),
                parse_color=defs.getParseColor(percentile),
                rank=parse['rank'],
                dps=str(parse['dps']),
            )

        avg_parse = 0
        avg_rank = 0
        avg_dps = 0

        n = len(current_parses)

        for name in current_parses:
            avg_parse += parses[name]['percentile'] / n
            avg_rank += int(parses[name]['rank'].replace('~', '')) / n
            avg_dps += parses[name]['dps'] / n

        avg_parse = round(avg_parse, 1)
        avg_rank = int(avg_rank)
        avg_dps = round(avg_dps, 1)

        tables += ranking_html_factory.get_table(
            group_name=group_names[i],
            metric=metric[i],
            rows=rows,
            avg_parse=str(avg_parse),
            avg_parse_color=defs.getParseColor(avg_parse),
            avg_rank=str(avg_rank),
            avg_dps=str(avg_dps))

    html = ranking_html_factory.get_html(fight['name'], tables)

    html_path = defs.dir_path + '/boss_summaries/' + fight['name'] + '.html'
    with open(html_path, 'w') as file:
        file.write(html)

    chrome_options = Options()
    chrome_options.add_argument('--headless')
    chrome_options.add_experimental_option('excludeSwitches',
                                           ['enable-logging'])

    driver = webdriver.Chrome(options=chrome_options)
    driver.get('file:///' + html_path)

    body = driver.find_element_by_tag_name('body')
    size = body.size
    driver.set_window_size(size['width'], size['height'])

    driver.save_screenshot(image_path)

    driver.close()
    driver.quit()