File size: 4,549 Bytes
f1ea283
 
 
 
 
7ee5459
93474f9
 
6ff8317
 
 
 
f1ea283
93474f9
 
 
f1ea283
93474f9
 
6ff8317
f1ea283
 
93474f9
6ff8317
 
 
 
 
 
 
 
93474f9
 
6ff8317
7ee5459
f1ea283
93474f9
 
6ff8317
93474f9
 
6ff8317
93474f9
 
 
 
6ff8317
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93474f9
 
6ff8317
 
 
 
 
 
93474f9
6ff8317
 
 
93474f9
6ff8317
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93474f9
6ff8317
 
 
 
 
 
868552c
6ff8317
 
 
 
 
868552c
6ff8317
 
 
 
 
 
 
 
 
 
 
868552c
 
 
 
6ff8317
 
 
 
 
868552c
6ff8317
93474f9
6ff8317
 
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import gradio as gr
import random
import threading
import time
from datetime import datetime

FLIP_LOG = "flips.md"
is_flipping = False
start_time = None
heads_count = 0
tails_count = 0
flip_lock = threading.Lock()

# Make sure the flip log exists
with open(FLIP_LOG, "a") as f:
    f.write("## Eternal Coin Flips\n\n")  # Add header once if not present

# Flip forever in the background
def flip_forever():
    global heads_count, tails_count
    while True:
        result = random.choice(["Heads", "Tails"])
        timestamp = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")
        
        # Update counters thread-safely
        with flip_lock:
            if result == "Heads":
                heads_count += 1
            else:
                tails_count += 1
        
        with open(FLIP_LOG, "a") as f:
            f.write(f"- {timestamp}: {result}\n")
        
        time.sleep(1)

# Trigger flipping once
def start_flipping():
    global is_flipping, start_time
    if not is_flipping:
        is_flipping = True
        start_time = datetime.utcnow()
        threading.Thread(target=flip_forever, daemon=True).start()
        return "Started flipping! No going back now."
    return "Already flipping."

# Get runtime duration
def get_runtime():
    if start_time is None:
        return "Not started yet"
    
    current_time = datetime.utcnow()
    runtime = current_time - start_time
    
    # Format runtime nicely
    total_seconds = int(runtime.total_seconds())
    hours = total_seconds // 3600
    minutes = (total_seconds % 3600) // 60
    seconds = total_seconds % 60
    
    if hours > 0:
        return f"{hours}h {minutes}m {seconds}s"
    elif minutes > 0:
        return f"{minutes}m {seconds}s"
    else:
        return f"{seconds}s"

# Get current tally
def get_tally():
    with flip_lock:
        total_flips = heads_count + tails_count
        if total_flips == 0:
            return "No flips yet"
        
        heads_percent = (heads_count / total_flips) * 100
        tails_percent = (tails_count / total_flips) * 100
        
        return f"πŸͺ™ **Total Flips:** {total_flips}\n" \
               f"πŸ‘‘ **Heads:** {heads_count} ({heads_percent:.1f}%)\n" \
               f"πŸ”„ **Tails:** {tails_count} ({tails_percent:.1f}%)"

# Load last 20 flips from the log
def get_latest_flips():
    try:
        with open(FLIP_LOG, "r") as f:
            lines = f.readlines()
        return "".join(lines[-20:]) if lines else "No flips yet."
    except FileNotFoundError:
        return "No flips yet."

# Combined update function for all stats
def update_all_stats():
    return get_tally(), get_runtime(), get_latest_flips()

# Load existing data on startup (count flips from log)
def load_existing_data():
    global heads_count, tails_count
    try:
        with open(FLIP_LOG, "r") as f:
            lines = f.readlines()
        
        # Count existing flips
        for line in lines:
            if ": Heads" in line:
                heads_count += 1
            elif ": Tails" in line:
                tails_count += 1
    except FileNotFoundError:
        pass

# Load existing data on startup
load_existing_data()

# Build UI
with gr.Blocks(theme=gr.themes.Soft()) as app:
    gr.Markdown("# πŸͺ™ Eternal Coin Flipper")
    gr.Markdown("⚠️ **Zero CPU Limitation**: Click 'Refresh' to see updates (no real-time on free tier)")
    
    with gr.Row():
        with gr.Column():
            flip_button = gr.Button("πŸš€ Start Flipping", variant="primary", size="lg")
            refresh_button = gr.Button("πŸ”„ Refresh Stats", variant="secondary")
            gr.Markdown("πŸ’‘ *Tip: Bookmark and check back later to see progress!*")
        
        with gr.Column():
            # Stats display
            tally_display = gr.Markdown(value=get_tally(), label="Flip Tally")
            runtime_display = gr.Markdown(value=f"⏱️ **Runtime:** {get_runtime()}")
    
    # Flip log
    gr.Markdown("## Recent Flips")
    flip_log = gr.Textbox(label="Last 20 Flips", lines=15, max_lines=20)
    
    # Event handlers
    flip_button.click(
        fn=lambda: (start_flipping(), *update_all_stats()),
        outputs=[gr.Textbox(visible=False), tally_display, runtime_display, flip_log]
    )
    refresh_button.click(
        fn=update_all_stats, 
        outputs=[tally_display, runtime_display, flip_log]
    )
    
    # Auto-refresh when page loads
    app.load(fn=update_all_stats, outputs=[tally_display, runtime_display, flip_log])

if __name__ == "__main__":
    app.launch()