def parse(self, html):
        """
        Parse an event's details page from USFIRST.
        """
        # page_titles look like this:
        # <YEAR> <EVENT_NAME> (<EVENT_TYPE>)
        event_type_re = r'\((.+)\)'

        # locality_regions look like this:
        # <locality>, <region> <random string can have spaces>
        event_locality_region_re = r'(.*?), ([^ ]*)'

        result = dict()
        soup = BeautifulSoup(html)

        page_title = soup.find('h1', {'id': 'thepagetitle'}).text
        result['name'] = unicode(
            re.sub(r'\([^)]*\)', '', page_title[4:]).strip())
        result['short_name'] = EventHelper.getShortName(result['name'])
        result['event_type_enum'] = EventHelper.parseEventType(
            unicode(re.search(event_type_re, page_title).group(1).strip()))

        try:
            event_dates = soup.find('div', {'class': 'event-dates'}).text
            result['start_date'], result['end_date'] = self._parseEventDates(
                event_dates)
            result['year'] = int(event_dates[-4:])
        except Exception, detail:
            logging.error('Date Parse Failed: ' + str(detail))
    def post(self, event_key):
        self._require_admin()

        # Note, we don't actually use event_key.

        start_date = None
        if self.request.get("start_date"):
            start_date = datetime.strptime(self.request.get("start_date"), "%Y-%m-%d")

        end_date = None
        if self.request.get("end_date"):
            end_date = datetime.strptime(self.request.get("end_date"), "%Y-%m-%d")

        event = Event(
            id=str(self.request.get("year")) + str.lower(str(self.request.get("event_short"))),
            end_date=end_date,
            event_short=self.request.get("event_short"),
            event_type_enum=EventHelper.parseEventType(self.request.get("event_type_str")),
            location=self.request.get("location"),
            name=self.request.get("name"),
            short_name=self.request.get("short_name"),
            start_date=start_date,
            website=self.request.get("website"),
            year=int(self.request.get("year")),
            official={"true": True, "false": False}.get(self.request.get("official").lower()),
            facebook_eid=self.request.get("facebook_eid"),
            webcast_json=self.request.get("webcast_json"),
            rankings_json=self.request.get("rankings_json"),
        )
        event = EventManipulator.createOrUpdate(event)

        self.redirect("/admin/event/" + event.key_name)
    def parse(self, html):
        """
        Parse the list of events from USFIRST. This provides us with basic
        information about events and is how we first discover them.
        """
        events = list()
        soup = BeautifulSoup(html,
                             convertEntities=BeautifulSoup.HTML_ENTITIES)

        for tr in soup.findAll('tr'):  # Events are in table rows
            event = dict()
            try:
                tds = tr.findAll('td')
                event["event_type_enum"] = EventHelper.parseEventType(unicode(tds[0].string))
                
                url_get_params = urlparse.parse_qs(urlparse.urlparse(tds[1].a["href"]).query)
                event["first_eid"] = url_get_params["eid"][0]

                event["name"] = ''.join(tds[1].a.findAll(text=True)).strip()  # <em>s in event names fix
                #event.venue = unicode(tds[2].string)
                #event.location = unicode(tds[3].string)

                # try:
                #    event_dates = str(tds[4].string).strip()
                #    event.start_date, event.stop_date = self.parseEventDates(event_dates)
                #    event.year = int(event_dates[-4:])
                # except Exception, detail:
                #    logging.error('Date Parse Failed: ' + str(detail))

                if event.get("event_type_enum", None) in self.REGIONAL_EVENT_TYPES:
                    events.append(event)

            except Exception, detail:
                logging.info('Event parsing failed: ' + str(detail))
