Last active
November 20, 2019 12:47
-
-
Save DomiDre/dd592df37add898491de85e329736e40 to your computer and use it in GitHub Desktop.
Determine from Whatsapp Logs, who has posted how many times 1337 at 13:37 throughout the years
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from dataclasses import dataclass | |
import re, datetime | |
LEETTIME = "1337" | |
LEET_HOUR = "13" | |
LEET_MINUTE = "37" | |
datasrc = "./whatsapplog.txt" | |
scores = {} | |
class Score: | |
def __init__(self, name): | |
self.name = name | |
self.score = 0 | |
self.posted_dates = {} | |
def add(self, date = None): | |
self.score += 1 | |
if date: | |
self.posted_dates[date] = True | |
def subtract(self): | |
self.score -= 1 | |
def __lt__(self, other): | |
return self.score < other.score | |
@dataclass | |
class MessageLine: | |
date: str | |
hour: int | |
minute: int | |
user_name: str | |
text: str | |
def read_message_line(line): | |
# extract date, time user and message from the line | |
matchObj = re.match(r'\s*(\d{2}\.\d{2}\.\d{2}),\s(\d{2}):(\d{2})\s-\s(\D+):\s(.*)', line) | |
# print(line) | |
# skip lines that are just multi line bla bla | |
if not matchObj: | |
return | |
date = matchObj.group(1) | |
hour = matchObj.group(2) | |
minute = matchObj.group(3) | |
user_name = matchObj.group(4) | |
text = matchObj.group(5) | |
return MessageLine(date, hour, minute, user_name, text) | |
def eval_current_day(day_scorers): | |
if len(day_scorers) == 0: | |
return | |
elif len(day_scorers) == 1: | |
scores[day_scorers[0]].add() | |
def is_leet(hour, minute): | |
return (hour == LEET_HOUR or hour == "14") and minute == LEET_MINUTE | |
def check_user_on_scoreboard(user_name): | |
if not user_name in scores: | |
scores[user_name] = Score(user_name) | |
with open(datasrc, 'r') as f: | |
current_day = 0 | |
day_scorers = [] | |
for line in f: | |
# only want lines that contain a date and time at the beginning. Search 1337 lines at 13:37 | |
message = read_message_line(line) | |
if not message: | |
continue | |
day_ts = datetime.datetime.strptime(message.date, '%d.%m.%y').timestamp() | |
if day_ts > current_day: | |
eval_current_day(day_scorers) | |
day_scorers = [] | |
current_day = day_ts | |
is_leet_time = is_leet(message.hour, message.minute) | |
if is_leet_time and message.text == LEETTIME: | |
# check if user is already within score board, otherwise initialize | |
check_user_on_scoreboard(message.user_name) | |
# if hasn't already scored today: | |
# add one point and note that has scored today | |
if not message.date in scores[message.user_name].posted_dates: | |
scores[message.user_name].add(message.date) | |
day_scorers.append(message.user_name) | |
if message.text == LEETTIME and not is_leet_time: | |
check_user_on_scoreboard(message.user_name) | |
scores[message.user_name].subtract() | |
# final day evaluation | |
eval_current_day(day_scorers) | |
for score in sorted(scores.values()): | |
print(f'{score.name}: {score.score}') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment