예제 #1
0
    def do_body(self, args):
        """Render the HTMl for the goal scorer tally"""
        year = self.get_year(args)
        mem_key = ScorersPage.get_mem_key(year)
        scorer_page = memcache.get(mem_key)
        if scorer_page is None:
            if year == ALL_YEARS:
                players = Player.all()
            else:
                players = [
                    t.player for t in TeamList.gql('WHERE year = :1', year)
                ]

            scorers = []
            for p in players:
                tally = 0
                for g in p.goal_set:
                    round = g.result.round
                    if (year == ALL_YEARS
                            or year == round.date.year) and round.num > 0:
                        # Only count real goals - negative rounds are trials
                        tally += g.count
                if tally > 0:
                    scorers.append((p.get_short_name(), tally))
            scorers.sort(self.sort_scores)
            data = {
                'scorers': scorers,
            }

            tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, 'scorers.html')
            scorer_page = template.render(tpath, data)
            memcache.set(mem_key, scorer_page)
        self.response.out.write(scorer_page)
예제 #2
0
    def do_player_list(self, args, manage_mode=False):
        """Render the HTML for a list of players"""
        year = self.get_year(args)
        if manage_mode:
            mem_key = PlayerPage.get_manage_list_mem_key(year)
        else:
            mem_key = PlayerPage.get_list_mem_key(year)
        player_div = memcache.get(mem_key)
        if player_div is None:
            data = {
                'url_args': args,
            }
            if year == ALL_YEARS:
                data['players'] = Player.gql(
                    'ORDER BY last_name ASC, first_name ASC')
            else:
                data['players'] = [
                    p.player for p in TeamList.gql('WHERE year = :1', year)
                ]
                data['players'].sort(self.sort_players)

            tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, 'players.html')
            player_div = template.render(tpath, data)
            memcache.set(mem_key, player_div)
        self.response.out.write(player_div)
예제 #3
0
    def do_body(self, args):
        year = self.get_year(args)
        if year == ALL_YEARS:
            players = Player.all()
        else:
            players = [t.player for t in TeamList.gql('WHERE year = :1', year)]
        players.sort(self.sort_players)
        data = {
            'players': players,
        }

        tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, 'manage_protected.html')
        protected_page = template.render(tpath, data)
        self.response.out.write(protected_page)
예제 #4
0
    def do_body(self, args):
        """Render the HTML for all the results, and provide enough information to edit an game"""
        data = {
            'url_args': args,
        }
        year = self.get_year(args)
        if year == ALL_YEARS:
            data['rounds'] = Round.gql('ORDER BY date ASC')
        else:
            data['rounds'] = Round.gql('WHERE year = :1 ORDER BY date ASC',
                                       year)
        tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, 'rounds.html')
        self.response.out.write(template.render(tpath, data))

        data = {
            'url_args': args,
        }

        # Get the full data for the given round so they can edit it
        if args.has_key('round'):
            round_num = args['round']
            round_key = Round.get_key(round_num, year)
            result_key = Result.get_key(round_num, year)
            if round_key != '':
                curr_round = Round.get_by_key_name(round_key)
                if curr_round:
                    data['players'] = [
                        p.player for p in TeamList.gql('WHERE year = :1',
                                                       curr_round.date.year)
                    ]
                    data['players'].sort(self.sort_players)
                    data['round'] = curr_round
                curr_result = Result.get_by_key_name(result_key)
                if curr_result:
                    data['result'] = curr_result
                    if curr_result.other_goals == 0:
                        curr_result.other_goals = None
                    if curr_result.own_goals == 0:
                        curr_result.own_goals = None

                    #if curr_result.deewhy_forfeit:
                    #	curr_result.deewhy_goals = 0
                    #	curr_result.opponent_goals = 5
                    #elif curr_result.opponent_forfeit:
                    #	curr_result.deewhy_goals = 5
                    #	curr_result.opponent_goals = 0

        tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, 'manage_results.html')
        self.response.out.write(template.render(tpath, data))
