Beispiel #1
0
    def test_query_string_parse(self):
        """ Test parsing query strings, as used by the supybot plugin
        and (for city parsing) the command-line interface. """

        result = climate.parse_text_query("Toronto march".split())
        self.assertEqual(result["cities"], ["Toronto"])
        self.assertEqual(result["months"][2], True)
        self.assertEqual(result["months"][1], False)

        result = climate.parse_text_query("mar high r-low".split())
        self.assertEqual(result["categories"]["high C"], True)
        self.assertEqual(result["categories"]["record low C"], True)
        self.assertEqual(result["months"][2], True)
        self.assertEqual(result["cities"], [])

        result = climate.parse_text_query("low seattle hamilton New Zealand portland, or mar".split())
        self.assertEqual(result["categories"]["low C"], True)
        self.assertEqual(result["months"][2], True)
        self.assertEqual(result["cities"], ["Seattle", "Hamilton, New Zealand", "Portland, Or"])

        result = climate.parse_text_query(
            ("washington dc march albuquerque new mexico " + "high low seattle washington").split()
        )
        self.assertEqual(result["categories"]["high C"], True)
        self.assertEqual(result["categories"]["low C"], True)
        self.assertEqual(result["months"][2], True)
        self.assertEqual(result["cities"], ["Washington Dc", "Albuquerque", "Seattle"])
Beispiel #2
0
    def test_space_in_query_string(self):
        """ Test that localities with spaces, possibly multiple spaces,
        in the name are handled correctly. Examples: Washington, DC; 
        Albuquerque, New Mexico; Hamilton, New Zealand """

        result = climate.parse_text_query("Washington D.C. Toronto Elmira, Ontario Seattle".split())
        self.assertEqual(result["cities"], ["Washington D.C.", "Toronto", "Seattle"])

        result = climate.parse_text_query("Hamilton, New Zealand".split())
        self.assertEqual(result["cities"], ["Hamilton, New Zealand"])

        result = climate.parse_text_query("Washington, District of Columbia Toronto Ontario".split())
        self.assertEqual(result["cities"], ["Washington, District Of Columbia", "Toronto"])

        result = climate.parse_text_query("Washington, D.C. Toronto Hamilton New Zealand Seattle Washington".split())
        self.assertEqual(result["cities"], ["Washington, D.C.", "Toronto", "Hamilton, New Zealand", "Seattle"])

        result = climate.parse_text_query("Washington, D.C. Toronto Elmira, New Zealand Seattle Washington".split())
        self.assertEqual(result["cities"], ["Washington, D.C.", "Toronto", "Seattle"])
Beispiel #3
0
    def get(self, irc, msg, args, strings):
        """ <text> (including <places>, <months>, <categories>)
        Gets climate data for <places> during <months> for <categories>.
        Normally at least one each of place and month are required,
        except script will pick most contrasting month if two cities are given.
        Category will default to average high temperature if not specified.
        Get the list of recognized <categories> with `@climate categories`.
        Places, months, and categories can be mixed within <text> in any order.
        Unrecognized words will be silently ignored (this means you can write
        e.g. "Toronto and Sydney high for December"). """

        import climate

        query = climate.parse_text_query(strings)

        cities = query['cities']
        months = query['months']
        categories = query['categories']

        has_category = False
        has_month = False

        for month in months:
            has_month = has_month or month

        for category in categories:
            has_category = has_category or categories[category]

        if has_category is False:
            # default to showing high temperature if no category is specified
            categories['high C'] = True
            has_category = True

        if has_month is True:
            data = climate.get_comparison_data(cities, months, categories)
        elif len(cities) == 2:
            # get data for all, and pick most interesting one automagically
            # criterion is biggest difference between the numerical values
            # among chosen categories for the chosen cities

            # for now only two cities are supported
            # TODO: expand to arbitrary amount - will need to round-robin
            # the calculations or something

            for i in range(len(months)):
                months[i] = True

            data = climate.get_comparison_data(cities, months, categories)

            # get cities' names directly from data - they are likely 
            # different than in request (capitalization, redirects, etc)
            data_cities = data[data.keys()[0]].keys()

            comparisons = {}
            sums = {}
            for i in range(len(data_cities)):
                city = data_cities[i]
                for category,category_include in categories.items():
                    if not category_include:
                        continue

                    if category == 'location':
                        # only non-numerical 'category' so far. cannot 
                        # be compared. detect this case more robustly if we
                        # get more non-numerical categories
                        continue

                    if category not in comparisons:
                        comparisons[category] = {}
                        sums[category] = []

                    for month,month_include in enumerate(months):
                        if not month_include:
                            continue

                        if not month in comparisons[category]:
                            comparisons[category][month] = {}

                        comparisons[category][month][city] = \
                            data[month][city][category]

                    if i > 0:
                        for m,dummy_var in enumerate(months):
                            # calculate difference between the two cities for
                            # each month

                            # order within sums[category] list will be created
                            # automagically
                            sums[category].append(abs( \
                                comparisons[category][m][data_cities[i-1]] - \
                                comparisons[category][m][data_cities[i]]))

            max_month = -1
            max_value = float('-inf')
            for category in categories:
                if category in sums:
                    category_max = max(sums[category])
                    category_index = sums[category].index(category_max)
                    if category_max > max_value:
                        max_value = category_max
                        max_month = category_index

            filtered_data = {}
            if max_month > -1:
                filtered_data[max_month] = data[max_month]
            data = filtered_data
        else:
            # not supported, return empty
            data = {}

        # output format is roughly:
        """October: Toronto high 10, Melbourne high 20; April: Toronto high 10, Melbourne high 15

October: Toronto high 10, low 5, Melbourne high 20, low 12; April: Toronto high 10, low 3, Melbourne high 15, low 8"""
        # so each month first, then each city with its categories grouped

        output = []
        for month,month_data in data.items():
            month_line = calendar.month_name[month+1] + ': '

            city_lines = []
            for city,city_data in month_data.items():
                city_line = city + ' '

                category_lines = []
                for category,category_data in city_data.items():
                    if category in climate.PRINTED_ROW_TITLES:
                        category_lines.append(
                            climate.PRINTED_ROW_TITLES[category]
                            + ' ' + str(int(round(category_data, 0))))

                city_line += ', '.join(category_lines)
                city_lines.append(city_line)

            month_line += ', '.join(city_lines)
            output.append(month_line)

        output = '; '.join(output)

        response = ''
        if len(output) > 0:
            response = output
        elif len(cities) == 1 and 'location' in categories \
            and categories['location'] == True:
            data = climate.get_climate_data(cities[0])
            if 'location' in data and len(data['location']) > 0:
                response = data['title'] + ': ' + data['location']
        
        if len(response) == 0:
            response = 'No data found or invalid query. Try @help climate get.'

        irc.reply(response.encode('utf-8'), prefixNick = False)