// analyze_scene [python]
    def analyze_scene(self, scene):
        base_urls = scene.get_base_urls()
        users = scene.get_users()
        name = scene.get_name()
        LOG.info('found the following users for scene {}: {}'.format(name, users))

        # This scene might have one user who always posts the brackets on their challonge account
        for user in users:
            # Have we analyzed this user before?
            sql = "SELECT * FROM user_analyzed WHERE user='{user}';"
            args = {'user': user}
            results = self.db.exec(sql, args)

            # Did we have any matches in the database?
            if len(results) > 0:
                # We have analyzed this user before. Just grab one page of brackets to see if there have been any new tournaments
                # eg, just look at /users/christmasmike?page=1 instead of all the pages that exist
                most_recent_page = bracket_utils.get_brackets_from_user(user, pages=1)
                for bracket in most_recent_page:
                    LOG.info('here are the brackets from the most recent page of user {}: {}'.format(user, most_recent_page))
                    # This user has already been analyzed, there's a good chance this bracket has been analyzed also
                    sql = "SELECT * FROM user_analyzed WHERE url='{bracket}' AND user='{user}';"
                    args = {'bracket': bracket, 'user': user}
                    results = self.db.exec(sql, args)

                    if len(results) == 0:
                        # This is a new bracket that must have been published in the last hour or so
                        LOG.info('found this url from a user: {} {}'.format(bracket, user))
                        display_name = bracket_utils.get_display_base(bracket)
                        # We don't care about doubles tournaments
                        if 'doubles' in display_name.lower() or 'dubs' in display_name.lower():
                            LOG.info('We are skipping the tournament {} because it is a doubles tournament'.format(display_name))
                            continue

                        self.data_processor.process(bracket, name, display_name)

                        # mark this bracket as analyzed
                        sql = "INSERT INTO user_analyzed (url, user, scene) VALUES ('{bracket}', '{user}', '{name}');"
                        args = {'bracket': bracket, 'user':user, 'name':name}
                        self.db.exec(sql, args)

                        # Tweet that we found a new bracket
                        msg = "Found new {} bracket: {}".format(name, bracket)
                        tweet(msg)
                    else:
                        LOG.info('url {} is not new for user {}'.format(bracket, user))
            else:
                # This is a new user, analyze all brackets
                user_urls = bracket_utils.get_brackets_from_user(user)
                for url in user_urls:
                    LOG.info('found this url from a user: {} {}'.format(url, user))
                    display_name = bracket_utils.get_display_base(url)
                    # We don't care about doubles tournaments
                    if 'doubles' in display_name.lower() or 'dubs' in display_name.lower():
                        LOG.info('We are skipping the tournament {} because it is a doubles tournament'.format(display_name))
                        continue

                    self.data_processor.process(url, name, display_name)

                    # mark this bracket as analyzed
                    sql = "INSERT INTO user_analyzed (url, user, scene) VALUES ('{url}', '{user}', '{name}');"
                    args = {'url': url, 'user':user, 'name':name}
                    self.db.exec(sql, args)

                LOG.info('done with user {}'.format(user))


        # This scene might always call their brackets the same thing, eg weekly1, weekly2, weekly3 etc
        for base_url in base_urls:
            # attempt to load this data from the database
            LOG.info('About to start this analysis thread for scene {}'.format(scene.get_name()))
            sql = "SELECT first,last FROM valids WHERE base_url = '{base_url}';"
            args = {'base_url': base_url}
            result = self.db.exec(sql, args)
            has_results = len(result) > 0 

            # Did we find a match in the database?
            if has_results:
                LOG.info("validURLs found values in the database" + str(result))
                first = result[0][0]
                last = result[0][1]

                # Check for a new valid URL
                new_last = bracket_utils._get_last_valid_url(base_url, last-1)

                if not new_last == last:
                    if new_last - last > 5:
                        with open("DEBUGOUTPUT.txt", 'a') as f:
                            f.write("[validURLs.py:55]: found a SHIT TON of new tournaments for bracket: {}".format(base_url))

                    else:
                        bracket = base_url.replace('###', str(new_last))
                        LOG.info('Found new bracket: {}'.format(bracket))
                        msg = "Found new bracket: {}".format(bracket)
                        tweet(msg)

                    # If there's been a new last, update the database
                    sql = "UPDATE valids SET last={new_last} where base_url='{base_url}';"
                    args = {'new_last': new_last, 'base_url': base_url}
                    self.db.exec(sql, args)


                    # Analyze each of these new brackets
                    for i in range(last+1, new_last+1):
                        # Since this URL is new, we have to process the data
                        bracket = base_url.replace('###', str(i))
                        # Create the display name for this bracket
                        # Eg challonge.com/NP9ATX54 -> NP9 54
                        display_name = bracket_utils.get_display_base(bracket, counter=i)
                        # We don't care about doubles tournaments
                        if 'doubles' in display_name.lower() or 'dubs' in display_name.lower():
                            LOG.info('We are skipping the tournament {} because it is a doubles tournament'.format(display_name))
                            continue

                        self.data_processor.process(bracket, name, display_name, new_bracket=True)

            else:
                # We need to create first and last from scratch
                first = bracket_utils._get_first_valid_url(base_url)
                last = bracket_utils._get_last_valid_url(base_url, first)

                # This is new data, we need to put it into the db
                sql = "INSERT INTO valids (base_url, first, last, scene) VALUES ('{base_url}', '{first}', '{last}', '{name}');"
                args = {'base_url': base_url, 'first': first, 'last': last, 'name': name}
                self.db.exec(sql, args)

                for i in range(first, last+1):
                    bracket = base_url.replace('###', str(i))
                    # Create the display name for this bracket
                    # Eg challonge.com/NP9ATX54 -> NP9 54
                    display_name = bracket_utils.get_display_base(bracket, counter=i)
                    # We don't care about doubles tournaments
                    if 'doubles' in display_name.lower() or 'dubs' in display_name.lower():
                        LOG.info('We are skipping the tournament {} because it is a doubles tournament'.format(display_name))
                        continue

                    self.data_processor.process(bracket, name, display_name)

                    # Calculate ranks after each tournament so we can see how players are progressing
        if not analyzed_scenes and should_tweet:
            tweet('About to start ranking for scene {}'.format(name))
        self.data_processor.check_and_update_ranks(name)