예제 #5
0
    def do_body(self, args):
        """Render a given year's item summary. Makes no sense for multi-year."""
        year = self.get_year(args)
        mem_key = CommonItemPage.get_mem_key(self.type, year)
        item_page = memcache.get(mem_key)
        if item_page is None:
            items = self.data_class.gql('WHERE year = :1', year)
            items = [i for i in items]
            items.sort(self.sort_tuple)
            remaining = [
                t.player.get_short_name()
                for t in TeamList.gql('WHERE year = :1', year)
            ]

            rounds = []
            for i in items:
                round = i.round
                # Only display entries that already have a result
                if round.result.get() is not None:
                    caption = round.caption
                    if not caption:
                        caption = round.num

                    if self.get_person(i) in self.data_class.OTHERS:
                        person = self.data_class.OTHERS_FRIENDLY[
                            self.get_person(i)]
                    else:
                        person = i.player_ref.get_short_name()
                        try:
                            remaining.remove(person)
                        except ValueError:
                            # It was already removed before
                            pass
                    rounds.append((caption, person))
            if len(remaining) > 0:
                remaining_str = ', '.join(remaining)
            else:
                remaining_str = 'Nobody'
            data = {
                'rounds': rounds,
                'remaining': remaining_str,
                'url_args': args,
            }

            tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, self.template_file)
            item_page = template.render(tpath, data)
            memcache.set(mem_key, item_page)
        self.response.out.write(item_page)
예제 #6
0
    def do_body(self, args):
        """Render the HTML for the page containing private details for everybody currently in the team."""
        mem_key = ProtectedPage.get_mem_key()
        protected_page = None  #memcache.get(mem_key)
        if protected_page is None:
            players = [
                t.player for t in TeamList.gql('WHERE year = :1',
                                               datetime.now().year)
            ]  # Always this year
            players.sort(self.sort_players)
            data = {
                'players': players,
            }

            tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, 'protected.html')
            protected_page = template.render(tpath, data)
            memcache.set(mem_key, protected_page)
        self.response.out.write(protected_page)
예제 #7
0
 def do_body(self, args):
     """Render the HTML for all the items, and provide enough information to edit one of them."""
     updated_args = dict(args)
     year = self.get_year(args)
     updated_args['year'] = year
     data = {
         'url_args': updated_args,
     }
     if year == ALL_YEARS:
         data['rounds'] = Round.gql('ORDER BY date ASC')
         data['players'] = Player.gql(
             'ORDER BY last_name ASC, first_name ASC')
     else:
         data['rounds'] = Round.gql('WHERE year = :1 ORDER BY date ASC',
                                    int(year))
         data['players'] = [
             p.player for p in TeamList.gql('WHERE year = :1', int(year))
         ]
         data['players'].sort(self.sort_players)
     tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, self.template_file)
     self.response.out.write(template.render(tpath, data))
예제 #8
0
def quick_stalk(url):
    """
    Stalk all players in a match, requires a direct link to the match on challengermode
    :param url: Str, a link that shows a single match on challengermode
    :return: TeamList, containing both teams in the match
    """

    logger.debug("Beginning challengermode quick stalk for " + url)
    driver = open_session()
    driver.get(url)

    time.sleep(3)
    challenger_soup = bs4.BeautifulSoup(driver.page_source, features="html.parser")
    quit_session(driver)

    team_containers = challenger_soup.find_all('div', class_="col-md-6")
    title = challenger_soup.select("#arena-wrap > div.pos--rel.flx--1-1-auto.w--100 > div.m-b--base > div:nth-child(3) > div.pos--rel.z--999 > div.cm-arena-wrap.arena-padding-horizontal > div.ta--center.m-v--medium.p-t--base--sm.cm-text-shadow > div.h1.lh--title.ellipsis > div > a")[0].text

    teams = []
    for team_container in team_containers:
        team_name_block = team_container.find('div', class_="dis--none dis--blk--sm m-b--minimum")
        if team_name_block is None:
            team_name_block = team_container.find('div', class_="dis--none dis--blk--sm m-b--minimum m-t--medium")
        team_name_raw = team_name_block.text
        team_name_list = team_name_raw.split(" ")
        team_name = "".join(team_name_list[:len(team_name_list)-25]).strip()

        player_opggs_htmls = team_container.find_all('a', class_="link-white-dark")
        player_opggs = []
        for player_opggs_html in player_opggs_htmls:
            player_opggs.append(player_opggs_html['href'])
        players = []
        for player_opgg in player_opggs:
            rest, sum_name = player_opgg.split("=")
            players.append(Player(sum_name.replace("+", " ")))
        teams.append(Team(team_name, players))

    return TeamList(title.strip(), teams)