Example #4
0
    def parse(self, response):
        events = []
        for event in response['hits']['hits']:
            first_eid = event['_id']
            event = event['_source']

            event_type = EventHelper.parseEventType(event['event_subtype'])
            if event_type in self.TYPES_TO_SKIP:
                continue

            code = event['event_code'].lower()
            key = "{}{}".format(self.season, code)
            name = event['event_name']
            short_name = EventHelper.getShortName(name)
            if event_type in EventType.DISTRICT_EVENT_TYPES:
                district_enum = EventHelper.getDistrictFromEventName(name)
            else:
                district_enum = DistrictType.NO_DISTRICT
            city = event.get('event_city', None)
            state_prov = event.get('event_stateprov', None)
            country = event.get('event_country', None)
            postalcode = event.get('event_postalcode', None)
            start = datetime.datetime.strptime(event['date_start'],
                                               self.DATE_FORMAT_STR)
            end = datetime.datetime.strptime(
                event['date_end'], self.DATE_FORMAT_STR) + datetime.timedelta(
                    hours=23, minutes=59, seconds=59)
            venue_address = event['event_venue']
            if 'event_address1' in event and event['event_address1']:
                venue_address += '\n' + event['event_address1']
            if 'event_address2' in event and event['event_address2']:
                venue_address += '\n' + event['event_address2']
            venue_address += '\n{}, {} {}\n{}'.format(
                event['event_city'], event['event_stateprov'],
                event['event_postalcode'], event['event_country'])

            raw_website = event.get('event_web_url', None)
            website = urlparse.urlparse(
                raw_website, 'http').geturl() if raw_website else None

            events.append(
                Event(id=key,
                      name=name,
                      short_name=short_name,
                      event_short=code,
                      event_type_enum=event_type,
                      official=True,
                      start_date=start,
                      end_date=end,
                      venue=event['event_venue'],
                      city=city,
                      state_prov=state_prov,
                      country=country,
                      postalcode=postalcode,
                      venue_address=venue_address,
                      year=self.season,
                      event_district_enum=district_enum,
                      first_eid=first_eid,
                      website=website))
        return events
