<jupyter_start><jupyter_text>Before you begin This depends on the Reddit APIhttps://github.com/reddit-archive/reddit/wiki/OAuth2-Quick-Start-Examplefirst-steps<jupyter_code>import requests
import bs4
import praw
import re
from pprint import pprint
import enum
from collections import defaultdict
class MatchResultEnum(enum.Enum):
    HOME_WIN = 0
    DRAW = 1
    AWAY_WIN = 2

class MatchResult:
    def __init__(self, home_goals, away_goals):
        self.home_goals = home_goals
        self.away_goals = away_goals
    
    def exactly_equals(self, match_result):
        home_goals_equal =  self.home_goals == match_result.home_goals
        away_goals_equal =  self.away_goals == match_result.away_goals
        return home_goals_equal and away_goals_equal
    
    def same_result_as(self, match_result):
        return self.result() == match_result.result()
        
    def result(self):
        if self.home_goals == self.away_goals:
            return MatchResultEnum.DRAW
        if self.home_goals > self.away_goals:
            return MatchResultEnum.HOME_WIN
        if self.home_goals < self.away_goals:
            return MatchResultEnum.AWAY_WIN
    
    def as_tuple(self):
        return (self.home_goals, self.away_goals)
    
    def __str__(self):
        return "<MatchResult " + str(self.as_tuple()) + " >"
    __repr__ = __str__


def strip_alphas(s):
    return ''.join(list(filter(lambda x: (not x.isalpha()), s)))

def parse_comments(predthread):
    """{author: MatchResult}"""
    predictions = {}
    for top_level_comment in predthread.comments:
        predictions[top_level_comment.author.name] = extract_prediction_from(top_level_comment.body)
    return predictions
        
def extract_prediction_from(comment_body):
    home_away_pattern = "(\d+)\s*-?\s*(\d+)"
    match = re.search(home_away_pattern, strip_alphas(comment_body))
    if match:
        return MatchResult(*map(int, match.groups()))
def to_list_sort_by_points(standings):
    return sorted(standings.items(), key=lambda x: x[1])[::-1]
    
def format_standings_list(standings_list):
    header = "User|Points\n:--|:--|:--\n"
    rows = ''.join([f"{author} | {points}\n" for author, points in standings_list])
    return header + rows

def without_spaces(s):
    return ''.join(filter(lambda x: not x.isspace(), s))

def is_header_line(line):
    return "User|Points" in without_spaces(line)

def markdown_to_standings(markdown_string):
    lines = markdown_string.split("\n")
    return standings_from_lines(after_header_line(lines))

def after_header_line(lines):
    if lines == []:
        return []
    if is_header_line(lines[0]):
        return lines[2:]
    else:
        return after_header_line(lines[1:])

def standings_from_lines(lines):
    standings = {}
    for line in lines:
        autdihor, points = without_spaces(line).split('|')
        standings[author] = int(points)
    return standings

def points_from_results(predicted, true):
    if predicted.exactly_equals(true):
        return 3
    elif predicted.same_result_as(true):
        return 1
    else:
        return 0

def update_standings(standings, predictions, true_result):
    """
    standings {author: points}
    predictions {author: MatchResult}
    true_result MatchResult
    """
    standings = defaultdict(lambda: 0, standings)
    for author, match_result in predictions.items():
        standings[author] = standings[author] + points_from_results(predicted=match_result, true=true_result)
    return dict(standings)
lines_str = """Man City at St. Mary's

Home - Away format

1 point for correct result, 3 points for predicting the final score.

Make your prediction before lineups are released

User	|	Points
:--	|:--	|:--
DrShaftmanPhD	|	13
docdope	|	12
Ik427	|	11
KeepItWavey	|	11
MyoMike	|	11"""
print(format_standings_list(to_list_sort_by_points(markdown_to_standings(lines_str))))
reddit = praw.Reddit(client_id="vWkVu4zcFAp-_A", client_secret="<KEY>", user_agent="mozilla:predthread (by u/gradi3nt)")<jupyter_output><empty_output><jupyter_text>This code tests whether the `reddit` instance worked as planned<jupyter_code>for submission in reddit.subreddit("saintsfc").hot(limit=10):
    print(submission.title)<jupyter_output>Weekly Transfer Thread
Free Talk Friday - December 25, 2020
Saints 20/21 Shirt Replacements
Lawro predicts the Saints to lose to Fulham. Hopefully we prove him wrong.
<NAME> receives an early Christmas present
Che and Salisu nutmeg DJ
Almost Christmas here
Prediction Thread Week 15!
<NAME> won't be at our game against Fulham on boxing day
JOSÉ FONTE: All Goals For Southampton!<jupyter_text>Get the last prediction thread by URI<jupyter_code>url = "https://www.reddit.com/r/SaintsFC/comments/kf40c7/prediction_thread_week_14/"
predthread = reddit.submission(url=url)
print(predthread.selftext)
extract_prediction_from("2-1 Saints")
pprint(parse_comments(predthread))
for c in predthread.comments:
#     print(c.author.name, strip_alphas(c.body))
    print(c.author.name, c.body)
standings = markdown_to_standings(predthread.selftext)
predictions_list = parse_comments(predthread)
new_standings = update_standings(standings, predictions_list, MatchResult(0,1))
new_standings
type(reddit)
type(predthread)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10469314079422383, 'fraction_numerical': 0.010260307809234277, 'mean_word_length': 4.222222222222222, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 2, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '471853', 'license': 'MIT', 'n_tokens_mistral': 1785, 'n_tokens_neox': 1729, 'n_words': 386, 'path': 'Untitled.ipynb', 'repo_name': 'julianirwin/predthread', 'size': '5301'}