Загрузка данных


import tkinter as tk
from tkinter import messagebox
import json
import os
import hashlib
import random
from datetime import datetime

USERS_FILE = "users.json"
BANS_FILE = "bans.json"

def load_users():
    if os.path.exists(USERS_FILE):
        with open(USERS_FILE, "r") as f:
            return json.load(f)
    return {}

def save_users(users):
    with open(USERS_FILE, "w") as f:
        json.dump(users, f, indent=2, ensure_ascii=False)

def load_bans():
    if os.path.exists(BANS_FILE):
        with open(BANS_FILE, "r") as f:
            return json.load(f)
    return {}

def save_bans(bans):
    with open(BANS_FILE, "w") as f:
        json.dump(bans, f, indent=2, ensure_ascii=False)

def is_banned(uid):
    bans = load_bans()
    if uid in bans:
        ban_until = bans[uid].get("until")
        if ban_until:
            if datetime.now() < datetime.fromisoformat(ban_until):
                return True, bans[uid]
            else:
                # Бан истёк, удаляем
                del bans[uid]
                save_bans(bans)
    return False, None

def hash_pass(pwd):
    return hashlib.sha256(pwd.encode()).hexdigest()

root = tk.Tk()
root.title("Casino")
root.geometry("400x600")
root.configure(bg="#1a3a2a")

current_user = None
balance = 0
current_bet = 100

def show_deposit():
    messagebox.showinfo("Пополнение", "Свяжитесь с владельцем через Telegram: @pegvi")

def update_balance_label():
    balance_label.config(text=f"Баланс: {balance}$")
    bet_label.config(text=f"Ставка: {current_bet}$")

def save_balance():
    users = load_users()
    if current_user in users:
        users[current_user]["balance"] = balance
        save_users(users)