Example #5
0
    def post(self, event_key):
        self._require_admin()

        # Note, we don't actually use event_key.

        start_date = None
        if self.request.get("start_date"):
            start_date = datetime.strptime(self.request.get("start_date"),
                                           "%Y-%m-%d")

        end_date = None
        if self.request.get("end_date"):
            end_date = datetime.strptime(self.request.get("end_date"),
                                         "%Y-%m-%d")

        district_key = self.request.get("event_district_key", None)

        event = Event(
            id=str(self.request.get("year")) +
            str.lower(str(self.request.get("event_short"))),
            end_date=end_date,
            event_short=self.request.get("event_short"),
            event_type_enum=EventHelper.parseEventType(
                self.request.get("event_type_str")),
            district_key=ndb.Key(District,
                                 self.request.get("event_district_key"))
            if district_key and district_key != 'None' else None,
            venue=self.request.get("venue"),
            venue_address=self.request.get("venue_address"),
            city=self.request.get("city"),
            state_prov=self.request.get("state_prov"),
            postalcode=self.request.get("postalcode"),
            country=self.request.get("country"),
            name=self.request.get("name"),
            short_name=self.request.get("short_name"),
            start_date=start_date,
            website=self.request.get("website"),
            year=int(self.request.get("year")),
            official={
                "true": True,
                "false": False
            }.get(self.request.get("official").lower()),
            facebook_eid=self.request.get("facebook_eid"),
            custom_hashtag=self.request.get("custom_hashtag"),
            webcast_json=self.request.get("webcast_json"),
        )
        event = EventManipulator.createOrUpdate(event)

        if self.request.get("alliance_selections_json") or self.request.get(
                "rankings_json"):
            event_details = EventDetails(
                id=event_key,
                alliance_selections=json.loads(
                    self.request.get("alliance_selections_json")),
                rankings=json.loads(self.request.get("rankings_json")))
            EventDetailsManipulator.createOrUpdate(event_details)

        MemcacheWebcastFlusher.flushEvent(event.key_name)

        self.redirect("/admin/event/" + event.key_name)
    def parse(self, html):
        """
        Parse an event's details page from USFIRST.
        """
        # page_titles look like this:
        # <YEAR> <EVENT_NAME> (<EVENT_TYPE>)
        event_type_re = r'\((.+)\)'

        # locality_regions look like this:
        # <locality>, <region> <random string can have spaces>
        event_locality_region_re = r'(.*?), ([^ ]*)'

        result = dict()
        soup = BeautifulSoup(html, convertEntities=BeautifulSoup.HTML_ENTITIES)

        page_title = soup.find('h1', {'id': 'thepagetitle'}).text
        result['name'] = unicode(re.sub(r'\([^)]*\)', '', page_title[4:]).strip())
        result['short_name'] = EventHelper.getShortName(result['name'])
        result['event_type_enum'] = EventHelper.parseEventType(unicode(re.search(event_type_re, page_title).group(1).strip()))

        try:
            event_dates = soup.find('div', {'class': 'event-dates'}).text
            result['start_date'], result['end_date'] = self._parseEventDates(event_dates)
            result['year'] = int(event_dates[-4:])
        except Exception, detail:
            logging.error('Date Parse Failed: ' + str(detail))
    def parse(self, response):
        events = []
        for event in response["hits"]["hits"]:
            first_eid = event["_id"]
            event = event["_source"]

            event_type = EventHelper.parseEventType(event["event_subtype"])
            if event_type in self.TYPES_TO_SKIP:
                continue

            code = event["event_code"].lower()
            key = "{}{}".format(self.season, code)
            name = event["event_name"]
            short_name = EventHelper.getShortName(name)
            if event_type in EventType.DISTRICT_EVENT_TYPES:
                district_enum = EventHelper.getDistrictFromEventName(name)
            else:
                district_enum = DistrictType.NO_DISTRICT
            city = event.get("event_city", None)
            state_prov = event.get("event_stateprov", None)
            country = event.get("event_country", None)
            start = datetime.datetime.strptime(event["date_start"], self.DATE_FORMAT_STR)
            end = datetime.datetime.strptime(event["date_end"], self.DATE_FORMAT_STR) + datetime.timedelta(
                hours=23, minutes=59, seconds=59
            )
            venue_address = event["event_venue"]
            if "event_address1" in event and event["event_address1"]:
                venue_address += "\n" + event["event_address1"]
            if "event_address2" in event and event["event_address2"]:
                venue_address += "\n" + event["event_address2"]
            venue_address += "\n{}, {} {}\n{}".format(
                event["event_city"], event["event_stateprov"], event["event_postalcode"], event["event_country"]
            )

            raw_website = event.get("event_web_url", None)
            website = urlparse.urlparse(raw_website, "http").geturl() if raw_website else None

            events.append(
                Event(
                    id=key,
                    name=name,
                    short_name=short_name,
                    event_short=code,
                    event_type_enum=event_type,
                    official=True,
                    start_date=start,
                    end_date=end,
                    venue=event["event_venue"],
                    city=city,
                    state_prov=state_prov,
                    country=country,
                    venue_address=venue_address,
                    year=self.season,
                    event_district_enum=district_enum,
                    first_eid=first_eid,
                    website=website,
                )
            )
        return events
    def parse(self, html):
        """
        Parse an event's details page from USFIRST.
        """
        # locality_regions look like this:
        # <locality>, <region> <random string can have spaces>
        event_locality_region_re = r'(.*?), ([^ ]*)'

        result = dict()
        soup = BeautifulSoup(html)

        for tr in soup.findAll('tr'):
            tds = tr.findAll('td')
            if len(tds) > 1:
                field = str(tds[0].string)
                if field == "Event":
                    result["name"] = unicode(''.join(
                        tds[1].findAll(text=True))).strip()
                    result['short_name'] = EventHelper.getShortName(
                        result['name'])
                if field == "Event Subtype":
                    result["event_type_enum"] = EventHelper.parseEventType(
                        unicode(tds[1].string))
                if field == "When":
                    try:
                        event_dates = str(tds[1].string).strip()
                        result["start_date"], result[
                            "end_date"] = self._parseEventDates(event_dates)
                        result["year"] = int(event_dates[-4:])
                    except Exception, detail:
                        logging.error('Date Parse Failed: ' + str(detail))
                if field == "Where":
                    address_lines_stripped = [
                        re.sub('\s+', ' ', line.replace(u'\xa0', ' ')).strip()
                        for line in tds[1].findAll(text=True)
                    ]
                    result["venue_address"] = unicode(
                        '\r\n'.join(address_lines_stripped)).encode(
                            'ascii', 'ignore')

                    match = re.match(event_locality_region_re,
                                     address_lines_stripped[-2])
                    locality, region = match.group(1), match.group(2)
                    country = address_lines_stripped[-1]
                    result['location'] = '%s, %s, %s' % (locality, region,
                                                         country)
                if field == "Event Info":
                    result["website"] = unicode(tds[1].a['href'])
                if field == "Match Results":
                    #http://www2.usfirst.org/2010comp/Events/SDC/matchresults.html
                    m = re.match(
                        r"http://www2\.usfirst\.org/%scomp/Events/([a-zA-Z0-9]*)/matchresults\.html"
                        % result["year"], tds[1].a["href"])
                    if m is None:
                        # Some 2013 events are beautiful-souping tds[1].a["href"] to "http://www2.usfirst.org/2013comp/Events/FLBR" inexplicbly
                        m = re.match(
                            r"http://www2\.usfirst\.org/%scomp/Events/([a-zA-Z0-9]*)"
                            % result["year"], tds[1].a["href"])
                    result["event_short"] = m.group(1).lower()
    def parse(self, response):
        events = []
        for event in response['hits']['hits']:
            first_eid = event['_id']
            event = event['_source']

            event_type = EventHelper.parseEventType(event['event_subtype'])
            if event_type in self.TYPES_TO_SKIP:
                continue

            code = event['event_code'].lower()
            key = "{}{}".format(self.season, code)
            name = event['event_name']
            short_name = EventHelper.getShortName(name)
            if event_type in EventType.DISTRICT_EVENT_TYPES:
                district_enum = EventHelper.getDistrictFromEventName(name)
            else:
                district_enum = DistrictType.NO_DISTRICT
            city = event.get('event_city', None)
            state_prov = event.get('event_stateprov', None)
            country = event.get('event_country', None)
            postalcode = event.get('event_postalcode', None)
            start = datetime.datetime.strptime(event['date_start'], self.DATE_FORMAT_STR)
            end = datetime.datetime.strptime(event['date_end'], self.DATE_FORMAT_STR) + datetime.timedelta(hours=23, minutes=59, seconds=59)
            venue_address = event['event_venue']
            if 'event_address1' in event and event['event_address1']:
                venue_address += '\n' + event['event_address1']
            if 'event_address2' in event and event['event_address2']:
                venue_address += '\n' + event['event_address2']
            venue_address += '\n{}, {} {}\n{}'.format(event['event_city'], event['event_stateprov'], event['event_postalcode'], event['event_country'])

            raw_website = event.get('event_web_url', None)
            website = urlparse.urlparse(raw_website, 'http').geturl() if raw_website else None

            events.append(Event(
                id=key,
                name=name,
                short_name=short_name,
                event_short=code,
                event_type_enum=event_type,
                official=True,
                start_date=start,
                end_date=end,
                venue=event['event_venue'],
                city=city,
                state_prov=state_prov,
                country=country,
                postalcode=postalcode,
                venue_address=venue_address,
                year=self.season,
                event_district_enum=district_enum,
                first_eid=first_eid,
                website=website
            ))
        return events
    def post(self, event_key):
        self._require_admin()

        # Note, we don't actually use event_key.

        start_date = None
        if self.request.get("start_date"):
            start_date = datetime.strptime(self.request.get("start_date"), "%Y-%m-%d")

        end_date = None
        if self.request.get("end_date"):
            end_date = datetime.strptime(self.request.get("end_date"), "%Y-%m-%d")

        district_key = self.request.get("event_district_key", None)

        event = Event(
            id=str(self.request.get("year")) + str.lower(str(self.request.get("event_short"))),
            end_date=end_date,
            event_short=self.request.get("event_short"),
            event_type_enum=EventHelper.parseEventType(self.request.get("event_type_str")),
            district_key=ndb.Key(District, self.request.get("event_district_key")) if district_key and district_key != 'None' else None,
            venue=self.request.get("venue"),
            venue_address=self.request.get("venue_address"),
            city=self.request.get("city"),
            state_prov=self.request.get("state_prov"),
            postalcode=self.request.get("postalcode"),
            country=self.request.get("country"),
            name=self.request.get("name"),
            short_name=self.request.get("short_name"),
            start_date=start_date,
            website=self.request.get("website"),
            year=int(self.request.get("year")),
            official={"true": True, "false": False}.get(self.request.get("official").lower()),
            facebook_eid=self.request.get("facebook_eid"),
            custom_hashtag=self.request.get("custom_hashtag"),
            webcast_json=self.request.get("webcast_json"),
            playoff_type=int(self.request.get("playoff_type")),
        )
        event = EventManipulator.createOrUpdate(event)

        if self.request.get("alliance_selections_json") or self.request.get("rankings_json"):
            event_details = EventDetails(
                id=event_key,
                alliance_selections=json.loads(self.request.get("alliance_selections_json")),
                rankings=json.loads(self.request.get("rankings_json"))
            )
            EventDetailsManipulator.createOrUpdate(event_details)

        MemcacheWebcastFlusher.flushEvent(event.key_name)

        self.redirect("/admin/event/" + event.key_name)
    def parse(self, html):
        """
        Parse an event's details page from USFIRST.
        """
        # locality_regions look like this:
        # <locality>, <region> <random string can have spaces>
        event_locality_region_re = r"(.*?), ([^ ]*)"

        result = dict()
        soup = BeautifulSoup(html, convertEntities=BeautifulSoup.HTML_ENTITIES)

        for tr in soup.findAll("tr"):
            tds = tr.findAll("td")
            if len(tds) > 1:
                field = str(tds[0].string)
                if field == "Event":
                    result["name"] = unicode("".join(tds[1].findAll(text=True))).strip()
                    result["short_name"] = EventHelper.getShortName(result["name"])
                if field == "Event Subtype":
                    result["event_type_enum"] = EventHelper.parseEventType(unicode(tds[1].string))
                if field == "When":
                    try:
                        event_dates = str(tds[1].string).strip()
                        result["start_date"], result["end_date"] = self._parseEventDates(event_dates)
                        result["year"] = int(event_dates[-4:])
                    except Exception, detail:
                        logging.error("Date Parse Failed: " + str(detail))
                if field == "Where":
                    address_lines_stripped = [
                        re.sub("\s+", " ", line.replace(u"\xa0", " ")).strip() for line in tds[1].findAll(text=True)
                    ]
                    result["venue_address"] = unicode("\r\n".join(address_lines_stripped)).encode("ascii", "ignore")

                    match = re.match(event_locality_region_re, address_lines_stripped[-2])
                    locality, region = match.group(1), match.group(2)
                    country = address_lines_stripped[-1]
                    result["location"] = "%s, %s, %s" % (locality, region, country)
                if field == "Event Info":
                    result["website"] = unicode(tds[1].a["href"])
                if field == "Match Results":
                    # http://www2.usfirst.org/2010comp/Events/SDC/matchresults.html
                    m = re.match(
                        r"http://www2\.usfirst\.org/%scomp/Events/([a-zA-Z0-9]*)/matchresults\.html" % result["year"],
                        tds[1].a["href"],
                    )
                    if m is None:
                        # Some 2013 events are beautiful-souping tds[1].a["href"] to "http://www2.usfirst.org/2013comp/Events/FLBR" inexplicbly
                        m = re.match(
                            r"http://www2\.usfirst\.org/%scomp/Events/([a-zA-Z0-9]*)" % result["year"], tds[1].a["href"]
                        )
                    result["event_short"] = m.group(1).lower()
    def post(self, event_key):
        self._require_admin()

        # Note, we don't actually use event_key.

        start_date = None
        if self.request.get("start_date"):
            start_date = datetime.strptime(self.request.get("start_date"),
                                           "%Y-%m-%d")

        end_date = None
        if self.request.get("end_date"):
            end_date = datetime.strptime(self.request.get("end_date"),
                                         "%Y-%m-%d")

        event = Event(
            id=str(self.request.get("year")) +
            str.lower(str(self.request.get("event_short"))),
            end_date=end_date,
            event_short=self.request.get("event_short"),
            event_type_enum=EventHelper.parseEventType(
                self.request.get("event_type_str")),
            event_district_enum=EventHelper.parseDistrictName(
                self.request.get("event_district_str")),
            venue=self.request.get("venue"),
            venue_address=self.request.get("venue_address"),
            location=self.request.get("location"),
            name=self.request.get("name"),
            short_name=self.request.get("short_name"),
            start_date=start_date,
            website=self.request.get("website"),
            year=int(self.request.get("year")),
            official={
                "true": True,
                "false": False
            }.get(self.request.get("official").lower()),
            facebook_eid=self.request.get("facebook_eid"),
            custom_hashtag=self.request.get("custom_hashtag"),
            webcast_json=self.request.get("webcast_json"),
            alliance_selections_json=self.request.get(
                "alliance_selections_json"),
            rankings_json=self.request.get("rankings_json"),
        )
        event = EventManipulator.createOrUpdate(event)

        MemcacheWebcastFlusher.flushEvent(event.key_name)

        self.redirect("/admin/event/" + event.key_name)
