| import gradio as gr |
| import random |
| from statistics import mean |
| from datetime import datetime |
| import time |
|
|
| |
| MAX_ROUNDS = 50 |
| DEFAULT_ROUNDS = 20 |
|
|
| |
| PINK_WINDOWS = [ |
| {"start": 55, "end": 57, "name": "প্রাইম পিঙ্ক", "multiplier": 1.9}, |
| {"start": 59, "end": 1, "name": "প্রাইম পিঙ্ক", "multiplier": 1.9}, |
| {"start": 18, "end": 20, "name": "পিঙ্ক জোন", "multiplier": 1.4}, |
| {"start": 27, "end": 29, "name": "পিঙ্ক জোন", "multiplier": 1.4}, |
| {"start": 38, "end": 40, "name": "পিঙ্ক জোন", "multiplier": 1.4}, |
| {"start": 43, "end": 45, "name": "পিঙ্ক জোন", "multiplier": 1.4}, |
| {"start": 48, "end": 50, "name": "পিঙ্ক জোন", "multiplier": 1.4}, |
| ] |
|
|
| |
| CUSTOM_CSS = """ |
| footer {visibility: hidden} |
| .active-window { background: linear-gradient(135deg, #ff1493, #ff69b4) !important; color: white !important; } |
| .approaching-window { background: linear-gradient(135deg, #ffa726, #ff9800) !important; color: white !important; } |
| .waiting-window { background: linear-gradient(135deg, #1a1a2e, #16213e) !important; color: white !important; } |
| .pink-text { color: #ff1493 !important; font-weight: bold !important; } |
| .confidence-bar { height: 8px; background: #333; border-radius: 4px; overflow: hidden; margin: 5px 0; } |
| .confidence-fill { height: 100%; background: linear-gradient(90deg, #00d4ff, #ff1493); transition: width 0.3s; } |
| .risk-badge { padding: 2px 8px; border-radius: 12px; font-size: 12px; font-weight: 600; } |
| .risk-high { background: #ff4757; color: white; padding: 2px 8px; border-radius: 12px; } |
| .risk-medium { background: #ffa726; color: black; padding: 2px 8px; border-radius: 12px; } |
| .risk-low { background: #66bb6a; color: white; padding: 2px 8px; border-radius: 12px; } |
| .time-box { text-align: center; padding: 15px; border-radius: 10px; margin-bottom: 20px; transition: all 0.3s; font-weight: 500; } |
| .gradio-container { background: #0a0a0f !important; } |
| h1 { text-align: center; margin-bottom: 10px; } |
| """ |
|
|
| |
| def get_current_time_window(): |
| """বর্তমান মিনিট অনুযায়ী পিঙ্ক জোন চেক করে""" |
| now = datetime.now() |
| minutes = now.minute |
| |
| for window in PINK_WINDOWS: |
| if window["start"] <= window["end"]: |
| if minutes >= window["start"] and minutes <= window["end"]: |
| return window |
| else: |
| |
| if minutes >= window["start"] or minutes <= window["end"]: |
| return window |
| return None |
|
|
| def get_next_time_window(): |
| """পরবর্তী পিঙ্ক জোন কত মিনিট পরে তা বের করে""" |
| now = datetime.now() |
| current_minutes = now.minute |
| |
| nearest = None |
| min_distance = 60 |
| |
| for window in PINK_WINDOWS: |
| if window["start"] <= window["end"]: |
| if current_minutes <= window["start"]: |
| distance = window["start"] - current_minutes |
| else: |
| distance = (60 - current_minutes) + window["start"] |
| else: |
| if current_minutes >= window["start"]: |
| distance = (60 - current_minutes) + window["end"] |
| elif current_minutes <= window["end"]: |
| distance = 0 |
| else: |
| distance = window["start"] - current_minutes |
| |
| if 0 < distance < min_distance: |
| min_distance = distance |
| nearest = {"window": window, "minutes": distance} |
| |
| return nearest |
|
|
| def compute_outputs(rounds): |
| """এক্সপেক্টেড মাল্টিপ্লায়ার, অ্যানালাইসিস এবং ডিসিশন ক্যালকুলেট করে""" |
| if not rounds: |
| return "0.0x", "কোন ডাটা নেই", "N/A", 0, "medium", False |
| |
| |
| recent = rounds[-10:] if len(rounds) >= 10 else rounds |
| avg = mean(recent) |
| |
| |
| expected = round(avg * random.uniform(0.92, 1.08), 2) |
| |
| |
| if len(recent) >= 2: |
| trend_val = recent[-1] - recent[-2] |
| if trend_val > 0.15: |
| trend = "উর্ধ্বমুখী 📈" |
| elif trend_val < -0.15: |
| trend = "নিম্নমুখী 📉" |
| else: |
| trend = "স্থিতিশীল ➡️" |
| else: |
| trend = "পর্যাপ্ত ডাটা নেই" |
| |
| |
| pink_count = sum(1 for r in recent if r >= 3.0) |
| pink_prob = min(0.9, pink_count / len(recent) + 0.1) |
| is_pink_expected = pink_prob > 0.4 or expected > 2.8 |
| |
| |
| current_window = get_current_time_window() |
| if current_window: |
| expected *= current_window["multiplier"] |
| expected = round(min(15.0, expected), 2) |
| pink_boost = f"✨ {current_window['name']} একটিভ!" |
| else: |
| pink_boost = "" |
| |
| |
| confidence = min(0.9, 0.5 + (len(rounds) / 100) + (pink_prob * 0.2)) |
| |
| |
| if expected > 5.0: |
| risk = "উচ্চ ⚠️" |
| elif expected > 2.5: |
| risk = "মাঝারি ⚖️" |
| else: |
| risk = "নিম্ন ✅" |
| |
| |
| if is_pink_expected: |
| decision = "পিঙ্ক আশান্বিত 🌸" |
| elif expected > 3.0: |
| decision = "বড় মাল্টিপ্লায়ার 🚀" |
| elif expected > 1.8: |
| decision = "মাঝারি 💪" |
| else: |
| decision = "ছোট 🎯" |
| |
| |
| analysis_parts = [trend] |
| if pink_boost: |
| analysis_parts.append(pink_boost) |
| if is_pink_expected: |
| analysis_parts.append("🌸 পিঙ্ক সম্ভাবনা") |
| analysis = " | ".join(analysis_parts) |
| |
| return f"{expected}x", analysis, decision, confidence, risk, is_pink_expected |
|
|
| def update_ui(rounds): |
| """UI আপডেট করার জন্য ডাটা প্রস্তুত করে""" |
| table = [[i+1, f"{val}x"] for i, val in enumerate(rounds)] |
| exp, ana, dec, conf, risk, pink = compute_outputs(rounds) |
| return table, exp, ana, dec, conf, risk, pink |
|
|
| def add_round(state, new_val): |
| """নতুন মাল্টিপ্লায়ার যোগ করে""" |
| if new_val <= 0: |
| return state + update_ui(state)[:6] |
| |
| rounds = state.copy() |
| rounds.append(new_val) |
| if len(rounds) > MAX_ROUNDS: |
| rounds = rounds[-MAX_ROUNDS:] |
| |
| table, exp, ana, dec, conf, risk, pink = update_ui(rounds) |
| return rounds, table, exp, ana, dec, conf, risk, pink |
|
|
| def reset_rounds(): |
| """ডাটা রিসেট করে""" |
| initial = [round(random.uniform(1.0, 3.5), 2) for _ in range(DEFAULT_ROUNDS)] |
| table, exp, ana, dec, conf, risk, pink = update_ui(initial) |
| return initial, table, exp, ana, dec, conf, risk, pink |
|
|
| def get_time_status(): |
| """সময়-ভিত্তিক স্ট্যাটাস আপডেট করে""" |
| now = datetime.now() |
| time_str = now.strftime("%H:%M:%S") |
| |
| current = get_current_time_window() |
| next_window = get_next_time_window() |
| |
| if current: |
| status = f"🌸 {current['name']} একটিভ! 🌸" |
| detail = f"বুস্ট: +{int((current['multiplier']-1)*100)}%" |
| css_class = "active-window" |
| elif next_window and next_window["minutes"] <= 2: |
| status = f"⚠️ {next_window['window']['name']} আসছে {next_window['minutes']} মিনিটে" |
| detail = "প্রস্তুত হোন!" |
| css_class = "approaching-window" |
| else: |
| status = "পিঙ্ক জোনের অপেক্ষায়..." |
| detail = next_window and f"পরবর্তী: {next_window['window']['name']} {next_window['minutes']} মিনিটে" or "কোন উইন্ডো নেই" |
| css_class = "waiting-window" |
| |
| return f""" |
| <div class="time-box {css_class}"> |
| <div style="font-size: 24px; font-weight: 700;">{time_str}</div> |
| <div style="font-size: 16px; font-weight: 600; margin: 5px 0;">{status}</div> |
| <div style="font-size: 12px; opacity: 0.9;">{detail}</div> |
| </div> |
| """ |
|
|
| def update_time_display(): |
| """টাইম ডিসপ্লে আপডেট করে""" |
| return get_time_status() |
|
|
| def update_confidence_display(conf, is_pink): |
| """কনফিডেন্স বার আপডেট করে""" |
| color_class = "pink-text" if is_pink else "" |
| pink_text = "🌸 পিঙ্ক মোড" if is_pink else "" |
| return f""" |
| <div style="margin: 10px 0;"> |
| <div style="display: flex; justify-content: space-between; margin-bottom: 4px;"> |
| <span class="{color_class}">এমএল কনফিডেন্স: {int(conf*100)}%</span> |
| <span class="{color_class}">{pink_text}</span> |
| </div> |
| <div class="confidence-bar"> |
| <div class="confidence-fill" style="width: {int(conf*100)}%;"></div> |
| </div> |
| </div> |
| """ |
|
|
| |
| with gr.Blocks() as demo: |
| |
| gr.HTML(""" |
| <div style="text-align: center; margin-bottom: 20px;"> |
| <h1 style="color: #00d4ff; font-size: 48px; margin: 0; text-shadow: 0 0 10px #00d4ff;">✈️ AVOLD</h1> |
| <p style="color: #888; font-size: 14px;">এভিয়েটর রাউন্ড অ্যানালাইজার</p> |
| </div> |
| """) |
| |
| |
| rounds_state = gr.State([round(random.uniform(1.0, 3.5), 2) for _ in range(DEFAULT_ROUNDS)]) |
| pink_state = gr.State(False) |
| conf_state = gr.State(0.5) |
| |
| |
| time_html = gr.HTML(value=get_time_status()) |
| |
| |
| with gr.Row(): |
| new_multiplier = gr.Number( |
| label="নতুন মাল্টিপ্লায়ার", |
| value=1.0, |
| step=0.1, |
| minimum=1.0, |
| maximum=100.0 |
| ) |
| add_btn = gr.Button("➕ যোগ করুন", variant="primary") |
| |
| |
| reset_btn = gr.Button("🔄 রিসেট ডাটা", variant="secondary") |
| |
| |
| with gr.Row(): |
| expected_out = gr.Textbox(label="📊 এক্সপেক্টেড", interactive=False) |
| analysis_out = gr.Textbox(label="📈 অ্যানালাইসিস", interactive=False) |
| decision_out = gr.Textbox(label="🎯 ডিসিশন", interactive=False) |
| |
| |
| with gr.Row(): |
| with gr.Column(scale=3): |
| confidence_html = gr.HTML(value=update_confidence_display(0.5, False)) |
| with gr.Column(scale=1): |
| risk_out = gr.Textbox(label="রিস্ক লেভেল", interactive=False) |
| |
| |
| rounds_table = gr.Dataframe( |
| label="📜 শেষ ৫০ রাউন্ড", |
| headers=["রাউন্ড", "মাল্টিপ্লায়ার"], |
| row_count=10, |
| interactive=False |
| ) |
| |
| |
| |
| |
| add_btn.click( |
| add_round, |
| inputs=[rounds_state, new_multiplier], |
| outputs=[rounds_state, rounds_table, expected_out, analysis_out, decision_out, conf_state, risk_out, pink_state] |
| ).then( |
| update_confidence_display, |
| inputs=[conf_state, pink_state], |
| outputs=[confidence_html] |
| ).then( |
| update_time_display, |
| outputs=[time_html] |
| ) |
| |
| |
| reset_btn.click( |
| reset_rounds, |
| outputs=[rounds_state, rounds_table, expected_out, analysis_out, decision_out, conf_state, risk_out, pink_state] |
| ).then( |
| update_confidence_display, |
| inputs=[conf_state, pink_state], |
| outputs=[confidence_html] |
| ).then( |
| update_time_display, |
| outputs=[time_html] |
| ) |
| |
| |
| demo.load( |
| fn=lambda s: update_ui(s) + (0.5, False), |
| inputs=[rounds_state], |
| outputs=[rounds_table, expected_out, analysis_out, decision_out, conf_state, risk_out, pink_state] |
| ).then( |
| update_confidence_display, |
| inputs=[conf_state, pink_state], |
| outputs=[confidence_html] |
| ).then( |
| update_time_display, |
| outputs=[time_html] |
| ) |
|
|
| |
| if __name__ == "__main__": |
| demo.launch( |
| server_name="0.0.0.0", |
| server_port=7860, |
| theme='dark', |
| css=CUSTOM_CSS |
| ) |