# ========== ВЫБОР СТАВКИ ==========
def open_bet_settings():
    bet_window = tk.Toplevel(root)
    bet_window.title("Настройка ставки")
    bet_window.geometry("300x350")
    bet_window.configure(bg="#1a3a2a")
    bet_window.transient(root)
    bet_window.grab_set()
    
    tk.Label(bet_window, text="ВЫБЕРИТЕ СТАВКУ", font=("Arial", 14, "bold"),
             bg="#1a3a2a", fg="gold").pack(pady=15)
    
    quick_frame = tk.Frame(bet_window, bg="#1a3a2a")
    quick_frame.pack(pady=10)
    
    bets = [50, 100, 200, 500, 1000]
    for i, b in enumerate(bets):
        btn = tk.Button(quick_frame, text=f"{b}$", command=lambda val=b: set_bet(val),
                        bg="#2e6b3e", fg="white", width=8)
        btn.grid(row=i//2, column=i%2, padx=10, pady=5)
    
    tk.Label(bet_window, text="ИЛИ СВОЯ СУММА", font=("Arial", 10),
             bg="#1a3a2a", fg="#aaa").pack(pady=10)
    
    custom_frame = tk.Frame(bet_window, bg="#1a3a2a")
    custom_frame.pack(pady=5)
    
    custom_entry = tk.Entry(custom_frame, width=10, font=("Arial", 14), justify="center")
    custom_entry.pack(side=tk.LEFT, padx=5)
    custom_entry.insert(0, "100")
    
    tk.Button(custom_frame, text="Установить", command=lambda: set_custom_bet(custom_entry.get()),
              bg="#f39c12", fg="black", width=10).pack(side=tk.LEFT, padx=5)
    
    tk.Label(bet_window, text=f"Текущий баланс: {balance}$", font=("Arial", 10),
             bg="#1a3a2a", fg="lightgreen").pack(pady=15)
    
    tk.Button(bet_window, text="ЗАКРЫТЬ", command=bet_window.destroy,
              bg="#555", fg="white", width=12).pack(pady=15)

def set_bet(value):
    global current_bet
    if value <= balance:
        current_bet = value
        update_balance_label()
        messagebox.showinfo("Ставка", f"Ставка установлена: {current_bet}$")
    else:
        messagebox.showerror("Ошибка", f"Ставка {value}$ больше баланса {balance}$!")

def set_custom_bet(value):
    global current_bet
    try:
        val = int(value)
        if val <= 0:
            messagebox.showerror("Ошибка", "Ставка должна быть больше 0!")
            return
        if val <= balance:
            current_bet = val
            update_balance_label()
            messagebox.showinfo("Ставка", f"Ставка установлена: {current_bet}$")
        else:
            messagebox.showerror("Ошибка", f"Ставка {val}$ больше баланса {balance}$!")
    except:
        messagebox.showerror("Ошибка", "Введите число!")

# ========== ТОП ИГРОКОВ ==========
def show_top_players():
    users = load_users()
    
    if not users:
        messagebox.showinfo("Топ игроков", "Нет зарегистрированных игроков")
        return
    
    sorted_users = sorted(users.items(), key=lambda x: x[1].get("balance", 0), reverse=True)
    
    top_window = tk.Toplevel(root)
    top_window.title("Топ игроков")
    top_window.geometry("350x450")
    top_window.configure(bg="#0f2819")
    top_window.transient(root)
    top_window.grab_set()
    
    tk.Label(top_window, text="ТОП ИГРОКОВ", font=("Arial", 16, "bold"),
             bg="#0f2819", fg="gold").pack(pady=10)
    
    frame = tk.Frame(top_window, bg="#1f3d2c", relief=tk.GROOVE, bd=2)
    frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
    
    canvas = tk.Canvas(frame, bg="#1f3d2c", highlightthickness=0)
    scrollbar = tk.Scrollbar(frame, orient="vertical", command=canvas.yview)
    scrollable_frame = tk.Frame(canvas, bg="#1f3d2c")
    
    scrollable_frame.bind("<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
    canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
    canvas.configure(yscrollcommand=scrollbar.set)
    
    for i, (uid, data) in enumerate(sorted_users[:20], 1):
        bg_color = "#2c3e3e" if i % 2 == 0 else "#1f3d2c"
        
        row = tk.Frame(scrollable_frame, bg=bg_color)
        row.pack(fill=tk.X)
        
        if i == 1:
            medal_text = "1 (GOLD)"
        elif i == 2:
            medal_text = "2 (SILVER)"
        elif i == 3:
            medal_text = "3 (BRONZE)"
        else:
            medal_text = str(i)
        
        tk.Label(row, text=medal_text, width=8, bg=bg_color, fg="gold" if i <= 3 else "white",
                 font=("Arial", 10)).pack(side=tk.LEFT)
        tk.Label(row, text=uid, width=15, bg=bg_color, fg="white",
                 font=("Arial", 10)).pack(side=tk.LEFT)
        tk.Label(row, text=f"{data.get('balance', 0)}$", width=12, bg=bg_color, 
                 fg="lightgreen", font=("Arial", 10, "bold")).pack(side=tk.LEFT)
    
    canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
    scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
    
    tk.Button(top_window, text="ЗАКРЫТЬ", command=top_window.destroy,
              bg="#555", fg="white", width=15).pack(pady=10)

# ========== БЛЭКДЖЕК ==========
def blackjack():
    global balance, current_bet
    
    # Проверка бана
    banned, ban_info = is_banned(current_user)
    if banned:
        messagebox.showerror("Доступ запрещён", f"Вы забанены!\nПричина: {ban_info['reason']}\nДо: {ban_info['until'][:10]}")
        return
    
    if balance <= 0:
        messagebox.showerror("Ошибка", "Нет денег! Пополните баланс")
        return
    
    bet = current_bet
    if bet > balance:
        messagebox.showerror("Ошибка", f"Ставка {bet}$ больше баланса {balance}$!\nУменьшите ставку")
        return
    
    player = random.randint(15, 21)
    dealer = random.randint(15, 21)
    
    msg = f"Ваша ставка: {bet}$\nВаши очки: {player}\nОчки дилера: {dealer}\n"
    
    if player > 21:
        balance -= bet
        msg += f"Перебор! Вы проиграли {bet}$"
    elif dealer > 21:
        balance += bet
        msg += f"Дилер перебрал! Вы выиграли {bet}$"
    elif player > dealer:
        balance += bet
        msg += f"Вы выиграли {bet}$"
    elif player < dealer:
        balance -= bet
        msg += f"Вы проиграли {bet}$"
    else:
        msg += "Ничья!"
    
    save_balance()
    update_balance_label()
    messagebox.showinfo("Результат", msg)

# ========== ИГРОВОЙ АВТОМАТ ==========
def slot_machine():
    global balance, current_bet
    
    # Проверка бана
    banned, ban_info = is_banned(current_user)
    if banned:
        messagebox.showerror("Доступ запрещён", f"Вы забанены!\nПричина: {ban_info['reason']}\nДо: {ban_info['until'][:10]}")
        return
    
    if balance <= 0:
        messagebox.showerror("Ошибка", "Нет денег! Пополните баланс")
        return
    
    bet = current_bet
    if bet > balance:
        messagebox.showerror("Ошибка", f"Ставка {bet}$ больше баланса {balance}$!\nУменьшите ставку")
        return
    
    symbols = ['7', 'C', 'L', 'O', 'B', 'D', 'S']
    
    r1 = random.choice(symbols)
    r2 = random.choice(symbols)
    r3 = random.choice(symbols)
    
    msg = f"Выпало: {r1} | {r2} | {r3}\n"
    
    if r1 == '7' and r2 == '7' and r3 == '7':
        win = bet * 100
        balance += win
        msg += f"ДЖЕКПОТ 777! +{win}$"
    elif r1 == r2 == r3:
        win = bet * 10
        balance += win
        msg += f"ТРИ ОДИНАКОВЫХ! +{win}$"
    elif r1 == r2 or r1 == r3 or r2 == r3:
        win = bet * 2
        balance += win
        msg += f"ДВА ОДИНАКОВЫХ! +{win}$"
    else:
        balance -= bet
        msg += f"ПРОИГРЫШ! -{bet}$"
    
    save_balance()
    update_balance_label()
    messagebox.showinfo("Результат", msg)

# ========== ВХОД ==========
def do_login():
    global current_user, balance
    uid = login_id.get().strip()
    pwd = login_pass.get()
    
    users = load_users()
    
    # Проверка бана при входе
    banned, ban_info = is_banned(uid)
    if banned:
        error_label.config(text=f"Вы забанены! Причина: {ban_info['reason']}", fg="red")
        return
    
    if uid in users and users[uid]["password"] == hash_pass(pwd):
        current_user = uid
        balance = users[uid].get("balance", 1000)
        update_balance_label()
        login_frame.pack_forget()
        game_frame.pack(fill=tk.BOTH, expand=True)
    else:
        error_label.config(text="Неверный ID или пароль!")

def do_register():
    uid = login_id.get().strip()
    pwd = login_pass.get()
    
    if not uid or not pwd:
        error_label.config(text="Заполните ID и пароль!")
        return
    
    if len(uid) < 3:
        error_label.config(text="ID от 3 символов!")
        return
    
    if len(pwd) < 4:
        error_label.config(text="Пароль от 4 символов!")
        return
    
    users = load_users()
    
    if uid in users:
        error_label.config(text="ID уже существует!")
        return
    
    users[uid] = {
        "password": hash_pass(pwd), 
        "balance": 1000,
        "created": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    }
    save_users(users)
    
    error_label.config(text=f"Аккаунт создан! Баланс: 1000$", fg="green")
    login_id.delete(0, tk.END)
    login_pass.delete(0, tk.END)

# ========== ИНТЕРФЕЙС ==========
login_frame = tk.Frame(root, bg="#1a3a2a")
login_frame.pack(fill=tk.BOTH, expand=True)

tk.Label(login_frame, text="КАЗИНО", font=("Arial", 28, "bold"),
         bg="#1a3a2a", fg="gold").pack(pady=40)

tk.Label(login_frame, text="ID:", bg="#1a3a2a", fg="white",
         font=("Arial", 12)).pack()
login_id = tk.Entry(login_frame, font=("Arial", 14), justify="center")
login_id.pack(pady=5)

tk.Label(login_frame, text="Пароль:", bg="#1a3a2a", fg="white",
         font=("Arial", 12)).pack()
login_pass = tk.Entry(login_frame, show="*", font=("Arial", 14), justify="center")
login_pass.pack(pady=5)

error_label = tk.Label(login_frame, text="", bg="#1a3a2a", fg="red")
error_label.pack(pady=10)

btn_frame = tk.Frame(login_frame, bg="#1a3a2a")
btn_frame.pack(pady=20)

tk.Button(btn_frame, text="ВОЙТИ", command=do_login,
          bg="green", fg="white", font=("Arial", 12), width=10).pack(side=tk.LEFT, padx=10)

tk.Button(btn_frame, text="РЕГИСТРАЦИЯ", command=do_register,
          bg="orange", fg="black", font=("Arial", 12), width=12).pack(side=tk.LEFT, padx=10)

# Игровое меню
game_frame = tk.Frame(root, bg="#0a2a1a")

top = tk.Frame(game_frame, bg="#1a3a2a")
top.pack(fill=tk.X, padx=10, pady=10)

balance_label = tk.Label(top, text="Баланс: 0$", font=("Arial", 14, "bold"),
                          bg="#1a3a2a", fg="gold")
balance_label.pack(side=tk.LEFT, padx=10)

bet_label = tk.Label(top, text="Ставка: 100$", font=("Arial", 12),
                      bg="#1a3a2a", fg="#ffaa66")
bet_label.pack(side=tk.LEFT, padx=10)

tk.Label(top, text="", font=("Arial", 10), bg="#1a3a2a", fg="#aaa").pack(side=tk.LEFT, padx=10, expand=True)

tk.Button(top, text="СТАВКА", command=open_bet_settings,
          bg="#f39c12", fg="black", font=("Arial", 10), width=6).pack(side=tk.LEFT, padx=5)

tk.Button(top, text="ПОПОЛНИТЬ", command=show_deposit,
          bg="green", fg="white", font=("Arial", 10), width=8).pack(side=tk.RIGHT, padx=5)

game_buttons = tk.Frame(game_frame, bg="#0a2a1a")
game_buttons.pack(expand=True)

tk.Button(game_buttons, text="БЛЭКДЖЕК", command=blackjack,
          bg="#2e6b3e", fg="white", font=("Arial", 18, "bold"), width=14, height=1).pack(pady=8)

tk.Button(game_buttons, text="ИГРОВОЙ АВТОМАТ", command=slot_machine,
          bg="#8b5a2b", fg="white", font=("Arial", 16, "bold"), width=14, height=1).pack(pady=8)

tk.Button(game_buttons, text="ТОП ИГРОКОВ", command=show_top_players,
          bg="#9b59b6", fg="white", font=("Arial", 14, "bold"), width=14, height=1).pack(pady=8)

game_frame.pack_forget()

login_pass.bind("<Return>", lambda e: do_login())

root.mainloop()