def stalk_group(url):
    """
    Returns a TeamList object for all teams in the group behind the given url.
    :param url: Str, a link to a group in a SINN League
    :return: TeamList, a TeamList object containing all teams of the group
    """

    logger.debug("Beginning sinn league group stalk for " + url)
    # open web session
    page = requests.get(url)

    # Select Rangliste Container and find division name
    soup = bs4.BeautifulSoup(page.text, features="html.parser")
    list_container = soup.find(
        'table', class_="table table-fixed-single table-responsive")
    # div_name = driver.find_element_by_xpath("//*[@id=\"container\"]/div/h1").text
    div_name = soup.select("#container > div > h1")[0].text

    # extract all team-links
    links = [link["href"] for link in list_container.find_all("a", href=True)]
    links = list(dict.fromkeys(links))

    # create task Q over all team-links
    single_tasks = []
    for link in links:
        single_task = task_queue.SingleTask(stalk_team, link)
        single_tasks.append(single_task)
    task_group = task_queue.TaskGroup(single_tasks, "stalk: " + div_name)

    teams = task_queue.submit_task_group(task_group)

    # return results
    for team in teams:
        if team is None:
            teams.remove(team)
    return TeamList(div_name, teams)
예제 #10
0
    def do_body(self, args):
        """Generate the HTML email if there is an upcoming game"""
        day_skip = 2
        if args.has_key('days'):
            try:
                day_skip = int(args['days'])
            except:
                pass
        admin_address = '*****@*****.**'
        curr_date = datetime.now()
        start_date = curr_date.replace(hour=0, minute=0,
                                       second=0) + timedelta(days=day_skip)
        end_date = curr_date.replace(hour=0, minute=0,
                                     second=0) + timedelta(days=day_skip + 1)

        # Find all the games that are within the given date range - really only expect one, behaviour
        # could end up a little strange if there's multiple...
        query = Round.gql('WHERE date >= :1 AND date <= :2', start_date,
                          end_date)
        curr_round = query.get()
        logging.debug('WHERE date >= %s AND date <= %s' %
                      (start_date, end_date))
        logging.debug(curr_round)

        if curr_round:
            data = {
                'current': curr_round,
            }

            tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, 'mailer.html')
            email_content = template.render(tpath, data)
            self.response.out.write(
                email_content)  # Print the content as an added debug

            players = [
                p.player
                for p in TeamList.gql('WHERE year = :1', curr_round.date.year)
            ]
            non_admins = []
            admin = ''
            for p in players:
                details = '%s %s<%s>' % (p.first_name, p.last_name, p.email)
                if p.email == admin_address:
                    admin = details
                else:
                    non_admins.append(details)
            recipients = ','.join(non_admins)
            cc_recipients = admin  # working around a server bug where cron emails fail when sent to me!
            #recipients = 'Test Guy<*****@*****.**>' % (curr_date.strftime('%A %d %B %I:%M'))	# To make sure tests don't go out!
            logging.debug('Sending to ' + recipients)
            """
			recipients = ','.join([
				'Adam1<*****@*****.**>',
				'Adam2<*****@*****.**>',
				])
			logging.debug('Really sending to ' + recipients)
			"""

            caption = curr_round.caption
            if not caption:
                caption = 'Round ' + ` int(curr_round.num) `
            kickoffStr = ` int(curr_round.time.strftime('%I')) `
            if curr_round.time.minute > 0:
                kickoffStr += ':' + curr_round.time.strftime('%M')
            kickoffStr += curr_round.time.strftime('%p')
            subject = caption + ' - ' + curr_round.date.strftime(
                '%A %d %B') + ' at ' + kickoffStr

            message = mail.EmailMessage()
            message.subject = subject
            message.sender = 'Dee Why AL5 Team Page<*****@*****.**>'
            message.to = recipients
            message.cc = cc_recipients
            # Too lazy to add BCC recipients as a UI option so just add them here
            message.bcc = '*****@*****.**'
            message.html = email_content
            message.check_initialized()
            message.send()