Example #13
0
    def parse(self, html):
        """
        Parse the list of events from USFIRST. This provides us with basic
        information about events and is how we first discover them.
        """
        events = list()
        soup = BeautifulSoup(html, convertEntities=BeautifulSoup.HTML_ENTITIES)

        for tr in soup.findAll('tr'):  # Events are in table rows
            event = dict()
            try:
                tds = tr.findAll('td')
                if tds[0].string is None:
                    # this may happen if this is a district event, in which case we can also extract the district name
                    event_type_str = unicode(
                        tds[0].findAll(text=True)[2].string)

                    district_name_str = unicode(tds[0].findAll('em')[0].string)
                else:
                    event_type_str = unicode(tds[0].string)
                    district_name_str = None
                event["event_type_enum"] = EventHelper.parseEventType(
                    event_type_str)
                event["event_district_enum"] = EventHelper.parseDistrictName(
                    district_name_str)
                url_get_params = urlparse.parse_qs(
                    urlparse.urlparse(tds[1].a["href"]).query)
                event["first_eid"] = url_get_params["eid"][0]

                event["name"] = ''.join(tds[1].a.findAll(
                    text=True)).strip()  # <em>s in event names fix
                #event.venue = unicode(tds[2].string)
                #event.location = unicode(tds[3].string)

                # try:
                #    event_dates = str(tds[4].string).strip()
                #    event.start_date, event.stop_date = self.parseEventDates(event_dates)
                #    event.year = int(event_dates[-4:])
                # except Exception, detail:
                #    logging.error('Date Parse Failed: ' + str(detail))

                if event.get("event_type_enum",
                             None) in EventType.NON_CMP_EVENT_TYPES:
                    events.append(event)

            except Exception, detail:
                logging.info('Event parsing failed: ' + str(detail))
    def parse(self, response):
        events = []
        for event in response['Events']:
            code = event['code'].lower()
            key = "{}{}".format(self.season, code)
            name = event['name']
            short_name = EventHelper.getShortName(name)
            event_type = EventHelper.parseEventType(event['type'])
            district_enum = EventHelper.parseDistrictName(
                event['districtCode'].lower(
                )) if event['districtCode'] else DistrictType.NO_DISTRICT
            venue = event['venue']
            location = "{}, {}, {}".format(event['city'], event['stateprov'],
                                           event['country'])
            start = datetime.datetime.strptime(event['dateStart'],
                                               self.DATE_FORMAT_STR)
            end = datetime.datetime.strptime(event['dateEnd'],
                                             self.DATE_FORMAT_STR)

            # TODO read timezone from API

            # Do not read in CMP divisions, we'll add those manually
            if event_type in EventType.CMP_EVENT_TYPES:
                continue

            events.append(
                Event(
                    id=key,
                    name=name,
                    short_name=short_name,
                    event_short=code,
                    event_type_enum=event_type,
                    official=True,
                    start_date=start,
                    end_date=end,
                    venue=venue,
                    location=location,
                    venue_address=
                    None,  # FIRST API doesn't provide detailed venue address
                    year=self.season,
                    event_district_enum=district_enum))
        return events
    def parse(self, html):
        """
        Parse the list of events from USFIRST. This provides us with basic
        information about events and is how we first discover them.
        """
        events = list()
        soup = BeautifulSoup(html)

        for tr in soup.findAll('tr'):  # Events are in table rows
            event = dict()
            try:
                tds = tr.findAll('td')
                if tds[0].string is None:
                    # this may happen if this is a district event, in which case we can also extract the district name
                    event_type_str = unicode(tds[0].findAll(text=True)[2].string)

                    district_name_str = unicode(tds[0].findAll('em')[0].string)
                else:
                    event_type_str = unicode(tds[0].string)
                    district_name_str = None
                event["event_type_enum"] = EventHelper.parseEventType(event_type_str)
                event["event_district_enum"] = EventHelper.parseDistrictName(district_name_str)
                url_get_params = urlparse.parse_qs(urlparse.urlparse(tds[1].a["href"]).query)
                event["first_eid"] = url_get_params["eid"][0]

                event["name"] = ''.join(tds[1].a.findAll(text=True)).strip()  # <em>s in event names fix
                #event.venue = unicode(tds[2].string)
                #event.location = unicode(tds[3].string)

                # try:
                #    event_dates = str(tds[4].string).strip()
                #    event.start_date, event.stop_date = self.parseEventDates(event_dates)
                #    event.year = int(event_dates[-4:])
                # except Exception, detail:
                #    logging.error('Date Parse Failed: ' + str(detail))

                if event.get("event_type_enum", None) in EventType.NON_CMP_EVENT_TYPES:
                    events.append(event)

            except Exception, detail:
                logging.info('Event parsing failed: ' + str(detail))
    def parse(self, html):
        """
        Parse an event's details page from USFIRST.
        """
        result = dict()
        soup = BeautifulSoup(html,
                convertEntities=BeautifulSoup.HTML_ENTITIES)

        for tr in soup.findAll('tr'):
            tds = tr.findAll('td')
            if len(tds) > 1:
                field = str(tds[0].string)
                if field == "Event":
                    result["name"] = unicode(''.join(tds[1].findAll(text=True))).strip()
                if field == "Event Subtype":
                    result["event_type_enum"] = EventHelper.parseEventType(unicode(tds[1].string))
                if field == "When":
                    try:
                        event_dates = str(tds[1].string).strip()
                        result["start_date"], result["end_date"] = self._parseEventDates(event_dates)
                        result["year"] = int(event_dates[-4:])
                    except Exception, detail:
                        logging.error('Date Parse Failed: ' + str(detail))
                if field == "Where":
                    # TODO: This next line is awful. Make this suck less.
                    # I think \t tabs mess it up or something. -greg 5/20/2010
                    result["venue_address"] = unicode(''.join(tds[1].findAll(text=True))).encode('ascii', 'ignore').strip().replace("\t","").replace("\r\n\r\n", "\r\n")
                if field == "Event Info":
                    result["website"] = unicode(tds[1].a['href'])
                if field == "Match Results":
                    #http://www2.usfirst.org/2010comp/Events/SDC/matchresults.html
                    m = re.match(r"http://www2\.usfirst\.org/%scomp/Events/([a-zA-Z0-9]*)/matchresults\.html" % result["year"], tds[1].a["href"])
                    if m is None:
                        # Some 2013 events are beautiful-souping tds[1].a["href"] to "http://www2.usfirst.org/2013comp/Events/FLBR" inexplicbly
                        m = re.match(r"http://www2\.usfirst\.org/%scomp/Events/([a-zA-Z0-9]*)" % result["year"], tds[1].a["href"])
                    result["event_short"] = m.group(1).lower()
    def parse(self, response):
        events = []
        for event in response['Events']:
            code = event['code'].lower()
            key = "{}{}".format(self.season, code)
            name = event['name']
            short_name = EventHelper.getShortName(name)
            event_type = EventHelper.parseEventType(event['type'])
            district_enum = EventHelper.parseDistrictName(event['districtCode'].lower()) if event['districtCode'] else DistrictType.NO_DISTRICT
            venue = event['venue']
            location = "{}, {}, {}".format(event['city'], event['stateprov'], event['country'])
            start = datetime.datetime.strptime(event['dateStart'], self.DATE_FORMAT_STR)
            end = datetime.datetime.strptime(event['dateEnd'], self.DATE_FORMAT_STR)

            # TODO read timezone from API

            # Do not read in CMP divisions, we'll add those manually
            if event_type in EventType.CMP_EVENT_TYPES:
                continue

            events.append(Event(
                id=key,
                name=name,
                short_name=short_name,
                event_short=code,
                event_type_enum=event_type,
                official=True,
                start_date=start,
                end_date=end,
                venue=venue,
                location=location,
                venue_address="{}, {}".format(venue, location),
                year=self.season,
                event_district_enum=district_enum
            ))
        return events
    def test_parse(self):
        self.assertEqual(EventHelper.parseEventType("Regional"),
                         EventType.REGIONAL)
        self.assertEqual(EventHelper.parseEventType("regional"),
                         EventType.REGIONAL)

        self.assertEqual(EventHelper.parseEventType("District"),
                         EventType.DISTRICT)
        self.assertEqual(EventHelper.parseEventType("district"),
                         EventType.DISTRICT)
        self.assertEqual(EventHelper.parseEventType("MI District"),
                         EventType.DISTRICT)
        self.assertEqual(EventHelper.parseEventType("District Event"),
                         EventType.DISTRICT)
        self.assertEqual(EventHelper.parseEventType("Qualifying Event"),
                         EventType.DISTRICT)
        self.assertEqual(EventHelper.parseEventType("Qualifier"),
                         EventType.DISTRICT)

        self.assertEqual(EventHelper.parseEventType("District Championship"),
                         EventType.DISTRICT_CMP)
        self.assertEqual(
            EventHelper.parseEventType("MI FRC State Championship"),
            EventType.DISTRICT_CMP)
        self.assertEqual(EventHelper.parseEventType("Qualifying Championship"),
                         EventType.DISTRICT_CMP)

        self.assertEqual(EventHelper.parseEventType("Championship Division"),
                         EventType.CMP_DIVISION)

        self.assertEqual(EventHelper.parseEventType("Championship Finals"),
                         EventType.CMP_FINALS)
        self.assertEqual(EventHelper.parseEventType("Championship"),
                         EventType.CMP_FINALS)

        self.assertEqual(EventHelper.parseEventType("Offseason"),
                         EventType.OFFSEASON)
        self.assertEqual(EventHelper.parseEventType("Preseason"),
                         EventType.PRESEASON)

        self.assertEqual(EventHelper.parseEventType("Division"),
                         EventType.UNLABLED)
    def test_parse(self):
        self.assertEqual(EventHelper.parseEventType("Regional"), EventType.REGIONAL)
        self.assertEqual(EventHelper.parseEventType("regional"), EventType.REGIONAL)

        self.assertEqual(EventHelper.parseEventType("District"), EventType.DISTRICT)
        self.assertEqual(EventHelper.parseEventType("district"), EventType.DISTRICT)
        self.assertEqual(EventHelper.parseEventType("MI District"), EventType.DISTRICT)
        self.assertEqual(EventHelper.parseEventType("District Event"), EventType.DISTRICT)
        self.assertEqual(EventHelper.parseEventType("Qualifying Event"), EventType.DISTRICT)
        self.assertEqual(EventHelper.parseEventType("Qualifier"), EventType.DISTRICT)

        self.assertEqual(EventHelper.parseEventType("District Championship"), EventType.DISTRICT_CMP)
        self.assertEqual(EventHelper.parseEventType("MI FRC State Championship"), EventType.DISTRICT_CMP)
        self.assertEqual(EventHelper.parseEventType("Qualifying Championship"), EventType.DISTRICT_CMP)

        self.assertEqual(EventHelper.parseEventType("Championship Division"), EventType.CMP_DIVISION)

        self.assertEqual(EventHelper.parseEventType("Championship Finals"), EventType.CMP_FINALS)
        self.assertEqual(EventHelper.parseEventType("Championship"), EventType.CMP_FINALS)

        self.assertEqual(EventHelper.parseEventType("Offseason"), EventType.OFFSEASON)
        self.assertEqual(EventHelper.parseEventType("Preseason"), EventType.PRESEASON)

        self.assertEqual(EventHelper.parseEventType("Division"), EventType.UNLABLED)