-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
108 lines (98 loc) · 3.43 KB
/
Copy pathmain.py
File metadata and controls
108 lines (98 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import os
import gzip
import re
import matplotlib.pyplot as plt
import pandas as pd
import calmap
from datetime import datetime, timedelta
from collections import defaultdict
# --- CONFIGURE THESE ---
LOG_DIRS = [
os.path.expanduser("~/AppData/Roaming/.minecraft/logs"),
# os.path.expanduser("~/AppData/Roaming/.minecraft/instances/SomeModpack/logs"),
# Add as many folders as you like
]
CUTOFF_DATE = datetime.strptime("2000-01-01", "%Y-%m-%d")
START_PATTERN = re.compile(r"\[(\d{2}:\d{2}:\d{2})\]")
END_PATTERN = re.compile(r"\[(\d{2}:\d{2}:\d{2})\]")
def extract_date_from_filename(filename):
match = re.match(r"(\d{4}-\d{2}-\d{2})", filename)
if match:
return datetime.strptime(match.group(1), "%Y-%m-%d")
return None
def read_session_times(filepath, is_gz, inferred_date):
open_func = gzip.open if is_gz else open
start_time = end_time = None
with open_func(filepath, 'rt', errors='ignore') as f:
for line in f:
if not start_time:
m = START_PATTERN.search(line)
if m:
start_time = m.group(1)
m = END_PATTERN.search(line)
if m:
end_time = m.group(1)
if start_time and end_time and inferred_date:
try:
base = inferred_date.strftime('%Y-%m-%d')
start_dt = datetime.strptime(f"{base} {start_time}", "%Y-%m-%d %H:%M:%S")
end_dt = datetime.strptime(f"{base} {end_time}", "%Y-%m-%d %H:%M:%S")
if end_dt > start_dt:
return start_dt.date(), end_dt - start_dt
except Exception:
pass
return None, None
playtime_per_day = defaultdict(timedelta)
for log_dir in LOG_DIRS:
if not os.path.isdir(log_dir):
print(f"Skipping missing folder: {log_dir}")
continue
for filename in sorted(os.listdir(log_dir)):
if not (filename.endswith(".log") or filename.endswith(".log.gz")):
continue
filepath = os.path.join(log_dir, filename)
is_gz = filename.endswith(".gz")
file_date = extract_date_from_filename(filename)
if file_date:
if file_date < CUTOFF_DATE:
continue
else:
file_date = datetime.today()
print(f"Found a log from: {file_date} [{log_dir}]")
day, duration = read_session_times(filepath, is_gz, file_date)
if day and duration:
playtime_per_day[day] += duration
TOTAL = 0
print("\n=== Playtime per Day ===")
for day in sorted(playtime_per_day.keys()):
total = playtime_per_day[day]
hours, remainder = divmod(total.total_seconds(), 3600)
minutes, seconds = divmod(remainder, 60)
print(f"{day}: {int(hours)}h {int(minutes)}m {int(seconds)}s")
TOTAL += total.total_seconds()
series = pd.Series({
pd.Timestamp(date): duration.total_seconds() / 3600
for date, duration in playtime_per_day.items()
})
calmap.calendarplot(
series,
how='sum',
cmap='YlGnBu',
fillcolor='lightgray',
linewidth=0.5,
daylabels='MTWTFSS',
dayticks=[0, 1, 2, 3, 4, 5, 6],
monthticks=1,
yearlabels=True,
yearlabel_kws={'color': 'black', 'fontsize': 14},
fig_kws={'figsize': (16, 6)},
)
hours, remainder = divmod(TOTAL, 3600)
days, hours = divmod(hours, 24)
minutes, seconds = divmod(remainder, 60)
plt.suptitle(
f"Total playtime: {int(days)}d {int(hours)}h {int(minutes)}m {int(seconds)}s",
fontsize=18
)
plt.tight_layout()
plt.show()