예제 #11
0
    def post(self, base_url, extra):
        """Save the data posted about the result from the HTML form"""
        try:
            curr_round = None
            round_num = int(self.request.get('round_num'))
            year = int(self.request.get('year'))
            round_key = Round.get_key(round_num, year)
            if round_key:
                curr_round = Round.get_by_key_name(round_key)

            if curr_round:
                # Quite a few cached pages depend upon this output, need to delete them all
                # - Removing this page from the summary
                memcache.delete(PlayerPage.get_draw_mem_key(year))
                memcache.delete(PlayerPage.get_draw_mem_key(ALL_YEARS))
                # - Disabling the options for this page for each player
                for t in TeamList.gql('WHERE year = :1', year):
                    memcache.delete(
                        PlayerPage.get_player_mem_key(t.player.db_key, year))
                # - Changing the result and who scored
                memcache.delete(ResultsPage.get_mem_key(year))
                memcache.delete(ResultsPage.get_mem_key(ALL_YEARS))
                # - Changing the number of goals
                memcache.delete(ScorersPage.get_mem_key(year))
                memcache.delete(ScorersPage.get_mem_key(ALL_YEARS))
                # - Triggering previously suppressed rounds for the beer and shirts
                memcache.delete(BeerPage.get_mem_key('beer', year))
                memcache.delete(BeerPage.get_mem_key('beer', ALL_YEARS))
                memcache.delete(ShirtsPage.get_mem_key('shirts', year))
                memcache.delete(ShirtsPage.get_mem_key('shirts', ALL_YEARS))

                args = {
                    'year': year,
                    'key_name': Result.get_key(round_num, year),
                    'round': curr_round,
                }

                deewhy_forfeit = self.request.get('deewhy_forfeit')
                opponent_forfeit = self.request.get('opponent_forfeit')
                if not (deewhy_forfeit or opponent_forfeit):
                    # Regular operation - read the goal counts
                    args['deewhy_goals'] = self.get_goals('deewhy_goals')
                    args['opponent_goals'] = self.get_goals('opponent_goals')
                    args['other_goals'] = self.get_goals('other_goals')
                    args['own_goals'] = self.get_goals('own_goals')
                elif deewhy_forfeit is not None and self.request.get(
                        'deewhy_forfeit') == 'on':
                    # No goals in a forfeit
                    args['deewhy_forfeit'] = True
                elif opponent_forfeit is not None and self.request.get(
                        'opponent_forfeit') == 'on':
                    # No goals in a forfeit
                    args['opponent_forfeit'] = True
                curr_result = Result(**args)
                curr_result.put()

                # Need to delete any existing scorers for this round - otherwise orphaned goals will stuff up the tallies
                for scorer in curr_result.scorer_set:
                    scorer.delete()

                if not (deewhy_forfeit or opponent_forfeit):
                    for post_key in self.request.POST.keys():
                        # Each goal scorer in the game needs a separate record
                        if post_key.startswith('goals_'):
                            player = Player.get_by_key_name(
                                post_key[len('goals_'):])
                            goals = self.get_goals(post_key)
                            if player is not None and goals > 0:
                                GoalsScored(
                                    key_name=GoalsScored.get_key(
                                        player.db_key, round_num, year),
                                    year=int(year),
                                    player=player,
                                    result=curr_result,
                                    count=goals,
                                ).put()
            self.get(base_url, extra)
        except Exception, e:
            self.get(base_url, extra, error=e)
