def spam_rating(self, message):
        """Calculate and return spam rating of message"""
        totals = self.storage.totals
        if not totals:
            return 0.4
        total_spam = totals['spam']
        total_ham = totals['ham']
        tokens = self.storage.tokens
        if not tokens:
            return 0.4

        hashes = map(lambda x: hash(string.upper(x)), \
                     self.__get_words_list(message))
        ratings = []
        for h in hashes:
            try:
                ham_count, spam_count = tokens[h]
                # ham_count *= 2  # this increases weight of ham
                if spam_count > 0 and ham_count == 0:
                    rating = 0.99
                elif spam_count == 0 and ham_count > 0:
                    rating = 0.01
                elif total_spam > 0 and total_ham > 0:
                    ham_prob = float(ham_count) / float(total_ham)
                    spam_prob = float(spam_count) / float(total_spam)
                    rating = spam_prob / (ham_prob + spam_prob)
                    if rating < 0.01:
                        rating = 0.01
                else:
                    rating = 0.4 # normally this won't happen
            except __HOLE__:
                rating = 0.4 # never seen this word
            ratings.append(rating)

        if (len(ratings) > 20):
            # leave only 20 most "interesting" ratings: 
            # 10  hightest and 10 lowest
            ratings.sort()
            ratings = ratings[:10] + ratings[-10:]
                    
        p = reduce(operator.mul, ratings)
        omp = reduce(operator.mul, map(lambda r: 1.0-r, ratings))
        try:
            return p / (p + omp)
        except ZeroDivisionError: # got float underflow, not sure about rating
            return 0.5
dataset/ETHPy150Open dchest/pybayesantispam/bayes.py/Bayes.spam_rating