예제 #12
0
    def post(self, base_url, extra):
        """Save the data posted about the player from the HTML form"""
        #try:
        affected_years = set()
        old_key = self.request.get('key_name')
        if self.request.POST.has_key('do_delete') and self.request.POST.get(
                'do_delete') == 'true':
            # Delete the selected player
            # Also need to delete anything else they were involved with e.g. teamlists, goals scored, etc...
            key = old_key
            player = Player.get_by_key_name(key)
            for x in player.year_list:
                x.delete()
            for x in player.beer_set:
                x.delete()
            for x in player.shirt_set:
                x.delete()
            for x in player.goal_set:
                x.delete()
            for x in player.availability_set:
                x.delete()
            self.delete_player(key)
        else:
            # Create/update the player
            first = self.request.get('first_name').strip()
            last = self.request.get('last_name').strip()
            key = Player.get_key(first, last)
            nick = self.request.get('nick_name').strip()
            email = self.request.get('email').strip()
            phone = self.request.get('phone').strip()
            registration = self.request.get('registration').strip()
            shirt = self.request.get('shirt').strip()
            if key != '':
                new_player = Player(
                    key_name=key,
                    db_key=key,
                    first_name=first,
                    last_name=last,
                    nick_name=nick,
                    email=email,
                    phone=phone,
                    registration=registration,
                    shirt=shirt,
                )
                new_player.put()
                for y in xrange(datetime.now().year, FIRST_YEAR - 1, -1):
                    year_key = TeamList.get_key(key, y)
                    if self.request.POST.has_key('played_' + str(y)):
                        TeamList(
                            key_name=year_key,
                            player=new_player,
                            year=y,
                        ).put()
                    else:
                        self.delete_player_year(year_key)
            if old_key != key:
                # If changing the info changes the key, be sure to scrap the old entry too
                self.delete_player(old_key)

        # Quite a few pages are potentially affected when you change a player's details. But only do it if the
        # form says to do so, because it's so expensive to regenerate everything!
        nickname_update = (self.request.POST.has_key('do_flush')
                           and self.request.get('do_flush') == 'on')

        # Update the side listings
        memcache.delete(PlayerPage.get_list_mem_key(ALL_YEARS))
        memcache.delete(PlayerManagePage.get_list_mem_key(ALL_YEARS))
        memcache.delete(PlayerPage.get_player_mem_key(
            key, ALL_YEARS))  # Their availability
        if nickname_update:
            memcache.delete(PlayerPage.get_draw_mem_key(ALL_YEARS))
            memcache.delete(ResultsPage.get_mem_key(ALL_YEARS))
            memcache.delete(ScorersPage.get_mem_key(ALL_YEARS))
            memcache.delete(BeerPage.get_mem_key('beer', ALL_YEARS))
            memcache.delete(ShirtsPage.get_mem_key('shirts', ALL_YEARS))
            memcache.delete(ProtectedPage.get_mem_key())

        for y in xrange(datetime.now().year, FIRST_YEAR - 1, -1):
            memcache.delete(PlayerPage.get_list_mem_key(y))
            memcache.delete(PlayerManagePage.get_list_mem_key(y))
            memcache.delete(PlayerPage.get_player_mem_key(
                key, y))  # Their availability

            if nickname_update:
                memcache.delete(PlayerPage.get_draw_mem_key(y))
                memcache.delete(ResultsPage.get_mem_key(y))
                memcache.delete(ScorersPage.get_mem_key(y))
                memcache.delete(BeerPage.get_mem_key('beer', y))
                memcache.delete(ShirtsPage.get_mem_key('shirts', y))

        self.get(base_url, extra)
예제 #13
0
 def delete_player_year(self, key):
     """Remove the association between the player and the year"""
     if key:
         t = TeamList.get_by_key_name(key)
         if t:
             t.delete()
예제 #14
0
    def post(self, base_url, extra):
        """Save the details for the given round"""
        try:
            old_key = self.request.get('key_name')
            if self.request.POST.get('do_delete') == 'true':
                # Delete the selected round
                self.delete_round(old_key)
                year = old_key.split('-')[0]
            else:
                # Create/update the round
                num = int(self.request.get('num').strip())
                caption = self.request.get('caption').strip()
                #if caption == '':
                #	caption = 'Rd ' + `num`
                try:
                    date = datetime.strptime(
                        self.request.get('date').strip(), '%d/%m/%Y').date()
                except:
                    date = datetime.strptime(
                        self.request.get('date').strip(), '%d/%m/%y').date()
                time_value = self.request.get('time').strip()
                if time_value == '':
                    time = None
                else:
                    time = datetime.strptime(time_value, '%H:%M').time()
                opponent = self.request.get('opponent').strip()
                homeaway = self.request.get('homeaway').strip()
                location = Ground.get(self.request.get('location'))
                key = Round.get_key(num, date.year)
                if key != '' and num != '':
                    new_round = Round(
                        key_name=key,
                        num=num,
                        year=date.year,
                        caption=caption,
                        date=date,
                        time=time,
                        opponent=opponent,
                        homeaway=homeaway,
                        location=location,
                    )
                    new_round.put()
                if old_key != key:
                    # If changing the info changes the key, be sure to scrap the old entry too
                    self.delete_round(old_key)
                year = date.year

            # Pages that are affected by this post:
            # - Draw, via a new item
            memcache.delete(PlayerPage.get_draw_mem_key(year))
            memcache.delete(PlayerPage.get_draw_mem_key(ALL_YEARS))
            # - All the individual player pages, via the items they can update
            for p in TeamList.gql('WHERE year = :1', year):
                memcache.delete(
                    PlayerPage.get_player_mem_key(p.player.db_key, year))
                memcache.delete(
                    PlayerPage.get_player_mem_key(p.player.db_key, ALL_YEARS))
            # NOT - results, beer or shirts (until results posted)

            self.get(base_url, extra)
        except Exception, e:
            self.get(base_url, extra, error=e)
예제 #15
0
def stalk(toornament_link):
    """
    Stalks all teams signed up for the given toornament and returns an op.gg multi link for each team
    :param toornament_link: String, url to a tournament on toornament
    :return: List[(String, String)], containing a tuple with the team name and the op.gg multi links for each team
    """

    logger.debug("Beginning toornament stalk for " + toornament_link)
    # open the websession
    driver = open_session()
    driver.get(toornament_link)

    # find the participants button and press it
    participants_button = driver.find_element_by_xpath(
        "//*[@id=\"tournament-nav\"]/div/section/div/ul/li[2]/a")
    participants_button.click()
    time.sleep(2)

    # find all teams and save the links
    participants_links = []
    base_url = "https://www.toornament.com"
    toornament_soup = bs4.BeautifulSoup(driver.page_source,
                                        features="html.parser")
    team_container = toornament_soup.find_all('div', class_="size-1-of-4")

    # multiple team page test
    driver.get(str(driver.current_url) + "?page=1")
    count = 1
    while True:
        count += 1
        driver.get(str(driver.current_url)[:-1] + str(count))
        toornament_soup2 = bs4.BeautifulSoup(driver.page_source,
                                             features="html.parser")
        if len(toornament_soup2.find_all('div', class_="size-1-of-4")) > 0:
            team_container.extend(
                toornament_soup2.find_all('div', class_="size-1-of-4"))
        else:
            break

    quit_session(driver)

    # extract toornament name
    tournament_name = toornament_soup.select(
        "#main-container > div.layout-section.header > div > section > div > div.information > div.name > h1"
    )[0].text

    for team in team_container:
        a = team.find('a', href=True)
        participants_links.append(base_url + a['href'])

    # open each link, switch to information and collect the Summoner Names
    single_tasks = []
    for link in participants_links:
        single_tasks.append(SingleTask(stalk_team, link))
    task_group = TaskGroup(single_tasks, "stalk: " + tournament_name)

    teams_players_tuples = submit_task_group(task_group)

    # build Player, Team and TeamList objects
    team_list = []
    for team in teams_players_tuples:
        sum_names = team[0]
        team_name = team[1]
        players = []
        for sum_name in sum_names:
            players.append(Player(sum_name))
        team_list.append(Team(team_name, players))

    return TeamList(tournament_name, team_list)